[automerger skipped] [Do Not Merge] Update Platform Security String to 2019-05-05 for oc-mr1-dev Bug:128322951
am: 796d90c141 -s ours
am skip reason: subject contains skip directive
Change-Id: I088058f32b6e2a990e1f4f6db432ed74adde43a6
diff --git a/Android.mk b/Android.mk
index a1455d4..5053e7d 100644
--- a/Android.mk
+++ b/Android.mk
@@ -1,8 +1 @@
-LOCAL_PATH := $(call my-dir)
-
-# We're relocating the build project to a subdirectory, then using symlinks
-# to expose the subdirectories where they used to be. If the manifest hasn't
-# been updated, we need to include all the subdirectories.
-ifeq ($(LOCAL_PATH),build)
-include $(call first-makefiles-under,$(LOCAL_PATH))
-endif
+include $(call all-subdir-makefiles)
diff --git a/Changes.md b/Changes.md
new file mode 100644
index 0000000..37bbad0
--- /dev/null
+++ b/Changes.md
@@ -0,0 +1,116 @@
+# Build System Changes for Android.mk Writers
+
+## Deprecating / obsoleting envsetup.sh variables in Makefiles
+
+It is not required to source envsetup.sh before running a build. Many scripts,
+including a majority of our automated build systems, do not do so. Make will
+transparently make every environment variable available as a make variable.
+This means that relying on environment variables only set up in envsetup.sh will
+produce different output for local users and scripted users.
+
+Many of these variables also include absolute path names, which we'd like to
+keep out of the generated files, so that you don't need to do a full rebuild if
+you move the source tree.
+
+To fix this, we're marking the variables that are set in envsetup.sh as
+deprecated in the makefiles. This will trigger a warning every time one is read
+(or written) inside Kati. Once all the warnings have been removed for a
+particular variable, we'll switch it to obsolete, and any references will become
+errors.
+
+### envsetup.sh variables with make equivalents
+
+| instead of | use |
+|--------------------------------------------------------------|----------------------|
+| OUT {#OUT} | OUT_DIR |
+| ANDROID_HOST_OUT {#ANDROID_HOST_OUT} | HOST_OUT |
+| ANDROID_PRODUCT_OUT {#ANDROID_PRODUCT_OUT} | PRODUCT_OUT |
+| ANDROID_HOST_OUT_TESTCASES {#ANDROID_HOST_OUT_TESTCASES} | HOST_OUT_TESTCASES |
+| ANDROID_TARGET_OUT_TESTCASES {#ANDROID_TARGET_OUT_TESTCASES} | TARGET_OUT_TESTCASES |
+
+All of the make variables may be relative paths from the current directory, or
+absolute paths if the output directory was specified as an absolute path. If you
+need an absolute variable, convert it to absolute during a rule, so that it's
+not expanded into the generated ninja file:
+
+``` make
+$(PRODUCT_OUT)/gen.img: my/src/path/gen.sh
+ export PRODUCT_OUT=$$(cd $(PRODUCT_OUT); pwd); cd my/src/path; ./gen.sh -o $${PRODUCT_OUT}/gen.img
+```
+
+### ANDROID_BUILD_TOP {#ANDROID_BUILD_TOP}
+
+In Android.mk files, you can always assume that the current directory is the
+root of the source tree, so this can just be replaced with '.' (which is what
+$TOP is hardcoded to), or removed entirely. If you need an absolute path, see
+the instructions above.
+
+### Stop using PATH directly {#PATH}
+
+This isn't only set by envsetup.sh, but it is modified by it. Due to that it's
+rather easy for this to change between different shells, and it's not ideal to
+reread the makefiles every time this changes.
+
+In most cases, you shouldn't need to touch PATH at all. When you need to have a
+rule reference a particular binary that's part of the source tree or outputs,
+it's preferrable to just use the path to the file itself (since you should
+already be adding that as a dependency).
+
+Depending on the rule, passing the file path itself may not be feasible due to
+layers of unchangable scripts/binaries. In that case, be sure to add the
+dependency, but modify the PATH within the rule itself:
+
+``` make
+$(TARGET): myscript my/path/binary
+ PATH=my/path:$$PATH myscript -o $@
+```
+
+### Stop using PYTHONPATH directly {#PYTHONPATH}
+
+Like PATH, this isn't only set by envsetup.sh, but it is modified by it. Due to
+that it's rather easy for this to change between different shells, and it's not
+ideal to reread the makefiles every time.
+
+The best solution here is to start switching to Soong's python building support,
+which packages the python interpreter, libraries, and script all into one file
+that no longer needs PYTHONPATH. See fontchain_lint for examples of this:
+
+* [external/fonttools/Lib/fontTools/Android.bp] for python_library_host
+* [frameworks/base/Android.bp] for python_binary_host
+* [frameworks/base/data/fonts/Android.mk] to execute the python binary
+
+If you still need to use PYTHONPATH, do so within the rule itself, just like
+path:
+
+``` make
+$(TARGET): myscript.py $(sort $(shell find my/python/lib -name '*.py'))
+ PYTHONPATH=my/python/lib:$$PYTHONPATH myscript.py -o $@
+```
+### Stop using PRODUCT_COMPATIBILITY_MATRIX_LEVEL_OVERRIDE directly {#PRODUCT_COMPATIBILITY_MATRIX_LEVEL_OVERRIDE}
+
+Specify Framework Compatibility Matrix Version in device manifest by adding a `target-level`
+attribute to the root element `<manifest>`. If `PRODUCT_COMPATIBILITY_MATRIX_LEVEL_OVERRIDE`
+is 26 or 27, you can add `"target-level"="1"` to your device manifest instead.
+
+### Stop using USE_CLANG_PLATFORM_BUILD {#USE_CLANG_PLATFORM_BUILD}
+
+Clang is the default and only supported Android compiler, so there is no reason
+for this option to exist.
+
+### Other envsetup.sh variables {#other_envsetup_variables}
+
+* ANDROID_TOOLCHAIN
+* ANDROID_TOOLCHAIN_2ND_ARCH
+* ANDROID_DEV_SCRIPTS
+* ANDROID_EMULATOR_PREBUILTS
+* ANDROID_PRE_BUILD_PATHS
+
+These are all exported from envsetup.sh, but don't have clear equivalents within
+the makefile system. If you need one of them, you'll have to set up your own
+version.
+
+
+[build/soong/Changes.md]: https://android.googlesource.com/platform/build/soong/+/master/Changes.md
+[external/fonttools/Lib/fontTools/Android.bp]: https://android.googlesource.com/platform/external/fonttools/+/master/Lib/fontTools/Android.bp
+[frameworks/base/Android.bp]: https://android.googlesource.com/platform/frameworks/base/+/master/Android.bp
+[frameworks/base/data/fonts/Android.mk]: https://android.googlesource.com/platform/frameworks/base/+/master/data/fonts/Android.mk
diff --git a/CleanSpec.mk b/CleanSpec.mk
index fff622f..7677261 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -424,10 +424,70 @@
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/vendor/nativetest*)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/nativetest*)
+# Jack is no longer the default compiler, remove the intermediates
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/*/*/classes*.jack)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/*/*/jack*)
+
# Move adbd from $(PRODUCT_OUT)/root/sbin to $(PRODUCT_OUT)/system/bin
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/root/sbin/adbd)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/symbols/sbin/adbd)
+# Soong linux -> linux_glibc rename
+$(call add-clean-step, find $(SOONG_OUT_DIR)/.intermediates -name 'linux_x86*' | xargs rm -rf)
+$(call add-clean-step, find $(SOONG_OUT_DIR)/.intermediates -name 'linux_common*' | xargs rm -rf)
+
+# Remove old aidl/logtags files that may be in the generated source directory
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/*/*_intermediates/src)
+$(call add-clean-step, rm -f $(OUT_DIR)/target/common/obj/*/*_intermediates/java-source-list)
+$(call add-clean-step, rm -rf $(OUT_DIR)/host/common/obj/*/*_intermediates/src)
+$(call add-clean-step, rm -f $(OUT_DIR)/host/common/obj/*/*_intermediates/java-source-list)
+
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/APPS/*/flat-res)
+
+# Remove old VNDK directories without version
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib/vndk)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib/vndk-sp)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib64/vndk)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib64/vndk-sp)
+
+# Remove old dex output directories
+$(call add-clean-step, rm -rf $(TARGET_OUT_COMMON_INTERMEDIATES)/*/*_intermediates/with-local/)
+$(call add-clean-step, rm -rf $(TARGET_OUT_COMMON_INTERMEDIATES)/*/*_intermediates/no-local/)
+$(call add-clean-step, rm -rf $(HOST_OUT_COMMON_INTERMEDIATES)/*/*_intermediates/with-local/)
+$(call add-clean-step, rm -rf $(HOST_OUT_COMMON_INTERMEDIATES)/*/*_intermediates/no-local/)
+
+# Remove legacy VINTF metadata files
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/manifest.xml)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/vendor/manifest.xml)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/manifest.xml)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/vendor/compatibility_matrix.xml)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/compatibility_matrix.xml)
+
+# Remove DisplayCutoutEmulation overlays
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/overlay/DisplayCutoutEmulationWide)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/overlay/DisplayCutoutEmulationNarrow)
+
+# Remove obsolete intermedates src files
+$(call add-clean-step, rm -rf $(TARGET_OUT_COMMON_INTERMEDIATES)/*/*_intermediates/src/RenderScript.stamp*)
+$(call add-clean-step, rm -rf $(TARGET_OUT_COMMON_INTERMEDIATES)/APPS/*_intermediates/src)
+$(call add-clean-step, rm -rf $(TARGET_OUT_COMMON_INTERMEDIATES)/JAVA_LIBRARIES/*_intermediates/src)
+$(call add-clean-step, rm -rf $(TARGET_OUT_COMMON_INTERMEDIATES)/APPS/*_intermediates/java-source-list)
+$(call add-clean-step, rm -rf $(TARGET_OUT_COMMON_INTERMEDIATES)/JAVA_LIBRARIES/*_intermediates/java-source-list)
+$(call add-clean-step, rm -rf $(OUT_DOCS)/*-timestamp)
+
+$(call add-clean-step, rm -rf $(TARGET_COMMON_OUT_ROOT)/obj_asan/APPS/*_intermediates/src)
+$(call add-clean-step, rm -rf $(TARGET_COMMON_OUT_ROOT)/obj_asan/JAVA_LIBRARIES/*_intermediates/src)
+$(call add-clean-step, rm -rf $(TARGET_COMMON_OUT_ROOT)/obj_asan/APPS/*_intermediates/java-source-list)
+$(call add-clean-step, rm -rf $(TARGET_COMMON_OUT_ROOT)/obj_asan/JAVA_LIBRARIES/*_intermediates/java-source-list)
+
+# Remove stale init.noenforce.rc
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/etc/init/gsi/init.noenforce.rc)
+
+# Clean up Launcher3 which has been replaced with Launcher3QuickStep
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app/Launcher3)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/priv-app/Launcher3)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/Launcher3_intermediates)
+
# ************************************************
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
# ************************************************
diff --git a/OWNERS b/OWNERS
index 89cea0d..1e9b763 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,6 +1,11 @@
ccross@android.com
dwillemsen@google.com
+nanzhang@google.com
+
+per-file * = ccross@android.com
+per-file * = dwillemsen@google.com
+per-file * = nanzhang@google.com
# for version updates
per-file version_defaults.mk = aseaton@google.com
-per-file version_defaults.mk = elisapascual@google.com
\ No newline at end of file
+per-file version_defaults.mk = elisapascual@google.com
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..47809a9
--- /dev/null
+++ b/README.md
@@ -0,0 +1,23 @@
+# Android Make Build System
+
+This is the Makefile-based portion of the Android Build System.
+
+For documentation on how to run a build, see [Usage.txt](Usage.txt)
+
+For a list of behavioral changes useful for Android.mk writers see
+[Changes.md](Changes.md)
+
+For an outdated reference on Android.mk files, see
+[build-system.html](/core/build-system.html). Our Android.mk files look similar,
+but are entirely different from the Android.mk files used by the NDK build
+system. When searching for documentation elsewhere, ensure that it is for the
+platform build system -- most are not.
+
+This Makefile-based system is in the process of being replaced with [Soong], a
+new build system written in Go. During the transition, all of these makefiles
+are read by [Kati], and generate a ninja file instead of being executed
+directly. That's combined with a ninja file read by Soong so that the build
+graph of the two systems can be combined and run as one.
+
+[Kati]: https://github.com/google/kati
+[Soong]: https://android.googlesource.com/platform/build/soong/+/master
diff --git a/Usage.txt b/Usage.txt
new file mode 100644
index 0000000..004210b
--- /dev/null
+++ b/Usage.txt
@@ -0,0 +1,85 @@
+Android build system usage:
+
+m [-j] [<targets>] [<variable>=<value>...]
+
+
+Ways to specify what to build:
+ The common way to specify what to build is to set that information in the
+ environment via:
+
+ # Set up the shell environment.
+ source build/envsetup.sh # Run "hmm" after sourcing for more info
+ # Select the device and variant to target. If no argument is given, it
+ # will list choices and prompt.
+ lunch [<product>-<variant>] # Selects the device and variant to target.
+ # Invoke the configured build.
+ m [<options>] [<targets>] [<variable>=<value>...]
+
+ <product> is the device that the created image is intended to be run on.
+ This is saved in the shell environment as $TARGET_PRODUCT by `lunch`.
+ <variant> is one of "user", "userdebug", or "eng", and controls the
+ amount of debugging to be added into the generated image.
+ This gets saved in the shell environment as $TARGET_BUILD_VARIANT by
+ `lunch`.
+
+ Each of <options>, <targets>, and <variable>=<value> is optional.
+ If no targets are specified, the build system will build the images
+ for the configured product and variant.
+
+ An alternative to setting $TARGET_PRODUCT and $TARGET_BUILD_VARIANT,
+ which you may see in build servers, is to execute:
+
+ make PRODUCT-<product>-<variant>
+
+
+ A target may be a file path. For example, out/host/linux-x86/bin/adb .
+ Note that when giving a relative file path as a target, that path is
+ interpreted relative to the root of the source tree (rather than relative
+ to the current working directory).
+
+ A target may also be any other target defined within a Makefile. Run
+ `m help` to view the names of some common targets.
+
+ To view the modules and targets defined in a particular directory, look for:
+ files named *.mk (most commonly Android.mk)
+ these files are defined in Make syntax
+ files named Android.bp
+ these files are defined in Blueprint syntax
+
+ For now, the full (extremely large) compiled list of targets can be found
+ (after running the build once), split among these two files:
+
+ ${OUT}/build-<product>*.ninja
+ ${OUT}/soong/build.ninja
+
+ If you find yourself interacting with these files, you are encouraged to
+ provide a more convenient tool for browsing targets, and to mention the
+ tool here.
+
+Targets that adjust an existing build:
+ showcommands Display the individual commands run to implement
+ the build
+ dist Copy into ${DIST_DIR} the portion of the build
+ that must be distributed
+
+Flags
+ -j <N> Run <N> processes at once
+ -j Autodetect the number of processes to run at once,
+ and run that many
+
+Variables
+ Variables can either be set in the surrounding shell environment or can be
+ passed as command-line arguments. For example:
+ export I_AM_A_SHELL_VAR=1
+ I_AM_ANOTHER_SHELL_VAR=2 make droid I_AM_A_MAKE_VAR=3
+ Here are some common variables and their meanings:
+ TARGET_PRODUCT The <product> to build # as described above
+ TARGET_BUILD_VARIANT The <variant> to build # as described above
+ DIST_DIR The directory in which to place the distribution
+ artifacts.
+ OUT_DIR The directory in which to place non-distribution
+ artifacts.
+
+ There is not yet known a convenient method by which to discover the full
+ list of supported variables. Please mention it here when there is.
+
diff --git a/core/Makefile b/core/Makefile
index 618e983..0a2f6e3 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -4,15 +4,6 @@
# intermedites-dir-for
LOCAL_PATH := $(BUILD_SYSTEM)
-# Pick a reasonable string to use to identify files.
-ifneq (,$(filter eng.%,$(BUILD_NUMBER)))
- # BUILD_NUMBER has a timestamp in it, which means that
- # it will change every time. Pick a stable value.
- FILE_NAME_TAG := eng.$(USER)
-else
- FILE_NAME_TAG := $(BUILD_NUMBER)
-endif
-
# -----------------------------------------------------------------
# Define rules to copy PRODUCT_COPY_FILES defined by the product.
# PRODUCT_COPY_FILES contains words like <source file>:<dest file>[:<owner>].
@@ -21,9 +12,11 @@
# The filter part means "only eval the copy-one-file rule if this
# src:dest pair is the first one to match the same dest"
#$(1): the src:dest pair
+#$(2): the dest
define check-product-copy-files
-$(if $(filter %.apk, $(call word-colon, 2, $(1))),$(error \
- Prebuilt apk found in PRODUCT_COPY_FILES: $(1), use BUILD_PREBUILT instead!))
+$(if $(filter-out $(TARGET_COPY_OUT_SYSTEM_OTHER)/%,$(2)), \
+ $(if $(filter %.apk, $(2)),$(error \
+ Prebuilt apk found in PRODUCT_COPY_FILES: $(1), use BUILD_PREBUILT instead!)))
endef
# filter out the duplicate <source file>:<dest file> pairs.
unique_product_copy_files_pairs :=
@@ -31,22 +24,46 @@
$(if $(filter $(unique_product_copy_files_pairs),$(cf)),,\
$(eval unique_product_copy_files_pairs += $(cf))))
unique_product_copy_files_destinations :=
+product_copy_files_ignored :=
$(foreach cf,$(unique_product_copy_files_pairs), \
$(eval _src := $(call word-colon,1,$(cf))) \
$(eval _dest := $(call word-colon,2,$(cf))) \
- $(call check-product-copy-files,$(cf)) \
+ $(call check-product-copy-files,$(cf),$(_dest)) \
$(if $(filter $(unique_product_copy_files_destinations),$(_dest)), \
- $(info PRODUCT_COPY_FILES $(cf) ignored.), \
+ $(eval product_copy_files_ignored += $(cf)), \
$(eval _fulldest := $(call append-path,$(PRODUCT_OUT),$(_dest))) \
$(if $(filter %.xml,$(_dest)),\
$(eval $(call copy-xml-file-checked,$(_src),$(_fulldest))),\
- $(eval $(call copy-one-file,$(_src),$(_fulldest)))) \
+ $(if $(and $(filter %.jar,$(_dest)),$(filter $(basename $(notdir $(_dest))),$(PRODUCT_LOADED_BY_PRIVILEGED_MODULES))),\
+ $(eval $(call copy-and-uncompress-dexs,$(_src),$(_fulldest))), \
+ $(eval $(call copy-one-file,$(_src),$(_fulldest))))) \
$(eval ALL_DEFAULT_INSTALLED_MODULES += $(_fulldest)) \
$(eval unique_product_copy_files_destinations += $(_dest))))
+
+# Dump a list of overriden (and ignored PRODUCT_COPY_FILES entries)
+$(file >$(PRODUCT_OUT)/product_copy_files_ignored.txt,$(subst $(space),$(newline),$(strip $(product_copy_files_ignored))))
+ifdef dist_goal
+$(file >$(DIST_DIR)/logs/product_copy_files_ignored.txt,$(subst $(space),$(newline),$(strip $(product_copy_files_ignored))))
+endif
+
+product_copy_files_ignored :=
unique_product_copy_files_pairs :=
unique_product_copy_files_destinations :=
# -----------------------------------------------------------------
+# Returns the max allowed size for an image suitable for hash verification
+# (e.g., boot.img, recovery.img, etc).
+# The value 69632 derives from MAX_VBMETA_SIZE + MAX_FOOTER_SIZE in $(AVBTOOL).
+# $(1): partition size to flash the image
+define get-hash-image-max-size
+$(if $(1), \
+ $(if $(filter true,$(BOARD_AVB_ENABLE)), \
+ $(eval _hash_meta_size := 69632), \
+ $(eval _hash_meta_size := 0)) \
+ $(1)-$(_hash_meta_size))
+endef
+
+# -----------------------------------------------------------------
# Define rules to copy headers defined in copy_headers.mk
# If more than one makefile declared a header, print a warning,
# then copy the last one defined. This matches the previous make
@@ -70,6 +87,27 @@
@cp -f $< $@
endif
+ndk_doxygen_out := $(OUT_NDK_DOCS)
+ndk_headers := $(SOONG_OUT_DIR)/ndk/sysroot/usr/include
+ndk_docs_src_dir := frameworks/native/docs
+ndk_doxyfile := $(ndk_docs_src_dir)/Doxyfile
+ifneq ($(wildcard $(ndk_docs_src_dir)),)
+ndk_docs_srcs := $(addprefix $(ndk_docs_src_dir)/,\
+ $(call find-files-in-subdirs,$(ndk_docs_src_dir),"*",.))
+$(ndk_doxygen_out)/index.html: $(ndk_docs_srcs) $(SOONG_OUT_DIR)/ndk.timestamp
+ @mkdir -p $(ndk_doxygen_out)
+ @echo "Generating NDK docs to $(ndk_doxygen_out)"
+ @( cat $(ndk_doxyfile); \
+ echo "INPUT=$(ndk_headers)"; \
+ echo "HTML_OUTPUT=$(ndk_doxygen_out)" \
+ ) | doxygen -
+
+# Note: Not a part of the docs target because we don't have doxygen available.
+# You can run this target locally if you have doxygen installed.
+ndk-docs: $(ndk_doxygen_out)/index.html
+.PHONY: ndk-docs
+endif
+
# -----------------------------------------------------------------
# property_overrides_split_enabled
property_overrides_split_enabled :=
@@ -78,6 +116,28 @@
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))
+FINAL_VENDOR_DEFAULT_PROPERTIES := $(call uniq-pairs-by-first-component, \
+ $(FINAL_VENDOR_DEFAULT_PROPERTIES),=)
+
+# -----------------------------------------------------------------
# prop.default
ifdef property_overrides_split_enabled
INSTALLED_DEFAULT_PROP_TARGET := $(TARGET_OUT)/etc/prop.default
@@ -90,10 +150,11 @@
endif
ALL_DEFAULT_INSTALLED_MODULES += $(INSTALLED_DEFAULT_PROP_TARGET)
FINAL_DEFAULT_PROPERTIES := \
- $(call collapse-pairs, $(ADDITIONAL_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, $(PRODUCT_DEFAULT_PROPERTY_OVERRIDES))
+ $(call collapse-pairs, $(FINAL_VENDOR_DEFAULT_PROPERTIES))
endif
FINAL_DEFAULT_PROPERTIES := $(call uniq-pairs-by-first-component, \
$(FINAL_DEFAULT_PROPERTIES),=)
@@ -115,7 +176,7 @@
$(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) build/tools/post_process_props.py $@
+ $(hide) build/make/tools/post_process_props.py $@
ifdef property_overrides_split_enabled
$(hide) mkdir -p $(TARGET_ROOT_OUT)
$(hide) ln -sf system/etc/prop.default $(INSTALLED_DEFAULT_PROP_OLD_TARGET)
@@ -128,11 +189,6 @@
INSTALLED_VENDOR_DEFAULT_PROP_TARGET := $(TARGET_OUT_VENDOR)/default.prop
ALL_DEFAULT_INSTALLED_MODULES += $(INSTALLED_VENDOR_DEFAULT_PROP_TARGET)
-FINAL_VENDOR_DEFAULT_PROPERTIES += \
- $(call collapse-pairs, $(PRODUCT_DEFAULT_PROPERTY_OVERRIDES))
-FINAL_VENDOR_DEFAULT_PROPERTIES := $(call uniq-pairs-by-first-component, \
- $(FINAL_VENDOR_DEFAULT_PROPERTIES),=)
-
$(INSTALLED_VENDOR_DEFAULT_PROP_TARGET): $(INSTALLED_DEFAULT_PROP_TARGET)
@echo Target buildinfo: $@
@mkdir -p $(dir $@)
@@ -141,7 +197,7 @@
echo "#" >> $@;
$(hide) $(foreach line,$(FINAL_VENDOR_DEFAULT_PROPERTIES), \
echo "$(line)" >> $@;)
- $(hide) build/tools/post_process_props.py $@
+ $(hide) build/make/tools/post_process_props.py $@
endif # property_overrides_split_enabled
@@ -179,30 +235,37 @@
# The string used to uniquely identify the combined build and product; used by the OTA server.
ifeq (,$(strip $(BUILD_FINGERPRINT)))
- ifneq ($(filter eng.%,$(BUILD_NUMBER)),)
- # Trim down BUILD_FINGERPRINT: the default BUILD_NUMBER makes it easily exceed
- # the Android system property length limit (PROPERTY_VALUE_MAX=92).
- BF_BUILD_NUMBER := $(shell echo $${USER:0:6})$(shell $(DATE) +%m%d%H%M)
+ ifeq ($(strip $(HAS_BUILD_NUMBER)),false)
+ BF_BUILD_NUMBER := $(USER)$$($(DATE_FROM_FILE) +%m%d%H%M)
else
- BF_BUILD_NUMBER := $(BUILD_NUMBER)
+ 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
-ifneq ($(words $(BUILD_FINGERPRINT)),1)
- $(error BUILD_FINGERPRINT cannot contain spaces: "$(BUILD_FINGERPRINT)")
-endif
+# unset it for safety.
+BF_BUILD_NUMBER :=
-$(shell mkdir -p $(PRODUCT_OUT) && echo $(BUILD_FINGERPRINT) > $(PRODUCT_OUT)/build_fingerprint.txt)
-BUILD_FINGERPRINT_FROM_FILE := $$(cat $(PRODUCT_OUT)/build_fingerprint.txt)
+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):$(TARGET_BUILD_VARIANT)/$(BUILD_VERSION_TAGS)
+ BUILD_THUMBPRINT := $(PLATFORM_VERSION)/$(BUILD_ID)/$(BUILD_NUMBER_FROM_FILE):$(TARGET_BUILD_VARIANT)/$(BUILD_VERSION_TAGS)
endif
-ifneq ($(words $(BUILD_THUMBPRINT)),1)
- $(error BUILD_THUMBPRINT cannot contain spaces: "$(BUILD_THUMBPRINT)")
+
+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 \
@@ -235,15 +298,15 @@
$(strip $(subst _,-, $(firstword $(1))))
endef
-BUILDINFO_SH := build/tools/buildinfo.sh
-VENDOR_BUILDINFO_SH := build/tools/vendor_buildinfo.sh
+BUILDINFO_SH := build/make/tools/buildinfo.sh
+VENDOR_BUILDINFO_SH := build/make/tools/vendor_buildinfo.sh
# 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)
-ifdef SANITIZE_TARGET
+ifneq (, $(filter address, $(SANITIZE_TARGET)))
ifeq (,$(findstring _asan,$(TARGET_BUILD_FLAVOR)))
TARGET_BUILD_FLAVOR := $(TARGET_BUILD_FLAVOR)_asan
endif
@@ -254,7 +317,7 @@
else
system_prop_file := $(wildcard $(TARGET_DEVICE_DIR)/system.prop)
endif
-$(intermediate_system_build_prop): $(VENDOR_BUILDINFO_SH) $(BUILDINFO_SH) $(INTERNAL_BUILD_ID_MAKEFILE) $(BUILD_SYSTEM)/version_defaults.mk $(system_prop_file) $(INSTALLED_ANDROID_INFO_TXT_TARGET)
+$(intermediate_system_build_prop): $(BUILDINFO_SH) $(INTERNAL_BUILD_ID_MAKEFILE) $(BUILD_SYSTEM)/version_defaults.mk $(system_prop_file) $(INSTALLED_ANDROID_INFO_TXT_TARGET)
@echo Target buildinfo: $@
@mkdir -p $(dir $@)
$(hide) echo > $@
@@ -288,9 +351,10 @@
PLATFORM_PREVIEW_SDK_VERSION="$(PLATFORM_PREVIEW_SDK_VERSION)" \
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)" \
BUILD_FINGERPRINT="$(BUILD_FINGERPRINT_FROM_FILE)" \
- $(if $(OEM_THUMBPRINT_PROPERTIES),BUILD_THUMBPRINT="$(BUILD_THUMBPRINT)") \
+ $(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)" \
@@ -298,16 +362,6 @@
TARGET_CPU_ABI2="$(TARGET_CPU_ABI2)" \
TARGET_AAPT_CHARACTERISTICS="$(TARGET_AAPT_CHARACTERISTICS)" \
bash $(BUILDINFO_SH) >> $@
-ifndef property_overrides_split_enabled
- $(hide) TARGET_DEVICE="$(TARGET_DEVICE)" \
- PRODUCT_NAME="$(TARGET_PRODUCT)" \
- PRODUCT_BRAND="$(PRODUCT_BRAND)" \
- PRODUCT_MODEL="$(PRODUCT_MODEL)" \
- PRODUCT_MANUFACTURER="$(PRODUCT_MANUFACTURER)" \
- TARGET_BOOTLOADER_BOARD_NAME="$(TARGET_BOOTLOADER_BOARD_NAME)" \
- TARGET_BOARD_PLATFORM="$(TARGET_BOARD_PLATFORM)" \
- bash $(VENDOR_BUILDINFO_SH) >> $@
-endif
$(hide) $(foreach file,$(system_prop_file), \
if [ -f "$(file)" ]; then \
echo "#" >> $@; \
@@ -324,7 +378,7 @@
$(hide) $(foreach line,$(FINAL_BUILD_PROPERTIES), \
echo "$(line)" >> $@;)
$(hide) cat $(INSTALLED_ANDROID_INFO_TXT_TARGET) | grep 'require version-' | sed -e 's/require version-/ro.build.expect./g' >> $@
- $(hide) build/tools/post_process_props.py $@ $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SYSTEM_PROPERTY_BLACKLIST)
+ $(hide) build/make/tools/post_process_props.py $@ $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SYSTEM_PROPERTY_BLACKLIST)
build_desc :=
@@ -336,11 +390,7 @@
$(INSTALLED_BUILD_PROP_TARGET): $(intermediate_system_build_prop) $(INSTALLED_RECOVERYIMAGE_TARGET)
@echo "Target build info: $@"
-ifdef BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE
$(hide) grep -v 'ro.product.first_api_level' $(intermediate_system_build_prop) > $@
-else
- $(hide) cat $(intermediate_system_build_prop) > $@
-endif
ifdef INSTALLED_RECOVERYIMAGE_TARGET
$(hide) echo ro.expect.recovery_id=`cat $(RECOVERYIMAGE_ID_FILE)` >> $@
endif
@@ -349,7 +399,6 @@
# vendor build.prop
#
# For verifying that the vendor build is what we think it is
-ifdef BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE
INSTALLED_VENDOR_BUILD_PROP_TARGET := $(TARGET_OUT_VENDOR)/build.prop
ALL_DEFAULT_INSTALLED_MODULES += $(INSTALLED_VENDOR_BUILD_PROP_TARGET)
@@ -368,7 +417,10 @@
$(hide) echo ro.vendor.build.date=`$(DATE_FROM_FILE)`>>$@
$(hide) echo ro.vendor.build.date.utc=`$(DATE_FROM_FILE) +%s`>>$@
$(hide) echo ro.vendor.build.fingerprint="$(BUILD_FINGERPRINT_FROM_FILE)">>$@
-ifdef property_overrides_split_enabled
+ $(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) TARGET_DEVICE="$(TARGET_DEVICE)" \
PRODUCT_NAME="$(TARGET_PRODUCT)" \
PRODUCT_BRAND="$(PRODUCT_BRAND)" \
@@ -377,14 +429,40 @@
TARGET_BOOTLOADER_BOARD_NAME="$(TARGET_BOOTLOADER_BOARD_NAME)" \
TARGET_BOARD_PLATFORM="$(TARGET_BOARD_PLATFORM)" \
bash $(VENDOR_BUILDINFO_SH) >> $@
+ifdef property_overrides_split_enabled
$(hide) echo "#" >> $@; \
echo "# ADDITIONAL VENDOR BUILD PROPERTIES" >> $@; \
echo "#" >> $@;
$(hide) $(foreach line,$(FINAL_VENDOR_BUILD_PROPERTIES), \
echo "$(line)" >> $@;)
- $(hide) build/tools/post_process_props.py $@
endif # property_overrides_split_enabled
-endif # BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE
+ $(hide) build/make/tools/post_process_props.py $@ $(PRODUCTS.$(INTERNAL_PRODUCT).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)
+
+FINAL_PRODUCT_PROPERTIES += \
+ $(call collapse-pairs, $(PRODUCT_PRODUCT_PROPERTIES))
+FINAL_PRODUCT_PROPERTIES := $(call uniq-pairs-by-first-component, \
+ $(FINAL_PRODUCT_PROPERTIES),=)
+
+$(INSTALLED_PRODUCT_BUILD_PROP_TARGET):
+ @echo Target product buildinfo: $@
+ @mkdir -p $(dir $@)
+ $(hide) echo > $@
+ifdef BOARD_USES_PRODUCTIMAGE
+ $(hide) echo ro.product.build.date=`$(DATE_FROM_FILE)`>>$@
+ $(hide) echo ro.product.build.date.utc=`$(DATE_FROM_FILE) +%s`>>$@
+ $(hide) echo ro.product.build.fingerprint="$(BUILD_FINGERPRINT_FROM_FILE)">>$@
+endif # BOARD_USES_PRODUCTIMAGE
+ $(hide) echo "#" >> $@; \
+ echo "# ADDITIONAL PRODUCT PROPERTIES" >> $@; \
+ echo "#" >> $@;
+ $(hide) $(foreach line,$(FINAL_PRODUCT_PROPERTIES), \
+ echo "$(line)" >> $@;)
+ $(hide) build/make/tools/post_process_props.py $@
# ----------------------------------------------------------------
@@ -428,7 +506,7 @@
# Create empty package stats file if target builds no jar(s) or apk(s).
$(hide) touch $@
else
- $(hide) build/tools/dump-package-stats $^ > $@
+ $(hide) build/make/tools/dump-package-stats $^ > $@
endif
.PHONY: package-stats
@@ -488,9 +566,9 @@
SOONG_CONV_DATA := $(call intermediates-dir-for,PACKAGING,soong_conversion)/soong_conv_data
$(SOONG_CONV_DATA):
@rm -f $@
- @$(foreach s,$(SOONG_CONV),echo "$(s),$(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)))" >>$@;)
-SOONG_TO_CONVERT_SCRIPT := build/tools/soong_to_convert.py
+SOONG_TO_CONVERT_SCRIPT := build/make/tools/soong_to_convert.py
SOONG_TO_CONVERT := $(PRODUCT_OUT)/soong_to_convert.txt
$(SOONG_TO_CONVERT): $(SOONG_CONV_DATA) $(SOONG_TO_CONVERT_SCRIPT)
@rm -f $@
@@ -498,6 +576,28 @@
$(call dist-for-goals,droidcore,$(SOONG_TO_CONVERT))
# -----------------------------------------------------------------
+# Modules use -Wno-error, or added default -Wall -Werror
+WALL_WERROR := $(PRODUCT_OUT)/wall_werror.txt
+$(WALL_WERROR):
+ @rm -f $@
+ echo "# Modules using -Wno-error" >> $@
+ for m in $(sort $(SOONG_MODULES_USING_WNO_ERROR) $(MODULES_USING_WNO_ERROR)); do echo $$m >> $@; done
+ echo "# Modules added default -Wall" >> $@
+ for m in $(sort $(SOONG_MODULES_ADDED_WALL) $(MODULES_ADDED_WALL)); do echo $$m >> $@; done
+
+$(call dist-for-goals,droidcore,$(WALL_WERROR))
+
+# -----------------------------------------------------------------
+# Modules missing profile files
+PGO_PROFILE_MISSING := $(PRODUCT_OUT)/pgo_profile_file_missing.txt
+$(PGO_PROFILE_MISSING):
+ @rm -f $@
+ echo "# Modules missing PGO profile files" >> $@
+ for m in $(SOONG_MODULES_MISSING_PGO_PROFILE_FILE); do echo $$m >> $@; done
+
+$(call dist-for-goals,droidcore,$(PGO_PROFILE_MISSING))
+
+# -----------------------------------------------------------------
# The dev key is used to sign this package, and as the key required
# for future OTA packages installed by this system. Actual product
# deliverables will be re-signed by hand. We expect this file to
@@ -531,7 +631,7 @@
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/tools/event_log_tags.py
+$(all_event_log_tags_file): $(all_event_log_tags_src) $(pdk_fusion_log_tags_file) $(MERGETAGS) build/make/tools/event_log_tags.py
$(hide) mkdir -p $(dir $@)
$(hide) $(MERGETAGS) -o $@ $(PRIVATE_SRC_FILES)
@@ -547,7 +647,7 @@
$(event_log_tags_file): PRIVATE_SRC_FILES := $(event_log_tags_src) $(pdk_fusion_log_tags_file)
$(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/tools/event_log_tags.py
+$(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
$(hide) mkdir -p $(dir $@)
$(hide) $(MERGETAGS) -o $@ -m $(PRIVATE_MERGED_FILE) $(PRIVATE_SRC_FILES)
@@ -595,6 +695,8 @@
@echo "make $@: ignoring dependencies"
$(hide) $(MKBOOTFS) -d $(TARGET_OUT) $(TARGET_ROOT_OUT) | $(MINIGZIP) > $(INSTALLED_RAMDISK_TARGET)
+INSTALLED_BOOTIMAGE_TARGET := $(PRODUCT_OUT)/boot.img
+
ifneq ($(strip $(TARGET_NO_KERNEL)),true)
# -----------------------------------------------------------------
@@ -633,8 +735,6 @@
--os_version $(PLATFORM_VERSION) \
--os_patch_level $(PLATFORM_SECURITY_PATCH)
-INSTALLED_BOOTIMAGE_TARGET := $(PRODUCT_OUT)/boot.img
-
# BOARD_USES_RECOVERY_AS_BOOT = true must have BOARD_BUILD_SYSTEM_ROOT_IMAGE = true.
ifeq ($(BOARD_USES_RECOVERY_AS_BOOT),true)
ifneq ($(BOARD_BUILD_SYSTEM_ROOT_IMAGE),true)
@@ -652,7 +752,7 @@
$(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,$@,$(BOARD_BOOTIMAGE_PARTITION_SIZE))
+ $(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) \
@@ -663,9 +763,9 @@
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),$(BOARD_BOOTIMAGE_PARTITION_SIZE))
+ $(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 $@ \
+ --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)
@@ -717,6 +817,13 @@
endif # BOARD_USES_RECOVERY_AS_BOOT
else # TARGET_NO_KERNEL
+ifdef BOARD_PREBUILT_BOOTIMAGE
+ifneq ($(BOARD_BUILD_SYSTEM_ROOT_IMAGE),true)
+# Remove when b/63676296 is resolved.
+$(error Prebuilt bootimage is only supported for AB targets)
+endif
+$(eval $(call copy-one-file,$(BOARD_PREBUILT_BOOTIMAGE),$(INSTALLED_BOOTIMAGE_TARGET)))
+else
INTERNAL_KERNEL_CMDLINE := $(strip $(BOARD_KERNEL_CMDLINE))
# HACK: The top-level targets depend on the bootimage. Not all targets
# can produce a bootimage, though, and emulator targets need the ramdisk
@@ -725,6 +832,7 @@
# kernel-less inputs.
INSTALLED_BOOTIMAGE_TARGET := $(INSTALLED_RAMDISK_TARGET)
endif
+endif
# -----------------------------------------------------------------
# NOTICE files
@@ -764,8 +872,8 @@
$(2) $(3): PRIVATE_MESSAGE := $(4)
$(2) $(3): PRIVATE_DIR := $(5)
$(2) : $(3)
-$(3) : $(6) $(BUILD_SYSTEM)/Makefile build/tools/generate-notice-files.py
- build/tools/generate-notice-files.py --text-output $(2) \
+$(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),-e vendor --xml-output, \
$(if $(filter $(1),xml_vendor),-i vendor --xml-output, \
--html-output)) $(3) \
@@ -784,7 +892,8 @@
tools_notice_file_txt := $(HOST_OUT_INTERMEDIATES)/NOTICE.txt
tools_notice_file_html := $(HOST_OUT_INTERMEDIATES)/NOTICE.html
-ifeq ($(PRODUCT_FULL_TREBLE),true)
+# TODO(b/69865032): Make PRODUCT_NOTICE_SPLIT the default behavior.
+ifeq ($(PRODUCT_NOTICE_SPLIT),true)
target_notice_file_html_or_xml := $(TARGET_OUT_INTERMEDIATES)/NOTICE.xml
target_notice_file_html_or_xml_gz := $(TARGET_OUT_INTERMEDIATES)/NOTICE.xml.gz
installed_notice_html_or_xml_gz := $(TARGET_OUT)/etc/NOTICE.xml.gz
@@ -955,7 +1064,7 @@
ifneq (true,$(TARGET_USERIMAGES_SPARSE_SQUASHFS_DISABLED))
INTERNAL_USERIMAGES_SPARSE_SQUASHFS_FLAG := -s
endif
-ifneq ($(filter $(BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE) $(BOARD_SYSTEMIMAGE_FILE_SYSTEM_TYPE),squashfs),)
+ifneq ($(filter $(BOARD_PRODUCTIMAGE_FILE_SYSTEM_TYPE) $(BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE) $(BOARD_SYSTEMIMAGE_FILE_SYSTEM_TYPE),squashfs),)
INTERNAL_USERIMAGES_DEPS += $(MAKE_SQUASHFS) $(MKSQUASHFSUSERIMG) $(IMG2SIMG)
endif
@@ -985,8 +1094,9 @@
$(if $(BOARD_SYSTEMIMAGE_PARTITION_SIZE),$(hide) echo "system_size=$(BOARD_SYSTEMIMAGE_PARTITION_SIZE)" >> $(1))
$(if $(BOARD_SYSTEMIMAGE_FILE_SYSTEM_TYPE),$(hide) echo "system_fs_type=$(BOARD_SYSTEMIMAGE_FILE_SYSTEM_TYPE)" >> $(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))
-$(if $(BOARD_HAS_EXT4_RESERVED_BLOCKS),$(hide) echo "has_ext4_reserved_blocks=$(BOARD_HAS_EXT4_RESERVED_BLOCKS)" >> $(1))
+$(if $(BOARD_EXT4_SHARE_DUP_BLOCKS),$(hide) echo "ext4_share_dup_blocks=$(BOARD_EXT4_SHARE_DUP_BLOCKS)" >> $(1))
$(if $(BOARD_SYSTEMIMAGE_SQUASHFS_COMPRESSOR),$(hide) echo "system_squashfs_compressor=$(BOARD_SYSTEMIMAGE_SQUASHFS_COMPRESSOR)" >> $(1))
$(if $(BOARD_SYSTEMIMAGE_SQUASHFS_COMPRESSOR_OPT),$(hide) echo "system_squashfs_compressor_opt=$(BOARD_SYSTEMIMAGE_SQUASHFS_COMPRESSOR_OPT)" >> $(1))
$(if $(BOARD_SYSTEMIMAGE_SQUASHFS_BLOCK_SIZE),$(hide) echo "system_squashfs_block_size=$(BOARD_SYSTEMIMAGE_SQUASHFS_BLOCK_SIZE)" >> $(1))
@@ -1001,6 +1111,7 @@
$(if $(BOARD_CACHEIMAGE_PARTITION_SIZE),$(hide) echo "cache_size=$(BOARD_CACHEIMAGE_PARTITION_SIZE)" >> $(1))
$(if $(BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE),$(hide) echo "vendor_fs_type=$(BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE)" >> $(1))
$(if $(BOARD_VENDORIMAGE_EXTFS_INODE_COUNT),$(hide) echo "vendor_extfs_inode_count=$(BOARD_VENDORIMAGE_EXTFS_INODE_COUNT)" >> $(1))
+$(if $(BOARD_VENDORIMAGE_EXTFS_RSV_PCT),$(hide) echo "vendor_extfs_rsv_pct=$(BOARD_VENDORIMAGE_EXTFS_RSV_PCT)" >> $(1))
$(if $(BOARD_VENDORIMAGE_PARTITION_SIZE),$(hide) echo "vendor_size=$(BOARD_VENDORIMAGE_PARTITION_SIZE)" >> $(1))
$(if $(BOARD_VENDORIMAGE_JOURNAL_SIZE),$(hide) echo "vendor_journal_size=$(BOARD_VENDORIMAGE_JOURNAL_SIZE)" >> $(1))
$(if $(BOARD_VENDORIMAGE_SQUASHFS_COMPRESSOR),$(hide) echo "vendor_squashfs_compressor=$(BOARD_VENDORIMAGE_SQUASHFS_COMPRESSOR)" >> $(1))
@@ -1008,9 +1119,20 @@
$(if $(BOARD_VENDORIMAGE_SQUASHFS_BLOCK_SIZE),$(hide) echo "vendor_squashfs_block_size=$(BOARD_VENDORIMAGE_SQUASHFS_BLOCK_SIZE)" >> $(1))
$(if $(BOARD_VENDORIMAGE_SQUASHFS_DISABLE_4K_ALIGN),$(hide) echo "vendor_squashfs_disable_4k_align=$(BOARD_VENDORIMAGE_SQUASHFS_DISABLE_4K_ALIGN)" >> $(1))
$(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VENDOR_BASE_FS_PATH),$(hide) echo "vendor_base_fs_file=$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VENDOR_BASE_FS_PATH)" >> $(1))
+$(if $(BOARD_PRODUCTIMAGE_FILE_SYSTEM_TYPE),$(hide) echo "product_fs_type=$(BOARD_PRODUCTIMAGE_FILE_SYSTEM_TYPE)" >> $(1))
+$(if $(BOARD_PRODUCTIMAGE_EXTFS_INODE_COUNT),$(hide) echo "product_extfs_inode_count=$(BOARD_PRODUCTIMAGE_EXTFS_INODE_COUNT)" >> $(1))
+$(if $(BOARD_PRODUCTIMAGE_EXTFS_RSV_PCT),$(hide) echo "product_extfs_rsv_pct=$(BOARD_PRODUCTIMAGE_EXTFS_RSV_PCT)" >> $(1))
+$(if $(BOARD_PRODUCTIMAGE_PARTITION_SIZE),$(hide) echo "product_size=$(BOARD_PRODUCTIMAGE_PARTITION_SIZE)" >> $(1))
+$(if $(BOARD_PRODUCTIMAGE_JOURNAL_SIZE),$(hide) echo "product_journal_size=$(BOARD_PRODUCTIMAGE_JOURNAL_SIZE)" >> $(1))
+$(if $(BOARD_PRODUCTIMAGE_SQUASHFS_COMPRESSOR),$(hide) echo "product_squashfs_compressor=$(BOARD_PRODUCTIMAGE_SQUASHFS_COMPRESSOR)" >> $(1))
+$(if $(BOARD_PRODUCTIMAGE_SQUASHFS_COMPRESSOR_OPT),$(hide) echo "product_squashfs_compressor_opt=$(BOARD_PRODUCTIMAGE_SQUASHFS_COMPRESSOR_OPT)" >> $(1))
+$(if $(BOARD_PRODUCTIMAGE_SQUASHFS_BLOCK_SIZE),$(hide) echo "product_squashfs_block_size=$(BOARD_PRODUCTIMAGE_SQUASHFS_BLOCK_SIZE)" >> $(1))
+$(if $(BOARD_PRODUCTIMAGE_SQUASHFS_DISABLE_4K_ALIGN),$(hide) echo "product_squashfs_disable_4k_align=$(BOARD_PRODUCTIMAGE_SQUASHFS_DISABLE_4K_ALIGN)" >> $(1))
+$(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PRODUCT_BASE_FS_PATH),$(hide) echo "product_base_fs_file=$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PRODUCT_BASE_FS_PATH)" >> $(1))
$(if $(BOARD_OEMIMAGE_PARTITION_SIZE),$(hide) echo "oem_size=$(BOARD_OEMIMAGE_PARTITION_SIZE)" >> $(1))
$(if $(BOARD_OEMIMAGE_JOURNAL_SIZE),$(hide) echo "oem_journal_size=$(BOARD_OEMIMAGE_JOURNAL_SIZE)" >> $(1))
$(if $(BOARD_OEMIMAGE_EXTFS_INODE_COUNT),$(hide) echo "oem_extfs_inode_count=$(BOARD_OEMIMAGE_EXTFS_INODE_COUNT)" >> $(1))
+$(if $(BOARD_OEMIMAGE_EXTFS_RSV_PCT),$(hide) echo "oem_extfs_rsv_pct=$(BOARD_OEMIMAGE_EXTFS_RSV_PCT)" >> $(1))
$(if $(INTERNAL_USERIMAGES_SPARSE_EXT_FLAG),$(hide) echo "extfs_sparse_flag=$(INTERNAL_USERIMAGES_SPARSE_EXT_FLAG)" >> $(1))
$(if $(INTERNAL_USERIMAGES_SPARSE_SQUASHFS_FLAG),$(hide) echo "squashfs_sparse_flag=$(INTERNAL_USERIMAGES_SPARSE_SQUASHFS_FLAG)" >> $(1))
$(hide) echo "selinux_fc=$(SELINUX_FC)" >> $(1)
@@ -1019,8 +1141,10 @@
$(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VERITY),$(hide) echo "verity_key=$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VERITY_SIGNING_KEY)" >> $(1))
$(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VERITY),$(hide) echo "verity_signer_cmd=$(notdir $(VERITY_SIGNER))" >> $(1))
$(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VERITY_FEC),$(hide) echo "verity_fec=$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VERITY_FEC)" >> $(1))
+$(if $(filter eng, $(TARGET_BUILD_VARIANT)),$(hide) echo "verity_disable=true" >> $(1))
$(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SYSTEM_VERITY_PARTITION),$(hide) echo "system_verity_block_device=$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SYSTEM_VERITY_PARTITION)" >> $(1))
$(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VENDOR_VERITY_PARTITION),$(hide) echo "vendor_verity_block_device=$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VENDOR_VERITY_PARTITION)" >> $(1))
+$(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PRODUCT_VERITY_PARTITION),$(hide) echo "product_verity_block_device=$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PRODUCT_VERITY_PARTITION)" >> $(1))
$(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VBOOT),$(hide) echo "vboot=$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VBOOT)" >> $(1))
$(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VBOOT),$(hide) echo "vboot_key=$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VBOOT_SIGNING_KEY)" >> $(1))
$(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VBOOT),$(hide) echo "vboot_subkey=$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VBOOT_SIGNING_SUBKEY)" >> $(1))
@@ -1041,6 +1165,13 @@
$(hide) echo "avb_vendor_key_path=$(BOARD_AVB_VENDOR_KEY_PATH)" >> $(1)
$(hide) echo "avb_vendor_algorithm=$(BOARD_AVB_VENDOR_ALGORITHM)" >> $(1)
$(hide) echo "avb_vendor_rollback_index_location=$(BOARD_AVB_VENDOR_ROLLBACK_INDEX_LOCATION)" >> $(1)))
+$(if $(BOARD_AVB_ENABLE),$(hide) echo "avb_product_hashtree_enable=$(BOARD_AVB_ENABLE)" >> $(1))
+$(if $(BOARD_AVB_ENABLE),$(hide) echo "avb_product_add_hashtree_footer_args=$(BOARD_AVB_PRODUCT_ADD_HASHTREE_FOOTER_ARGS)" >> $(1))
+$(if $(BOARD_AVB_ENABLE),\
+ $(if $(BOARD_AVB_PRODUCT_KEY_PATH),\
+ $(hide) echo "avb_product_key_path=$(BOARD_AVB_PRODUCT_KEY_PATH)" >> $(1)
+ $(hide) echo "avb_product_algorithm=$(BOARD_AVB_PRODUCT_ALGORITHM)" >> $(1)
+ $(hide) echo "avb_product_rollback_index_location=$(BOARD_AVB_PRODUCT_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)),\
@@ -1049,6 +1180,23 @@
$(if $(2),$(hide) $(foreach kv,$(2),echo "$(kv)" >> $(1);))
endef
+# $(1): modules list
+# $(2): output dir
+# $(3): mount point
+# $(4): staging dir
+# Depmod requires a well-formed kernel version so 0.0 is used as a placeholder.
+define build-image-kernel-modules
+ $(hide) rm -rf $(2)/lib/modules
+ $(hide) mkdir -p $(2)/lib/modules
+ $(hide) cp $(1) $(2)/lib/modules/
+ $(hide) rm -rf $(4)
+ $(hide) mkdir -p $(4)/lib/modules/0.0/$(3)lib/modules
+ $(hide) cp $(1) $(4)/lib/modules/0.0/$(3)lib/modules
+ $(hide) $(DEPMOD) -b $(4) 0.0
+ $(hide) sed -e 's/\(.*modules.*\):/\/\1:/g' -e 's/ \([^ ]*modules[^ ]*\)/ \/\1/g' $(4)/lib/modules/0.0/modules.dep > $(2)/lib/modules/modules.dep
+ $(hide) cp $(4)/lib/modules/0.0/modules.alias $(2)/lib/modules
+endef
+
# -----------------------------------------------------------------
# Recovery image
@@ -1062,9 +1210,16 @@
recovery_sepolicy := \
$(TARGET_RECOVERY_ROOT_OUT)/sepolicy \
$(TARGET_RECOVERY_ROOT_OUT)/plat_file_contexts \
- $(TARGET_RECOVERY_ROOT_OUT)/nonplat_file_contexts \
+ $(TARGET_RECOVERY_ROOT_OUT)/vendor_file_contexts \
$(TARGET_RECOVERY_ROOT_OUT)/plat_property_contexts \
- $(TARGET_RECOVERY_ROOT_OUT)/nonplat_property_contexts
+ $(TARGET_RECOVERY_ROOT_OUT)/vendor_property_contexts
+
+ifdef BOARD_ODM_SEPOLICY_DIRS
+recovery_sepolicy += \
+ $(TARGET_RECOVERY_ROOT_OUT)/odm_file_contexts \
+ $(TARGET_RECOVERY_ROOT_OUT)/odm_property_contexts
+endif
+
# Passed into rsync from non-recovery root to recovery root, to avoid overwriting recovery-specific
# SELinux files
IGNORE_RECOVERY_SEPOLICY := $(patsubst $(TARGET_RECOVERY_OUT)/%,--exclude=/%,$(recovery_sepolicy))
@@ -1075,6 +1230,9 @@
ifdef property_overrides_split_enabled
recovery_build_props += $(INSTALLED_VENDOR_BUILD_PROP_TARGET)
endif
+ifdef BOARD_USES_PRODUCTIMAGE
+recovery_build_props += $(INSTALLED_PRODUCT_BUILD_PROP_TARGET)
+endif
recovery_resources_common := $(call include-path-for, recovery)/res
# Set recovery_density to the density bucket of the device.
@@ -1120,33 +1278,33 @@
recovery_wipe :=
endif
-# Prior to A/B update, we used to have:
+# Traditionally with non-A/B OTA we have:
# boot.img + recovery-from-boot.p + recovery-resource.dat = recovery.img.
-# recovery-resource.dat is needed only if we carry a patch of the boot and
-# recovery images and invoke install-recovery.sh on the first boot post an
-# OTA update.
+# recovery-resource.dat is needed only if we carry an imgdiff patch of the boot and recovery images
+# and invoke install-recovery.sh on the first boot post an OTA update.
#
# We no longer need that if one of the following conditions holds:
-# a) We carry a full copy of the recovery image
+# a) We carry a full copy of the recovery image - no patching needed
# (BOARD_USES_FULL_RECOVERY_IMAGE = true);
-# b) We build a single image that contains boot and recovery both
-# (BOARD_USES_RECOVERY_AS_BOOT = true).
+# b) We build a single image that contains boot and recovery both - no recovery image to install
+# (BOARD_USES_RECOVERY_AS_BOOT = true);
+# c) We build the root into system image - not needing the resource file as we do bsdiff
+# (BOARD_BUILD_SYSTEM_ROOT_IMAGE = true).
+# d) We include the recovery DTBO 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_DTBO = true).
+# Note that condition b) implies condition c), because of the earlier check in this file:
+# "BOARD_USES_RECOVERY_AS_BOOT = true must have BOARD_BUILD_SYSTEM_ROOT_IMAGE = true" (not vice
+# versa though).
-ifeq (,$(filter true, $(BOARD_USES_FULL_RECOVERY_IMAGE) $(BOARD_USES_RECOVERY_AS_BOOT)))
+ifeq (,$(filter true, $(BOARD_USES_FULL_RECOVERY_IMAGE) $(BOARD_BUILD_SYSTEM_ROOT_IMAGE) \
+ $(BOARD_INCLUDE_RECOVERY_DTBO)))
# Named '.dat' so we don't attempt to use imgdiff for patching it.
RECOVERY_RESOURCE_ZIP := $(TARGET_OUT)/etc/recovery-resource.dat
else
RECOVERY_RESOURCE_ZIP :=
endif
-ifeq ($(TARGET_PRIVATE_RES_DIRS),)
- $(info No private recovery resources for TARGET_DEVICE $(TARGET_DEVICE))
-endif
-
-ifeq ($(recovery_fstab),)
- $(info No recovery.fstab for TARGET_DEVICE $(TARGET_DEVICE))
-endif
-
INTERNAL_RECOVERYIMAGE_ARGS := \
$(addprefix --second ,$(INSTALLED_2NDBOOTLOADER_TARGET)) \
--kernel $(recovery_kernel) \
@@ -1162,6 +1320,9 @@
ifdef BOARD_KERNEL_PAGESIZE
INTERNAL_RECOVERYIMAGE_ARGS += --pagesize $(BOARD_KERNEL_PAGESIZE)
endif
+ifdef BOARD_INCLUDE_RECOVERY_DTBO
+ INTERNAL_RECOVERYIMAGE_ARGS += --recovery_dtbo $(BOARD_PREBUILT_DTBOIMAGE)
+endif
# Keys authorized to sign OTA packages this build will accept. The
# build always uses dev-keys for this; release packaging tools will
@@ -1183,37 +1344,21 @@
RECOVERYIMAGE_ID_FILE := $(PRODUCT_OUT)/recovery.id
-# $(1): modules list
-# $(2): output dir
-# $(3): mount point
-# $(4): staging dir
-# Depmod requires a well-formed kernel version so 0.0 is used as a placeholder.
-define build-image-kernel-modules
- $(hide) rm -rf $(2)/lib/modules
- $(hide) mkdir -p $(2)/lib/modules
- $(hide) cp $(1) $(2)/lib/modules/
- $(hide) rm -rf $(4)
- $(hide) mkdir -p $(4)/lib/modules/0.0/$(3)lib/modules
- $(hide) cp $(1) $(4)/lib/modules/0.0/$(3)lib/modules
- $(hide) $(DEPMOD) -b $(4) 0.0
- $(hide) sed -e 's/\(.*modules.*\):/\/\1:/g' -e 's/ \([^ ]*modules[^ ]*\)/ \/\1/g' $(4)/lib/modules/0.0/modules.dep > $(2)/lib/modules/modules.dep
- $(hide) cp $(4)/lib/modules/0.0/modules.alias $(2)/lib/modules
-endef
-
# $(1): output file
define build-recoveryimage-target
- @echo ----- Making recovery image ------
+ # Making recovery image
$(hide) mkdir -p $(TARGET_RECOVERY_OUT)
$(hide) mkdir -p $(TARGET_RECOVERY_ROOT_OUT)/etc $(TARGET_RECOVERY_ROOT_OUT)/sdcard $(TARGET_RECOVERY_ROOT_OUT)/tmp
- @echo Copying baseline ramdisk...
+ # Copying baseline ramdisk...
# Use rsync because "cp -Rf" fails to overwrite broken symlinks on Mac.
$(hide) rsync -a --exclude=etc --exclude=sdcard $(IGNORE_RECOVERY_SEPOLICY) $(IGNORE_CACHE_LINK) $(TARGET_ROOT_OUT) $(TARGET_RECOVERY_OUT)
# Copy adbd from system/bin to recovery/root/sbin
$(hide) cp -f $(TARGET_OUT_EXECUTABLES)/adbd $(TARGET_RECOVERY_ROOT_OUT)/sbin/adbd
- @echo Modifying ramdisk contents...
+ # Modifying ramdisk contents...
$(if $(BOARD_RECOVERY_KERNEL_MODULES), \
$(call build-image-kernel-modules,$(BOARD_RECOVERY_KERNEL_MODULES),$(TARGET_RECOVERY_ROOT_OUT),,$(call intermediates-dir-for,PACKAGING,depmod_recovery)))
- $(hide) rm -f $(TARGET_RECOVERY_ROOT_OUT)/init*.rc
+ # Removes $(TARGET_RECOVERY_ROOT_OUT)/init*.rc EXCEPT init.recovery*.rc.
+ $(hide) find $(TARGET_RECOVERY_ROOT_OUT) -maxdepth 1 -name 'init*.rc' -type f -not -name "init.recovery.*.rc" | xargs rm -f
$(hide) cp -f $(recovery_initrc) $(TARGET_RECOVERY_ROOT_OUT)/
$(hide) cp $(TARGET_ROOT_OUT)/init.recovery.*.rc $(TARGET_RECOVERY_ROOT_OUT)/ || true # Ignore error when the src file doesn't exist.
$(hide) mkdir -p $(TARGET_RECOVERY_ROOT_OUT)/res
@@ -1252,16 +1397,13 @@
)
$(if $(filter true,$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VBOOT)), \
$(VBOOT_SIGNER) $(FUTILITY) $(1).unsigned $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VBOOT_SIGNING_KEY).vbpubk $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VBOOT_SIGNING_KEY).vbprivk $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VBOOT_SIGNING_SUBKEY).vbprivk $(1).keyblock $(1))
- $(if $(and $(filter true,$(BOARD_USES_RECOVERY_AS_BOOT)),$(filter true,$(BOARD_AVB_ENABLE))), \
- $(hide) $(AVBTOOL) add_hash_footer \
- --image $(1) \
- --partition_size $(BOARD_BOOTIMAGE_PARTITION_SIZE) \
- --partition_name boot $(INTERNAL_AVB_BOOT_SIGNING_ARGS) \
- $(BOARD_AVB_BOOT_ADD_HASH_FOOTER_ARGS))
$(if $(filter true,$(BOARD_USES_RECOVERY_AS_BOOT)), \
- $(hide) $(call assert-max-image-size,$(1),$(BOARD_BOOTIMAGE_PARTITION_SIZE)), \
- $(hide) $(call assert-max-image-size,$(1),$(BOARD_RECOVERYIMAGE_PARTITION_SIZE)))
- @echo ----- Made recovery image: $(1) --------
+ $(hide) $(call assert-max-image-size,$(1),$(call get-hash-image-max-size,$(BOARD_BOOTIMAGE_PARTITION_SIZE))), \
+ $(hide) $(call assert-max-image-size,$(1),$(call get-hash-image-max-size,$(BOARD_RECOVERYIMAGE_PARTITION_SIZE))))
+ $(if $(filter true,$(BOARD_AVB_ENABLE)), \
+ $(if $(filter true,$(BOARD_USES_RECOVERY_AS_BOOT)), \
+ $(hide) $(AVBTOOL) add_hash_footer --image $(1) --partition_size $(BOARD_BOOTIMAGE_PARTITION_SIZE) --partition_name boot $(INTERNAL_AVB_BOOT_SIGNING_ARGS) $(BOARD_AVB_BOOT_ADD_HASH_FOOTER_ARGS),\
+ $(hide) $(AVBTOOL) add_hash_footer --image $(1) --partition_size $(BOARD_RECOVERYIMAGE_PARTITION_SIZE) --partition_name recovery $(INTERNAL_AVB_RECOVERY_SIGNING_ARGS) $(BOARD_AVB_RECOVERY_ADD_HASH_FOOTER_ARGS)))
endef
ADBD := $(TARGET_OUT_EXECUTABLES)/adbd
@@ -1324,12 +1466,12 @@
.PHONY: recoveryimage
recoveryimage: $(INSTALLED_RECOVERYIMAGE_TARGET) $(RECOVERY_RESOURCE_ZIP)
-ifeq ($(BOARD_NAND_PAGE_SIZE),)
-BOARD_NAND_PAGE_SIZE := 2048
+ifneq ($(BOARD_NAND_PAGE_SIZE),)
+$(error MTD device is no longer supported and thus BOARD_NAND_PAGE_SIZE is deprecated.)
endif
-ifeq ($(BOARD_NAND_SPARE_SIZE),)
-BOARD_NAND_SPARE_SIZE := 64
+ifneq ($(BOARD_NAND_SPARE_SIZE),)
+$(error MTD device is no longer supported and thus BOARD_NAND_SPARE_SIZE is deprecated.)
endif
# -----------------------------------------------------------------
@@ -1344,7 +1486,8 @@
$(ALL_GENERATED_SOURCES) \
$(ALL_DEFAULT_INSTALLED_MODULES) \
$(PDK_FUSION_SYSIMG_FILES) \
- $(RECOVERY_RESOURCE_ZIP))
+ $(RECOVERY_RESOURCE_ZIP)) \
+ $(PDK_FUSION_SYMLINK_STAMP)
FULL_SYSTEMIMAGE_DEPS := $(INTERNAL_SYSTEMIMAGE_FILES) $(INTERNAL_USERIMAGES_DEPS)
@@ -1368,7 +1511,7 @@
@mkdir -p $(dir $@)
@rm -f $@
$(hide) $(FILESLIST) $(TARGET_OUT) > $(@:.txt=.json)
- $(hide) build/tools/fileslist_util.py -c $(@:.txt=.json) > $@
+ $(hide) build/make/tools/fileslist_util.py -c $(@:.txt=.json) > $@
.PHONY: installed-file-list
installed-file-list: $(INSTALLED_FILES_FILE)
@@ -1394,23 +1537,36 @@
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
+
# $(1): output file
define build-systemimage-target
@echo "Target system fs image: $(1)"
$(call create-system-vendor-symlink)
+ $(call create-system-product-symlink)
@mkdir -p $(dir $(1)) $(systemimage_intermediates) && rm -rf $(systemimage_intermediates)/system_image_info.txt
$(call generate-userimage-prop-dictionary, $(systemimage_intermediates)/system_image_info.txt, \
skip_fsck=true)
$(hide) PATH=$(foreach p,$(INTERNAL_USERIMAGES_BINARY_PATHS),$(p):)$$PATH \
- ./build/tools/releasetools/build_image.py \
+ build/make/tools/releasetools/build_image.py \
$(TARGET_OUT) $(systemimage_intermediates)/system_image_info.txt $(1) $(TARGET_OUT) \
|| ( echo "Out of space? the tree size of $(TARGET_OUT) is (MB): " 1>&2 ;\
du -sm $(TARGET_OUT) 1>&2;\
if [ "$(INTERNAL_USERIMAGES_EXT_VARIANT)" == "ext4" ]; then \
maxsize=$(BOARD_SYSTEMIMAGE_PARTITION_SIZE); \
- if [ "$(BOARD_HAS_EXT4_RESERVED_BLOCKS)" == "true" ]; then \
- maxsize=$$((maxsize - 4096 * 4096)); \
- fi; \
echo "The max is $$(( maxsize / 1048576 )) MB." 1>&2 ;\
else \
echo "The max is $$(( $(BOARD_SYSTEMIMAGE_PARTITION_SIZE) / 1048576 )) MB." 1>&2 ;\
@@ -1432,15 +1588,21 @@
# image size check calculation.
ifneq ($(INSTALLED_RECOVERYIMAGE_TARGET),)
ifneq ($(BOARD_USES_FULL_RECOVERY_IMAGE),true)
+ifneq (,$(filter true, $(BOARD_BUILD_SYSTEM_ROOT_IMAGE) $(BOARD_INCLUDE_RECOVERY_DTBO)))
+diff_tool := $(HOST_OUT_EXECUTABLES)/bsdiff
+else
+diff_tool := $(HOST_OUT_EXECUTABLES)/imgdiff
+endif
intermediates := $(call intermediates-dir-for,PACKAGING,recovery_patch)
RECOVERY_FROM_BOOT_PATCH := $(intermediates)/recovery_from_boot.p
-$(RECOVERY_FROM_BOOT_PATCH): $(INSTALLED_RECOVERYIMAGE_TARGET) \
- $(INSTALLED_BOOTIMAGE_TARGET) \
- $(HOST_OUT_EXECUTABLES)/imgdiff \
- $(HOST_OUT_EXECUTABLES)/bsdiff
+$(RECOVERY_FROM_BOOT_PATCH): PRIVATE_DIFF_TOOL := $(diff_tool)
+$(RECOVERY_FROM_BOOT_PATCH): \
+ $(INSTALLED_RECOVERYIMAGE_TARGET) \
+ $(INSTALLED_BOOTIMAGE_TARGET) \
+ $(diff_tool)
@echo "Construct recovery from boot"
mkdir -p $(dir $@)
- PATH=$(HOST_OUT_EXECUTABLES):$$PATH $(HOST_OUT_EXECUTABLES)/imgdiff $(INSTALLED_BOOTIMAGE_TARGET) $(INSTALLED_RECOVERYIMAGE_TARGET) $@
+ $(PRIVATE_DIFF_TOOL) $(INSTALLED_BOOTIMAGE_TARGET) $(INSTALLED_RECOVERYIMAGE_TARGET) $@
else # $(BOARD_USES_FULL_RECOVERY_IMAGE) == true
RECOVERY_FROM_BOOT_PATCH := $(INSTALLED_RECOVERYIMAGE_TARGET)
endif
@@ -1475,6 +1637,7 @@
define build-systemtarball-target
$(call pretty,"Target system fs tarball: $(INSTALLED_SYSTEMTARBALL_TARGET)")
$(call create-system-vendor-symlink)
+ $(call create-system-product-symlink)
$(MKTARBALL) $(FS_GET_STATS) \
$(PRODUCT_OUT) system $(PRIVATE_SYSTEM_TAR) \
$(INSTALLED_SYSTEMTARBALL_TARGET) $(TARGET_OUT)
@@ -1555,6 +1718,10 @@
$(hide) cd $(dir $@) && zip -qryX $(notdir $@) \
$(TARGET_COPY_OUT_VENDOR)
endif
+ifdef BOARD_PRODUCTIMAGE_FILE_SYSTEM_TYPE
+ $(hide) cd $(dir $@) && zip -qryX $(notdir $@) \
+ $(TARGET_COPY_OUT_PRODUCT)
+endif
ifneq ($(PDK_PLATFORM_JAVA_ZIP_CONTENTS),)
$(hide) cd $(OUT_DIR) && zip -qryX $(patsubst $(OUT_DIR)/%,%,$@) $(PDK_PLATFORM_JAVA_ZIP_CONTENTS)
endif
@@ -1563,7 +1730,8 @@
endif
@# Add dex-preopt files and config.
$(if $(PRIVATE_DEX_FILES),$(hide) cd $(OUT_DIR) && zip -qryX $(patsubst $(OUT_DIR)/%,%,$@ $(PRIVATE_DEX_FILES)))
- $(hide) zip -qryXj $@ $(PRIVATE_ODEX_CONFIG)
+ $(hide) touch $(PRODUCT_OUT)/pdk.mk
+ $(hide) zip -qryXj $@ $(PRIVATE_ODEX_CONFIG) $(PRODUCT_OUT)/pdk.mk
.PHONY: platform
platform: $(INSTALLED_PLATFORM_ZIP)
@@ -1628,7 +1796,7 @@
@mkdir -p $(userdataimage_intermediates) && rm -rf $(userdataimage_intermediates)/userdata_image_info.txt
$(call generate-userimage-prop-dictionary, $(userdataimage_intermediates)/userdata_image_info.txt, skip_fsck=true)
$(hide) PATH=$(foreach p,$(INTERNAL_USERIMAGES_BINARY_PATHS),$(p):)$$PATH \
- ./build/tools/releasetools/build_image.py \
+ build/make/tools/releasetools/build_image.py \
$(TARGET_OUT_DATA) $(userdataimage_intermediates)/userdata_image_info.txt $(INSTALLED_USERDATAIMAGE_TARGET) $(TARGET_OUT)
$(hide) $(call assert-max-image-size,$(INSTALLED_USERDATAIMAGE_TARGET),$(BOARD_USERDATAIMAGE_PARTITION_SIZE))
endef
@@ -1735,7 +1903,7 @@
@mkdir -p $(cacheimage_intermediates) && rm -rf $(cacheimage_intermediates)/cache_image_info.txt
$(call generate-userimage-prop-dictionary, $(cacheimage_intermediates)/cache_image_info.txt, skip_fsck=true)
$(hide) PATH=$(foreach p,$(INTERNAL_USERIMAGES_BINARY_PATHS),$(p):)$$PATH \
- ./build/tools/releasetools/build_image.py \
+ build/make/tools/releasetools/build_image.py \
$(TARGET_OUT_CACHE) $(cacheimage_intermediates)/cache_image_info.txt $(INSTALLED_CACHEIMAGE_TARGET) $(TARGET_OUT)
$(hide) $(call assert-max-image-size,$(INSTALLED_CACHEIMAGE_TARGET),$(BOARD_CACHEIMAGE_PARTITION_SIZE))
endef
@@ -1770,7 +1938,8 @@
INTERNAL_SYSTEMOTHERIMAGE_FILES := \
$(filter $(TARGET_OUT_SYSTEM_OTHER)/%,\
$(ALL_DEFAULT_INSTALLED_MODULES)\
- $(ALL_PDK_FUSION_FILES))
+ $(ALL_PDK_FUSION_FILES)) \
+ $(PDK_FUSION_SYMLINK_STAMP)
INSTALLED_FILES_FILE_SYSTEMOTHER := $(PRODUCT_OUT)/installed-files-system-other.txt
$(INSTALLED_FILES_FILE_SYSTEMOTHER) : $(INTERNAL_SYSTEMOTHERIMAGE_FILES) $(FILESLIST)
@@ -1778,7 +1947,7 @@
@mkdir -p $(dir $@)
@rm -f $@
$(hide) $(FILESLIST) $(TARGET_OUT_SYSTEM_OTHER) > $(@:.txt=.json)
- $(hide) build/tools/fileslist_util.py -c $(@:.txt=.json) > $@
+ $(hide) build/make/tools/fileslist_util.py -c $(@:.txt=.json) > $@
systemotherimage_intermediates := \
$(call intermediates-dir-for,PACKAGING,system_other)
@@ -1791,15 +1960,18 @@
@mkdir -p $(systemotherimage_intermediates) && rm -rf $(systemotherimage_intermediates)/system_other_image_info.txt
$(call generate-userimage-prop-dictionary, $(systemotherimage_intermediates)/system_other_image_info.txt, skip_fsck=true)
$(hide) PATH=$(foreach p,$(INTERNAL_USERIMAGES_BINARY_PATHS),$(p):)$$PATH \
- ./build/tools/releasetools/build_image.py \
+ build/make/tools/releasetools/build_image.py \
$(TARGET_OUT_SYSTEM_OTHER) $(systemotherimage_intermediates)/system_other_image_info.txt $(INSTALLED_SYSTEMOTHERIMAGE_TARGET) $(TARGET_OUT)
$(hide) $(call assert-max-image-size,$(INSTALLED_SYSTEMOTHERIMAGE_TARGET),$(BOARD_SYSTEMIMAGE_PARTITION_SIZE))
endef
# We just build this directly to the install location.
INSTALLED_SYSTEMOTHERIMAGE_TARGET := $(BUILT_SYSTEMOTHERIMAGE_TARGET)
+ifneq (true,$(SANITIZE_LITE))
+# Only create system_other when not building the second stage of a SANITIZE_LITE build.
$(INSTALLED_SYSTEMOTHERIMAGE_TARGET): $(INTERNAL_USERIMAGES_DEPS) $(INTERNAL_SYSTEMOTHERIMAGE_FILES) $(INSTALLED_FILES_FILE_SYSTEMOTHER)
$(build-systemotherimage-target)
+endif
.PHONY: systemotherimage-nodeps
systemotherimage-nodeps: | $(INTERNAL_USERIMAGES_DEPS)
@@ -1814,7 +1986,8 @@
INTERNAL_VENDORIMAGE_FILES := \
$(filter $(TARGET_OUT_VENDOR)/%,\
$(ALL_DEFAULT_INSTALLED_MODULES)\
- $(ALL_PDK_FUSION_FILES))
+ $(ALL_PDK_FUSION_FILES)) \
+ $(PDK_FUSION_SYMLINK_STAMP)
# platform.zip depends on $(INTERNAL_VENDORIMAGE_FILES).
$(INSTALLED_PLATFORM_ZIP) : $(INTERNAL_VENDORIMAGE_FILES)
@@ -1825,7 +1998,7 @@
@mkdir -p $(dir $@)
@rm -f $@
$(hide) $(FILESLIST) $(TARGET_OUT_VENDOR) > $(@:.txt=.json)
- $(hide) build/tools/fileslist_util.py -c $(@:.txt=.json) > $@
+ $(hide) build/make/tools/fileslist_util.py -c $(@:.txt=.json) > $@
vendorimage_intermediates := \
$(call intermediates-dir-for,PACKAGING,vendor)
@@ -1838,7 +2011,7 @@
$(if $(BOARD_VENDOR_KERNEL_MODULES), \
$(call build-image-kernel-modules,$(BOARD_VENDOR_KERNEL_MODULES),$(TARGET_OUT_VENDOR),vendor/,$(call intermediates-dir-for,PACKAGING,depmod_vendor)))
$(hide) PATH=$(foreach p,$(INTERNAL_USERIMAGES_BINARY_PATHS),$(p):)$$PATH \
- ./build/tools/releasetools/build_image.py \
+ build/make/tools/releasetools/build_image.py \
$(TARGET_OUT_VENDOR) $(vendorimage_intermediates)/vendor_image_info.txt $(INSTALLED_VENDORIMAGE_TARGET) $(TARGET_OUT)
$(hide) $(call assert-max-image-size,$(INSTALLED_VENDORIMAGE_TARGET),$(BOARD_VENDORIMAGE_PARTITION_SIZE))
endef
@@ -1860,6 +2033,56 @@
endif
# -----------------------------------------------------------------
+# product partition image
+ifdef BOARD_PRODUCTIMAGE_FILE_SYSTEM_TYPE
+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)
+
+INSTALLED_FILES_FILE_PRODUCT := $(PRODUCT_OUT)/installed-files-product.txt
+$(INSTALLED_FILES_FILE_PRODUCT) : $(INTERNAL_PRODUCTIMAGE_FILES) $(FILESLIST)
+ @echo Installed file list: $@
+ @mkdir -p $(dir $@)
+ @rm -f $@
+ $(hide) $(FILESLIST) $(TARGET_OUT_PRODUCT) > $(@:.txt=.json)
+ $(hide) build/tools/fileslist_util.py -c $(@:.txt=.json) > $@
+
+productimage_intermediates := \
+ $(call intermediates-dir-for,PACKAGING,product)
+BUILT_PRODUCTIMAGE_TARGET := $(PRODUCT_OUT)/product.img
+define build-productimage-target
+ $(call pretty,"Target product fs image: $(INSTALLED_PRODUCTIMAGE_TARGET)")
+ @mkdir -p $(TARGET_OUT_PRODUCT)
+ @mkdir -p $(productimage_intermediates) && rm -rf $(productimage_intermediates)/product_image_info.txt
+ $(call generate-userimage-prop-dictionary, $(productimage_intermediates)/product_image_info.txt, skip_fsck=true)
+ $(hide) PATH=$(foreach p,$(INTERNAL_USERIMAGES_BINARY_PATHS),$(p):)$$PATH \
+ ./build/tools/releasetools/build_image.py \
+ $(TARGET_OUT_PRODUCT) $(productimage_intermediates)/product_image_info.txt $(INSTALLED_PRODUCTIMAGE_TARGET) $(TARGET_OUT)
+ $(hide) $(call assert-max-image-size,$(INSTALLED_PRODUCTIMAGE_TARGET),$(BOARD_PRODUCTIMAGE_PARTITION_SIZE))
+endef
+
+# We just build this directly to the install location.
+INSTALLED_PRODUCTIMAGE_TARGET := $(BUILT_PRODUCTIMAGE_TARGET)
+$(INSTALLED_PRODUCTIMAGE_TARGET): $(INTERNAL_USERIMAGES_DEPS) $(INTERNAL_PRODUCTIMAGE_FILES) $(INSTALLED_FILES_FILE_PRODUCT) $(BUILD_IMAGE_SRCS)
+ $(build-productimage-target)
+
+.PHONY: productimage-nodeps pnod
+productimage-nodeps pnod: | $(INTERNAL_USERIMAGES_DEPS)
+ $(build-productimage-target)
+
+sync: $(INTERNAL_PRODUCTIMAGE_FILES)
+
+else ifdef BOARD_PREBUILT_PRODUCTIMAGE
+INSTALLED_PRODUCTIMAGE_TARGET := $(PRODUCT_OUT)/product.img
+$(eval $(call copy-one-file,$(BOARD_PREBUILT_PRODUCTIMAGE),$(INSTALLED_PRODUCTIMAGE_TARGET)))
+endif
+
+# -----------------------------------------------------------------
# dtbo image
ifdef BOARD_PREBUILT_DTBOIMAGE
INSTALLED_DTBOIMAGE_TARGET := $(PRODUCT_OUT)/dtbo.img
@@ -1879,17 +2102,6 @@
endif
-# Convert to lower case without requiring a shell, which isn't cacheable.
-to-lower = $(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))))))))))))))))))))))))))
-# Convert to upper case without requiring a shell, which isn't cacheable.
-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))))))))))))))))))))))))))
-
# -----------------------------------------------------------------
# vbmeta image
ifeq ($(BOARD_AVB_ENABLE),true)
@@ -1912,6 +2124,8 @@
DTBO_FOOTER_ARGS := BOARD_AVB_DTBO_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
# Check and set required build variables for a chain partition.
# $(1): the partition to enable AVB chain, e.g., BOOT or SYSTEM.
@@ -1964,6 +2178,15 @@
endif
endif
+ifdef INSTALLED_PRODUCTIMAGE_TARGET
+ifdef BOARD_AVB_PRODUCT_KEY_PATH
+$(eval $(call check-and-set-avb-chain-args,PRODUCT))
+else
+INTERNAL_AVB_MAKE_VBMETA_IMAGE_ARGS += \
+ --include_descriptors_from_image $(INSTALLED_PRODUCTIMAGE_TARGET)
+endif
+endif
+
ifdef INSTALLED_DTBOIMAGE_TARGET
ifdef BOARD_AVB_DTBO_KEY_PATH
$(eval $(call check-and-set-avb-chain-args,DTBO))
@@ -1973,6 +2196,15 @@
endif
endif
+ifdef INSTALLED_RECOVERYIMAGE_TARGET
+ifdef BOARD_AVB_RECOVERY_KEY_PATH
+$(eval $(call check-and-set-avb-chain-args,RECOVERY))
+else
+INTERNAL_AVB_MAKE_VBMETA_IMAGE_ARGS += \
+ --include_descriptors_from_image $(INSTALLED_RECOVERYIMAGE_TARGET)
+endif
+endif
+
BOARD_AVB_MAKE_VBMETA_IMAGE_ARGS += --padding_size 4096
# Add kernel cmdline descriptor for kernel to mount system.img as root with
@@ -2008,9 +2240,15 @@
$(if $(BOARD_AVB_VENDOR_KEY_PATH),\
$(hide) $(AVBTOOL) extract_public_key --key $(BOARD_AVB_VENDOR_KEY_PATH) \
--output $(1)/vendor.avbpubkey)
+ $(if $(BOARD_AVB_PRODUCT_KEY_PATH),\
+ $(hide) $(AVBTOOL) extract_public_key --key $(BOARD_AVB_PRODUCT_KEY_PATH) \
+ --output $(1)/product.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_RECOVERY_KEY_PATH),\
+ $(hide) $(AVBTOOL) extract_public_key --key $(BOARD_AVB_RECOVERY_KEY_PATH) \
+ --output $(1)/recovery.avbpubkey)
endef
define build-vbmetaimage-target
@@ -2026,7 +2264,15 @@
endef
INSTALLED_VBMETAIMAGE_TARGET := $(BUILT_VBMETAIMAGE_TARGET)
-$(INSTALLED_VBMETAIMAGE_TARGET): $(AVBTOOL) $(INSTALLED_BOOTIMAGE_TARGET) $(INSTALLED_SYSTEMIMAGE) $(INSTALLED_VENDORIMAGE_TARGET) $(INSTALLED_DTBOIMAGE_TARGET) $(BOARD_AVB_KEY_PATH)
+$(INSTALLED_VBMETAIMAGE_TARGET): \
+ $(AVBTOOL) \
+ $(INSTALLED_BOOTIMAGE_TARGET) \
+ $(INSTALLED_SYSTEMIMAGE) \
+ $(INSTALLED_VENDORIMAGE_TARGET) \
+ $(INSTALLED_PRODUCTIMAGE_TARGET) \
+ $(INSTALLED_DTBOIMAGE_TARGET) \
+ $(INSTALLED_RECOVERYIMAGE_TARGET) \
+ $(BOARD_AVB_KEY_PATH)
$(build-vbmetaimage-target)
.PHONY: vbmetaimage-nodeps
@@ -2081,6 +2327,7 @@
ifeq ($(build_ota_package),true)
OTATOOLS := $(HOST_OUT_EXECUTABLES)/minigzip \
$(HOST_OUT_EXECUTABLES)/aapt \
+ $(HOST_OUT_EXECUTABLES)/checkvintf \
$(HOST_OUT_EXECUTABLES)/mkbootfs \
$(HOST_OUT_EXECUTABLES)/mkbootimg \
$(HOST_OUT_EXECUTABLES)/fs_config \
@@ -2091,8 +2338,6 @@
$(HOST_OUT_JAVA_LIBRARIES)/signapk.jar \
$(HOST_OUT_JAVA_LIBRARIES)/BootSignature.jar \
$(HOST_OUT_JAVA_LIBRARIES)/VeritySigner.jar \
- $(HOST_OUT_EXECUTABLES)/make_ext4fs \
- $(HOST_OUT_EXECUTABLES)/mkuserimg.sh \
$(HOST_OUT_EXECUTABLES)/mke2fs \
$(HOST_OUT_EXECUTABLES)/mkuserimg_mke2fs.sh \
$(HOST_OUT_EXECUTABLES)/e2fsdroid \
@@ -2100,9 +2345,11 @@
$(HOST_OUT_EXECUTABLES)/mksquashfs \
$(HOST_OUT_EXECUTABLES)/mkf2fsuserimg.sh \
$(HOST_OUT_EXECUTABLES)/make_f2fs \
+ $(HOST_OUT_EXECUTABLES)/sload_f2fs \
$(HOST_OUT_EXECUTABLES)/simg2img \
$(HOST_OUT_EXECUTABLES)/e2fsck \
$(HOST_OUT_EXECUTABLES)/build_verity_tree \
+ $(HOST_OUT_EXECUTABLES)/generate_verity_key \
$(HOST_OUT_EXECUTABLES)/verity_signer \
$(HOST_OUT_EXECUTABLES)/verity_verifier \
$(HOST_OUT_EXECUTABLES)/append2simg \
@@ -2114,7 +2361,7 @@
$(HOST_OUT_EXECUTABLES)/delta_generator \
$(AVBTOOL) \
$(BLK_ALLOC_TO_BASE_FS) \
- $(BRO)
+ $(BROTLI)
ifeq (true,$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VBOOT))
OTATOOLS += \
@@ -2128,6 +2375,7 @@
$(HOST_LIBRARY_PATH)/liblog$(HOST_SHLIB_SUFFIX) \
$(HOST_LIBRARY_PATH)/libcutils$(HOST_SHLIB_SUFFIX) \
$(HOST_LIBRARY_PATH)/libselinux$(HOST_SHLIB_SUFFIX) \
+ $(HOST_LIBRARY_PATH)/libcrypto_utils$(HOST_SHLIB_SUFFIX) \
$(HOST_LIBRARY_PATH)/libcrypto-host$(HOST_SHLIB_SUFFIX) \
$(HOST_LIBRARY_PATH)/libext2fs-host$(HOST_SHLIB_SUFFIX) \
$(HOST_LIBRARY_PATH)/libext2_blkid-host$(HOST_SHLIB_SUFFIX) \
@@ -2161,18 +2409,20 @@
OTATOOLS_DEPS := \
system/extras/verity/build_verity_metadata.py \
system/extras/ext4_utils/mke2fs.conf \
- external/avb/test/data/testkey_rsa4096.pem \
- $(shell find build/target/product/security -type f -name \*.x509.pem -o -name \*.pk8 -o \
- -name verity_key | sort) \
- $(shell find device vendor -type f -name \*.pk8 -o -name verifiedboot\* -o \
- -name \*.x509.pem -o -name oem\*.prop | sort)
+ $(sort $(shell find external/avb/test/data -type f -name "testkey_*.pem" -o \
+ -name "atx_metadata.bin")) \
+ $(sort $(shell find system/update_engine/scripts -name \*.pyc -prune -o -type f -print)) \
+ $(sort $(shell find build/target/product/security -type f -name \*.x509.pem -o -name \*.pk8 -o \
+ -name verity_key)) \
+ $(sort $(shell find device $(wildcard vendor) -type f -name \*.pk8 -o -name verifiedboot\* -o \
+ -name \*.x509.pem -o -name oem\*.prop))
OTATOOLS_RELEASETOOLS := \
- $(shell find build/tools/releasetools -name \*.pyc -prune -o -type f | sort)
+ $(sort $(shell find build/make/tools/releasetools -name \*.pyc -prune -o -type f))
ifeq (true,$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VBOOT))
OTATOOLS_DEPS += \
- $(shell find external/vboot_reference/tests/devkeys -type f | sort)
+ $(sort $(shell find external/vboot_reference/tests/devkeys -type f))
endif
$(BUILT_OTATOOLS_PACKAGE): $(OTATOOLS) $(OTATOOLS_DEPS) $(OTATOOLS_RELEASETOOLS) | $(ACP)
@@ -2180,7 +2430,7 @@
$(hide) rm -rf $@ $(zip_root)
$(hide) mkdir -p $(dir $@) $(zip_root)/bin $(zip_root)/framework $(zip_root)/releasetools
$(call copy-files-with-structure,$(OTATOOLS),$(HOST_OUT)/,$(zip_root))
- $(hide) $(ACP) -r -d -p build/tools/releasetools/* $(zip_root)/releasetools
+ $(hide) $(ACP) -r -d -p build/make/tools/releasetools/* $(zip_root)/releasetools
$(hide) rm -rf $@ $(zip_root)/releasetools/*.pyc
$(hide) (cd $(zip_root) && zip -qryX $(abspath $@) *)
$(hide) echo $(OTATOOLS_DEPS) | xargs zip -qryX $(abspath $@)>/dev/null || true
@@ -2241,9 +2491,7 @@
$(BUILT_TARGET_FILES_PACKAGE): PRIVATE_TOOL_EXTENSION := $(tool_extension)
ifeq ($(AB_OTA_UPDATER),true)
-# Build zlib fingerprint if using the AB Updater.
-updater_dep := $(TARGET_OUT_COMMON_GEN)/zlib_fingerprint
-updater_dep += system/update_engine/update_engine.conf
+updater_dep := system/update_engine/update_engine.conf
else
# Build OTA tools if not using the AB Updater.
updater_dep := $(built_ota_tools)
@@ -2273,7 +2521,7 @@
# $1: root directory
# $2: add prefix
define fs_config
-(cd $(1); find . -type d | sed 's,$$,/,'; find . \! -type d) | cut -c 3- | sort | sed 's,^,$(2),' | $(HOST_OUT_EXECUTABLES)/fs_config -C -D $(TARGET_OUT) -S $(SELINUX_FC)
+(cd $(1); find . -type d | sed 's,$$,/,'; find . \! -type d) | cut -c 3- | sort | sed 's,^,$(2),' | $(HOST_OUT_EXECUTABLES)/fs_config -C -D $(TARGET_OUT) -S $(SELINUX_FC) -R "$(2)"
endef
# Depending on the various images guarantees that the underlying
@@ -2286,6 +2534,7 @@
$(INSTALLED_USERDATAIMAGE_TARGET) \
$(INSTALLED_CACHEIMAGE_TARGET) \
$(INSTALLED_VENDORIMAGE_TARGET) \
+ $(INSTALLED_PRODUCTIMAGE_TARGET) \
$(INSTALLED_VBMETAIMAGE_TARGET) \
$(INSTALLED_DTBOIMAGE_TARGET) \
$(INTERNAL_SYSTEMOTHERIMAGE_FILES) \
@@ -2294,6 +2543,7 @@
$(INSTALLED_2NDBOOTLOADER_TARGET) \
$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SYSTEM_BASE_FS_PATH) \
$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VENDOR_BASE_FS_PATH) \
+ $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PRODUCT_BASE_FS_PATH) \
$(SELINUX_FC) \
$(APKCERTS_FILE) \
$(SOONG_ZIP) \
@@ -2301,11 +2551,12 @@
$(HOST_OUT_EXECUTABLES)/imgdiff \
$(HOST_OUT_EXECUTABLES)/bsdiff \
$(BUILD_IMAGE_SRCS) \
- $(INSTALLED_VENDOR_MANIFEST) \
- $(INSTALLED_VENDOR_MATRIX) \
+ $(BUILT_VENDOR_MANIFEST) \
+ $(BUILT_VENDOR_MATRIX) \
| $(ACP)
@echo "Package target files: $@"
$(call create-system-vendor-symlink)
+ $(call create-system-product-symlink)
$(hide) rm -rf $@ $@.list $(zip_root)
$(hide) mkdir -p $(dir $@) $(zip_root)
ifneq (,$(INSTALLED_RECOVERYIMAGE_TARGET)$(filter true,$(BOARD_USES_RECOVERY_AS_BOOT)))
@@ -2319,6 +2570,9 @@
ifdef INSTALLED_2NDBOOTLOADER_TARGET
$(hide) cp $(INSTALLED_2NDBOOTLOADER_TARGET) $(zip_root)/$(PRIVATE_RECOVERY_OUT)/second
endif
+ifdef BOARD_INCLUDE_RECOVERY_DTBO
+ $(hide) cp $(INSTALLED_DTBOIMAGE_TARGET) $(zip_root)/$(PRIVATE_RECOVERY_OUT)/recovery_dtbo
+endif
ifdef INTERNAL_KERNEL_CMDLINE
$(hide) echo "$(INTERNAL_KERNEL_CMDLINE)" > $(zip_root)/$(PRIVATE_RECOVERY_OUT)/cmdline
endif
@@ -2371,6 +2625,11 @@
$(hide) $(call package_files-copy-root, \
$(TARGET_OUT_VENDOR),$(zip_root)/VENDOR)
endif
+ifdef BOARD_PRODUCTIMAGE_FILE_SYSTEM_TYPE
+ @# Contents of the product image
+ $(hide) $(call package_files-copy-root, \
+ $(TARGET_OUT_PRODUCT),$(zip_root)/PRODUCT)
+endif
ifdef INSTALLED_SYSTEMOTHERIMAGE_TARGET
@# Contents of the system_other image
$(hide) $(call package_files-copy-root, \
@@ -2402,18 +2661,15 @@
ifdef BOARD_BOOTIMAGE_PARTITION_SIZE
$(hide) echo "boot_size=$(BOARD_BOOTIMAGE_PARTITION_SIZE)" >> $(zip_root)/META/misc_info.txt
endif
-ifeq ($(BOARD_USES_RECOVERY_AS_BOOT),)
- $(hide) echo "recovery_as_boot=$(BOARD_USES_RECOVERY_AS_BOOT)" >> $(zip_root)/META/misc_info.txt
-endif
ifeq ($(INSTALLED_RECOVERYIMAGE_TARGET),)
$(hide) echo "no_recovery=true" >> $(zip_root)/META/misc_info.txt
endif
+ifdef BOARD_INCLUDE_RECOVERY_DTBO
+ $(hide) echo "include_recovery_dtbo=true" >> $(zip_root)/META/misc_info.txt
+endif
ifdef BOARD_RECOVERYIMAGE_PARTITION_SIZE
$(hide) echo "recovery_size=$(BOARD_RECOVERYIMAGE_PARTITION_SIZE)" >> $(zip_root)/META/misc_info.txt
endif
-ifdef BOARD_HAS_EXT4_RESERVED_BLOCKS
- $(hide) echo "has_ext4_reserved_blocks=$(BOARD_HAS_EXT4_RESERVED_BLOCKS)" >> $(zip_root)/META/misc_info.txt
-endif
ifdef TARGET_RECOVERY_FSTYPE_MOUNT_OPTIONS
@# TARGET_RECOVERY_FSTYPE_MOUNT_OPTIONS can be empty to indicate that nothing but defaults should be used.
$(hide) echo "recovery_mount_options=$(TARGET_RECOVERY_FSTYPE_MOUNT_OPTIONS)" >> $(zip_root)/META/misc_info.txt
@@ -2441,6 +2697,10 @@
$(hide) cp $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VENDOR_BASE_FS_PATH) \
$(zip_root)/META/$(notdir $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VENDOR_BASE_FS_PATH))
endif
+ifneq ($(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PRODUCT_BASE_FS_PATH),)
+ $(hide) cp $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PRODUCT_BASE_FS_PATH) \
+ $(zip_root)/META/$(notdir $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PRODUCT_BASE_FS_PATH))
+endif
ifneq ($(strip $(SANITIZE_TARGET)),)
# We need to create userdata.img with real data because the instrumented libraries are in userdata.img.
$(hide) echo "userdata_img_with_data=true" >> $(zip_root)/META/misc_info.txt
@@ -2459,6 +2719,12 @@
$(hide) echo "avb_boot_algorithm=$(BOARD_AVB_BOOT_ALGORITHM)" >> $(zip_root)/META/misc_info.txt
$(hide) echo "avb_boot_rollback_index_location=$(BOARD_AVB_BOOT_ROLLBACK_INDEX_LOCATION)" >> $(zip_root)/META/misc_info.txt
endif # BOARD_AVB_BOOT_KEY_PATH
+ $(hide) echo "avb_recovery_add_hash_footer_args=$(BOARD_AVB_RECOVERY_ADD_HASH_FOOTER_ARGS)" >> $(zip_root)/META/misc_info.txt
+ifdef BOARD_AVB_RECOVERY_KEY_PATH
+ $(hide) echo "avb_recovery_key_path=$(BOARD_AVB_RECOVERY_KEY_PATH)" >> $(zip_root)/META/misc_info.txt
+ $(hide) echo "avb_recovery_algorithm=$(BOARD_AVB_RECOVERY_ALGORITHM)" >> $(zip_root)/META/misc_info.txt
+ $(hide) echo "avb_recovery_rollback_index_location=$(BOARD_AVB_RECOVERY_ROLLBACK_INDEX_LOCATION)" >> $(zip_root)/META/misc_info.txt
+endif # BOARD_AVB_RECOVERY_KEY_PATH
endif # BOARD_AVB_ENABLE
ifdef BOARD_BPT_INPUT_FILES
$(hide) echo "board_bpt_enable=true" >> $(zip_root)/META/misc_info.txt
@@ -2471,12 +2737,11 @@
$(call generate-userimage-prop-dictionary, $(zip_root)/META/misc_info.txt)
ifneq ($(INSTALLED_RECOVERYIMAGE_TARGET),)
$(hide) PATH=$(foreach p,$(INTERNAL_USERIMAGES_BINARY_PATHS),$(p):)$$PATH MKBOOTIMG=$(MKBOOTIMG) \
- ./build/tools/releasetools/make_recovery_patch $(zip_root) $(zip_root)
+ build/make/tools/releasetools/make_recovery_patch $(zip_root) $(zip_root)
endif
ifeq ($(AB_OTA_UPDATER),true)
@# When using the A/B updater, include the updater config files in the zip.
$(hide) cp $(TOPDIR)system/update_engine/update_engine.conf $(zip_root)/META/update_engine_config.txt
- $(hide) cp $(TARGET_OUT_COMMON_GEN)/zlib_fingerprint $(zip_root)/META/zlib_fingerprint.txt
$(hide) for part in $(AB_OTA_PARTITIONS); do \
echo "$${part}" >> $(zip_root)/META/ab_partitions.txt; \
done
@@ -2519,6 +2784,14 @@
$(hide) mkdir -p $(zip_root)/IMAGES
$(hide) cp $(INSTALLED_VENDORIMAGE_TARGET) $(zip_root)/IMAGES/
endif
+ifdef BOARD_PREBUILT_PRODUCTIMAGE
+ $(hide) mkdir -p $(zip_root)/IMAGES
+ $(hide) cp $(INSTALLED_PRODUCTIMAGE_TARGET) $(zip_root)/IMAGES/
+endif
+ifdef BOARD_PREBUILT_BOOTIMAGE
+ $(hide) mkdir -p $(zip_root)/IMAGES
+ $(hide) cp $(INSTALLED_BOOTIMAGE_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/
@@ -2545,18 +2818,25 @@
ifdef BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE
$(hide) $(call fs_config,$(zip_root)/VENDOR,vendor/) > $(zip_root)/META/vendor_filesystem_config.txt
endif
-ifeq ($(BOARD_BUILD_SYSTEM_ROOT_IMAGE),true)
- $(hide) $(call fs_config,$(zip_root)/ROOT,) > $(zip_root)/META/root_filesystem_config.txt
+ifdef BOARD_PRODUCTIMAGE_FILE_SYSTEM_TYPE
+ $(hide) $(call fs_config,$(zip_root)/PRODUCT,product/) > $(zip_root)/META/product_filesystem_config.txt
endif
+ifeq ($(BOARD_BUILD_SYSTEM_ROOT_IMAGE),true)
+ @# When using BOARD_BUILD_SYSTEM_ROOT_IMAGE, ROOT always contains the files for the root under
+ @# normal boot. BOOT/RAMDISK exists only if additionally using BOARD_USES_RECOVERY_AS_BOOT.
+ $(hide) $(call fs_config,$(zip_root)/ROOT,) > $(zip_root)/META/root_filesystem_config.txt
+ifeq ($(BOARD_USES_RECOVERY_AS_BOOT),true)
$(hide) $(call fs_config,$(zip_root)/BOOT/RAMDISK,) > $(zip_root)/META/boot_filesystem_config.txt
+endif
+else # BOARD_BUILD_SYSTEM_ROOT_IMAGE != true
+ $(hide) $(call fs_config,$(zip_root)/BOOT/RAMDISK,) > $(zip_root)/META/boot_filesystem_config.txt
+endif
ifneq ($(INSTALLED_RECOVERYIMAGE_TARGET),)
$(hide) $(call fs_config,$(zip_root)/RECOVERY/RAMDISK,) > $(zip_root)/META/recovery_filesystem_config.txt
endif
ifdef INSTALLED_SYSTEMOTHERIMAGE_TARGET
$(hide) $(call fs_config,$(zip_root)/SYSTEM_OTHER,system/) > $(zip_root)/META/system_other_filesystem_config.txt
endif
-
-ifeq ($(PRODUCT_FULL_TREBLE),true)
@# Metadata for compatibility verification.
$(hide) cp $(BUILT_SYSTEM_MANIFEST) $(zip_root)/META/system_manifest.xml
$(hide) cp $(BUILT_SYSTEM_COMPATIBILITY_MATRIX) $(zip_root)/META/system_matrix.xml
@@ -2566,10 +2846,9 @@
ifdef BUILT_VENDOR_MATRIX
$(hide) cp $(BUILT_VENDOR_MATRIX) $(zip_root)/META/vendor_matrix.xml
endif
-endif
$(hide) PATH=$(foreach p,$(INTERNAL_USERIMAGES_BINARY_PATHS),$(p):)$$PATH MKBOOTIMG=$(MKBOOTIMG) \
- ./build/tools/releasetools/add_img_to_target_files -a -v -p $(HOST_OUT) $(zip_root)
+ build/make/tools/releasetools/add_img_to_target_files -a -v -p $(HOST_OUT) $(zip_root)
@# Zip everything up, preserving symlinks and placing META/ files first to
@# help early validation of the .zip file while uploading it.
$(hide) find $(zip_root)/META | sort >$@.list
@@ -2609,14 +2888,14 @@
ifeq ($(AB_OTA_UPDATER),true)
$(INTERNAL_OTA_PACKAGE_TARGET): $(BRILLO_UPDATE_PAYLOAD)
else
-$(INTERNAL_OTA_PACKAGE_TARGET): $(BRO)
+$(INTERNAL_OTA_PACKAGE_TARGET): $(BROTLI)
endif
$(INTERNAL_OTA_PACKAGE_TARGET): $(BUILT_TARGET_FILES_PACKAGE) \
- build/tools/releasetools/ota_from_target_files
+ build/make/tools/releasetools/ota_from_target_files
@echo "Package OTA: $@"
$(hide) PATH=$(foreach p,$(INTERNAL_USERIMAGES_BINARY_PATHS),$(p):)$$PATH MKBOOTIMG=$(MKBOOTIMG) \
- ./build/tools/releasetools/ota_from_target_files -v \
+ build/make/tools/releasetools/ota_from_target_files -v \
--block \
--extracted_input_target_files $(patsubst %.zip,%,$(BUILT_TARGET_FILES_PACKAGE)) \
-p $(HOST_OUT) \
@@ -2659,12 +2938,13 @@
name := $(name)-symbols-$(FILE_NAME_TAG)
SYMBOLS_ZIP := $(PRODUCT_OUT)/$(name).zip
-# For apps_only build we'll establish the dependency later in build/core/main.mk.
+# For apps_only build we'll establish the dependency later in build/make/core/main.mk.
ifndef TARGET_BUILD_APPS
$(SYMBOLS_ZIP): $(INSTALLED_SYSTEMIMAGE) \
$(INSTALLED_BOOTIMAGE_TARGET) \
$(INSTALLED_USERDATAIMAGE_TARGET) \
$(INSTALLED_VENDORIMAGE_TARGET) \
+ $(INSTALLED_PRODUCTIMAGE_TARGET) \
$(updater_dep)
endif
$(SYMBOLS_ZIP): PRIVATE_LIST_FILE := $(call intermediates-dir-for,PACKAGING,symbols)/filelist
@@ -2687,7 +2967,8 @@
$(COVERAGE_ZIP): $(INSTALLED_SYSTEMIMAGE) \
$(INSTALLED_BOOTIMAGE_TARGET) \
$(INSTALLED_USERDATAIMAGE_TARGET) \
- $(INSTALLED_VENDORIMAGE_TARGET)
+ $(INSTALLED_VENDORIMAGE_TARGET) \
+ $(INSTALLED_PRODUCTIMAGE_TARGET)
endif
$(COVERAGE_ZIP): PRIVATE_LIST_FILE := $(call intermediates-dir-for,PACKAGING,coverage)/filelist
$(COVERAGE_ZIP): $(SOONG_ZIP)
@@ -2721,14 +3002,13 @@
fi
ifeq (true,$(EMMA_INSTRUMENT))
- #------------------------------------------------------------------
- # An archive of classes for use in generating code-coverage reports
- # These are the uninstrumented versions of any classes that were
- # to be instrumented.
- # Any dependencies are set up later in build/core/main.mk.
+#------------------------------------------------------------------
+# An archive of classes for use in generating code-coverage reports
+# These are the uninstrumented versions of any classes that were
+# to be instrumented.
+# Any dependencies are set up later in build/make/core/main.mk.
- ifeq ($(ANDROID_COMPILE_WITH_JACK),false)
- JACOCO_REPORT_CLASSES_ALL := $(PRODUCT_OUT)/jacoco-report-classes-all.jar
+JACOCO_REPORT_CLASSES_ALL := $(PRODUCT_OUT)/jacoco-report-classes-all.jar
$(JACOCO_REPORT_CLASSES_ALL) :
@echo "Collecting uninstrumented classes"
$(hide) find $(TARGET_COMMON_OUT_ROOT) $(HOST_COMMON_OUT_ROOT) -name "jacoco-report-classes.jar" | \
@@ -2739,14 +3019,6 @@
# -q supress most output
# -X skip storing extended file attributes
- else
- EMMA_META_ZIP := $(PRODUCT_OUT)/emma_meta.zip
-$(EMMA_META_ZIP) :
- @echo "Collecting Emma coverage meta files."
- $(hide) find $(TARGET_COMMON_OUT_ROOT) $(HOST_COMMON_OUT_ROOT) -name "coverage.em" | \
- zip -@ -qX $@
-endif
-
endif # EMMA_INSTRUMENT=true
@@ -2756,10 +3028,10 @@
#
ifdef TARGET_BUILD_APPS
PROGUARD_DICT_ZIP := $(PRODUCT_OUT)/$(TARGET_PRODUCT)-proguard-dict-$(FILE_NAME_TAG).zip
-# the dependency will be set up later in build/core/main.mk.
+# the dependency will be set up later in build/make/core/main.mk.
$(PROGUARD_DICT_ZIP) :
@echo "Packaging Proguard obfuscation dictionary files."
- $(hide) dict_files=`find $(TARGET_OUT_COMMON_INTERMEDIATES)/APPS -name proguard_dictionary -o -name jack_dictionary`; \
+ $(hide) dict_files=`find $(TARGET_OUT_COMMON_INTERMEDIATES)/APPS -name proguard_dictionary`; \
if [ -n "$$dict_files" ]; then \
unobfuscated_jars=$${dict_files//proguard_dictionary/classes.jar}; \
zip -qX $@ $$dict_files $$unobfuscated_jars; \
@@ -2796,6 +3068,15 @@
vendorimage: $(INSTALLED_QEMU_VENDORIMAGE)
droidcore: $(INSTALLED_QEMU_VENDORIMAGE)
endif
+ifeq ($(BOARD_USES_PRODUCTIMAGE),true)
+INSTALLED_QEMU_PRODUCTIMAGE := $(PRODUCT_OUT)/product-qemu.img
+$(INSTALLED_QEMU_PRODUCTIMAGE): $(INSTALLED_PRODUCTIMAGE_TARGET) $(MK_QEMU_IMAGE_SH) $(SGDISK_HOST)
+ @echo Create product-qemu.img
+ (export SGDISK=$(SGDISK_HOST); $(MK_QEMU_IMAGE_SH) ${PRODUCT_OUT}/product.img)
+
+productimage: $(INSTALLED_QEMU_PRODUCTIMAGE)
+droidcore: $(INSTALLED_QEMU_PRODUCTIMAGE)
+endif
endif
# -----------------------------------------------------------------
# The emulator package
@@ -2942,7 +3223,6 @@
-v "TARGET_CPU_ABI=$(TARGET_CPU_ABI)" \
-v "DLL_EXTENSION=$(HOST_SHLIB_SUFFIX)" \
-v "FONT_OUT=$(SDK_FONT_TEMP)" \
- -v "JACK_SDKTOOL_VERSION=$(JACK_SDKTOOL_VERSION)" \
-o $(PRIVATE_DIR) && \
cp -f $(target_notice_file_txt) \
$(PRIVATE_DIR)/system-images/android-$(PLATFORM_VERSION)/$(TARGET_CPU_ABI)/NOTICE.txt && \
@@ -3003,3 +3283,9 @@
ifneq ($(sdk_repo_goal),)
include $(TOPDIR)development/build/tools/sdk_repo.mk
endif
+
+#------------------------------------------------------------------
+# Find lsdump paths
+FIND_LSDUMPS_FILE := $(PRODUCT_OUT)/lsdump_paths.txt
+$(FIND_LSDUMPS_FILE) : $(LSDUMP_PATHS)
+ $(hide) rm -rf $@ && echo "$^" > $@
diff --git a/core/aapt2.mk b/core/aapt2.mk
index 287f933..b3a7c93 100644
--- a/core/aapt2.mk
+++ b/core/aapt2.mk
@@ -12,6 +12,7 @@
# - proguard_options_file
# - my_generated_res_dirs: Resources generated during the build process and we have to compile them in a single run of aapt2.
# - my_generated_res_dirs_deps: the dependency to use for my_generated_res_dirs.
+# - my_generated_res_zips: Zip files containing resources
# - my_apk_split_configs: The configurations for which to generate splits.
# - built_apk_splits: The paths where AAPT should generate the splits.
#
@@ -35,7 +36,7 @@
$(eval $(call aapt2-compile-one-resource-file-rule,$(r),$(o)))\
$(o))
-my_generated_resources_flata :=
+my_resources_flata :=
# Compile generated resources
ifneq ($(my_generated_res_dirs),)
my_generated_resources_flata := $(my_compiled_res_base_dir)/gen_res.flata
@@ -44,14 +45,29 @@
@echo "AAPT2 compile $@ <- $(PRIVATE_SOURCE_RES_DIRS)"
$(call aapt2-compile-resource-dirs)
-my_generated_resources_flata += $(my_generated_resources_flata)
+my_resources_flata += $(my_generated_resources_flata)
endif
-$(my_res_resources_flat) $(my_overlay_resources_flat) $(my_generated_resources_flata): \
- PRIVATE_AAPT2_CFLAGS := $(PRODUCT_AAPT2_CFLAGS)
+# Compile zipped resources
+ifneq ($(my_generated_res_zips),)
+my_zipped_resources_flata := $(my_compiled_res_base_dir)/zip_res.flata
+$(my_zipped_resources_flata): PRIVATE_SOURCE_RES_ZIPS := $(my_generated_res_zips)
+$(my_zipped_resources_flata) : $(my_generated_res_zips) $(AAPT2) $(ZIPSYNC)
+ @echo "AAPT2 compile $@ <- $(PRIVATE_SOURCE_RES_ZIPS)"
+ $(call aapt2-compile-resource-zips)
+
+my_resources_flata += $(my_zipped_resources_flata)
+endif
+
+# Always set --pseudo-localize, it will be stripped out later for release
+# builds that don't want it.
+$(my_res_resources_flat) $(my_overlay_resources_flat) $(my_resources_flata): \
+ PRIVATE_AAPT2_CFLAGS := --pseudo-localize
my_static_library_resources := $(foreach l, $(call reverse-list,$(LOCAL_STATIC_ANDROID_LIBRARIES)),\
$(call intermediates-dir-for,JAVA_LIBRARIES,$(l),,COMMON)/package-res.apk)
+my_static_library_extra_packages := $(foreach l, $(call reverse-list,$(LOCAL_STATIC_ANDROID_LIBRARIES)),\
+ $(call intermediates-dir-for,JAVA_LIBRARIES,$(l),,COMMON)/extra_packages)
my_shared_library_resources := $(foreach l, $(LOCAL_SHARED_ANDROID_LIBRARIES),\
$(call intermediates-dir-for,JAVA_LIBRARIES,$(l),,COMMON)/package-res.apk)
@@ -64,28 +80,25 @@
$(my_res_package): PRIVATE_AAPT_FLAGS += $(addprefix --split ,$(join $(built_apk_splits),$(addprefix :,$(my_apk_split_configs))))
endif
+my_srcjar := $(intermediates.COMMON)/aapt2.srcjar
+LOCAL_SRCJARS += $(my_srcjar)
+
+aapt_extra_packages := $(intermediates.COMMON)/extra_packages
+
$(my_res_package): PRIVATE_RES_FLAT := $(my_res_resources_flat)
-$(my_res_package): PRIVATE_OVERLAY_FLAT := $(my_static_library_resources) $(my_generated_resources_flata) $(my_overlay_resources_flat)
+$(my_res_package): PRIVATE_OVERLAY_FLAT := $(my_static_library_resources) $(my_resources_flata) $(my_overlay_resources_flat)
$(my_res_package): PRIVATE_SHARED_ANDROID_LIBRARIES := $(my_shared_library_resources)
$(my_res_package): PRIVATE_PROGUARD_OPTIONS_FILE := $(proguard_options_file)
$(my_res_package): PRIVATE_ASSET_DIRS := $(my_asset_dirs)
-$(my_res_package): $(full_android_manifest) $(my_static_library_resources) $(my_shared_library_resources)
-$(my_res_package): $(my_full_asset_paths)
-$(my_res_package): $(my_res_resources_flat) $(my_overlay_resources_flat) \
- $(my_generated_resources_flata) $(my_static_library_resources) \
- $(AAPT2)
- @echo "AAPT2 link $@"
- $(call aapt2-link)
+$(my_res_package): PRIVATE_JAVA_GEN_DIR := $(intermediates.COMMON)/aapt2
+$(my_res_package): PRIVATE_SRCJAR := $(my_srcjar)
+$(my_res_package): PRIVATE_STATIC_LIBRARY_EXTRA_PACKAGES := $(my_static_library_extra_packages)
+$(my_res_package): PRIVATE_AAPT_EXTRA_PACKAGES := $(aapt_extra_packages)
+$(my_res_package): .KATI_IMPLICIT_OUTPUTS := $(my_srcjar) $(aapt_extra_packages)
ifdef R_file_stamp
-$(R_file_stamp) : $(my_res_package) | $(ACP)
- @echo "target R.java/Manifest.java: $(PRIVATE_MODULE) ($@)"
- @rm -rf $@ && mkdir -p $(dir $@)
- $(call find-generated-R.java)
-endif
-
-ifdef proguard_options_file
-$(proguard_options_file) : $(my_res_package)
+$(my_res_package): PRIVATE_R_FILE_STAMP := $(R_file_stamp)
+$(my_res_package): .KATI_IMPLICIT_OUTPUTS += $(R_file_stamp)
endif
resource_export_package :=
@@ -94,10 +107,38 @@
# other packages can use to build their own PRODUCT-agnostic R.java (etc.)
# files.
resource_export_package := $(intermediates.COMMON)/package-export.apk
-$(R_file_stamp) : $(resource_export_package)
-
-$(resource_export_package) : $(my_res_package) | $(ACP)
- @echo "target Export Resources: $(PRIVATE_MODULE) $(@)"
- $(copy-file-to-new-target)
-
+$(my_res_package): PRIVATE_RESOURCE_EXPORT_PACKAGE := $(resource_export_package)
+$(my_res_package): .KATI_IMPLICIT_OUTPUTS += $(resource_export_package)
endif
+
+ifdef proguard_options_file
+$(my_res_package): .KATI_IMPLICIT_OUTPUTS += $(proguard_options_file)
+endif
+
+$(my_res_package): $(full_android_manifest) $(my_static_library_resources) $(my_shared_library_resources)
+$(my_res_package): $(my_full_asset_paths)
+$(my_res_package): $(my_res_resources_flat) $(my_overlay_resources_flat) \
+ $(my_resources_flata) $(my_static_library_resources) $(my_static_library_extra_packages) \
+ $(AAPT2) $(SOONG_ZIP) $(EXTRACT_JAR_PACKAGES)
+ @echo "AAPT2 link $@"
+ $(call aapt2-link)
+ifdef R_file_stamp
+ @rm -f $(PRIVATE_R_FILE_STAMP)
+ $(call find-generated-R.java,$(PRIVATE_JAVA_GEN_DIR),$(PRIVATE_R_FILE_STAMP))
+endif
+ifdef LOCAL_EXPORT_PACKAGE_RESOURCES
+ @rm -f $(PRIVATE_RESOURCE_EXPORT_PACKAGE)
+
+ cp $@ $(PRIVATE_RESOURCE_EXPORT_PACKAGE)
+endif
+
+# Clear inputs only used in this file, so that they're not re-used during the next build
+my_res_resources :=
+my_overlay_resources :=
+my_compiled_res_base_dir :=
+my_asset_dirs :=
+my_full_asset_paths :=
+my_apk_split_configs :=
+my_generated_res_dirs :=
+my_generated_res_dirs_deps :=
+my_generated_res_zips :=
diff --git a/core/aapt_flags.mk b/core/aapt_flags.mk
new file mode 100644
index 0000000..13d4817
--- /dev/null
+++ b/core/aapt_flags.mk
@@ -0,0 +1,15 @@
+## AAPT Flags
+# aapt doesn't accept multiple --extra-packages flags.
+# We have to collapse them into a single --extra-packages flag here.
+LOCAL_AAPT_FLAGS := $(strip $(LOCAL_AAPT_FLAGS))
+ifdef LOCAL_AAPT_FLAGS
+ ifeq ($(filter 0 1,$(words $(filter --extra-packages,$(LOCAL_AAPT_FLAGS)))),)
+ aapt_flags := $(subst --extra-packages$(space),--extra-packages@,$(LOCAL_AAPT_FLAGS))
+ aapt_flags_extra_packages := $(patsubst --extra-packages@%,%,$(filter --extra-packages@%,$(aapt_flags)))
+ aapt_flags_extra_packages := $(sort $(subst :,$(space),$(aapt_flags_extra_packages)))
+ LOCAL_AAPT_FLAGS := $(filter-out --extra-packages@%,$(aapt_flags)) \
+ --extra-packages $(subst $(space),:,$(aapt_flags_extra_packages))
+ aapt_flags_extra_packages :=
+ aapt_flags :=
+ endif
+endif
diff --git a/core/allowed_ndk_types.mk b/core/allowed_ndk_types.mk
new file mode 100644
index 0000000..b88b9e8
--- /dev/null
+++ b/core/allowed_ndk_types.mk
@@ -0,0 +1,84 @@
+# Determines the types of NDK modules the current module is allowed to link to.
+# Input variables:
+# LOCAL_MODULE
+# LOCAL_MODULE_CLASS
+# LOCAL_NDK_STL_VARIANT
+# LOCAL_SDK_VERSION
+# Output variables:
+# my_ndk_stl_family: Family of the NDK STL.
+# my_ndk_stl_link_type: STL link type, static or shared.
+# my_allowed_ndk_types: Types of NDK modules that may be linked.
+# my_warn_ndk_types: Types of NDK modules that shouldn't be linked, but are.
+
+my_allowed_ndk_types :=
+my_warn_ndk_types :=
+my_ndk_stl_family :=
+my_ndk_stl_link_type :=
+
+ifdef LOCAL_SDK_VERSION
+ ifeq ($(LOCAL_NDK_STL_VARIANT),)
+ my_ndk_stl_family := system
+ my_ndk_stl_link_type := shared
+ else ifeq ($(LOCAL_NDK_STL_VARIANT),system)
+ my_ndk_stl_family := system
+ my_ndk_stl_link_type := shared
+ else ifeq ($(LOCAL_NDK_STL_VARIANT),c++_shared)
+ my_ndk_stl_family := libc++
+ my_ndk_stl_link_type := shared
+ else ifeq ($(LOCAL_NDK_STL_VARIANT),c++_static)
+ my_ndk_stl_family := libc++
+ my_ndk_stl_link_type := static
+ else ifeq ($(LOCAL_NDK_STL_VARIANT),none)
+ my_ndk_stl_family := none
+ my_ndk_stl_link_type := none
+ else
+ $(call pretty-error,invalid LOCAL_NDK_STL_VARIANT: $(LOCAL_NDK_STL_VARIANT))
+ endif
+
+ ifeq ($(LOCAL_MODULE_CLASS),STATIC_LIBRARIES)
+ # The "none" link type indicates that nothing is actually linked. Since
+ # this is a static library, it's still up to the final use of the
+ # library whether a static or shared STL should be used.
+ my_ndk_stl_link_type := none
+ endif
+
+ # The system STL is only the C++ ABI layer, so it's compatible with any STL.
+ my_allowed_ndk_types += native:ndk:system:shared
+ my_allowed_ndk_types += native:ndk:system:none
+
+ # Libaries that don't use the STL can be linked to anything.
+ my_allowed_ndk_types += native:ndk:none:none
+
+ # And it's always okay to link a static library that uses your own STL type.
+ # Since nothing was actually linked for the static library, it is up to the
+ # first linked library in the dependency chain which gets used.
+ my_allowed_ndk_types += native:ndk:$(my_ndk_stl_family):none
+
+ ifeq ($(LOCAL_MODULE_CLASS),APPS)
+ # For an app package, it's actually okay to depend on any set of STLs.
+ # If any of the individual libraries depend on each other they've
+ # already been checked for consistency, and if they don't they'll be
+ # kept isolated by RTLD_LOCAL anyway.
+ my_allowed_ndk_types += \
+ native:ndk:libc++:shared native:ndk:libc++:static
+
+ # The "none" link type that used by static libraries is intentionally
+ # omitted here. We should only be dealing with shared libraries in
+ # LOCAL_JNI_SHARED_LIBRARIES.
+ else ifeq ($(my_ndk_stl_link_type),shared)
+ # Modules linked to a shared STL can only use another shared STL.
+ my_allowed_ndk_types += native:ndk:$(my_ndk_stl_family):shared
+ endif
+ # Else we are a non-static library that uses a static STL, and are
+ # incompatible with all other shared libraries that use an STL.
+else
+ my_allowed_ndk_types := \
+ native:ndk:none:none \
+ native:ndk:system:none \
+ native:ndk:system:shared \
+
+ ifeq ($(LOCAL_MODULE_CLASS),APPS)
+ # CTS is bad and it should feel bad: http://b/13249737
+ my_warn_ndk_types += native:ndk:libc++:static
+ endif
+endif
diff --git a/core/android_manifest.mk b/core/android_manifest.mk
index 0093e02..7d573d3 100644
--- a/core/android_manifest.mk
+++ b/core/android_manifest.mk
@@ -34,10 +34,12 @@
main_android_manifest := $(full_android_manifest)
full_android_manifest := $(intermediates.COMMON)/AndroidManifest.xml
$(full_android_manifest): PRIVATE_LIBS_MANIFESTS := $(my_full_libs_manifest_files)
+$(full_android_manifest): $(ANDROID_MANIFEST_MERGER_CLASSPATH)
$(full_android_manifest) : $(main_android_manifest) $(my_full_libs_manifest_deps)
@echo "Merge android manifest files: $@ <-- $< $(PRIVATE_LIBS_MANIFESTS)"
@mkdir -p $(dir $@)
- $(hide) $(ANDROID_MANIFEST_MERGER) --main $< --libs $(PRIVATE_LIBS_MANIFESTS) \
+ $(hide) $(ANDROID_MANIFEST_MERGER) --main $< \
+ --libs $(call normalize-path-list,$(PRIVATE_LIBS_MANIFESTS)) \
--out $@
endif
diff --git a/core/apidiff.mk b/core/apidiff.mk
new file mode 100644
index 0000000..36d75fe
--- /dev/null
+++ b/core/apidiff.mk
@@ -0,0 +1,181 @@
+#
+# 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 to both jdiff and javadoc
+##
+##
+
+LOCAL_IS_HOST_MODULE := $(call true-or-empty,$(LOCAL_IS_HOST_MODULE))
+ifeq ($(LOCAL_IS_HOST_MODULE),true)
+my_prefix := HOST_
+LOCAL_HOST_PREFIX :=
+else
+my_prefix := TARGET_
+endif
+
+LOCAL_MODULE_CLASS := $(strip $(LOCAL_MODULE_CLASS))
+ifndef LOCAL_MODULE_CLASS
+$(error $(LOCAL_PATH): LOCAL_MODULE_CLASS not defined)
+endif
+
+full_src_files := $(patsubst %,$(LOCAL_PATH)/%,$(LOCAL_SRC_FILES))
+out_dir := $(OUT_DOCS)/$(LOCAL_MODULE)/api_diff/current
+full_target := $(call doc-timestamp-for,$(LOCAL_MODULE)-diff)
+
+ifeq ($(LOCAL_IS_HOST_MODULE),true)
+$(full_target): PRIVATE_BOOTCLASSPATH :=
+full_java_libs := $(addprefix $(HOST_OUT_JAVA_LIBRARIES)/,\
+ $(addsuffix $(COMMON_JAVA_PACKAGE_SUFFIX),$(LOCAL_JAVA_LIBRARIES)))
+full_java_lib_deps := $(full_java_libs)
+
+else
+
+ifneq ($(LOCAL_SDK_VERSION),)
+ ifeq ($(LOCAL_SDK_VERSION)$(TARGET_BUILD_APPS),current)
+ # Use android_stubs_current if LOCAL_SDK_VERSION is current and no TARGET_BUILD_APPS.
+ LOCAL_JAVA_LIBRARIES := android_stubs_current $(LOCAL_JAVA_LIBRARIES)
+ $(full_target): PRIVATE_BOOTCLASSPATH := $(call java-lib-files, android_stubs_current)
+ else ifeq ($(LOCAL_SDK_VERSION)$(TARGET_BUILD_APPS),system_current)
+ LOCAL_JAVA_LIBRARIES := android_system_stubs_current $(LOCAL_JAVA_LIBRARIES)
+ $(full_target): PRIVATE_BOOTCLASSPATH := $(call java-lib-files, android_system_stubs_current)
+ else ifeq ($(LOCAL_SDK_VERSION)$(TARGET_BUILD_APPS),test_current)
+ LOCAL_JAVA_LIBRARIES := android_test_stubs_current $(LOCAL_JAVA_LIBRARIES)
+ $(full_target): PRIVATE_BOOTCLASSPATH := $(call java-lib-files, android_test_stubs_current)
+ else
+ # core_<ver> is subset of <ver>. Instead of defining a prebuilt lib for core_<ver>,
+ # use the stub for <ver> when building for apps.
+ _version := $(patsubst core_%,%,$(LOCAL_SDK_VERSION))
+ LOCAL_JAVA_LIBRARIES := sdk_v$(_version) $(LOCAL_JAVA_LIBRARIES)
+ $(full_target): PRIVATE_BOOTCLASSPATH := $(call java-lib-files, sdk_v$(_version))
+ _version :=
+ endif
+else
+ LOCAL_JAVA_LIBRARIES := core-oj core-libart ext framework $(LOCAL_JAVA_LIBRARIES)
+ $(full_target): PRIVATE_BOOTCLASSPATH := $(call java-lib-files, core-oj):$(call java-lib-files, core-libart)
+endif # LOCAL_SDK_VERSION
+LOCAL_JAVA_LIBRARIES := $(sort $(LOCAL_JAVA_LIBRARIES))
+
+full_java_libs := $(call java-lib-files,$(LOCAL_JAVA_LIBRARIES)) $(LOCAL_CLASSPATH)
+full_java_lib_deps := $(call java-lib-deps,$(LOCAL_JAVA_LIBRARIES)) $(LOCAL_CLASSPATH)
+endif # !LOCAL_IS_HOST_MODULE
+
+$(full_target): PRIVATE_CLASSPATH := $(subst $(space),:,$(full_java_libs))
+$(full_target): PRIVATE_DOCLAVA_CLASSPATH := $(HOST_OUT_JAVA_LIBRARIES)/jsilver$(COMMON_JAVA_PACKAGE_SUFFIX):$(HOST_OUT_JAVA_LIBRARIES)/doclava$(COMMON_JAVA_PACKAGE_SUFFIX)
+
+intermediates.COMMON := $(call local-intermediates-dir,COMMON)
+
+$(full_target): PRIVATE_SOURCE_PATH := $(call normalize-path-list,$(LOCAL_DROIDDOC_SOURCE_PATH))
+$(full_target): PRIVATE_JAVA_FILES := $(filter %.java,$(full_src_files))
+$(full_target): PRIVATE_JAVA_FILES += $(addprefix $($(my_prefix)OUT_COMMON_INTERMEDIATES)/, $(filter %.java,$(LOCAL_INTERMEDIATE_SOURCES)))
+$(full_target): PRIVATE_SOURCE_INTERMEDIATES_DIR := $(intermediates.COMMON)/src
+$(full_target): PRIVATE_SRC_LIST_FILE := $(intermediates.COMMON)/droiddoc-src-list
+
+ifneq ($(strip $(LOCAL_ADDITIONAL_JAVA_DIR)),)
+$(full_target): PRIVATE_ADDITIONAL_JAVA_DIR := $(LOCAL_ADDITIONAL_JAVA_DIR)
+endif
+
+# Lists the input files for the doc build into a text file
+# suitable for the @ syntax of javadoc.
+# $(1): the file to create
+# $(2): files to include
+# $(3): list of directories to search for java files in
+define prepare-doc-source-list
+$(hide) mkdir -p $(dir $(1))
+$(call dump-words-to-file, $(2), $(1))
+$(hide) for d in $(3) ; do find $$d -name '*.java' -and -not -name '.*' >> $(1) 2> /dev/null ; done ; true
+endef
+
+##
+##
+## jdiff only
+##
+##
+
+jdiff := \
+ $(HOST_JDK_TOOLS_JAR) \
+ $(HOST_OUT_JAVA_LIBRARIES)/jdiff$(COMMON_JAVA_PACKAGE_SUFFIX)
+
+doclava := \
+ $(HOST_JDK_TOOLS_JAR) \
+ $(HOST_OUT_JAVA_LIBRARIES)/doclava$(COMMON_JAVA_PACKAGE_SUFFIX)
+
+$(full_target): PRIVATE_NEWAPI := $(LOCAL_APIDIFF_NEWAPI)
+$(full_target): PRIVATE_OLDAPI := $(LOCAL_APIDIFF_OLDAPI)
+$(full_target): PRIVATE_OUT_DIR := $(out_dir)
+$(full_target): PRIVATE_OUT_NEWAPI := $(out_dir)/current.xml
+$(full_target): PRIVATE_OUT_OLDAPI := $(out_dir)/$(notdir $(basename $(LOCAL_APIDIFF_OLDAPI))).xml
+$(full_target): PRIVATE_DOCLETPATH := $(HOST_OUT_JAVA_LIBRARIES)/jdiff$(COMMON_JAVA_PACKAGE_SUFFIX)
+$(full_target): \
+ $(full_src_files) \
+ $(full_java_lib_deps) \
+ $(jdiff) \
+ $(doclava) \
+ $(LOCAL_MODULE)-docs \
+ $(LOCAL_ADDITIONAL_DEPENDENCIES)
+ @echo Generating API diff: $(PRIVATE_OUT_DIR)
+ @echo Old API: $(PRIVATE_OLDAPI)
+ @echo New API: $(PRIVATE_NEWAPI)
+ @echo Old XML: $(PRIVATE_OUT_OLDAPI)
+ @echo New XML: $(PRIVATE_OUT_NEWAPI)
+ $(hide) mkdir -p $(dir $@)
+ @echo Converting API files to XML...
+ $(hide) mkdir -p $(PRIVATE_OUT_DIR)
+ $(hide) ( \
+ $(JAVA) \
+ $(addprefix -classpath ,$(PRIVATE_CLASSPATH):$(PRIVATE_DOCLAVA_CLASSPATH):$(PRIVATE_BOOTCLASSPATH):$(HOST_JDK_TOOLS_JAR)) \
+ com.google.doclava.apicheck.ApiCheck \
+ -convert2xml \
+ $(basename $(PRIVATE_NEWAPI)).txt \
+ $(basename $(PRIVATE_OUT_NEWAPI)).xml \
+ ) || (rm -rf $(PRIVATE_OUT_DIR) $(PRIVATE_SRC_LIST_FILE); exit 45)
+ $(hide) ( \
+ $(JAVA) \
+ $(addprefix -classpath ,$(PRIVATE_CLASSPATH):$(PRIVATE_DOCLAVA_CLASSPATH):$(PRIVATE_BOOTCLASSPATH):$(HOST_JDK_TOOLS_JAR)) \
+ com.google.doclava.apicheck.ApiCheck \
+ -convert2xml \
+ $(basename $(PRIVATE_OLDAPI)).txt \
+ $(basename $(PRIVATE_OUT_OLDAPI)).xml \
+ ) || (rm -rf $(PRIVATE_OUT_DIR) $(PRIVATE_SRC_LIST_FILE); exit 45)
+ @echo Running JDiff...
+ $(call prepare-doc-source-list,$(PRIVATE_SRC_LIST_FILE),$(PRIVATE_JAVA_FILES), \
+ $(PRIVATE_SOURCE_INTERMEDIATES_DIR) $(PRIVATE_ADDITIONAL_JAVA_DIR))
+ $(hide) ( \
+ $(JAVADOC) \
+ -encoding UTF-8 \
+ \@$(PRIVATE_SRC_LIST_FILE) \
+ -J-Xmx1600m \
+ -XDignore.symbol.file \
+ -quiet \
+ -doclet jdiff.JDiff \
+ -docletpath $(PRIVATE_DOCLETPATH) \
+ $(addprefix -bootclasspath ,$(PRIVATE_BOOTCLASSPATH)) \
+ $(addprefix -classpath ,$(PRIVATE_CLASSPATH)) \
+ -sourcepath $(PRIVATE_SOURCE_PATH)$(addprefix :,$(PRIVATE_CLASSPATH)) \
+ -d $(PRIVATE_OUT_DIR) \
+ -newapi $(notdir $(basename $(PRIVATE_OUT_NEWAPI))) \
+ -newapidir $(dir $(PRIVATE_OUT_NEWAPI)) \
+ -oldapi $(notdir $(basename $(PRIVATE_OUT_OLDAPI))) \
+ -oldapidir $(dir $(PRIVATE_OUT_OLDAPI)) \
+ -javadocnew ../../../reference/ \
+ && touch -f $@ \
+ ) || (rm -rf $(PRIVATE_OUT_DIR) $(PRIVATE_SRC_LIST_FILE); exit 45)
+
+ALL_DOCS += $(full_target)
+
+.PHONY: $(LOCAL_MODULE)-diff
+$(LOCAL_MODULE)-diff : $(full_target)
diff --git a/core/autogen_test_config.mk b/core/autogen_test_config.mk
new file mode 100644
index 0000000..c359bac
--- /dev/null
+++ b/core/autogen_test_config.mk
@@ -0,0 +1,64 @@
+#
+# 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.
+#
+
+# This build rule allows TradeFed test config file to be created based on
+# following inputs:
+# is_native: If the test is a native test.
+# LOCAL_MANIFEST_FILE: Name of the AndroidManifest file for the test. If it's
+# not set, default value `AndroidManifest.xml` will be used.
+# Output:
+# autogen_test_config_file: Path to the test config file generated.
+
+autogen_test_config_file := $(dir $(LOCAL_BUILT_MODULE))$(LOCAL_MODULE).config
+ifeq (true,$(is_native))
+# Auto generating test config file for native test
+$(autogen_test_config_file) : $(NATIVE_TEST_CONFIG_TEMPLATE)
+ @echo "Auto generating test config $(notdir $@)"
+ $(hide) sed 's&{MODULE}&$(PRIVATE_MODULE)&g' $^ > $@
+my_auto_generate_config := true
+else
+# Auto generating test config file for instrumentation test
+ifeq ($(strip $(LOCAL_MANIFEST_FILE)),)
+ LOCAL_MANIFEST_FILE := AndroidManifest.xml
+endif
+ifdef LOCAL_FULL_MANIFEST_FILE
+ my_android_manifest := $(LOCAL_FULL_MANIFEST_FILE)
+else
+ my_android_manifest := $(LOCAL_PATH)/$(LOCAL_MANIFEST_FILE)
+endif
+ifneq (,$(wildcard $(my_android_manifest)))
+$(autogen_test_config_file): PRIVATE_AUTOGEN_TEST_CONFIG_SCRIPT := $(AUTOGEN_TEST_CONFIG_SCRIPT)
+$(autogen_test_config_file): PRIVATE_TEST_CONFIG_ANDROID_MANIFEST := $(my_android_manifest)
+$(autogen_test_config_file): PRIVATE_EMPTY_TEST_CONFIG := $(EMPTY_TEST_CONFIG)
+$(autogen_test_config_file): PRIVATE_TEMPLATE := $(INSTRUMENTATION_TEST_CONFIG_TEMPLATE)
+$(autogen_test_config_file) : $(my_android_manifest) $(EMPTY_TEST_CONFIG) $(INSTRUMENTATION_TEST_CONFIG_TEMPLATE) $(AUTOGEN_TEST_CONFIG_SCRIPT)
+ @echo "Auto generating test config $(notdir $@)"
+ @rm -f $@
+ $(hide) $(PRIVATE_AUTOGEN_TEST_CONFIG_SCRIPT) $@ $(PRIVATE_TEST_CONFIG_ANDROID_MANIFEST) $(PRIVATE_EMPTY_TEST_CONFIG) $(PRIVATE_TEMPLATE)
+my_auto_generate_config := true
+endif # ifeq (,$(wildcard $(my_android_manifest)))
+endif # ifneq (true,$(is_native))
+
+ifeq (true,$(my_auto_generate_config))
+ LOCAL_INTERMEDIATE_TARGETS += $(autogen_test_config_file)
+ $(LOCAL_BUILT_MODULE): $(autogen_test_config_file)
+ ALL_MODULES.$(my_register_name).auto_test_config := true
+else
+ autogen_test_config_file :=
+endif
+
+my_android_manifest :=
+my_auto_generate_config :=
diff --git a/core/aux_config.mk b/core/aux_config.mk
index c40b8cc..6a5cd63 100644
--- a/core/aux_config.mk
+++ b/core/aux_config.mk
@@ -32,7 +32,7 @@
# setup AUX globals
AUX_SHLIB_SUFFIX := .so
-AUX_GLOBAL_ARFLAGS := crsPD
+AUX_GLOBAL_ARFLAGS := cqsD
AUX_STATIC_LIB_SUFFIX := .a
# Load ever-lasting "indexed" version of AUX variant environment; it is treated as READ-ONLY from this
@@ -102,10 +102,10 @@
$(eval AUX_OS_VARIANT_LIST_$(AUX_OS_$(1)):=) \
$(call aux-variant-setup-paths,$(_name)) \
$(eval AUX_ALL_VARIANTS += $(_name)) \
-$(eval AUX_ALL_OSES := $(filterout $(AUX_OS_$(_name)),$(AUX_ALL_OSES)) $(AUX_OS_$(_name))) \
-$(eval AUX_ALL_CPUS := $(filterout $(AUX_CPU_$(_name)),$(AUX_ALL_CPUS)) $(AUX_CPU_$(_name))) \
-$(eval AUX_ALL_ARCHS := $(filterout $(AUX_ARCH_$(_name)),$(AUX_ALL_ARCHS)) $(AUX_ARCH_$(_name))) \
-$(eval AUX_ALL_SUBARCHS := $(filterout $(AUX_SUBARCH_$(_name)),$(AUX_ALL_SUBARCHS)) $(AUX_SUBARCH_$(_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;
@@ -138,7 +138,7 @@
$(eval _all:=) \
$(eval _req:=$(addsuffix _$(1),$(aux_env))) \
$(foreach var,$(_req),$(eval _all += $(var))) \
-$(eval _missing := $(filterout $(_all),$(_req))) \
+$(eval _missing := $(filter-out $(_all),$(_req))) \
$(if $(_missing),$(error AUX variant $(1) must define vars: $(_missing)))
endef
@@ -154,7 +154,7 @@
config_roots := $(wildcard device vendor)
all_configs :=
ifdef config_roots
-all_configs := $(shell find $(config_roots) -maxdepth 4 -name '*$(variant_sfx)' -o -name '*$(os_sfx)' | sort)
+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))
diff --git a/core/base_rules.mk b/core/base_rules.mk
index 07d1cd9..22e7aef 100644
--- a/core/base_rules.mk
+++ b/core/base_rules.mk
@@ -65,6 +65,18 @@
my_host_cross :=
endif
+_path := $(LOCAL_MODULE_PATH) $(LOCAL_MODULE_PATH_32) $(LOCAL_MODULE_PATH_64)
+ifneq ($(filter $(TARGET_OUT_VENDOR)%,$(_path)),)
+LOCAL_VENDOR_MODULE := true
+else ifneq ($(filter $(TARGET_OUT_OEM)/%,$(_path)),)
+LOCAL_OEM_MODULE := true
+else ifneq ($(filter $(TARGET_OUT_ODM)/%,$(_path)),)
+LOCAL_ODM_MODULE := true
+else ifneq ($(filter $(TARGET_OUT_PRODUCT)/%,$(_path)),)
+LOCAL_PRODUCT_MODULE := true
+endif
+_path :=
+
ifndef LOCAL_PROPRIETARY_MODULE
LOCAL_PROPRIETARY_MODULE := $(LOCAL_VENDOR_MODULE)
endif
@@ -76,6 +88,7 @@
endif
include $(BUILD_SYSTEM)/local_vndk.mk
+include $(BUILD_SYSTEM)/local_systemsdk.mk
my_module_tags := $(LOCAL_MODULE_TAGS)
ifeq ($(my_host_cross),true)
@@ -96,6 +109,13 @@
# base_rules.mk, but it will fix the most common ones.
LOCAL_ADDITIONAL_DEPENDENCIES := $(filter-out %.mk,$(LOCAL_ADDITIONAL_DEPENDENCIES))
+my_bad_deps := $(strip $(foreach dep,$(filter-out | ||,$(LOCAL_ADDITIONAL_DEPENDENCIES)),\
+ $(if $(findstring /,$(dep)),,$(dep))))
+ifneq ($(my_bad_deps),)
+$(call pretty-warning,"Bad LOCAL_ADDITIONAL_DEPENDENCIES: $(my_bad_deps)")
+$(call pretty-error,"LOCAL_ADDITIONAL_DEPENDENCIES must only contain paths (not module names)")
+endif
+
###########################################################
## Validate and define fallbacks for input LOCAL_* variables.
###########################################################
@@ -131,7 +151,7 @@
# makefiles. Anything else is either a typo or a source of unexpected
# behaviors.
ifneq ($(filter-out debug eng tests optional samples,$(my_module_tags)),)
-$(call pretty-warning,unusual tags $(my_module_tags))
+$(call pretty-error,unusual tags: $(filter-out debug eng tests optional samples,$(my_module_tags)))
endif
# Add implicit tags.
@@ -182,6 +202,8 @@
partition_tag := _OEM
else ifeq (true,$(LOCAL_ODM_MODULE))
partition_tag := _ODM
+else ifeq (true,$(LOCAL_PRODUCT_MODULE))
+ partition_tag := _PRODUCT
else ifeq (NATIVE_TESTS,$(LOCAL_MODULE_CLASS))
partition_tag := _DATA
else
@@ -443,6 +465,50 @@
endif
###########################################################
+## Test Data
+###########################################################
+my_test_data_pairs :=
+my_installed_test_data :=
+# Source to relative dst file paths for reuse in LOCAL_COMPATIBILITY_SUITE.
+my_test_data_file_pairs :=
+
+ifneq ($(filter NATIVE_TESTS,$(LOCAL_MODULE_CLASS)),)
+ifneq ($(strip $(LOCAL_TEST_DATA)),)
+ifneq (true,$(LOCAL_UNINSTALLABLE_MODULE))
+
+my_test_data_pairs := $(strip $(foreach td,$(LOCAL_TEST_DATA), \
+ $(eval _file := $(call word-colon,2,$(td))) \
+ $(if $(_file), \
+ $(eval _src_base := $(call word-colon,1,$(td))), \
+ $(eval _src_base := $(LOCAL_PATH)) \
+ $(eval _file := $(call word-colon,1,$(td)))) \
+ $(if $(findstring ..,$(_file)),$(error $(LOCAL_MODULE_MAKEFILE): LOCAL_TEST_DATA may not include '..': $(_file))) \
+ $(if $(filter /%,$(_src_base) $(_file)),$(error $(LOCAL_MODULE_MAKEFILE): LOCAL_TEST_DATA may not include absolute paths: $(_src_base) $(_file))) \
+ $(eval my_test_data_file_pairs := $(my_test_data_file_pairs) $(call append-path,$(_src_base),$(_file)):$(_file)) \
+ $(call append-path,$(_src_base),$(_file)):$(call append-path,$(my_module_path),$(_file))))
+
+my_installed_test_data := $(call copy-many-files,$(my_test_data_pairs))
+$(LOCAL_INSTALLED_MODULE): $(my_installed_test_data)
+
+endif
+endif
+endif
+
+# For test modules that lack a suite tag, set null-suite as the default.
+# We only support adding a default suite to native tests, native benchmarks, and instrumentation tests.
+# This is because they are the only tests we currently auto-generate test configs for.
+ifndef LOCAL_COMPATIBILITY_SUITE
+ifneq ($(filter NATIVE_TESTS NATIVE_BENCHMARK, $(LOCAL_MODULE_CLASS)),)
+LOCAL_COMPATIBILITY_SUITE := null-suite
+endif
+ifneq ($(filter APPS, $(LOCAL_MODULE_CLASS)),)
+ifneq ($(filter $(my_module_tags),tests),)
+LOCAL_COMPATIBILITY_SUITE := null-suite
+endif
+endif
+endif
+
+###########################################################
## Compatibility suite files.
###########################################################
ifdef LOCAL_COMPATIBILITY_SUITE
@@ -451,19 +517,22 @@
# separate the multiple architectures into subdirectories of the testcase folder.
arch_dir :=
is_native :=
+multi_arch :=
ifeq ($(LOCAL_MODULE_CLASS),NATIVE_TESTS)
is_native := true
+ multi_arch := true
endif
ifeq ($(LOCAL_MODULE_CLASS),NATIVE_BENCHMARK)
is_native := true
+ multi_arch := true
endif
ifdef LOCAL_MULTILIB
- is_native := true
+ multi_arch := true
endif
-ifdef is_native
+ifdef multi_arch
arch_dir := /$($(my_prefix)$(LOCAL_2ND_ARCH_VAR_PREFIX)ARCH)
- is_native :=
endif
+multi_arch :=
# The module itself.
$(foreach suite, $(LOCAL_COMPATIBILITY_SUITE), \
@@ -483,13 +552,44 @@
$(foreach dir, $(call compatibility_suite_dirs,$(suite)), \
$(s):$(dir)/$(n)))))
+test_config := $(wildcard $(LOCAL_PATH)/AndroidTest.xml)
+ifeq (,$(test_config))
+ ifneq (true,$(is_native))
+ is_instrumentation_test := true
+ ifeq (true, $(LOCAL_IS_HOST_MODULE))
+ is_instrumentation_test := false
+ endif
+ # If LOCAL_MODULE_CLASS is not APPS, it's certainly not an instrumentation
+ # test. However, some packages for test data also have LOCAL_MODULE_CLASS
+ # set to APPS. These will require flag LOCAL_DISABLE_AUTO_GENERATE_TEST_CONFIG
+ # to disable auto-generating test config file.
+ ifneq (APPS, $(LOCAL_MODULE_CLASS))
+ is_instrumentation_test := false
+ endif
+ endif
+ # CTS modules can be used for test data, so test config files must be
+ # explicitly created using AndroidTest.xml
+ ifeq (,$(filter cts, $(LOCAL_COMPATIBILITY_SUITE)))
+ ifneq (true, $(LOCAL_DISABLE_AUTO_GENERATE_TEST_CONFIG))
+ ifeq (true, $(filter true,$(is_native) $(is_instrumentation_test)))
+ include $(BUILD_SYSTEM)/autogen_test_config.mk
+ test_config := $(autogen_test_config_file)
+ autogen_test_config_file :=
+ endif
+ endif
+ endif
+endif
-ifneq (,$(wildcard $(LOCAL_PATH)/AndroidTest.xml))
+is_instrumentation_test :=
+
+ifneq (,$(test_config))
$(foreach suite, $(LOCAL_COMPATIBILITY_SUITE), \
$(eval my_compat_dist_$(suite) += $(foreach dir, $(call compatibility_suite_dirs,$(suite)), \
- $(LOCAL_PATH)/AndroidTest.xml:$(dir)/$(LOCAL_MODULE).config)))
+ $(test_config):$(dir)/$(LOCAL_MODULE).config)))
endif
+test_config :=
+
ifneq (,$(wildcard $(LOCAL_PATH)/DynamicConfig.xml))
$(foreach suite, $(LOCAL_COMPATIBILITY_SUITE), \
$(eval my_compat_dist_$(suite) += $(foreach dir, $(call compatibility_suite_dirs,$(suite)), \
@@ -504,38 +604,24 @@
endif
endif # $(my_prefix)$(LOCAL_MODULE_CLASS)_$(LOCAL_MODULE)_compat_files
+ifneq ($(my_test_data_file_pairs),)
+$(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)), \
+ $(src_path):$(call append-path,$(dir),$(file))))))
+endif
+
+arch_dir :=
+is_native :=
+
$(call create-suite-dependencies)
endif # LOCAL_COMPATIBILITY_SUITE
###########################################################
-## Test Data
-###########################################################
-my_test_data_pairs :=
-my_installed_test_data :=
-
-ifneq ($(filter NATIVE_TESTS,$(LOCAL_MODULE_CLASS)),)
-ifneq ($(strip $(LOCAL_TEST_DATA)),)
-ifneq (true,$(LOCAL_UNINSTALLABLE_MODULE))
-
-my_test_data_pairs := $(strip $(foreach td,$(LOCAL_TEST_DATA), \
- $(eval _file := $(call word-colon,2,$(td))) \
- $(if $(_file), \
- $(eval _base := $(call word-colon,1,$(td))), \
- $(eval _base := $(LOCAL_PATH)) \
- $(eval _file := $(call word-colon,1,$(td)))) \
- $(if $(findstring ..,$(_file)),$(error $(LOCAL_MODULE_MAKEFILE): LOCAL_TEST_DATA may not include '..': $(_file))) \
- $(if $(filter /%,$(_base) $(_file)),$(error $(LOCAL_MODULE_MAKEFILE): LOCAL_TEST_DATA may not include absolute paths: $(_base) $(_file))) \
- $(call append-path,$(_base),$(_file)):$(call append-path,$(my_module_path),$(_file))))
-
-my_installed_test_data := $(call copy-many-files,$(my_test_data_pairs))
-$(LOCAL_INSTALLED_MODULE): $(my_installed_test_data)
-
-endif
-endif
-endif
-
-###########################################################
## Register with ALL_MODULES
###########################################################
@@ -579,6 +665,12 @@
ALL_MODULES.$(my_register_name).EXPLICITLY_REQUIRED := \
$(strip $(ALL_MODULES.$(my_register_name).EXPLICITLY_REQUIRED)\
$(my_required_modules))
+ALL_MODULES.$(my_register_name).TARGET_REQUIRED := \
+ $(strip $(ALL_MODULES.$(my_register_name).TARGET_REQUIRED)\
+ $(LOCAL_TARGET_REQUIRED_MODULES))
+ALL_MODULES.$(my_register_name).HOST_REQUIRED := \
+ $(strip $(ALL_MODULES.$(my_register_name).HOST_REQUIRED)\
+ $(LOCAL_HOST_REQUIRED_MODULES))
ALL_MODULES.$(my_register_name).EVENT_LOG_TAGS := \
$(ALL_MODULES.$(my_register_name).EVENT_LOG_TAGS) $(event_log_tags)
ALL_MODULES.$(my_register_name).MAKEFILE := \
@@ -591,6 +683,7 @@
ALL_MODULES.$(my_register_name).FOR_2ND_ARCH := true
endif
ALL_MODULES.$(my_register_name).FOR_HOST_CROSS := $(my_host_cross)
+ALL_MODULES.$(my_register_name).COMPATIBILITY_SUITES := $(LOCAL_COMPATIBILITY_SUITE)
INSTALLABLE_FILES.$(LOCAL_INSTALLED_MODULE).MODULE := $(my_register_name)
@@ -619,7 +712,7 @@
# Add this module name to the tag list of each specified tag.
$(foreach tag,$(my_module_tags),\
- $(eval ALL_MODULE_NAME_TAGS.$(tag) += $(my_register_name)))
+ $(eval ALL_MODULE_NAME_TAGS.$(tag) := $$(ALL_MODULE_NAME_TAGS.$(tag)) $(my_register_name)))
###########################################################
## umbrella targets used to verify builds
@@ -646,7 +739,7 @@
ifdef j_or_n
-$(j_or_n) $(h_or_t) $(j_or_n)-$(h_or_t) : $(my_checked_module)
+$(j_or_n) $(h_or_t) $(j_or_n)-$(h_or_hc_or_t) : $(my_checked_module)
ifneq (,$(filter $(my_module_tags),tests))
$(j_or_n)-$(h_or_t)-tests $(j_or_n)-tests $(h_or_t)-tests : $(my_checked_module)
endif
@@ -657,6 +750,15 @@
endif
###########################################################
+# Ensure privileged applications always have LOCAL_PRIVILEGED_MODULE
+###########################################################
+ifndef LOCAL_PRIVILEGED_MODULE
+ ifneq (,$(filter $(TARGET_OUT_APPS_PRIVILEGED)/% $(TARGET_OUT_VENDOR_APPS_PRIVILEGED)/%,$(my_module_path)))
+ LOCAL_PRIVILEGED_MODULE := true
+ endif
+endif
+
+###########################################################
## NOTICE files
###########################################################
diff --git a/core/binary.mk b/core/binary.mk
index 7dd9a13..61cd5cf 100644
--- a/core/binary.mk
+++ b/core/binary.mk
@@ -62,8 +62,8 @@
my_export_c_include_deps := $(LOCAL_EXPORT_C_INCLUDE_DEPS)
my_arflags :=
-ifneq (,$(strip $(foreach dir,$(subst $(comma),$(space),$(COVERAGE_PATHS)),$(filter $(dir)%,$(LOCAL_PATH)))))
-ifeq (,$(strip $(foreach dir,$(subst $(comma),$(space),$(COVERAGE_EXCLUDE_PATHS)),$(filter $(dir)%,$(LOCAL_PATH)))))
+ifneq (,$(strip $(foreach dir,$(COVERAGE_PATHS),$(filter $(dir)%,$(LOCAL_PATH)))))
+ifeq (,$(strip $(foreach dir,$(COVERAGE_EXCLUDE_PATHS),$(filter $(dir)%,$(LOCAL_PATH)))))
my_native_coverage := true
else
my_native_coverage := false
@@ -88,7 +88,7 @@
endif
# Make sure we've built the NDK.
- my_additional_dependencies += $(SOONG_OUT_DIR)/ndk.timestamp
+ 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 :(
@@ -105,7 +105,7 @@
ifneq (,$(filter arm64 mips64 x86_64,$(my_arch)))
my_min_sdk_version := 21
else
- my_min_sdk_version := 9
+ my_min_sdk_version := $(MIN_SUPPORTED_SDK_VERSION)
endif
# Historically we've just set up a bunch of symlinks in prebuilts/ndk to map
@@ -180,7 +180,6 @@
my_ndk_stl_include_path :=
my_ndk_stl_shared_lib_fullpath :=
my_ndk_stl_static_lib :=
- my_ndk_cpp_std_version :=
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
@@ -189,89 +188,52 @@
ifeq (,$(LOCAL_NDK_STL_VARIANT))
LOCAL_NDK_STL_VARIANT := system
endif
- ifneq (1,$(words $(filter none system stlport_static stlport_shared c++_static c++_shared gnustl_static, $(LOCAL_NDK_STL_VARIANT))))
+ ifneq (1,$(words $(filter none system c++_static c++_shared, $(LOCAL_NDK_STL_VARIANT))))
$(error $(LOCAL_PATH): Unknown LOCAL_NDK_STL_VARIANT $(LOCAL_NDK_STL_VARIANT))
endif
+
ifeq (system,$(LOCAL_NDK_STL_VARIANT))
my_ndk_stl_include_path := $(my_ndk_source_root)/cxx-stl/system/include
my_system_shared_libraries += libstdc++
- else # LOCAL_NDK_STL_VARIANT is not system
- ifneq (,$(filter stlport_%, $(LOCAL_NDK_STL_VARIANT)))
- my_ndk_stl_include_path := $(my_ndk_source_root)/cxx-stl/stlport/stlport
- my_system_shared_libraries += libstdc++
- ifeq (stlport_static,$(LOCAL_NDK_STL_VARIANT))
- my_ndk_stl_static_lib := $(my_ndk_source_root)/cxx-stl/stlport/libs/$(my_cpu_variant)/libstlport_static.a
- my_ldlibs += -ldl
- else
- my_ndk_stl_shared_lib_fullpath := $(my_ndk_source_root)/cxx-stl/stlport/libs/$(my_cpu_variant)/libstlport_shared.so
- endif
- else # LOCAL_NDK_STL_VARIANT is not stlport_* either
- ifneq (,$(filter c++_%, $(LOCAL_NDK_STL_VARIANT)))
- # Pre-r11 NDKs used libgabi++ for libc++'s C++ ABI, but r11 and later use
- # libc++abi.
- #
- # r13 no longer has the inner directory as a side effect of just using
- # external/libcxx.
- ifeq (r10,$(LOCAL_NDK_VERSION))
- my_ndk_stl_include_path := \
- $(my_ndk_source_root)/cxx-stl/llvm-libc++/libcxx/include
- my_ndk_stl_include_path += \
- $(my_ndk_source_root)/cxx-stl/llvm-libc++/gabi++/include
- else ifeq (r11,$(LOCAL_NDK_VERSION))
- my_ndk_stl_include_path := \
- $(my_ndk_source_root)/cxx-stl/llvm-libc++/libcxx/include
- my_ndk_stl_include_path += \
- $(my_ndk_source_root)/cxx-stl/llvm-libc++abi/libcxxabi/include
- else
- my_ndk_stl_include_path := \
- $(my_ndk_source_root)/cxx-stl/llvm-libc++/include
- my_ndk_stl_include_path += \
- $(my_ndk_source_root)/cxx-stl/llvm-libc++abi/include
- endif
+ else ifneq (,$(filter c++_%, $(LOCAL_NDK_STL_VARIANT)))
+ my_ndk_stl_include_path := \
+ $(my_ndk_source_root)/cxx-stl/llvm-libc++/include
+ my_ndk_stl_include_path += \
+ $(my_ndk_source_root)/cxx-stl/llvm-libc++abi/include
my_ndk_stl_include_path += $(my_ndk_source_root)/android/support/include
my_libcxx_libdir := \
$(my_ndk_source_root)/cxx-stl/llvm-libc++/libs/$(my_cpu_variant)
- ifneq (,$(filter r10 r11,$(LOCAL_NDK_VERSION)))
- ifeq (c++_static,$(LOCAL_NDK_STL_VARIANT))
- my_ndk_stl_static_lib := $(my_libcxx_libdir)/libc++_static.a
- else
- my_ndk_stl_shared_lib_fullpath := $(my_libcxx_libdir)/libc++_shared.so
- endif
+ ifeq (c++_static,$(LOCAL_NDK_STL_VARIANT))
+ my_ndk_stl_static_lib := \
+ $(my_libcxx_libdir)/libc++_static.a \
+ $(my_libcxx_libdir)/libc++abi.a
else
- ifeq (c++_static,$(LOCAL_NDK_STL_VARIANT))
- my_ndk_stl_static_lib := \
- $(my_libcxx_libdir)/libc++_static.a \
- $(my_libcxx_libdir)/libc++abi.a
- else
- my_ndk_stl_shared_lib_fullpath := $(my_libcxx_libdir)/libc++_shared.so
- endif
+ my_ndk_stl_shared_lib_fullpath := $(my_libcxx_libdir)/libc++_shared.so
+ endif
- my_ndk_stl_static_lib += $(my_libcxx_libdir)/libandroid_support.a
- ifneq (,$(filter armeabi armeabi-v7a,$(my_cpu_variant)))
- my_ndk_stl_static_lib += $(my_libcxx_libdir)/libunwind.a
- endif
+ my_ndk_stl_static_lib += $(my_libcxx_libdir)/libandroid_support.a
+ ifneq (,$(filter armeabi armeabi-v7a,$(my_cpu_variant)))
+ my_ndk_stl_static_lib += $(my_libcxx_libdir)/libunwind.a
endif
my_ldlibs += -ldl
-
- my_ndk_cpp_std_version := c++11
- else # LOCAL_NDK_STL_VARIANT is not c++_* either
- ifneq (,$(filter gnustl_%, $(LOCAL_NDK_STL_VARIANT)))
- my_ndk_stl_include_path := $(my_ndk_source_root)/cxx-stl/gnu-libstdc++/$($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_NDK_GCC_VERSION)/libs/$(my_cpu_variant)/include \
- $(my_ndk_source_root)/cxx-stl/gnu-libstdc++/$($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_NDK_GCC_VERSION)/include
- my_ndk_stl_static_lib := $(my_ndk_source_root)/cxx-stl/gnu-libstdc++/$($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_NDK_GCC_VERSION)/libs/$(my_cpu_variant)/libgnustl_static.a
else # LOCAL_NDK_STL_VARIANT must be none
# Do nothing.
endif
- endif
- endif
- endif
endif
ifneq ($(LOCAL_USE_VNDK),)
- my_cflags += -D__ANDROID_API__=__ANDROID_API_FUTURE__ -D__ANDROID_VNDK__
+ # Required VNDK version for vendor modules is BOARD_VNDK_VERSION.
+ my_vndk_version := $(BOARD_VNDK_VERSION)
+ ifeq ($(my_vndk_version),current)
+ # Build with current PLATFORM_VNDK_VERSION.
+ # If PLATFORM_VNDK_VERSION has a CODENAME, it will return
+ # __ANDROID_API_FUTURE__.
+ my_vndk_version := $(call codename-or-sdk-to-sdk,$(PLATFORM_VNDK_VERSION))
+ endif
+ my_cflags += -D__ANDROID_API__=$(my_vndk_version) -D__ANDROID_VNDK__
endif
ifndef LOCAL_IS_HOST_MODULE
@@ -290,6 +252,15 @@
# Move other ldlibs back to shared libraries
my_shared_libraries += $(patsubst -l%,lib%,$(filter-out $(my_allowed_ldlibs),$(my_ldlibs)))
my_ldlibs := $(filter $(my_allowed_ldlibs),$(my_ldlibs))
+else # LOCAL_IS_HOST_MODULE
+ # Add -ldl, -lpthread, -lm and -lrt to host builds to match the default behavior of
+ # device builds
+ ifneq ($($(my_prefix)OS),windows)
+ my_ldlibs += -ldl -lpthread -lm
+ ifneq ($(HOST_OS),darwin)
+ my_ldlibs += -lrt
+ endif
+ endif
endif
ifneq ($(LOCAL_SDK_VERSION),)
@@ -378,9 +349,9 @@
# clang is enabled by default for host builds
# enable it unless we've specifically disabled clang above
ifdef LOCAL_IS_HOST_MODULE
- ifeq ($($(my_prefix)OS),windows)
+ ifneq ($($(my_prefix)CLANG_SUPPORTED),true)
ifeq ($(my_clang),true)
- $(error $(LOCAL_MODULE_MAKEFILE): $(LOCAL_MODULE): Clang is not yet supported for windows binaries)
+ $(call pretty-error,Clang is not yet supported for $($(my_prefix)OS) binaries)
endif
my_clang := false
else
@@ -388,11 +359,6 @@
my_clang := true
endif
endif
-# Add option to make gcc the default for device build
-else ifeq ($(USE_CLANG_PLATFORM_BUILD),false)
- ifeq ($(my_clang),)
- my_clang := false
- endif
else ifeq ($(my_clang),)
my_clang := true
endif
@@ -420,11 +386,6 @@
my_cpp_std_version := $(DEFAULT_GCC_CPP_STD_VERSION)
endif
-ifdef LOCAL_SDK_VERSION
- # The NDK handles this itself.
- my_cpp_std_version := $(my_ndk_cpp_std_version)
-endif
-
ifdef LOCAL_IS_HOST_MODULE
ifneq ($(my_clang),true)
# The host GCC doesn't support C++14 (and is deprecated, so likely
@@ -656,6 +617,9 @@
my_cc := $(my_cc_wrapper) $(my_cc)
endif
+SYNTAX_TOOLS_PREFIX := \
+ $(LLVM_PREBUILTS_BASE)/$(BUILD_OS)-x86/$(LLVM_PREBUILTS_VERSION)/libexec
+
ifneq ($(LOCAL_NO_STATIC_ANALYZER),true)
my_cc := CCC_CC=$(CLANG) CLANG=$(CLANG) \
$(SYNTAX_TOOLS_PREFIX)/ccc-analyzer
@@ -797,7 +761,7 @@
ifneq (,$(LOCAL_SDK_VERSION))
# Set target-api for LOCAL_SDK_VERSIONs other than current.
ifneq (,$(filter-out current system_current test_current, $(LOCAL_SDK_VERSION)))
-renderscript_target_api := $(LOCAL_SDK_VERSION)
+renderscript_target_api := $(call get-numeric-sdk-version,$(LOCAL_SDK_VERSION))
endif
endif # LOCAL_SDK_VERSION is set
endif # LOCAL_RENDERSCRIPT_TARGET_API is set
@@ -861,6 +825,9 @@
###########################################################
## Compile the .proto files to .cc (or .c) and then to .o
###########################################################
+ifeq ($(strip $(LOCAL_PROTOC_OPTIMIZE_TYPE)),)
+ LOCAL_PROTOC_OPTIMIZE_TYPE := lite
+endif
proto_sources := $(filter %.proto,$(my_src_files))
ifneq ($(proto_sources),)
proto_gen_dir := $(generated_sources_dir)/proto
@@ -882,7 +849,7 @@
endif
my_proto_c_includes := external/protobuf/src
my_cflags += -DGOOGLE_PROTOBUF_NO_RTTI
-my_protoc_flags := --cpp_out=$(proto_gen_dir)
+my_protoc_flags := --cpp_out=$(if $(filter lite lite-static,$(LOCAL_PROTOC_OPTIMIZE_TYPE)),lite:,)$(proto_gen_dir)
my_protoc_deps :=
endif
my_proto_c_includes += $(proto_gen_dir)
@@ -1321,6 +1288,22 @@
asm_objects += $(asm_objects_asm)
endif
+###################################################################
+## 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))
+endif
+
###########################################################
## When compiling against the VNDK, use LL-NDK libraries
###########################################################
@@ -1347,6 +1330,15 @@
endif
endif
+# Platform can use vendor public libraries. If a required shared lib is one of
+# the vendor public libraries, the lib is switched to the stub version of the lib.
+ifeq ($(LOCAL_USE_VNDK),)
+ ifneq ($(LOCAL_MODULE_MAKEFILE),$(SOONG_ANDROID_MK))
+ my_shared_libraries := $(foreach l,$(my_shared_libraries),\
+ $(if $(filter $(l),$(VENDOR_PUBLIC_LIBRARIES)),$(l).vendorpublic,$(l)))
+ endif
+endif
+
##########################################################
## Set up installed module dependency
## We cannot compute the full path of the LOCAL_SHARED_LIBRARIES for
@@ -1401,18 +1393,33 @@
## other NDK-built libraries
####################################################
+include $(BUILD_SYSTEM)/allowed_ndk_types.mk
+
ifdef LOCAL_SDK_VERSION
-my_link_type := native:ndk
-my_warn_types :=
-my_allowed_types := native:ndk
+my_link_type := native:ndk:$(my_ndk_stl_family):$(my_ndk_stl_link_type)
+my_warn_types := $(my_warn_ndk_types)
+my_allowed_types := $(my_allowed_ndk_types)
else ifdef LOCAL_USE_VNDK
-my_link_type := native:vendor
-my_warn_types :=
-my_allowed_types := native:vendor
+ _name := $(patsubst %.vendor,%,$(LOCAL_MODULE))
+ ifneq ($(filter $(_name),$(VNDK_CORE_LIBRARIES) $(VNDK_SAMEPROCESS_LIBRARIES) $(LLNDK_LIBRARIES)),)
+ ifeq ($(filter $(_name),$(VNDK_PRIVATE_LIBRARIES)),)
+ my_link_type := native:vndk
+ else
+ my_link_type := native:vndk_private
+ endif
+ my_warn_types :=
+ my_allowed_types := native:vndk native:vndk_private
+ else
+ # Modules installed to /vendor cannot directly depend on modules marked
+ # with vendor_available: false
+ my_link_type := native:vendor
+ my_warn_types :=
+ my_allowed_types := native:vendor native:vndk
+ endif
else
my_link_type := native:platform
-my_warn_types :=
-my_allowed_types := native:ndk native:platform
+my_warn_types := $(my_warn_ndk_types)
+my_allowed_types := $(my_allowed_ndk_types) native:platform
endif
my_link_deps := $(addprefix STATIC_LIBRARIES:,$(my_whole_static_libraries) $(my_static_libraries))
@@ -1580,6 +1587,9 @@
$(foreach lib,$(my_static_libraries) $(my_whole_static_libraries), \
NOTICE-$(if $(LOCAL_IS_HOST_MODULE),HOST,TARGET)-STATIC_LIBRARIES-$(lib))
+$(notice_target): | $(installed_static_library_notice_file_targets)
+$(LOCAL_INSTALLED_MODULE): | $(notice_target)
+
# Default is -fno-rtti.
ifeq ($(strip $(LOCAL_RTTI_FLAG)),)
LOCAL_RTTI_FLAG := -fno-rtti
@@ -1642,13 +1652,30 @@
my_cflags += -DANDROID_STRICT
endif
-# Add -Werror if LOCAL_PATH is in the WARNING_DISALLOWED project list,
-# or not in the WARNING_ALLOWED project list.
-ifneq (,$(strip $(call find_warning_disallowed_projects,$(LOCAL_PATH))))
- my_cflags_no_override += -Werror
-else
- ifeq (,$(strip $(call find_warning_allowed_projects,$(LOCAL_PATH))))
- my_cflags_no_override += -Werror
+# Check if -Werror or -Wno-error is used in C compiler flags.
+# Modules defined in $(SOONG_ANDROID_MK) are checked in soong's cc.go.
+ifneq ($(LOCAL_MODULE_MAKEFILE),$(SOONG_ANDROID_MK))
+ # Header libraries do not need cflags.
+ ifneq (HEADER_LIBRARIES,$(LOCAL_MODULE_CLASS))
+ # Prebuilt modules do not need cflags.
+ ifeq (,$(LOCAL_PREBUILT_MODULE_FILE))
+ my_all_cflags := $(my_cflags) $(my_cppflags) $(my_cflags_no_override)
+ # Issue warning if -Wno-error is used.
+ ifneq (,$(filter -Wno-error,$(my_all_cflags)))
+ $(eval MODULES_USING_WNO_ERROR := $(MODULES_USING_WNO_ERROR) $(LOCAL_MODULE_MAKEFILE):$(LOCAL_MODULE))
+ else
+ # Issue warning if -Werror is not used. Add it.
+ ifeq (,$(filter -Werror,$(my_all_cflags)))
+ # Add -Wall -Werror unless the project is in the WARNING_ALLOWED project list.
+ ifeq (,$(strip $(call find_warning_allowed_projects,$(LOCAL_PATH))))
+ my_cflags := -Wall -Werror $(my_cflags)
+ else
+ $(eval MODULES_ADDED_WALL := $(MODULES_ADDED_WALL) $(LOCAL_MODULE_MAKEFILE):$(LOCAL_MODULE))
+ my_cflags := -Wall $(my_cflags)
+ endif
+ endif
+ endif
+ endif
endif
endif
@@ -1681,21 +1708,20 @@
ifneq ($(LOCAL_TIDY_CHECKS),)
my_tidy_checks := $(my_tidy_checks),$(LOCAL_TIDY_CHECKS)
endif
- # Set up global default clang-tidy flags, which is none.
- my_tidy_flags := $(WITH_TIDY_FLAGS)
- # Use local clang-tidy flags if specified.
- ifneq ($(LOCAL_TIDY_FLAGS),)
- my_tidy_flags := $(LOCAL_TIDY_FLAGS)
- endif
+ my_tidy_flags += $(WITH_TIDY_FLAGS) $(LOCAL_TIDY_FLAGS)
# If tidy flags are not specified, default to check all header files.
ifeq ($(my_tidy_flags),)
my_tidy_flags := $(call default_tidy_header_filter,$(LOCAL_PATH))
endif
+ # If clang-tidy is not enabled globally, add the -quiet flag.
+ ifeq (,$(filter 1 true,$(WITH_TIDY)))
+ my_tidy_flags += -quiet -extra-arg-before=-fno-caret-diagnostics
+ endif
# We might be using the static analyzer through clang-tidy.
# https://bugs.llvm.org/show_bug.cgi?id=32914
ifneq ($(my_tidy_checks),)
- my_tidy_flags += "-extra-arg-before=-D__clang_analyzer__"
+ my_tidy_flags += -extra-arg-before=-D__clang_analyzer__
endif
endif
endif
@@ -1708,17 +1734,19 @@
my_ldflags := $(filter-out -l%,$(my_ldlib_flags))
# One last verification check for ldlibs
-ifndef LOCAL_IS_HOST_MODULE
my_allowed_ldlibs :=
-ifneq ($(LOCAL_SDK_VERSION),)
- my_allowed_ldlibs := $(addprefix -l,$(NDK_PREBUILT_SHARED_LIBRARIES))
+ifndef LOCAL_IS_HOST_MODULE
+ ifneq ($(LOCAL_SDK_VERSION),)
+ my_allowed_ldlibs := $(addprefix -l,$(NDK_PREBUILT_SHARED_LIBRARIES))
+ endif
+else
+ my_allowed_ldlibs := $($(my_prefix)AVAILABLE_LIBRARIES)
endif
my_bad_ldlibs := $(filter-out $(my_allowed_ldlibs),$(my_ldlibs))
ifneq ($(my_bad_ldlibs),)
$(error $(LOCAL_MODULE_MAKEFILE): $(LOCAL_MODULE): Bad LOCAL_LDLIBS entries: $(my_bad_ldlibs))
endif
-endif
# my_cxx_ldlibs may contain linker flags need to wrap certain libraries
# (start-group/end-group), so append after the check above.
@@ -1758,11 +1786,6 @@
$(built_static_libraries) \
$(built_whole_libraries)
-# Also depend on the notice files for any static libraries that
-# are linked into this module. This will force them to be installed
-# when this module is.
-$(LOCAL_INSTALLED_MODULE): | $(installed_static_library_notice_file_targets)
-
###########################################################
# Export includes
###########################################################
@@ -1832,6 +1855,7 @@
$(my_whole_static_libraries) \
$(my_shared_libraries) \
$(my_system_shared_libraries))
+SOONG_CONV.$(LOCAL_MODULE).TYPE := native
SOONG_CONV := $(SOONG_CONV) $(LOCAL_MODULE)
endif
diff --git a/core/build-system.html b/core/build-system.html
index c7938cc..3d86e24 100644
--- a/core/build-system.html
+++ b/core/build-system.html
@@ -762,6 +762,19 @@
Dialer, Contacts, etc. This will probably change or go away when we switch
to an ant-based build system for the apps.</p>
+<h4>LOCAL_PATCH_MODULE (experimental option)</h4>
+<p>As of January 2018, you almost certainly don't need this option, so please
+ask and only use it if you understand what you're doing. This feature is
+experimental and may go away in future.</p>
+<p>
+When compiling language level 9+ .java code in packages that are part of a
+a system module, <code>LOCAL_PATCH_MODULE</code> names the module that your
+sources and dependencies should be patched into. The Android runtime currently
+(Jan 2018) doesn't implement the JEP 261 module system so this option is only
+supported at compile time. It should only be needed to compile tests in packages
+that exist in libcore and which are inconvenient to move elsewhere.
+</p>
+
<h4>LOCAL_PATH</h4>
<p>The directory your Android.mk file is in. You can set it by putting the
following as the first line in your Android.mk:</p>
diff --git a/core/build_id.mk b/core/build_id.mk
index ff4d013..932e214 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.
-export BUILD_ID=OC-MR1
+export BUILD_ID=PI
diff --git a/core/clang/HOST_CROSS_x86.mk b/core/clang/HOST_CROSS_x86.mk
index bf48f95..ffd7811 100644
--- a/core/clang/HOST_CROSS_x86.mk
+++ b/core/clang/HOST_CROSS_x86.mk
@@ -1 +1 @@
-$(clang_2nd_arch_prefix)HOST_CROSS_LIBPROFILE_RT := $(LLVM_RTLIB_PATH)/libclang_rt.profile-i686.a
+$(clang_2nd_arch_prefix)HOST_CROSS_LIBPROFILE_RT := $(LLVM_RTLIB_PATH)/libclang_rt.profile-i386.a
diff --git a/core/clang/HOST_x86.mk b/core/clang/HOST_x86.mk
index 0722b2a..2803517 100644
--- a/core/clang/HOST_x86.mk
+++ b/core/clang/HOST_x86.mk
@@ -1 +1 @@
-$(clang_2nd_arch_prefix)HOST_LIBPROFILE_RT := $(LLVM_RTLIB_PATH)/libclang_rt.profile-i686.a
+$(clang_2nd_arch_prefix)HOST_LIBPROFILE_RT := $(LLVM_RTLIB_PATH)/libclang_rt.profile-i386.a
diff --git a/core/clang/config.mk b/core/clang/config.mk
index 0e59930..408f688 100644
--- a/core/clang/config.mk
+++ b/core/clang/config.mk
@@ -72,6 +72,7 @@
# INTERNAL_LOCAL_CLANG_EXCEPTION_PROJECTS is defined later in other config.mk.
LOCAL_CLANG_EXCEPTION_PROJECTS = \
bionic/tests/ \
+ device/google/contexthub/ \
device/huawei/angler/ \
device/lge/bullhead/ \
external/gentoo/integration/ \
diff --git a/core/clang/versions.mk b/core/clang/versions.mk
deleted file mode 100644
index c2473cd..0000000
--- a/core/clang/versions.mk
+++ /dev/null
@@ -1,4 +0,0 @@
-## Clang/LLVM release versions.
-
-LLVM_PREBUILTS_VERSION ?= clang-4053586
-LLVM_PREBUILTS_BASE ?= prebuilts/clang/host
diff --git a/core/cleanbuild.mk b/core/cleanbuild.mk
index 0e1c88d..5576785 100644
--- a/core/cleanbuild.mk
+++ b/core/cleanbuild.mk
@@ -13,8 +13,32 @@
# limitations under the License.
#
-# Don't bother with the cleanspecs if you are running mm/mmm
-ifeq ($(ONE_SHOT_MAKEFILE)$(dont_bother)$(NO_ANDROID_CLEANSPEC),)
+# Absolute path of the present working direcotry.
+# This overrides the shell variable $PWD, which does not necessarily points to
+# the top of the source tree, for example when "make -C" is used in m/mm/mmm.
+PWD := $(shell pwd)
+
+TOP := .
+TOPDIR :=
+
+BUILD_SYSTEM := $(TOPDIR)build/make/core
+
+# Set up various standard variables based on configuration
+# and host information.
+include $(BUILD_SYSTEM)/config.mk
+
+include $(SOONG_MAKEVARS_MK)
+
+include $(BUILD_SYSTEM)/clang/config.mk
+
+# CTS-specific config.
+-include cts/build/config.mk
+# VTS-specific config.
+-include test/vts/tools/vts-tradefed/build/config.mk
+# device-tests-specific-config.
+-include tools/tradefederation/build/suites/device-tests/config.mk
+# general-tests-specific-config.
+-include tools/tradefederation/build/suites/general-tests/config.mk
INTERNAL_CLEAN_STEPS :=
@@ -24,7 +48,7 @@
#
# $(1): shell command to run
# $(2): indicate to not use makefile path as part of step id if not empty.
-# $(2) should only be used in build/core/cleanspec.mk: just for compatibility.
+# $(2) should only be used in build/make/core/cleanspec.mk: just for compatibility.
define _add-clean-step
$(if $(strip $(INTERNAL_CLEAN_BUILD_VERSION)),, \
$(error INTERNAL_CLEAN_BUILD_VERSION not set))
@@ -43,7 +67,7 @@
$(eval _acs_makefile_prefix :=)
endef
define add-clean-step
-$(eval # for build/core/cleanspec.mk, dont use makefile path as part of step id) \
+$(eval # for build/make/core/cleanspec.mk, dont use makefile path as part of step id) \
$(if $(filter %/cleanspec.mk,$(lastword $(MAKEFILE_LIST))),\
$(eval $(call _add-clean-step,$(1),true)),\
$(eval $(call _add-clean-step,$(1))))
@@ -58,7 +82,7 @@
# If the clean_steps.mk file is missing (usually after a clean build)
# then we won't do anything.
-CURRENT_CLEAN_BUILD_VERSION := $(INTERNAL_CLEAN_BUILD_VERSION)
+CURRENT_CLEAN_BUILD_VERSION := MISSING
CURRENT_CLEAN_STEPS := $(INTERNAL_CLEAN_STEPS)
# Read the current state from the file, if present.
@@ -67,7 +91,9 @@
clean_steps_file := $(PRODUCT_OUT)/clean_steps.mk
-include $(clean_steps_file)
-ifneq ($(CURRENT_CLEAN_BUILD_VERSION),$(INTERNAL_CLEAN_BUILD_VERSION))
+ifeq ($(CURRENT_CLEAN_BUILD_VERSION),MISSING)
+ # Do nothing
+else ifneq ($(CURRENT_CLEAN_BUILD_VERSION),$(INTERNAL_CLEAN_BUILD_VERSION))
# The major clean version is out-of-date. Do a full clean, and
# don't even bother with the clean steps.
$(info *** A clean build is required because of a recent change.)
@@ -109,57 +135,18 @@
# Write the new state to the file.
#
-rewrite_clean_steps_file :=
ifneq ($(CURRENT_CLEAN_BUILD_VERSION)-$(CURRENT_CLEAN_STEPS),$(INTERNAL_CLEAN_BUILD_VERSION)-$(INTERNAL_CLEAN_STEPS))
-rewrite_clean_steps_file := true
-endif
-ifeq ($(wildcard $(clean_steps_file)),)
-# This is the first build.
-rewrite_clean_steps_file := true
-endif
-ifeq ($(rewrite_clean_steps_file),true)
-$(shell \
- mkdir -p $(dir $(clean_steps_file)) && \
- echo "CURRENT_CLEAN_BUILD_VERSION := $(INTERNAL_CLEAN_BUILD_VERSION)" > \
- $(clean_steps_file) ;\
- echo "CURRENT_CLEAN_STEPS := $(wordlist 1,500,$(INTERNAL_CLEAN_STEPS))" >> $(clean_steps_file) \
- )
-define -cs-write-clean-steps-if-arg1-not-empty
-$(if $(1),$(shell echo "CURRENT_CLEAN_STEPS += $(1)" >> $(clean_steps_file)))
-endef
-$(call -cs-write-clean-steps-if-arg1-not-empty,$(wordlist 501,1000,$(INTERNAL_CLEAN_STEPS)))
-$(call -cs-write-clean-steps-if-arg1-not-empty,$(wordlist 1001,1500,$(INTERNAL_CLEAN_STEPS)))
-$(call -cs-write-clean-steps-if-arg1-not-empty,$(wordlist 1501,2000,$(INTERNAL_CLEAN_STEPS)))
-$(call -cs-write-clean-steps-if-arg1-not-empty,$(wordlist 2001,2500,$(INTERNAL_CLEAN_STEPS)))
-$(call -cs-write-clean-steps-if-arg1-not-empty,$(wordlist 2501,3000,$(INTERNAL_CLEAN_STEPS)))
-$(call -cs-write-clean-steps-if-arg1-not-empty,$(wordlist 3001,99999,$(INTERNAL_CLEAN_STEPS)))
+$(shell mkdir -p $(dir $(clean_steps_file)))
+$(file >$(clean_steps_file).tmp,CURRENT_CLEAN_BUILD_VERSION := $(INTERNAL_CLEAN_BUILD_VERSION)$(newline)CURRENT_CLEAN_STEPS := $(INTERNAL_CLEAN_STEPS)$(newline))
+$(shell if ! cmp -s $(clean_steps_file).tmp $(clean_steps_file); then \
+ mv $(clean_steps_file).tmp $(clean_steps_file); \
+ else \
+ rm $(clean_steps_file).tmp; \
+ fi)
endif
CURRENT_CLEAN_BUILD_VERSION :=
CURRENT_CLEAN_STEPS :=
clean_steps_file :=
-rewrite_clean_steps_file :=
INTERNAL_CLEAN_STEPS :=
INTERNAL_CLEAN_BUILD_VERSION :=
-
-endif # if not ONE_SHOT_MAKEFILE dont_bother NO_ANDROID_CLEANSPEC
-
-###########################################################
-
-.PHONY: clean-jack-files
-clean-jack-files: clean-dex-files
- $(hide) find $(OUT_DIR) -name "*.jack" | xargs rm -f
- $(hide) find $(OUT_DIR) -type d -name "jack" | xargs rm -rf
- @echo "All jack files have been removed."
-
-.PHONY: clean-dex-files
-clean-dex-files:
- $(hide) find $(OUT_DIR) -name "*.dex" ! -path "*/jack-incremental/*" | xargs rm -f
- $(hide) for i in `find $(OUT_DIR) -name "*.jar" -o -name "*.apk"` ; do ((unzip -l $$i 2> /dev/null | \
- grep -q "\.dex$$" && rm -f $$i) || continue ) ; done
- @echo "All dex files and archives containing dex files have been removed."
-
-.PHONY: clean-jack-incremental
-clean-jack-incremental:
- $(hide) find $(OUT_DIR) -name "jack-incremental" -type d | xargs rm -rf
- @echo "All jack incremental dirs have been removed."
diff --git a/core/cleanspec.mk b/core/cleanspec.mk
index 4441e2a..af28954 100644
--- a/core/cleanspec.mk
+++ b/core/cleanspec.mk
@@ -64,6 +64,6 @@
# ************************************************
subdir_cleanspecs := \
- $(shell build/tools/findleaves.py $(FIND_LEAVES_EXCLUDES) . CleanSpec.mk)
+ $(file <$(OUT_DIR)/.module_paths/CleanSpec.mk.list)
include $(subdir_cleanspecs)
subdir_cleanspecs :=
diff --git a/core/clear_vars.mk b/core/clear_vars.mk
index a687866..bd86cfb 100644
--- a/core/clear_vars.mk
+++ b/core/clear_vars.mk
@@ -4,8 +4,10 @@
# '',true
LOCAL_32_BIT_ONLY:=
+LOCAL_AAPT2_ONLY:=
LOCAL_AAPT_FLAGS:=
LOCAL_AAPT_INCLUDE_ALL_RESOURCES:=
+LOCAL_AAPT_NAMESPACES:=
LOCAL_ADDITIONAL_CERTIFICATES:=
LOCAL_ADDITIONAL_DEPENDENCIES:=
LOCAL_ADDITIONAL_HTML_DIR:=
@@ -14,6 +16,8 @@
LOCAL_ALLOW_UNDEFINED_SYMBOLS:=
LOCAL_ANNOTATION_PROCESSORS:=
LOCAL_ANNOTATION_PROCESSOR_CLASSES:=
+LOCAL_APIDIFF_NEWAPI:=
+LOCAL_APIDIFF_OLDAPI:=
LOCAL_APK_LIBRARIES:=
LOCAL_ARM_MODE:=
LOCAL_ASFLAGS:=
@@ -54,6 +58,8 @@
LOCAL_DEX_PREOPT_IMAGE_LOCATION:=
LOCAL_DEX_PREOPT_PROFILE_CLASS_LISTING:=
LOCAL_DEX_PREOPT:= # '',true,false,nostripping
+LOCAL_DISABLE_AUTO_GENERATE_TEST_CONFIG:=
+LOCAL_DISABLE_RESOLVE_SUPPORT_LIBRARIES:=
LOCAL_DONT_CHECK_MODULE:=
# Don't delete the META_INF dir when merging static Java libraries.
LOCAL_DONT_DELETE_JAR_META_INF:=
@@ -68,15 +74,22 @@
LOCAL_DROIDDOC_STUB_OUT_DIR:=
LOCAL_DROIDDOC_TEMPLATE_DIR:=
LOCAL_DROIDDOC_USE_STANDARD_DOCLET:=
+LOCAL_DROIDDOC_USE_METALAVA:=
+LOCAL_DROIDDOC_METALAVA_PREVIOUS_API:=
+LOCAL_DROIDDOC_METALAVA_ANNOTATIONS_ENABLED:=
+LOCAL_DROIDDOC_METALAVA_MERGE_ANNOTATIONS_DIR:=
+LOCAL_DROIDDOC_METALAVA_DOCS_STUB_OUT_DIR:=
LOCAL_DX_FLAGS:=
LOCAL_EMMA_COVERAGE_FILTER:=
LOCAL_EMMA_INSTRUMENT:=
+LOCAL_ENFORCE_USES_LIBRARIES:=
LOCAL_ERROR_PRONE_FLAGS:=
LOCAL_EXPORT_CFLAGS:=
LOCAL_EXPORT_C_INCLUDE_DEPS:=
LOCAL_EXPORT_C_INCLUDE_DIRS:=
LOCAL_EXPORT_HEADER_LIBRARY_HEADERS:=
LOCAL_EXPORT_PACKAGE_RESOURCES:=
+LOCAL_EXPORT_PROGUARD_FLAG_FILES:=
LOCAL_EXPORT_SHARED_LIBRARY_HEADERS:=
LOCAL_EXPORT_STATIC_LIBRARY_HEADERS:=
LOCAL_EXTRACT_APK:=
@@ -88,6 +101,7 @@
LOCAL_FULL_MANIFEST_FILE:=
LOCAL_FULL_CLASSES_JACOCO_JAR:=
LOCAL_FULL_CLASSES_PRE_JACOCO_JAR:=
+LOCAL_FUZZ_ENGINE:=
LOCAL_GCNO_FILES:=
LOCAL_GENERATED_SOURCES:=
# Group static libraries with "-Wl,--start-group" and "-Wl,--end-group" when linking.
@@ -95,6 +109,7 @@
LOCAL_GTEST:=true
LOCAL_HAL_STATIC_LIBRARIES:=
LOCAL_HEADER_LIBRARIES:=
+LOCAL_HOST_REQUIRED_MODULES:=
LOCAL_INIT_RC:=
LOCAL_INSTALLED_MODULE:=
LOCAL_INSTALLED_MODULE_STEM:=
@@ -126,6 +141,7 @@
LOCAL_JAVA_LIBRARIES:=
LOCAL_JAVA_RESOURCE_DIRS:=
LOCAL_JAVA_RESOURCE_FILES:=
+LOCAL_JETIFIER_ENABLED:=
LOCAL_JNI_SHARED_LIBRARIES:=
LOCAL_JNI_SHARED_LIBRARIES_ABI:=
LOCAL_LDFLAGS:=
@@ -173,11 +189,13 @@
LOCAL_NOTICE_FILE:=
LOCAL_ODM_MODULE:=
LOCAL_OEM_MODULE:=
+LOCAL_OPTIONAL_USES_LIBRARIES:=
LOCAL_OVERRIDES_PACKAGES:=
LOCAL_OVERRIDES_MODULES:=
LOCAL_PACKAGE_NAME:=
LOCAL_PACKAGE_SPLITS:=
LOCAL_PACK_MODULE_RELOCATIONS:=
+LOCAL_PATCH_MODULE:=
LOCAL_PICKUP_FILES:=
LOCAL_POST_INSTALL_CMD:=
LOCAL_POST_LINK_CMD:=
@@ -190,8 +208,10 @@
LOCAL_PREBUILT_OBJ_FILES:=
LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES:=
LOCAL_PREBUILT_STRIP_COMMENTS:=
+LOCAL_PRIVATE_PLATFORM_APIS:=
LOCAL_PRIVILEGED_MODULE:=
-# '',full,custom,nosystem,disabled,obfuscation,optimization
+# '',full,custom,disabled,obfuscation,optimization
+LOCAL_PRODUCT_MODULE:=
LOCAL_PROGUARD_ENABLED:=
LOCAL_PROGUARD_FLAG_FILES:=
LOCAL_PROGUARD_FLAGS:=
@@ -200,6 +220,7 @@
# lite(default),micro,nano,stream,full,nanopb-c,nanopb-c-enable_malloc
LOCAL_PROTOC_OPTIMIZE_TYPE:=
LOCAL_PROTO_JAVA_OUTPUT_PARAMS:=
+LOCAL_R8_FLAG_FILES:=
LOCAL_RECORDED_MODULE_TYPE:=
LOCAL_RENDERSCRIPT_CC:=
LOCAL_RENDERSCRIPT_COMPATIBILITY:=
@@ -224,16 +245,30 @@
LOCAL_SDK_VERSION:=
LOCAL_SHARED_ANDROID_LIBRARIES:=
LOCAL_SHARED_LIBRARIES:=
+LOCAL_SOONG_CLASSES_JAR :=
+LOCAL_SOONG_DEX_JAR :=
+LOCAL_SOONG_EXPORT_PROGUARD_FLAGS :=
+LOCAL_SOONG_HEADER_JAR :=
+LOCAL_SOONG_JACOCO_REPORT_CLASSES_JAR :=
+LOCAL_SOONG_PROGUARD_DICT :=
+LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE :=
+LOCAL_SOONG_RRO_DIRS :=
+LOCAL_SOONG_STATIC_LIBRARY_EXTRA_PACKAGES :=
+LOCAL_DROIDDOC_STUBS_JAR :=
+LOCAL_DROIDDOC_DOC_ZIP :=
# '',true
LOCAL_SOURCE_FILES_ALL_GENERATED:=
LOCAL_SRC_FILES:=
LOCAL_SRC_FILES_EXCLUDE:=
+LOCAL_SRCJARS:=
LOCAL_STATIC_ANDROID_LIBRARIES:=
LOCAL_STATIC_JAVA_AAR_LIBRARIES:=
LOCAL_STATIC_JAVA_LIBRARIES:=
LOCAL_STATIC_LIBRARIES:=
LOCAL_STRIP_MODULE:=
LOCAL_SYSTEM_SHARED_LIBRARIES:=none
+LOCAL_TARGET_REQUIRED_MODULES:=
+LOCAL_TEST_CONFIG_OPTIONS:=
LOCAL_TEST_DATA:=
LOCAL_TEST_MODULE_TO_PROGUARD_WITH:=
LOCAL_TIDY:=
@@ -243,6 +278,7 @@
LOCAL_UNSTRIPPED_PATH:=
LOCAL_USE_AAPT2:=$(USE_AAPT2)
LOCAL_USE_VNDK:=
+LOCAL_USES_LIBRARIES:=
LOCAL_VENDOR_MODULE:=
LOCAL_VTSC_FLAGS:=
LOCAL_VTS_INCLUDES:=
@@ -418,6 +454,13 @@
LOCAL_WHOLE_STATIC_LIBRARIES_32:=
LOCAL_WHOLE_STATIC_LIBRARIES_64:=
+# Robolectric variables
+LOCAL_INSTRUMENT_SOURCE_DIRS :=
+LOCAL_ROBOTEST_FAILURE_FATAL :=
+LOCAL_ROBOTEST_FILES :=
+LOCAL_ROBOTEST_TIMEOUT :=
+LOCAL_TEST_PACKAGE :=
+
# Aux specific variables
LOCAL_AUX_ARCH :=
LOCAL_AUX_CPU :=
diff --git a/core/combo/TARGET_linux-arm.mk b/core/combo/TARGET_linux-arm.mk
index 2e179f6..3ce64f9 100644
--- a/core/combo/TARGET_linux-arm.mk
+++ b/core/combo/TARGET_linux-arm.mk
@@ -29,8 +29,28 @@
# include defines, and compiler settings for the given architecture
# version.
#
+ifeq ($(strip $(TARGET_$(combo_2nd_arch_prefix)CPU_VARIANT)),)
+TARGET_$(combo_2nd_arch_prefix)CPU_VARIANT := generic
+endif
+
+KNOWN_ARMv8_CORES := cortex-a53 cortex-a53.a57 cortex-a55 cortex-a73 cortex-a75
+KNOWN_ARMv8_CORES += kryo denver64 exynos-m1 exynos-m2
+
+# Many devices (incorrectly) use armv7-a-neon as the 2nd architecture variant
+# for cores that implement armv8-a ISAs. The following sets it to armv8-a.
+ifneq (,$(filter $(TARGET_$(combo_2nd_arch_prefix)CPU_VARIANT), $(KNOWN_ARMv8_CORES)))
+ ifneq ($(TARGET_$(combo_2nd_arch_prefix)ARCH_VARIANT),armv8-a)
+ $(warning $(TARGET_$(combo_2nd_arch_prefix)CPU_VARIANT) is armv8-a.)
+ ifneq (,$(TARGET_$(combo_2nd_arch_prefix)ARCH_VARIANT))
+ $(warning TARGET_$(combo_2nd_arch_prefix)ARCH_VARIANT, $(TARGET_$(combo_2nd_arch_prefix)ARCH_VARIANT), ignored! Use armv8-a instead.)
+ endif
+ # Overwrite TARGET_$(combo_2nd_arch_prefix)ARCH_VARIANT
+ TARGET_$(combo_2nd_arch_prefix)ARCH_VARIANT := armv8-a
+ endif
+endif
+
ifeq ($(strip $(TARGET_$(combo_2nd_arch_prefix)ARCH_VARIANT)),)
-TARGET_$(combo_2nd_arch_prefix)ARCH_VARIANT := armv5te
+$(error TARGET_$(combo_2nd_arch_prefix)ARCH_VARIANT must be set)
endif
TARGET_ARCH_SPECIFIC_MAKEFILE := $(BUILD_COMBOS)/arch/$(TARGET_$(combo_2nd_arch_prefix)ARCH)/$(TARGET_$(combo_2nd_arch_prefix)ARCH_VARIANT).mk
diff --git a/core/combo/arch/arm/armv5te-vfp.mk b/core/combo/arch/arm/armv5te-vfp.mk
deleted file mode 100644
index 75299ac..0000000
--- a/core/combo/arch/arm/armv5te-vfp.mk
+++ /dev/null
@@ -1,7 +0,0 @@
-# At the moment, use the same settings than the one
-# for armv5te, since TARGET_ARCH_VARIANT := armv5te-vfp
-# will only be used to select an optimized VFP-capable assembly
-# interpreter loop for Dalvik.
-#
-include $(BUILD_COMBOS)/arch/arm/armv5te.mk
-
diff --git a/core/combo/arch/arm/armv5te.mk b/core/combo/arch/arm/armv5te.mk
deleted file mode 100644
index bd75695..0000000
--- a/core/combo/arch/arm/armv5te.mk
+++ /dev/null
@@ -1,4 +0,0 @@
-# Configuration for Linux on ARM.
-# Generating binaries for the ARMv5TE architecture and higher
-#
-
diff --git a/core/combo/arch/arm/armv8-a.mk b/core/combo/arch/arm/armv8-a.mk
new file mode 100644
index 0000000..9ef5c49
--- /dev/null
+++ b/core/combo/arch/arm/armv8-a.mk
@@ -0,0 +1,9 @@
+# Configuration for Linux on ARM.
+# Generating binaries for the ARMv8-a architecture
+#
+# Many libraries are not aware of armv8-a, and AArch32 is (almost) a superset
+# of armv7-a-neon. So just let them think we are just like v7.
+ARCH_ARM_HAVE_ARMV7A := true
+ARCH_ARM_HAVE_VFP := true
+ARCH_ARM_HAVE_VFP_D32 := true
+ARCH_ARM_HAVE_NEON := true
diff --git a/core/combo/arch/arm64/armv8-2a.mk b/core/combo/arch/arm64/armv8-2a.mk
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/core/combo/arch/arm64/armv8-2a.mk
diff --git a/core/combo/arch/x86/atom.mk b/core/combo/arch/x86/atom.mk
index d313a9a..43a170c 100644
--- a/core/combo/arch/x86/atom.mk
+++ b/core/combo/arch/x86/atom.mk
@@ -2,7 +2,7 @@
# 'x86-atom' arch variant. This is an extension of the 'x86' base variant
# that adds Atom-specific features.
#
-# See build/core/combo/arch/x86/x86.mk for differences.
+# See build/make/core/combo/arch/x86/x86.mk for differences.
#
ARCH_X86_HAVE_SSSE3 := true
ARCH_X86_HAVE_MOVBE := true
diff --git a/core/combo/arch/x86/silvermont.mk b/core/combo/arch/x86/silvermont.mk
index 70b718c..cba1079 100644
--- a/core/combo/arch/x86/silvermont.mk
+++ b/core/combo/arch/x86/silvermont.mk
@@ -1,7 +1,7 @@
# This file contains feature macro definitions specific to the
# silvermont arch variant.
#
-# See build/core/combo/arch/x86/x86-atom.mk for differences.
+# See build/make/core/combo/arch/x86/x86-atom.mk for differences.
#
ARCH_X86_HAVE_SSSE3 := true
diff --git a/core/combo/arch/x86_64/silvermont.mk b/core/combo/arch/x86_64/silvermont.mk
index 70b718c..cba1079 100644
--- a/core/combo/arch/x86_64/silvermont.mk
+++ b/core/combo/arch/x86_64/silvermont.mk
@@ -1,7 +1,7 @@
# This file contains feature macro definitions specific to the
# silvermont arch variant.
#
-# See build/core/combo/arch/x86/x86-atom.mk for differences.
+# See build/make/core/combo/arch/x86/x86-atom.mk for differences.
#
ARCH_X86_HAVE_SSSE3 := true
diff --git a/core/combo/javac.mk b/core/combo/javac.mk
index 5c2668c..dac2628 100644
--- a/core/combo/javac.mk
+++ b/core/combo/javac.mk
@@ -1,53 +1,19 @@
# Selects a Java compiler.
#
-# Inputs:
-# CUSTOM_JAVA_COMPILER -- "eclipse", "openjdk". or nothing for the system
-# default
-# ALTERNATE_JAVAC -- the alternate java compiler to use
-#
# Outputs:
-# COMMON_JAVAC -- Java compiler command with common arguments
+# ANDROID_JAVA_TOOLCHAIN -- Directory that contains javac and other java tools
#
-ifndef ANDROID_COMPILE_WITH_JACK
-# Defines if compilation with jack is enabled by default.
-ANDROID_COMPILE_WITH_JACK := true
+ANDROID_COMPILE_WITH_JACK := false
+
+ifdef TARGET_BUILD_APPS
+ ifndef TURBINE_ENABLED
+ TURBINE_ENABLED := false
+ endif
endif
-common_jdk_flags := -Xmaxerrs 9999999
+ANDROID_JAVA_TOOLCHAIN := $(ANDROID_JAVA_HOME)/bin
-# Use the indexer wrapper to index the codebase instead of the javac compiler
-ifeq ($(ALTERNATE_JAVAC),)
-JAVACC := javac
-else
-JAVACC := $(ALTERNATE_JAVAC)
-endif
-
-JAVA := java
-JAVADOC := javadoc
-JAR := jar
-
-# The actual compiler can be wrapped by setting the JAVAC_WRAPPER var.
-ifdef JAVAC_WRAPPER
- ifneq ($(JAVAC_WRAPPER),$(firstword $(JAVACC)))
- JAVACC := $(JAVAC_WRAPPER) $(JAVACC)
- endif
-endif
-
-# Whatever compiler is on this system.
-COMMON_JAVAC := $(JAVACC) -J-Xmx2048M $(common_jdk_flags)
-
-# Eclipse.
-ifeq ($(CUSTOM_JAVA_COMPILER), eclipse)
- COMMON_JAVAC := java -Xmx256m -jar prebuilt/common/ecj/ecj.jar -5 \
- -maxProblems 9999999 -nowarn
- $(info CUSTOM_JAVA_COMPILER=eclipse)
-endif
-
-GLOBAL_JAVAC_DEBUG_FLAGS := -g
-
-HOST_JAVAC ?= $(COMMON_JAVAC)
-TARGET_JAVAC ?= $(COMMON_JAVAC)
-
-#$(info HOST_JAVAC=$(HOST_JAVAC))
-#$(info TARGET_JAVAC=$(TARGET_JAVAC))
+# TODO(ccross): remove this, it is needed for now because it is used by
+# config.mk before makevars from soong are loaded
+JAVA := $(ANDROID_JAVA_TOOLCHAIN)/java
diff --git a/core/combo/select.mk b/core/combo/select.mk
index 5e181b9..eab4c72 100644
--- a/core/combo/select.mk
+++ b/core/combo/select.mk
@@ -28,7 +28,7 @@
# Set reasonable defaults for the various variables
-$(combo_var_prefix)GLOBAL_ARFLAGS := crsPD
+$(combo_var_prefix)GLOBAL_ARFLAGS := cqsD -format=gnu
$(combo_var_prefix)STATIC_LIB_SUFFIX := .a
diff --git a/core/config.mk b/core/config.mk
index cc2b2af..d218408 100644
--- a/core/config.mk
+++ b/core/config.mk
@@ -3,6 +3,20 @@
# current configuration and platform, which
# are not specific to what is being built.
+ifndef KATI
+$(warning Directly using config.mk from make is no longer supported.)
+$(warning )
+$(warning If you are just attempting to build, you probably need to re-source envsetup.sh:)
+$(warning )
+$(warning $$ source build/envsetup.sh)
+$(warning )
+$(warning If you are attempting to emulate get_build_var, use one of the following:)
+$(warning $$ build/soong/soong_ui.bash --dumpvar-mode)
+$(warning $$ build/soong/soong_ui.bash --dumpvars-mode)
+$(warning )
+$(error done)
+endif
+
# Only use ANDROID_BUILD_SHELL to wrap around bash.
# DO NOT use other shells such as zsh.
ifdef ANDROID_BUILD_SHELL
@@ -44,17 +58,27 @@
# If a rule fails, delete $@.
.DELETE_ON_ERROR:
-# Check for broken versions of make.
-ifndef KATI
-ifneq (1,$(strip $(shell expr $(MAKE_VERSION) \>= 3.81)))
-$(warning ********************************************************************************)
-$(warning * You are using version $(MAKE_VERSION) of make.)
-$(warning * Android can only be built by versions 3.81 and higher.)
-$(warning * see https://source.android.com/source/download.html)
-$(warning ********************************************************************************)
-$(error stopping)
-endif
-endif
+# Mark variables deprecated/obsolete
+CHANGES_URL := https://android.googlesource.com/platform/build/+/master/Changes.md
+$(KATI_obsolete_var PATH,Do not use PATH directly. See $(CHANGES_URL)#PATH)
+$(KATI_obsolete_var PYTHONPATH,Do not use PYTHONPATH directly. See $(CHANGES_URL)#PYTHONPATH)
+$(KATI_obsolete_var OUT,Use OUT_DIR instead. See $(CHANGES_URL)#OUT)
+$(KATI_obsolete_var ANDROID_HOST_OUT,Use HOST_OUT instead. See $(CHANGES_URL)#ANDROID_HOST_OUT)
+$(KATI_obsolete_var ANDROID_PRODUCT_OUT,Use PRODUCT_OUT instead. See $(CHANGES_URL)#ANDROID_PRODUCT_OUT)
+$(KATI_obsolete_var ANDROID_HOST_OUT_TESTCASES,Use HOST_OUT_TESTCASES instead. See $(CHANGES_URL)#ANDROID_HOST_OUT_TESTCASES)
+$(KATI_obsolete_var ANDROID_TARGET_OUT_TESTCASES,Use TARGET_OUT_TESTCASES instead. See $(CHANGES_URL)#ANDROID_TARGET_OUT_TESTCASES)
+$(KATI_obsolete_var ANDROID_BUILD_TOP,Use '.' instead. See $(CHANGES_URL)#ANDROID_BUILD_TOP)
+$(KATI_obsolete_var \
+ ANDROID_TOOLCHAIN \
+ ANDROID_TOOLCHAIN_2ND_ARCH \
+ ANDROID_DEV_SCRIPTS \
+ ANDROID_EMULATOR_PREBUILTS \
+ ANDROID_PRE_BUILD_PATHS \
+ ,See $(CHANGES_URL)#other_envsetup_variables)
+$(KATI_obsolete_var PRODUCT_COMPATIBILITY_MATRIX_LEVEL_OVERRIDE,Set FCM Version in device manifest instead. See $(CHANGES_URL)#PRODUCT_COMPATIBILITY_MATRIX_LEVEL_OVERRIDE)
+$(KATI_obsolete_var USE_CLANG_PLATFORM_BUILD,Clang is the only supported Android compiler. See $(CHANGES_URL)#USE_CLANG_PLATFORM_BUILD)
+
+CHANGES_URL :=
# Used to force goals to build. Only use for conditionally defined goals.
.PHONY: FORCE
@@ -62,14 +86,10 @@
ORIGINAL_MAKECMDGOALS := $(MAKECMDGOALS)
-# Tell python not to spam the source tree with .pyc files. This
-# only has an effect on python 2.6 and above.
-export PYTHONDONTWRITEBYTECODE := 1
+dist_goal := $(strip $(filter dist,$(MAKECMDGOALS)))
+MAKECMDGOALS := $(strip $(filter-out dist,$(MAKECMDGOALS)))
-ifneq ($(filter --color=always, $(GREP_OPTIONS)),)
-$(warning The build system needs unmodified output of grep.)
-$(error Please remove --color=always from your $$GREP_OPTIONS)
-endif
+UNAME := $(shell uname -sm)
SRC_TARGET_DIR := $(TOPDIR)build/target
SRC_API_DIR := $(TOPDIR)prebuilts/sdk/api
@@ -77,7 +97,7 @@
SRC_TEST_API_DIR := $(TOPDIR)prebuilts/sdk/test-api
# Some specific paths to tools
-SRC_DROIDDOC_DIR := $(TOPDIR)build/tools/droiddoc
+SRC_DROIDDOC_DIR := $(TOPDIR)build/make/tools/droiddoc
# Set up efficient math functions which are used in make.
# Here since this file is included by envsetup as well as during build.
@@ -86,6 +106,9 @@
# Various mappings to avoid hard-coding paths all over the place
include $(BUILD_SYSTEM)/pathmap.mk
+# Allow projects to define their own globally-available variables
+include $(BUILD_SYSTEM)/project_definitions.mk
+
# ###############################################################
# Build system internal files
# ###############################################################
@@ -112,6 +135,7 @@
BUILD_STATIC_JAVA_LIBRARY:= $(BUILD_SYSTEM)/static_java_library.mk
BUILD_HOST_JAVA_LIBRARY:= $(BUILD_SYSTEM)/host_java_library.mk
BUILD_DROIDDOC:= $(BUILD_SYSTEM)/droiddoc.mk
+BUILD_APIDIFF:= $(BUILD_SYSTEM)/apidiff.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
@@ -128,6 +152,15 @@
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
+
+INSTRUMENTATION_TEST_CONFIG_TEMPLATE := $(BUILD_SYSTEM)/instrumentation_test_config_template.xml
+NATIVE_TEST_CONFIG_TEMPLATE := $(BUILD_SYSTEM)/native_test_config_template.xml
+EMPTY_TEST_CONFIG := $(BUILD_SYSTEM)/empty_test_config.xml
+
+# Tool to generate TradeFed test config file automatically.
+AUTOGEN_TEST_CONFIG_SCRIPT := build/make/tools/auto_gen_test_config.py
# ###############################################################
# Parse out any modifier targets.
@@ -138,7 +171,7 @@
################################################################
# Tools needed in product configuration makefiles.
################################################################
-NORMALIZE_PATH := build/tools/normalize_path.py
+NORMALIZE_PATH := build/make/tools/normalize_path.py
# $(1): the paths to be normalized
define normalize-paths
@@ -149,6 +182,9 @@
# Set common values
# ###############################################################
+# Initialize SOONG_CONFIG_NAMESPACES so that it isn't recursive.
+SOONG_CONFIG_NAMESPACES :=
+
# Set the extensions used for various packages
COMMON_PACKAGE_SUFFIX := .zip
COMMON_JAVA_PACKAGE_SUFFIX := .jar
@@ -160,6 +196,11 @@
JAVA_TMPDIR_ARG :=
endif
+# Default to remove the org.apache.http.legacy from bootclasspath
+ifeq ($(REMOVE_OAHL_FROM_BCP),)
+REMOVE_OAHL_FROM_BCP := true
+endif
+
# ###############################################################
# Include sub-configuration files
# ###############################################################
@@ -302,7 +343,7 @@
include $(BUILD_SYSTEM)/combo/select.mk
endif
-ifndef KATI
+ifeq ($(CALLED_FROM_SETUP),true)
include $(BUILD_SYSTEM)/ccache.mk
include $(BUILD_SYSTEM)/goma.mk
@@ -375,33 +416,11 @@
WITH_STATIC_ANALYZER :=
endif
-# define clang/llvm versions and base directory.
-include $(BUILD_SYSTEM)/clang/versions.mk
-
# Unset WITH_TIDY_ONLY if global WITH_TIDY_ONLY is not true nor 1.
ifeq (,$(filter 1 true,$(WITH_TIDY_ONLY)))
WITH_TIDY_ONLY :=
endif
-PATH_TO_CLANG_TIDY := \
- $(LLVM_PREBUILTS_BASE)/$(BUILD_OS)-x86/$(LLVM_PREBUILTS_VERSION)/bin/clang-tidy
-ifeq ($(wildcard $(PATH_TO_CLANG_TIDY)),)
- ifneq (,$(filter 1 true,$(WITH_TIDY)))
- $(warning *** Disable WITH_TIDY because $(PATH_TO_CLANG_TIDY) does not exist)
- endif
- PATH_TO_CLANG_TIDY :=
-endif
-
-# Disable WITH_STATIC_ANALYZER if tool can't be found
-SYNTAX_TOOLS_PREFIX := \
- $(LLVM_PREBUILTS_BASE)/$(BUILD_OS)-x86/$(LLVM_PREBUILTS_VERSION)/tools/scan-build/libexec
-ifneq ($(strip $(WITH_STATIC_ANALYZER)),)
- ifeq ($(wildcard $(SYNTAX_TOOLS_PREFIX)/ccc-analyzer),)
- $(warning *** Disable WITH_STATIC_ANALYZER because $(SYNTAX_TOOLS_PREFIX)/ccc-analyzer does not exist)
- WITH_STATIC_ANALYZER :=
- endif
-endif
-
# Pick a Java compiler.
include $(BUILD_SYSTEM)/combo/javac.mk
@@ -432,9 +451,9 @@
# What to build:
# pdk fusion if:
-# 1) PDK_FUSION_PLATFORM_ZIP is passed in from the environment
+# 1) PDK_FUSION_PLATFORM_ZIP / PDK_FUSION_PLATFORM_DIR is passed in from the environment
# or
-# 2) the platform.zip exists in the default location
+# 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?
@@ -443,27 +462,44 @@
# or
# 2) TARGET_BUILD_PDK is passed in from the environment
-# if PDK_FUSION_PLATFORM_ZIP is specified, do not override.
-ifndef PDK_FUSION_PLATFORM_ZIP
-# Most PDK project paths should be using vendor/pdk/TARGET_DEVICE
-# but some legacy ones (e.g. mini_armv7a_neon generic PDK) were setup
-# with vendor/pdk/TARGET_PRODUCT.
-_pdk_fusion_default_platform_zip = $(strip \
- $(wildcard vendor/pdk/$(TARGET_DEVICE)/$(TARGET_PRODUCT)-$(TARGET_BUILD_VARIANT)/platform/platform.zip) \
- $(wildcard vendor/pdk/$(TARGET_DEVICE)/$(patsubst aosp_%,full_%,$(TARGET_PRODUCT))-$(TARGET_BUILD_VARIANT)/platform/platform.zip) \
- $(wildcard vendor/pdk/$(TARGET_PRODUCT)/$(TARGET_PRODUCT)-$(TARGET_BUILD_VARIANT)/platform/platform.zip) \
- $(wildcard vendor/pdk/$(TARGET_PRODUCT)/$(patsubst aosp_%,full_%,$(TARGET_PRODUCT))-$(TARGET_BUILD_VARIANT)/platform/platform.zip))
-ifneq (,$(_pdk_fusion_default_platform_zip))
-PDK_FUSION_PLATFORM_ZIP := $(word 1, $(_pdk_fusion_default_platform_zip))
-TARGET_BUILD_PDK := true
-endif # _pdk_fusion_default_platform_zip
-endif # !PDK_FUSION_PLATFORM_ZIP
+# 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)))
-ifndef PDK_FUSION_PLATFORM_ZIP
- $(error Specify PDK_FUSION_PLATFORM_ZIP to do a PDK fusion.)
+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
@@ -471,7 +507,19 @@
ifdef PDK_FUSION_PLATFORM_ZIP
TARGET_BUILD_PDK := true
ifeq (,$(wildcard $(PDK_FUSION_PLATFORM_ZIP)))
- $(error Cannot find file $(PDK_FUSION_PLATFORM_ZIP).)
+ ifneq (,$(wildcard $(dir $(PDK_FUSION_PLATFORM_ZIP))/pdk.mk))
+ PDK_FUSION_PLATFORM_DIR := $(dir $(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
@@ -497,8 +545,29 @@
prebuilt_sdk_tools := prebuilts/sdk/tools
prebuilt_sdk_tools_bin := $(prebuilt_sdk_tools)/$(HOST_OS)/bin
+# Always use prebuilts for ckati and makeparallel
+prebuilt_build_tools := prebuilts/build-tools
+prebuilt_build_tools_wrappers := prebuilts/build-tools/common/bin
+prebuilt_build_tools_jars := prebuilts/build-tools/common/framework
+ifeq ($(filter address,$(SANITIZE_HOST)),)
+prebuilt_build_tools_bin := $(prebuilt_build_tools)/$(HOST_PREBUILT_TAG)/bin
+else
+prebuilt_build_tools_bin := $(prebuilt_build_tools)/$(HOST_PREBUILT_TAG)/asan/bin
+endif
+
USE_PREBUILT_SDK_TOOLS_IN_PLACE := true
+# Work around for b/68406220
+# This should match the soong version.
+ifndef USE_D8
+ USE_D8 := true
+endif
+
+# Default R8 behavior when USE_R8 is not specified.
+ifndef USE_R8
+ USE_R8 := false
+endif
+
#
# Tools that are prebuilts for TARGET_BUILD_APPS
#
@@ -506,28 +575,21 @@
AIDL := $(HOST_OUT_EXECUTABLES)/aidl
AAPT := $(HOST_OUT_EXECUTABLES)/aapt
AAPT2 := $(HOST_OUT_EXECUTABLES)/aapt2
+ DESUGAR := $(HOST_OUT_JAVA_LIBRARIES)/desugar.jar
MAINDEXCLASSES := $(HOST_OUT_EXECUTABLES)/mainDexClasses
SIGNAPK_JAR := $(HOST_OUT_JAVA_LIBRARIES)/signapk$(COMMON_JAVA_PACKAGE_SUFFIX)
SIGNAPK_JNI_LIBRARY_PATH := $(HOST_OUT_SHARED_LIBRARIES)
ZIPALIGN := $(HOST_OUT_EXECUTABLES)/zipalign
- ifndef DX_ALT_JAR
- DX := $(HOST_OUT_EXECUTABLES)/dx
- DX_COMMAND := $(DX) -JXms16M -JXmx2048M
- else
- DX := $(DX_ALT_JAR)
- DX_COMMAND := $(JAVA) -Xms16M -Xmx2048M -jar $(DX)
- endif
else # TARGET_BUILD_APPS || TARGET_BUILD_PDK
- AIDL := $(prebuilt_sdk_tools_bin)/aidl
+ AIDL := $(prebuilt_build_tools_bin)/aidl
AAPT := $(prebuilt_sdk_tools_bin)/aapt
AAPT2 := $(prebuilt_sdk_tools_bin)/aapt2
- DX := $(prebuilt_sdk_tools)/dx
- DX_COMMAND := $(DX) -JXms16M -JXmx2048M
+ DESUGAR := $(prebuilt_build_tools_jars)/desugar.jar
MAINDEXCLASSES := $(prebuilt_sdk_tools)/mainDexClasses
- ZIPALIGN := $(prebuilt_sdk_tools_bin)/zipalign
SIGNAPK_JAR := $(prebuilt_sdk_tools)/lib/signapk$(COMMON_JAVA_PACKAGE_SUFFIX)
SIGNAPK_JNI_LIBRARY_PATH := $(prebuilt_sdk_tools)/$(HOST_OS)/lib64
+ ZIPALIGN := $(prebuilt_build_tools_bin)/zipalign
endif # TARGET_BUILD_APPS || TARGET_BUILD_PDK
ifeq (,$(TARGET_BUILD_APPS))
@@ -542,38 +604,30 @@
prebuilt_sdk_tools :=
prebuilt_sdk_tools_bin :=
-# Always use prebuilts for ckati and makeparallel
-prebuilt_build_tools := prebuilts/build-tools
-ifeq ($(filter address,$(SANITIZE_HOST)),)
-prebuilt_build_tools_bin := $(prebuilt_build_tools)/$(HOST_PREBUILT_TAG)/bin
-else
-prebuilt_build_tools_bin := $(prebuilt_build_tools)/$(HOST_PREBUILT_TAG)/asan/bin
-endif
-
ACP := $(prebuilt_build_tools_bin)/acp
CKATI := $(prebuilt_build_tools_bin)/ckati
DEPMOD := $(HOST_OUT_EXECUTABLES)/depmod
FILESLIST := $(SOONG_HOST_OUT_EXECUTABLES)/fileslist
-IJAR := $(prebuilt_build_tools_bin)/ijar
MAKEPARALLEL := $(prebuilt_build_tools_bin)/makeparallel
SOONG_JAVAC_WRAPPER := $(SOONG_HOST_OUT_EXECUTABLES)/soong_javac_wrapper
SOONG_ZIP := $(SOONG_HOST_OUT_EXECUTABLES)/soong_zip
+MERGE_ZIPS := $(SOONG_HOST_OUT_EXECUTABLES)/merge_zips
+XMLLINT := $(SOONG_HOST_OUT_EXECUTABLES)/xmllint
ZIP2ZIP := $(SOONG_HOST_OUT_EXECUTABLES)/zip2zip
ZIPTIME := $(prebuilt_build_tools_bin)/ziptime
# ---------------------------------------------------------------
# Generic tools.
-JACK := $(HOST_OUT_EXECUTABLES)/jack
LEX := prebuilts/misc/$(BUILD_OS)-$(HOST_PREBUILT_ARCH)/flex/flex-2.5.39
# The default PKGDATADIR built in the prebuilt bison is a relative path
-# external/bison/data.
+# prebuilts/build-tools/common/bison.
# To run bison from elsewhere you need to set up enviromental variable
# BISON_PKGDATADIR.
-BISON_PKGDATADIR := $(PWD)/external/bison/data
-BISON := prebuilts/misc/$(BUILD_OS)-$(HOST_PREBUILT_ARCH)/bison/bison
+BISON_PKGDATADIR := $(PWD)/prebuilts/build-tools/common/bison
+BISON := prebuilts/build-tools/$(BUILD_OS)-$(HOST_PREBUILT_ARCH)/bin/bison
YACC := $(BISON) -d
-BISON_DATA := $(wildcard external/bison/data/* external/bison/data/*/*)
+BISON_DATA := $(wildcard $(BISON_PKGDATADIR)/* $(BISON_PKGDATADIR)/*/*)
YASM := prebuilts/misc/$(BUILD_OS)-$(HOST_PREBUILT_ARCH)/yasm/yasm
@@ -592,7 +646,7 @@
VTSC := $(HOST_OUT_EXECUTABLES)/vtsc$(HOST_EXECUTABLE_SUFFIX)
MKBOOTFS := $(HOST_OUT_EXECUTABLES)/mkbootfs$(HOST_EXECUTABLE_SUFFIX)
MINIGZIP := $(HOST_OUT_EXECUTABLES)/minigzip$(HOST_EXECUTABLE_SUFFIX)
-BRO := $(HOST_OUT_EXECUTABLES)/bro$(HOST_EXECUTABLE_SUFFIX)
+BROTLI := $(HOST_OUT_EXECUTABLES)/brotli$(HOST_EXECUTABLE_SUFFIX)
ifeq (,$(strip $(BOARD_CUSTOM_MKBOOTIMG)))
MKBOOTIMG := $(HOST_OUT_EXECUTABLES)/mkbootimg$(HOST_EXECUTABLE_SUFFIX)
else
@@ -610,15 +664,9 @@
endif
APICHECK := $(HOST_OUT_EXECUTABLES)/apicheck$(HOST_EXECUTABLE_SUFFIX)
FS_GET_STATS := $(HOST_OUT_EXECUTABLES)/fs_get_stats$(HOST_EXECUTABLE_SUFFIX)
-ifeq ($(TARGET_USES_MKE2FS),true)
MAKE_EXT4FS := $(HOST_OUT_EXECUTABLES)/mke2fs$(HOST_EXECUTABLE_SUFFIX)
MKEXTUSERIMG := $(HOST_OUT_EXECUTABLES)/mkuserimg_mke2fs.sh
MKE2FS_CONF := system/extras/ext4_utils/mke2fs.conf
-else
-MAKE_EXT4FS := $(HOST_OUT_EXECUTABLES)/make_ext4fs$(HOST_EXECUTABLE_SUFFIX)
-MKEXTUSERIMG := $(HOST_OUT_EXECUTABLES)/mkuserimg.sh
-MKE2FS_CONF :=
-endif
BLK_ALLOC_TO_BASE_FS := $(HOST_OUT_EXECUTABLES)/blk_alloc_to_base_fs$(HOST_EXECUTABLE_SUFFIX)
MAKE_SQUASHFS := $(HOST_OUT_EXECUTABLES)/mksquashfs$(HOST_EXECUTABLE_SUFFIX)
MKSQUASHFSUSERIMG := $(HOST_OUT_EXECUTABLES)/mksquashfsimage.sh
@@ -627,31 +675,17 @@
SIMG2IMG := $(HOST_OUT_EXECUTABLES)/simg2img$(HOST_EXECUTABLE_SUFFIX)
IMG2SIMG := $(HOST_OUT_EXECUTABLES)/img2simg$(HOST_EXECUTABLE_SUFFIX)
E2FSCK := $(HOST_OUT_EXECUTABLES)/e2fsck$(HOST_EXECUTABLE_SUFFIX)
-MKTARBALL := build/tools/mktarball.sh
+MKTARBALL := build/make/tools/mktarball.sh
TUNE2FS := $(HOST_OUT_EXECUTABLES)/tune2fs$(HOST_EXECUTABLE_SUFFIX)
JARJAR := $(HOST_OUT_JAVA_LIBRARIES)/jarjar.jar
-DESUGAR := $(HOST_OUT_JAVA_LIBRARIES)/desugar.jar
DATA_BINDING_COMPILER := $(HOST_OUT_JAVA_LIBRARIES)/databinding-compiler.jar
-FAT16COPY := build/tools/fat16copy.py
-CHECK_LINK_TYPE := build/tools/check_link_type.py
-
-ifeq ($(ANDROID_COMPILE_WITH_JACK),true)
-DEFAULT_JACK_ENABLED:=full
-else
-DEFAULT_JACK_ENABLED:=
-endif
-ifneq ($(ANDROID_JACK_EXTRA_ARGS),)
-JACK_DEFAULT_ARGS :=
-DEFAULT_JACK_EXTRA_ARGS := $(ANDROID_JACK_EXTRA_ARGS)
-else
-JACK_DEFAULT_ARGS := $(BUILD_SYSTEM)/jack-default.args
-DEFAULT_JACK_EXTRA_ARGS := @$(JACK_DEFAULT_ARGS)
-endif
+FAT16COPY := build/make/tools/fat16copy.py
+CHECK_LINK_TYPE := build/make/tools/check_link_type.py
PROGUARD := external/proguard/bin/proguard.sh
-JAVATAGS := build/tools/java-event-log-tags.py
-MERGETAGS := build/tools/merge-event-log-tags.py
-BUILD_IMAGE_SRCS := $(wildcard build/tools/releasetools/*.py)
+JAVATAGS := build/make/tools/java-event-log-tags.py
+MERGETAGS := build/make/tools/merge-event-log-tags.py
+BUILD_IMAGE_SRCS := $(wildcard build/make/tools/releasetools/*.py)
APPEND2SIMG := $(HOST_OUT_EXECUTABLES)/append2simg
VERITY_SIGNER := $(HOST_OUT_EXECUTABLES)/verity_signer
BUILD_VERITY_TREE := $(HOST_OUT_EXECUTABLES)/build_verity_tree
@@ -663,43 +697,48 @@
DEXDUMP := $(HOST_OUT_EXECUTABLES)/dexdump2$(BUILD_EXECUTABLE_SUFFIX)
PROFMAN := $(HOST_OUT_EXECUTABLES)/profman
+HIDDENAPI := $(HOST_OUT_EXECUTABLES)/hiddenapi
# relocation packer
RELOCATION_PACKER := prebuilts/misc/$(BUILD_OS)-$(HOST_PREBUILT_ARCH)/relocation_packer/relocation_packer
FINDBUGS_DIR := external/owasp/sanitizer/tools/findbugs/bin
FINDBUGS := $(FINDBUGS_DIR)/findbugs
-JACOCO_CLI_JAR := $(HOST_OUT_JAVA_LIBRARIES)/jacoco-cli$(COMMON_JAVA_PACKAGE_SUFFIX)
+
+JETIFIER := prebuilts/sdk/tools/jetifier/jetifier-standalone/bin/jetifier-standalone
# Tool to merge AndroidManifest.xmls
-ANDROID_MANIFEST_MERGER := $(JAVA) -classpath prebuilts/devtools/tools/lib/manifest-merger.jar com.android.manifmerger.Main merge
+ANDROID_MANIFEST_MERGER_CLASSPATH := \
+ prebuilts/gradle-plugin/com/android/tools/build/manifest-merger/26.0.0-beta2/manifest-merger-26.0.0-beta2.jar \
+ prebuilts/gradle-plugin/com/android/tools/sdk-common/26.0.0-beta2/sdk-common-26.0.0-beta2.jar \
+ prebuilts/gradle-plugin/com/android/tools/common/26.0.0-beta2/common-26.0.0-beta2.jar \
+ prebuilts/misc/common/guava/guava-21.0.jar
+ANDROID_MANIFEST_MERGER := $(JAVA) \
+ -classpath $(subst $(space),:,$(strip $(ANDROID_MANIFEST_MERGER_CLASSPATH))) \
+ com.android.manifmerger.Merger
COLUMN:= column
-# We may not have the right JAVA_HOME/PATH set up yet when this is run from envsetup.sh.
-ifneq ($(CALLED_FROM_SETUP),true)
-
-# Path to tools.jar, or empty if EXPERIMENTAL_USE_OPENJDK9 is set
-HOST_JDK_TOOLS_JAR :=
-# TODO: Remove HOST_JDK_TOOLS_JAR and all references to it once OpenJDK 8
-# toolchains are no longer supported (i.e. when what is now
-# EXPERIMENTAL_USE_OPENJDK9 becomes the standard). http://b/38418220
ifeq ($(EXPERIMENTAL_USE_OPENJDK9),)
-HOST_JDK_TOOLS_JAR := $(shell $(BUILD_SYSTEM)/find-jdk-tools-jar.sh)
+ifeq ($(RUN_ERROR_PRONE),true)
+USE_OPENJDK9 :=
+else
+USE_OPENJDK9 := true
+endif
+TARGET_OPENJDK9 :=
+else ifeq ($(EXPERIMENTAL_USE_OPENJDK9),false)
+USE_OPENJDK9 :=
+TARGET_OPENJDK9 :=
+else ifeq ($(EXPERIMENTAL_USE_OPENJDK9),1.8)
+USE_OPENJDK9 := true
+TARGET_OPENJDK9 :=
+else ifeq ($(EXPERIMENTAL_USE_OPENJDK9),true)
+USE_OPENJDK9 := true
+TARGET_OPENJDK9 := true
+endif
-ifneq ($(HOST_JDK_TOOLS_JAR),)
-ifeq ($(wildcard $(HOST_JDK_TOOLS_JAR)),)
-$(error Error: could not find jdk tools.jar at $(HOST_JDK_TOOLS_JAR), please check if your JDK was installed correctly)
-endif
-endif
-endif # ifeq ($(EXPERIMENTAL_USE_OPENJDK9),)
-
-# Is the host JDK 64-bit version?
-HOST_JDK_IS_64BIT_VERSION :=
-ifneq ($(filter 64-Bit, $(shell $(JAVA) -version 2>&1)),)
-HOST_JDK_IS_64BIT_VERSION := true
-endif
-endif # CALLED_FROM_SETUP not true
+# Path to tools.jar
+HOST_JDK_TOOLS_JAR := $(ANDROID_JAVA8_HOME)/lib/tools.jar
# It's called md5 on Mac OS and md5sum on Linux
ifeq ($(HOST_OS),darwin)
@@ -717,6 +756,19 @@
APICHECK_COMMAND := $(APICHECK) -JXmx1024m -J"classpath $(APICHECK_CLASSPATH)"
+# Boolean variable determining if the whitelist 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
+endif
+
+.KATI_READONLY := \
+ PRODUCT_COMPATIBLE_PROPERTY
+
# Boolean variable determining if Treble is fully enabled
PRODUCT_FULL_TREBLE := false
ifneq ($(PRODUCT_FULL_TREBLE_OVERRIDE),)
@@ -727,12 +779,103 @@
PRODUCT_FULL_TREBLE := true
endif
+# TODO(b/69865032): Make PRODUCT_NOTICE_SPLIT the default behavior and remove
+# references to it here and below.
+ifdef PRODUCT_NOTICE_SPLIT_OVERRIDE
+ $(error PRODUCT_NOTICE_SPLIT_OVERRIDE cannot be set.)
+endif
+
+requirements := \
+ PRODUCT_TREBLE_LINKER_NAMESPACES \
+ PRODUCT_SEPOLICY_SPLIT \
+ PRODUCT_ENFORCE_VINTF_MANIFEST \
+ PRODUCT_NOTICE_SPLIT
+
+# If it is overriden, then the requirement override is taken, otherwise it's
+# PRODUCT_FULL_TREBLE
+$(foreach req,$(requirements),$(eval \
+ $(req) := $(if $($(req)_OVERRIDE),$($(req)_OVERRIDE),$(PRODUCT_FULL_TREBLE))))
+# If the requirement is false for any reason, then it's not PRODUCT_FULL_TREBLE
+$(foreach req,$(requirements),$(eval \
+ PRODUCT_FULL_TREBLE := $(if $(filter false,$($(req))),false,$(PRODUCT_FULL_TREBLE))))
+
+PRODUCT_FULL_TREBLE_OVERRIDE ?=
+$(foreach req,$(requirements),$(eval $(req)_OVERRIDE ?=))
+
+.KATI_READONLY := \
+ PRODUCT_FULL_TREBLE_OVERRIDE \
+ $(foreach req,$(requirements),$(req)_OVERRIDE) \
+ $(requirements) \
+ PRODUCT_FULL_TREBLE \
+
+requirements :=
+
+# BOARD_PROPERTY_OVERRIDES_SPLIT_ENABLED can be true only if early-mount of
+# partitions is supported. But the early-mount must be supported for full
+# treble products, and so BOARD_PROPERTY_OVERRIDES_SPLIT_ENABLED should be set
+# by default for full treble products.
+ifeq ($(PRODUCT_FULL_TREBLE),true)
+ BOARD_PROPERTY_OVERRIDES_SPLIT_ENABLED ?= true
+endif
+
+# If PRODUCT_USE_VNDK is true and BOARD_VNDK_VERSION is not defined yet,
+# BOARD_VNDK_VERSION will be set to "current" as default.
+# PRODUCT_USE_VNDK will be true in Android-P or later launching devices.
+PRODUCT_USE_VNDK := false
+ifneq ($(PRODUCT_USE_VNDK_OVERRIDE),)
+ PRODUCT_USE_VNDK := $(PRODUCT_USE_VNDK_OVERRIDE)
+else ifeq ($(PRODUCT_SHIPPING_API_LEVEL),)
+ # No shipping level defined
+else ifeq ($(call math_gt_or_eq,27,$(PRODUCT_SHIPPING_API_LEVEL)),)
+ PRODUCT_USE_VNDK := $(PRODUCT_FULL_TREBLE)
+endif
+
+ifeq ($(PRODUCT_USE_VNDK),true)
+ ifndef BOARD_VNDK_VERSION
+ BOARD_VNDK_VERSION := current
+ endif
+endif
+
+$(KATI_obsolete_var PRODUCT_USE_VNDK_OVERRIDE,Use PRODUCT_USE_VNDK instead)
+.KATI_READONLY := \
+ PRODUCT_USE_VNDK
+
+# Set BOARD_SYSTEMSDK_VERSIONS to the latest SystemSDK version starting from P-launching
+# devices if unset.
+ifndef BOARD_SYSTEMSDK_VERSIONS
+ ifdef PRODUCT_SHIPPING_API_LEVEL
+ ifneq ($(call math_gt_or_eq,$(PRODUCT_SHIPPING_API_LEVEL),28),)
+ ifeq (REL,$(PLATFORM_VERSION_CODENAME))
+ BOARD_SYSTEMSDK_VERSIONS := $(PLATFORM_SDK_VERSION)
+ else
+ BOARD_SYSTEMSDK_VERSIONS := $(PLATFORM_VERSION_CODENAME)
+ endif
+ endif
+ endif
+endif
+
+
ifdef PRODUCT_SHIPPING_API_LEVEL
ifneq ($(call math_gt_or_eq,$(PRODUCT_SHIPPING_API_LEVEL),27),)
ifneq ($(TARGET_USES_MKE2FS),true)
$(error When PRODUCT_SHIPPING_API_LEVEL >= 27, TARGET_USES_MKE2FS must be true)
endif
endif
+ ifneq ($(call numbers_less_than,$(PRODUCT_SHIPPING_API_LEVEL),$(BOARD_SYSTEMSDK_VERSIONS)),)
+ $(error BOARD_SYSTEMSDK_VERSIONS ($(BOARD_SYSTEMSDK_VERSIONS)) must all be greater than or equal to PRODUCT_SHIPPING_API_LEVEL ($(PRODUCT_SHIPPING_API_LEVEL)))
+ endif
+ ifneq ($(call math_gt_or_eq,$(PRODUCT_SHIPPING_API_LEVEL),28),)
+ ifneq ($(TARGET_IS_64_BIT), true)
+ ifneq ($(TARGET_USES_64_BIT_BINDER), true)
+ $(error When PRODUCT_SHIPPING_API_LEVEL >= 28, TARGET_USES_64_BIT_BINDER must be true)
+ endif
+ endif
+ ifeq ($(PRODUCT_FULL_TREBLE),true)
+ ifneq ($(BOARD_BUILD_SYSTEM_ROOT_IMAGE), true)
+ $(error When PRODUCT_SHIPPING_API_LEVEL >= 28, BOARD_BUILD_SYSTEM_ROOT_IMAGE must be true)
+ endif
+ endif
+ endif
endif
# The default key if not set as LOCAL_CERTIFICATE
@@ -742,45 +885,46 @@
DEFAULT_SYSTEM_DEV_CERTIFICATE := build/target/product/security/testkey
endif
-FRAMEWORK_MANIFEST_FILE := system/libhidl/manifest.xml
+BUILD_NUMBER_FROM_FILE := $$(cat $(OUT_DIR)/build_number.txt)
+BUILD_DATETIME_FROM_FILE := $$(cat $(BUILD_DATETIME_FILE))
-# Compatibility matrix versioning:
-# MATRIX_LEVEL_OVERRIDE defined: MATRIX_LEVEL = MATRIX_LEVEL_OVERRIDE
-# MATRIX_LEVEL_OVERRIDE undefined:
-# FULL_TREBLE != true: MATRIX_LEVEL = legacy
-# FULL_TREBLE == true:
-# SHIPPING_API_LEVEL defined: MATRIX_LEVEL = SHIPPING_API_LEVEL
-# SHIPPING_API_LEVEL undefined: MATRIX_LEVEL = PLATFORM_SDK_VERSION
-# MATRIX_LEVEL == legacy => legacy.xml
-# MATRIX_LEVEL <= 26 => 26.xml
-# MATRIX_LEVEL == 27 => 27.xml # define when 27 releases
-# MATRIX_LEVEL == 28 => 28.xml # define when 28 releases
-# ...
-# otherwise => current.xml
+# SEPolicy versions
-ifneq ($(PRODUCT_COMPATIBILITY_MATRIX_LEVEL_OVERRIDE),)
- PRODUCT_COMPATIBILITY_MATRIX_LEVEL := $(PRODUCT_COMPATIBILITY_MATRIX_LEVEL_OVERRIDE)
-else ifneq ($(PRODUCT_FULL_TREBLE),true)
- PRODUCT_COMPATIBILITY_MATRIX_LEVEL := legacy
-else ifneq ($(PRODUCT_SHIPPING_API_LEVEL),)
- PRODUCT_COMPATIBILITY_MATRIX_LEVEL := $(PRODUCT_SHIPPING_API_LEVEL)
-else
- PRODUCT_COMPATIBILITY_MATRIX_LEVEL := $(PLATFORM_SDK_VERSION)
+# PLATFORM_SEPOLICY_VERSION is a number of the form "NN.m" with "NN" mapping to
+# PLATFORM_SDK_VERSION and "m" as a minor number which allows for SELinux
+# changes independent of PLATFORM_SDK_VERSION. This value will be set to
+# 10000.0 to represent tip-of-tree development that is inherently unstable and
+# thus designed not to work with any shipping vendor policy. This is similar in
+# spirit to how DEFAULT_APP_TARGET_SDK is set.
+# The minor version ('m' component) must be updated every time a platform release
+# is made which breaks compatibility with the previous platform sepolicy version,
+# not just on every increase in PLATFORM_SDK_VERSION. The minor version should
+# be reset to 0 on every bump of the PLATFORM_SDK_VERSION.
+sepolicy_major_vers := 28
+sepolicy_minor_vers := 0
+
+ifneq ($(sepolicy_major_vers), $(PLATFORM_SDK_VERSION))
+$(error sepolicy_major_version does not match PLATFORM_SDK_VERSION, please update.)
endif
-ifeq ($(strip $(PRODUCT_COMPATIBILITY_MATRIX_LEVEL)),legacy)
- FRAMEWORK_COMPATIBILITY_MATRIX_FILE := hardware/interfaces/compatibility_matrix.legacy.xml
-else ifeq ($(call math_gt_or_eq,$(PRODUCT_COMPATIBILITY_MATRIX_LEVEL),26),)
- # All PRODUCT_FULL_TREBLE devices with shipping API levels < 26 get the level 26 manifest
- # as that is the first.
- FRAMEWORK_COMPATIBILITY_MATRIX_FILE := hardware/interfaces/compatibility_matrix.26.xml
-else ifeq ($(call math_gt_or_eq,$(PRODUCT_COMPATIBILITY_MATRIX_LEVEL),28),)
- # All shipping API levels with released compatibility matrices get the corresponding matrix.
- FRAMEWORK_COMPATIBILITY_MATRIX_FILE := \
- hardware/interfaces/compatibility_matrix.$(PRODUCT_COMPATIBILITY_MATRIX_LEVEL).xml
+TOT_SEPOLICY_VERSION := 10000.0
+ifneq (REL,$(PLATFORM_VERSION_CODENAME))
+ PLATFORM_SEPOLICY_VERSION := $(TOT_SEPOLICY_VERSION)
else
- FRAMEWORK_COMPATIBILITY_MATRIX_FILE := hardware/interfaces/compatibility_matrix.current.xml
+ PLATFORM_SEPOLICY_VERSION := $(join $(addsuffix .,$(sepolicy_major_vers)), $(sepolicy_minor_vers))
endif
+sepolicy_major_vers :=
+sepolicy_minor_vers :=
+
+# A list of SEPolicy versions, besides PLATFORM_SEPOLICY_VERSION, that the framework supports.
+PLATFORM_SEPOLICY_COMPAT_VERSIONS := \
+ 26.0 \
+ 27.0
+
+.KATI_READONLY := \
+ PLATFORM_SEPOLICY_COMPAT_VERSIONS \
+ PLATFORM_SEPOLICY_VERSION \
+ TOT_SEPOLICY_VERSION \
# ###############################################################
# Set up final options.
@@ -818,12 +962,6 @@
$(TARGET_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_INSTRUCTION_SET_FEATURES := default
endif
-# These will come from Soong, drop the environment versions
-unexport CLANG
-unexport CLANG_CXX
-unexport CCC_CC
-unexport CCC_CXX
-
# ###############################################################
# Collect a list of the SDK versions that we could compile against
# For use with the LOCAL_SDK_VERSION variable for include $(BUILD_PACKAGE)
@@ -859,18 +997,40 @@
$(patsubst $(HISTORICAL_SDK_VERSIONS_ROOT)/%/android.jar,%, \
$(wildcard $(HISTORICAL_SDK_VERSIONS_ROOT)/*/android.jar)))
-# We don't have prebuilt test_current SDK yet.
-TARGET_AVAILABLE_SDK_VERSIONS := test_current $(TARGET_AVAILABLE_SDK_VERSIONS)
+TARGET_AVAILABLE_SDK_VERSIONS := $(addprefix system_,$(call numerically_sort,\
+ $(patsubst $(HISTORICAL_SDK_VERSIONS_ROOT)/%/android_system.jar,%, \
+ $(wildcard $(HISTORICAL_SDK_VERSIONS_ROOT)/*/android_system.jar)))) \
+ $(TARGET_AVAILABLE_SDK_VERSIONS)
+
+# We don't have prebuilt test_current and core_current SDK yet.
+TARGET_AVAILABLE_SDK_VERSIONS := test_current core_current $(TARGET_AVAILABLE_SDK_VERSIONS)
+
+TARGET_SDK_VERSIONS_WITHOUT_JAVA_18_SUPPORT := $(call numbers_less_than,24,$(TARGET_AVAILABLE_SDK_VERSIONS))
+TARGET_SDK_VERSIONS_WITHOUT_JAVA_19_SUPPORT := $(call numbers_less_than,27,$(TARGET_AVAILABLE_SDK_VERSIONS))
INTERNAL_PLATFORM_API_FILE := $(TARGET_OUT_COMMON_INTERMEDIATES)/PACKAGING/public_api.txt
+INTERNAL_PLATFORM_DEX_API_FILE := $(TARGET_OUT_COMMON_INTERMEDIATES)/PACKAGING/public-dex.txt
+INTERNAL_PLATFORM_PRIVATE_API_FILE := $(TARGET_OUT_COMMON_INTERMEDIATES)/PACKAGING/private.txt
+INTERNAL_PLATFORM_PRIVATE_DEX_API_FILE := $(TARGET_OUT_COMMON_INTERMEDIATES)/PACKAGING/private-dex.txt
INTERNAL_PLATFORM_REMOVED_API_FILE := $(TARGET_OUT_COMMON_INTERMEDIATES)/PACKAGING/removed.txt
+INTERNAL_PLATFORM_REMOVED_DEX_API_FILE := $(TARGET_OUT_COMMON_INTERMEDIATES)/PACKAGING/removed-dex.txt
INTERNAL_PLATFORM_SYSTEM_API_FILE := $(TARGET_OUT_COMMON_INTERMEDIATES)/PACKAGING/system-api.txt
+INTERNAL_PLATFORM_SYSTEM_PRIVATE_API_FILE := $(TARGET_OUT_COMMON_INTERMEDIATES)/PACKAGING/system-private.txt
+INTERNAL_PLATFORM_SYSTEM_PRIVATE_DEX_API_FILE := $(TARGET_OUT_COMMON_INTERMEDIATES)/PACKAGING/system-private-dex.txt
INTERNAL_PLATFORM_SYSTEM_REMOVED_API_FILE := $(TARGET_OUT_COMMON_INTERMEDIATES)/PACKAGING/system-removed.txt
INTERNAL_PLATFORM_SYSTEM_EXACT_API_FILE := $(TARGET_OUT_COMMON_INTERMEDIATES)/PACKAGING/system-exact.txt
INTERNAL_PLATFORM_TEST_API_FILE := $(TARGET_OUT_COMMON_INTERMEDIATES)/PACKAGING/test-api.txt
INTERNAL_PLATFORM_TEST_REMOVED_API_FILE := $(TARGET_OUT_COMMON_INTERMEDIATES)/PACKAGING/test-removed.txt
INTERNAL_PLATFORM_TEST_EXACT_API_FILE := $(TARGET_OUT_COMMON_INTERMEDIATES)/PACKAGING/test-exact.txt
+INTERNAL_PLATFORM_HIDDENAPI_LIGHT_GREYLIST := $(TARGET_OUT_COMMON_INTERMEDIATES)/PACKAGING/hiddenapi-light-greylist.txt
+INTERNAL_PLATFORM_HIDDENAPI_DARK_GREYLIST := $(TARGET_OUT_COMMON_INTERMEDIATES)/PACKAGING/hiddenapi-dark-greylist.txt
+INTERNAL_PLATFORM_HIDDENAPI_BLACKLIST := $(TARGET_OUT_COMMON_INTERMEDIATES)/PACKAGING/hiddenapi-blacklist.txt
+
+# Missing optional uses-libraries so that the platform doesn't create build rules that depend on
+# them. See setup_one_odex.mk.
+INTERNAL_PLATFORM_MISSING_USES_LIBRARIES := com.google.android.ble com.google.android.wearable
+
# This is the standard way to name a directory containing prebuilt target
# objects. E.g., prebuilt/$(TARGET_PREBUILT_TAG)/libc.so
TARGET_PREBUILT_TAG := android-$(TARGET_ARCH)
@@ -882,57 +1042,23 @@
RS_PREBUILT_CLCORE := prebuilts/sdk/renderscript/lib/$(TARGET_ARCH)/librsrt_$(TARGET_ARCH).bc
RS_PREBUILT_COMPILER_RT := prebuilts/sdk/renderscript/lib/$(TARGET_ARCH)/libcompiler_rt.a
-ifeq (true,$(TARGET_IS_64_BIT))
-RS_PREBUILT_LIBPATH := -L prebuilts/ndk/r10/platforms/android-21/arch-$(TARGET_ARCH)/usr/lib64 \
- -L prebuilts/ndk/r10/platforms/android-21/arch-$(TARGET_ARCH)/usr/lib
-else
-RS_PREBUILT_LIBPATH := -L prebuilts/ndk/r10/platforms/android-9/arch-$(TARGET_ARCH)/usr/lib
-endif
# API Level lists for Renderscript Compat lib.
RSCOMPAT_32BIT_ONLY_API_LEVELS := 8 9 10 11 12 13 14 15 16 17 18 19 20
RSCOMPAT_NO_USAGEIO_API_LEVELS := 8 9 10 11 12 13
-ifeq ($(JAVA_NOT_REQUIRED),true)
-# Remove java and tools from our path so that we make sure nobody uses them.
-unexport ANDROID_JAVA_HOME
-unexport JAVA_HOME
-export ANDROID_BUILD_PATHS:=$(abspath $(BUILD_SYSTEM)/no_java_path):$(ANDROID_BUILD_PATHS)
-export PATH:=$(abspath $(BUILD_SYSTEM)/no_java_path):$(PATH)
+# Add BUILD_NUMBER to apps default version name if it's unbundled build.
+ifdef TARGET_BUILD_APPS
+TARGET_BUILD_WITH_APPS_VERSION_NAME := true
endif
-# Projects clean of compiler warnings should be compiled with -Werror.
-# If most modules in a directory such as external/ have warnings,
-# the directory should be in ANDROID_WARNING_ALLOWED_PROJECTS list.
-# When some of its subdirectories are cleaned up, the subdirectories
-# can be added into ANDROID_WARNING_DISALLOWED_PROJECTS list, e.g.
-# external/fio/.
-ANDROID_WARNING_DISALLOWED_PROJECTS := \
- art/% \
- bionic/% \
- external/fio/% \
- hardware/interfaces/% \
+ifdef TARGET_BUILD_WITH_APPS_VERSION_NAME
+APPS_DEFAULT_VERSION_NAME := $(PLATFORM_VERSION)-$(BUILD_NUMBER_FROM_FILE)
+else
+APPS_DEFAULT_VERSION_NAME := $(PLATFORM_VERSION)
+endif
-define find_warning_disallowed_projects
- $(filter $(ANDROID_WARNING_DISALLOWED_PROJECTS),$(1)/)
-endef
-
-# Projects with compiler warnings are compiled without -Werror.
-ANDROID_WARNING_ALLOWED_PROJECTS := \
- bootable/% \
- cts/% \
- dalvik/% \
- development/% \
- device/% \
- external/% \
- frameworks/% \
- hardware/% \
- packages/% \
- system/% \
- test/vts/% \
- tools/adt/idea/android/ultimate/get_modification_time/jni/% \
- vendor/% \
-
+# ANDROID_WARNING_ALLOWED_PROJECTS is generated by build/soong.
define find_warning_allowed_projects
$(filter $(ANDROID_WARNING_ALLOWED_PROJECTS),$(1)/)
endef
@@ -946,6 +1072,7 @@
cacheimage-nodeps \
bptimage-nodeps \
vnod vendorimage-nodeps \
+ pnod productimage-nodeps \
systemotherimage-nodeps \
ramdisk-nodeps \
bootimage-nodeps \
@@ -953,7 +1080,7 @@
vbmetaimage-nodeps \
product-graph dump-products
-ifndef KATI
+ifeq ($(CALLED_FROM_SETUP),true)
include $(BUILD_SYSTEM)/ninja_config.mk
include $(BUILD_SYSTEM)/soong_config.mk
endif
diff --git a/core/config_sanitizers.mk b/core/config_sanitizers.mk
index 0d182e9..d570ccd 100644
--- a/core/config_sanitizers.mk
+++ b/core/config_sanitizers.mk
@@ -22,6 +22,30 @@
endif
endif
+# Disable global integer_overflow in excluded paths.
+ifneq ($(filter integer_overflow, $(my_global_sanitize)),)
+ combined_exclude_paths := $(INTEGER_OVERFLOW_EXCLUDE_PATHS) \
+ $(PRODUCT_INTEGER_OVERFLOW_EXCLUDE_PATHS)
+
+ ifneq ($(strip $(foreach dir,$(subst $(comma),$(space),$(combined_exclude_paths)),\
+ $(filter $(dir)%,$(LOCAL_PATH)))),)
+ my_global_sanitize := $(filter-out integer_overflow,$(my_global_sanitize))
+ my_global_sanitize_diag := $(filter-out integer_overflow,$(my_global_sanitize_diag))
+ endif
+endif
+
+# Disable global CFI in excluded paths
+ifneq ($(filter cfi, $(my_global_sanitize)),)
+ combined_exclude_paths := $(CFI_EXCLUDE_PATHS) \
+ $(PRODUCT_CFI_EXCLUDE_PATHS)
+
+ ifneq ($(strip $(foreach dir,$(subst $(comma),$(space),$(combined_exclude_paths)),\
+ $(filter $(dir)%,$(LOCAL_PATH)))),)
+ my_global_sanitize := $(filter-out cfi,$(my_global_sanitize))
+ my_global_sanitize_diag := $(filter-out cfi,$(my_global_sanitize_diag))
+ endif
+endif
+
ifneq ($(my_global_sanitize),)
my_sanitize := $(my_global_sanitize) $(my_sanitize)
endif
@@ -72,6 +96,20 @@
my_sanitize_diag :=
endif
+# Enable CFI in included paths (for Arm64 only).
+ifeq ($(filter cfi, $(my_sanitize)),)
+ ifneq ($(filter arm64,$(TARGET_$(LOCAL_2ND_ARCH_VAR_PREFIX)ARCH)),)
+ combined_include_paths := $(CFI_INCLUDE_PATHS) \
+ $(PRODUCT_CFI_INCLUDE_PATHS)
+
+ ifneq ($(strip $(foreach dir,$(subst $(comma),$(space),$(combined_include_paths)),\
+ $(filter $(dir)%,$(LOCAL_PATH)))),)
+ my_sanitize := cfi $(my_sanitize)
+ my_sanitize_diag := cfi $(my_sanitize_diag)
+ endif
+ endif
+endif
+
# If CFI is disabled globally, remove it from my_sanitize.
ifeq ($(strip $(ENABLE_CFI)),false)
my_sanitize := $(filter-out cfi,$(my_sanitize))
@@ -96,6 +134,12 @@
my_sanitize_diag := $(filter-out cfi,$(my_sanitize_diag))
endif
+# Disable CFI for host targets
+ifdef LOCAL_IS_HOST_MODULE
+ my_sanitize := $(filter-out cfi,$(my_sanitize))
+ my_sanitize_diag := $(filter-out cfi,$(my_sanitize_diag))
+endif
+
# Support for local sanitize blacklist paths.
ifneq ($(my_sanitize)$(my_global_sanitize),)
ifneq ($(LOCAL_SANITIZE_BLACKLIST),)
@@ -103,17 +147,8 @@
endif
endif
+# Disable integer_overflow if LOCAL_NOSANITIZE=integer.
ifneq ($(filter integer_overflow, $(my_global_sanitize) $(my_sanitize)),)
- # Disable integer_overflow in excluded paths.
- combined_exclude_paths := $(INTEGER_OVERFLOW_EXCLUDE_PATHS) \
- $(PRODUCT_INTEGER_OVERFLOW_EXCLUDE_PATHS)
-
- ifneq ($(strip $(foreach dir,$(subst $(comma),$(space),$(combined_exclude_paths)),\
- $(filter $(dir)%,$(LOCAL_PATH)))),)
- my_sanitize := $(filter-out integer_overflow,$(my_sanitize))
- my_sanitize_diag := $(filter-out integer_overflow,$(my_sanitize_diag))
- endif
- # Disable integer_overflow if LOCAL_NOSANITIZE=integer.
ifneq ($(filter integer, $(strip $(LOCAL_NOSANITIZE))),)
my_sanitize := $(filter-out integer_overflow,$(my_sanitize))
my_sanitize_diag := $(filter-out integer_overflow,$(my_sanitize_diag))
@@ -134,6 +169,8 @@
else
$(error $(LOCAL_PATH): $(LOCAL_MODULE): TSAN cannot be used for 32-bit modules.)
endif
+ else
+ my_shared_libraries += $(TSAN_RUNTIME_LIBRARY)
endif
endif
@@ -172,7 +209,7 @@
ifeq ($(filter address,$(my_sanitize)),)
$(error $(LOCAL_PATH): $(LOCAL_MODULE): Use of 'coverage' also requires 'address')
endif
- my_cflags += -fsanitize-coverage=trace-pc-guard
+ my_cflags += -fsanitize-coverage=trace-pc-guard,indirect-calls,trace-cmp
my_sanitize := $(filter-out coverage,$(my_sanitize))
endif
@@ -182,19 +219,17 @@
# Respect LOCAL_NOSANITIZE for integer-overflow flags.
ifeq ($(filter signed-integer-overflow, $(strip $(LOCAL_NOSANITIZE))),)
- my_cflags += -fsanitize=signed-integer-overflow
+ my_sanitize += signed-integer-overflow
endif
ifeq ($(filter unsigned-integer-overflow, $(strip $(LOCAL_NOSANITIZE))),)
- my_cflags += -fsanitize=unsigned-integer-overflow
+ my_sanitize += unsigned-integer-overflow
endif
- my_cflags += -fsanitize-trap=all
- my_cflags += -ftrap-function=abort
my_cflags += $(INTEGER_OVERFLOW_EXTRA_CFLAGS)
# Check for diagnostics mode (on by default).
ifneq ($(filter integer_overflow,$(my_sanitize_diag)),)
- my_cflags += -fno-sanitize-trap=signed-integer-overflow,unsigned-integer-overflow
- my_shared_libraries := $($(LOCAL_2ND_ARCH_VAR_PREFIX)UBSAN_RUNTIME_LIBRARY) $(my_shared_libraries)
+ my_sanitize_diag += signed-integer-overflow
+ my_sanitize_diag += unsigned-integer-overflow
endif
endif
endif
@@ -214,7 +249,6 @@
ifdef LOCAL_IS_HOST_MODULE
my_cflags += -fno-sanitize-recover=all
my_ldflags += -fsanitize=$(fsanitize_arg)
- my_ldlibs += -lrt -ldl
else
my_cflags += -fsanitize-trap=all
my_cflags += -ftrap-function=abort
@@ -231,12 +265,21 @@
# entire module.
LOCAL_ARM_MODE := thumb
my_cflags += $(CFI_EXTRA_CFLAGS)
+ # Only append the default visibility flag if -fvisibility has not already been
+ # set to hidden.
+ ifeq ($(filter -fvisibility=hidden,$(LOCAL_CFLAGS)),)
+ my_cflags += -fvisibility=default
+ endif
my_ldflags += $(CFI_EXTRA_LDFLAGS)
my_arflags += --plugin $(LLVM_PREBUILTS_PATH)/../lib64/LLVMgold.so
- # Workaround for b/33678192. CFI jumptables need Thumb2 codegen. Revert when
- # Clang is updated past r290384.
- ifneq ($(filter arm,$(TARGET_$(LOCAL_2ND_ARCH_VAR_PREFIX)ARCH)),)
- my_ldflags += -march=armv7-a
+
+ ifeq ($(LOCAL_FORCE_STATIC_EXECUTABLE),true)
+ my_ldflags := $(filter-out -fsanitize-cfi-cross-dso,$(my_ldflags))
+ my_cflags := $(filter-out -fsanitize-cfi-cross-dso,$(my_cflags))
+ else
+ # Apply the version script to non-static executables
+ my_ldflags += -Wl,--version-script,build/soong/cc/config/cfi_exports.map
+ LOCAL_ADDITIONAL_DEPENDENCIES += build/soong/cc/config/cfi_exports.map
endif
endif
@@ -246,7 +289,6 @@
ifdef LOCAL_IS_HOST_MODULE
# -nodefaultlibs (provided with libc++) prevents the driver from linking
# libraries needed with -fsanitize=address. http://b/18650275 (WAI)
- my_ldlibs += -lm -lpthread
my_ldflags += -Wl,--no-as-needed
else
# Add asan libraries unless LOCAL_MODULE is the asan library.
@@ -284,9 +326,25 @@
endif
endif
-ifneq ($(filter undefined,$(my_sanitize)),)
- ifndef LOCAL_IS_HOST_MODULE
- $(error ubsan is not yet supported on the target)
+# 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),)
+ # Pre-emptively add UBSAN minimal runtime incase a static library dependency requires it
+ ifeq ($(filter STATIC_LIBRARIES,$(LOCAL_MODULE_CLASS)),)
+ ifndef LOCAL_SDK_VERSION
+ my_static_libraries += $($(LOCAL_2ND_ARCH_VAR_PREFIX)UBSAN_MINIMAL_RUNTIME_LIBRARY)
+ my_ldflags += -Wl,--exclude-libs,$($(LOCAL_2ND_ARCH_VAR_PREFIX)UBSAN_MINIMAL_RUNTIME_LIBRARY).a
+ endif
+ endif
+ ifneq ($(filter unsigned-integer-overflow signed-integer-overflow integer,$(my_sanitize)),)
+ ifeq ($(filter unsigned-integer-overflow signed-integer overflow integer,$(my_sanitize_diag)),)
+ ifeq ($(filter cfi,$(my_sanitize_diag)),)
+ ifeq ($(filter address,$(my_sanitize)),)
+ my_cflags += -fsanitize-minimal-runtime
+ my_cflags += -fno-sanitize-trap=integer
+ my_cflags += -fno-sanitize-recover=integer
+ endif
+ endif
+ endif
endif
endif
@@ -296,11 +354,16 @@
endif
ifneq ($(my_sanitize_diag),)
- notrap_arg := $(subst $(space),$(comma),$(my_sanitize_diag)),
- my_cflags += -fno-sanitize-trap=$(notrap_arg)
- # Diagnostic requires a runtime library, unless ASan or TSan are also enabled.
- ifeq ($(filter address thread,$(my_sanitize)),)
- # Does not have to be the first DT_NEEDED unlike ASan.
- my_shared_libraries += $($(LOCAL_2ND_ARCH_VAR_PREFIX)UBSAN_RUNTIME_LIBRARY)
+ # TODO(vishwath): Add diagnostic support for static executables once
+ # we switch to clang-4393122 (which adds the static ubsan runtime
+ # that this depends on)
+ ifneq ($(LOCAL_FORCE_STATIC_EXECUTABLE),true)
+ notrap_arg := $(subst $(space),$(comma),$(my_sanitize_diag)),
+ my_cflags += -fno-sanitize-trap=$(notrap_arg)
+ # Diagnostic requires a runtime library, unless ASan or TSan are also enabled.
+ ifeq ($(filter address thread,$(my_sanitize)),)
+ # Does not have to be the first DT_NEEDED unlike ASan.
+ my_shared_libraries += $($(LOCAL_2ND_ARCH_VAR_PREFIX)UBSAN_RUNTIME_LIBRARY)
+ endif
endif
endif
diff --git a/core/configure_local_jack.mk b/core/configure_local_jack.mk
deleted file mode 100644
index f8049a3..0000000
--- a/core/configure_local_jack.mk
+++ /dev/null
@@ -1,44 +0,0 @@
-#
-# 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.
-#
-
-ifdef ANDROID_FORCE_JACK_ENABLED
-LOCAL_JACK_ENABLED := $(ANDROID_FORCE_JACK_ENABLED)
-endif
-
-ifneq ($(ANDROID_COMPILE_WITH_JACK),true)
-LOCAL_JACK_ENABLED :=
-endif
-
-LOCAL_JACK_ENABLED := $(strip $(LOCAL_JACK_ENABLED))
-LOCAL_MODULE := $(strip $(LOCAL_MODULE))
-
-valid_jack_enabled_values := full incremental javac_frontend disabled
-
-ifdef LOCAL_JACK_ENABLED
- ifneq ($(LOCAL_JACK_ENABLED),$(filter $(firstword $(LOCAL_JACK_ENABLED)),$(valid_jack_enabled_values)))
- $(error $(LOCAL_PATH): invalid LOCAL_JACK_ENABLED "$(LOCAL_JACK_ENABLED)" for $(LOCAL_MODULE))
- endif
-
- ifeq ($(LOCAL_JACK_ENABLED),disabled)
- LOCAL_JACK_ENABLED :=
- endif
-endif
-
-ifdef $(LOCAL_MODULE).JACK_VERSION
-LOCAL_JACK_VERSION := $($(LOCAL_MODULE).JACK_VERSION)
-else
-LOCAL_JACK_VERSION := $(JACK_DEFAULT_VERSION)
-endif
diff --git a/core/construct_context.sh b/core/construct_context.sh
new file mode 100755
index 0000000..b4ae519
--- /dev/null
+++ b/core/construct_context.sh
@@ -0,0 +1,54 @@
+#!/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
+
+# inputs:
+# $1 is PRIVATE_CONDITIONAL_USES_LIBRARIES_HOST
+# $2 is PRIVATE_CONDITIONAL_USES_LIBRARIES_TARGET
+
+# class_loader_context: library paths on the host
+# stored_class_loader_context_libs: library paths on device
+# these are both comma separated paths, example: lib1.jar:lib2.jar or /system/framework/lib1.jar:/system/framework/lib2.jar
+
+# target_sdk_version: parsed from manifest
+# my_conditional_host_libs: libraries conditionally added for non P
+# my_conditional_target_libs: target libraries conditionally added for non P
+#
+# outputs
+# class_loader_context_arg: final class loader conext arg
+# stored_class_loader_context_arg: final stored class loader context arg
+
+my_conditional_host_libs=$1
+my_conditional_target_libs=$2
+
+# Note that SDK 28 is P.
+if [[ "${target_sdk_version}" -lt "28" ]]; then
+ if [[ -z "${class_loader_context}" ]]; then
+ export class_loader_context="${my_conditional_host_libs}"
+ else
+ export class_loader_context="${my_conditional_host_libs}:${class_loader_context}"
+ fi
+ if [[ -z "${stored_class_loader_context_libs}" ]]; then
+ export stored_class_loader_context_libs="${my_conditional_target_libs}";
+ else
+ export stored_class_loader_context_libs="${my_conditional_target_libs}:${stored_class_loader_context_libs}";
+ fi
+fi
+
+# 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_libs}]"
diff --git a/core/cxx_stl_setup.mk b/core/cxx_stl_setup.mk
index 0baec26..5171b8a 100644
--- a/core/cxx_stl_setup.mk
+++ b/core/cxx_stl_setup.mk
@@ -74,6 +74,16 @@
ifneq ($(filter $(my_cxx_stl),libc++ libc++_static),)
my_cflags += -D_USING_LIBCXX
+ ifeq ($($(my_prefix)OS),darwin)
+ # libc++'s headers are annotated with availability macros that indicate
+ # which version of Mac OS was the first to ship with a libc++ feature
+ # available in its *system's* libc++.dylib. We do not use the system's
+ # library, but rather ship our own. As such, these availability
+ # attributes are meaningless for us but cause build breaks when we try
+ # to use code that would not be available in the system's dylib.
+ my_cppflags += -D_LIBCPP_DISABLE_AVAILABILITY
+ endif
+
# Note that the structure of this means that LOCAL_CXX_STL := libc++ will
# use the static libc++ for static executables.
ifeq ($(my_link_type),dynamic)
@@ -89,7 +99,6 @@
ifdef LOCAL_IS_HOST_MODULE
my_cppflags += -nostdinc++
my_ldflags += -nodefaultlibs
- my_ldlibs += -lpthread -lm
my_cxx_ldlibs += $($($(my_prefix)OS)_$(my_link_type)_gcclibs)
else
ifeq (arm,$($(my_prefix)$(LOCAL_2ND_ARCH_VAR_PREFIX)ARCH))
diff --git a/core/definitions.mk b/core/definitions.mk
index 95e9a02..599ab49 100644
--- a/core/definitions.mk
+++ b/core/definitions.mk
@@ -167,7 +167,7 @@
# $(1): directory to search under
# Ignores $(1)/Android.mk
define first-makefiles-under
-$(shell build/tools/findleaves.py $(FIND_LEAVES_EXCLUDES) \
+$(shell build/make/tools/findleaves.py $(FIND_LEAVES_EXCLUDES) \
--mindepth=2 $(addprefix --dir=,$(1)) Android.mk)
endef
@@ -671,27 +671,28 @@
## $(2): Non-empty if IS_HOST_MODULE
###########################################################
-# $(1): library name
-# $(2): Non-empty if IS_HOST_MODULE
-define _java-lib-dir
-$(call intermediates-dir-for, \
- JAVA_LIBRARIES,$(1),$(2),COMMON)
-endef
-
-# $(1): library name
-# $(2): Non-empty if IS_HOST_MODULE
-define _java-lib-full-classes.jar
-$(call _java-lib-dir,$(1),$(2))/classes.jar
-endef
-
# Get the jar files (you can pass to "javac -classpath") of static or shared
# Java libraries that you want to link against.
# $(1): library name list
# $(2): Non-empty if IS_HOST_MODULE
define java-lib-files
-$(foreach lib,$(1),$(call _java-lib-full-classes.jar,$(lib),$(2)))
+$(foreach lib,$(1),$(call intermediates-dir-for,JAVA_LIBRARIES,$(lib),$(2),COMMON)/classes.jar)
endef
+# Get the header jar files (you can pass to "javac -classpath") of static or shared
+# Java libraries that you want to link against.
+# $(1): library name list
+# $(2): Non-empty if IS_HOST_MODULE
+ifneq ($(TURBINE_ENABLED),false)
+define java-lib-header-files
+$(foreach lib,$(1),$(call intermediates-dir-for,JAVA_LIBRARIES,$(lib),$(2),COMMON)/classes-header.jar)
+endef
+else
+define java-lib-header-files
+$(call java-lib-files,$(1),$(2))
+endef
+endif
+
# Get the dependency files (you can put on the right side of "|" of a build rule)
# of the Java libraries.
# $(1): library name list
@@ -704,25 +705,26 @@
$(call java-lib-files,$(1),$(2))
endef
-
-###########################################################
-## Convert "core ext framework" to "out/.../classes.jack ..."
-## $(1): library list
-## $(2): Non-empty if IS_HOST_MODULE
-###########################################################
-
-# $(1): library name
-# $(2): Non-empty if IS_HOST_MODULE
-define _jack-lib-full-classes
-$(call _java-lib-dir,$(1),$(2))/classes.jack
-endef
-
+# Get the jar files (you can pass to "javac -classpath") of static or shared
+# APK libraries that you want to link against.
# $(1): library name list
-# $(2): Non-empty if IS_HOST_MODULE
-define jack-lib-files
-$(foreach lib,$(1),$(call _jack-lib-full-classes,$(lib),$(2)))
+define app-lib-files
+$(foreach lib,$(1),$(call intermediates-dir-for,APPS,$(lib),,COMMON)/classes.jar)
endef
+# Get the header jar files (you can pass to "javac -classpath") of static or shared
+# APK libraries that you want to link against.
+# $(1): library name list
+ifneq ($(TURBINE_ENABLED),false)
+define app-lib-header-files
+$(foreach lib,$(1),$(call intermediates-dir-for,APPS,$(lib),,COMMON)/classes-header.jar)
+endef
+else
+define app-lib-header-files
+$(call app-lib-files,$(1))
+endef
+endif
+
###########################################################
## Returns true if $(1) and $(2) are equal. Returns
## the empty string if they are not equal.
@@ -1034,9 +1036,9 @@
$(PRIVATE_RS_FLAGS) \
$(foreach inc,$(PRIVATE_RS_INCLUDES),$(addprefix -I , $(inc))) \
$(PRIVATE_RS_SOURCE_FILES)
+$(SOONG_ZIP) -o $@ -C $(PRIVATE_RS_OUTPUT_DIR)/src -D $(PRIVATE_RS_OUTPUT_DIR)/src
+$(SOONG_ZIP) -o $(PRIVATE_RS_OUTPUT_RES_ZIP) -C $(PRIVATE_RS_OUTPUT_DIR)/res -D $(PRIVATE_RS_OUTPUT_DIR)/res
$(call _merge-renderscript-d,$(PRIVATE_DEP_FILES),$@.d)
-$(hide) mkdir -p $(dir $@)
-$(hide) touch $@
endef
define transform-bc-to-so
@@ -1048,8 +1050,9 @@
-Wl,-rpath,\$$ORIGIN/../lib \
$(dir $@)/$(notdir $(<:.bc=.o)) \
$(RS_PREBUILT_COMPILER_RT) \
- -o $@ $(TARGET_GLOBAL_LDFLAGS) -Wl,--hash-style=sysv -L prebuilts/gcc/ \
- $(RS_PREBUILT_LIBPATH) \
+ -o $@ $(TARGET_GLOBAL_LDFLAGS) -Wl,--hash-style=sysv \
+ -L $(SOONG_OUT_DIR)/ndk/platforms/android-$(PRIVATE_SDK_VERSION)/arch-$(TARGET_ARCH)/usr/lib64 \
+ -L $(SOONG_OUT_DIR)/ndk/platforms/android-$(PRIVATE_SDK_VERSION)/arch-$(TARGET_ARCH)/usr/lib \
$(call intermediates-dir-for,SHARED_LIBRARIES,libRSSupport)/libRSSupport.so \
-lm -lc
endef
@@ -1553,7 +1556,7 @@
filelist="$$filelist $$ldir/$$ext$$f"; \
done ; \
$($(PRIVATE_2ND_ARCH_VAR_PREFIX)TARGET_AR) $($(PRIVATE_2ND_ARCH_VAR_PREFIX)TARGET_GLOBAL_ARFLAGS) \
- $(2) $$filelist
+ $(PRIVATE_ARFLAGS) $(2) $$filelist
endef
@@ -1720,6 +1723,10 @@
$(if $(PRIVATE_ALL_OBJECTS),,$(hide) $($(PRIVATE_2ND_ARCH_VAR_PREFIX)$(PRIVATE_PREFIX)AR) d $(1) $(dir $(1))dummy.o \
&& rm -f $(dir $(1))dummy.o)
endef
+else
+create-dummy.o-if-no-objs =
+get-dummy.o-if-no-objs =
+delete-dummy.o-if-no-objs =
endif # HOST_OS is darwin
# Explicitly delete the archive first so that ar doesn't
@@ -1842,6 +1849,7 @@
$(PRIVATE_NM) -D $< --format=posix --defined-only | awk '{ print $$1 }' | sort >$@.dynsyms && \
$(PRIVATE_NM) $< --format=posix --defined-only | awk '{ if ($$2 == "T" || $$2 == "t" || $$2 == "D") print $$1 }' | sort >$@.funcsyms && \
comm -13 $@.dynsyms $@.funcsyms >$@.keep_symbols && \
+ echo >>$@.keep_symbols && \
$(PRIVATE_OBJCOPY) --rename-section .debug_frame=saved_debug_frame $@.debug $@.mini_debuginfo && \
$(PRIVATE_OBJCOPY) -S --remove-section .gdb_index --remove-section .comment --keep-symbols=$@.keep_symbols $@.mini_debuginfo && \
$(PRIVATE_OBJCOPY) --rename-section saved_debug_frame=.debug_frame $@.mini_debuginfo && \
@@ -1999,17 +2007,6 @@
## Commands for running javac to make .class files
###########################################################
-# Add BUILD_NUMBER to apps default version name if it's unbundled build.
-ifdef TARGET_BUILD_APPS
-TARGET_BUILD_WITH_APPS_VERSION_NAME := true
-endif
-
-ifdef TARGET_BUILD_WITH_APPS_VERSION_NAME
-APPS_DEFAULT_VERSION_NAME := $(PLATFORM_VERSION)-$(BUILD_NUMBER_FROM_FILE)
-else
-APPS_DEFAULT_VERSION_NAME := $(PLATFORM_VERSION)
-endif
-
# b/37750224
AAPT_ASAN_OPTIONS := ASAN_OPTIONS=detect_leaks=0
@@ -2025,11 +2022,12 @@
# This rule creates the R.java and Manifest.java files, both of which
# are PRODUCT-neutral. Don't pass PRIVATE_PRODUCT_AAPT_CONFIG to this invocation.
define create-resource-java-files
-@mkdir -p $(PRIVATE_SOURCE_INTERMEDIATES_DIR)
@mkdir -p $(dir $(PRIVATE_RESOURCE_PUBLICS_OUTPUT))
+rm -rf $(PRIVATE_JAVA_GEN_DIR)
+mkdir -p $(PRIVATE_JAVA_GEN_DIR)
$(hide) $(AAPT_ASAN_OPTIONS) $(AAPT) package $(PRIVATE_AAPT_FLAGS) -m \
$(eval # PRIVATE_PRODUCT_AAPT_CONFIG is intentionally missing-- see comment.) \
- $(addprefix -J , $(PRIVATE_SOURCE_INTERMEDIATES_DIR)) \
+ $(addprefix -J , $(PRIVATE_JAVA_GEN_DIR)) \
$(addprefix -M , $(PRIVATE_ANDROID_MANIFEST)) \
$(addprefix -P , $(PRIVATE_RESOURCE_PUBLICS_OUTPUT)) \
$(addprefix -S , $(PRIVATE_RESOURCE_DIR)) \
@@ -2043,28 +2041,31 @@
$(addprefix --rename-manifest-package , $(PRIVATE_MANIFEST_PACKAGE_NAME)) \
$(addprefix --rename-instrumentation-target-package , $(PRIVATE_MANIFEST_INSTRUMENTATION_FOR)) \
--skip-symbols-without-default-localization
+$(SOONG_ZIP) -o $(PRIVATE_SRCJAR) -C $(PRIVATE_JAVA_GEN_DIR) -D $(PRIVATE_JAVA_GEN_DIR)
+# So that we re-run aapt when the list of input files change
+$(hide) echo $(PRIVATE_RESOURCE_LIST) >/dev/null
endef
-# Search for generated R.java/Manifest.java, copy the found R.java as $@.
+# Search for generated R.java/Manifest.java in $1, copy the found R.java as $2.
# Also copy them to a central 'R' directory to make it easier to add the files to an IDE.
define find-generated-R.java
-$(hide) for GENERATED_MANIFEST_FILE in `find $(PRIVATE_SOURCE_INTERMEDIATES_DIR) \
+$(hide) for GENERATED_MANIFEST_FILE in `find $(1) \
-name Manifest.java 2> /dev/null`; do \
dir=`awk '/package/{gsub(/\./,"/",$$2);gsub(/;/,"",$$2);print $$2;exit}' $$GENERATED_MANIFEST_FILE`; \
mkdir -p $(TARGET_COMMON_OUT_ROOT)/R/$$dir; \
$(ACP) -fp $$GENERATED_MANIFEST_FILE $(TARGET_COMMON_OUT_ROOT)/R/$$dir; \
done;
-$(hide) for GENERATED_R_FILE in `find $(PRIVATE_SOURCE_INTERMEDIATES_DIR) \
+$(hide) for GENERATED_R_FILE in `find $(1) \
-name R.java 2> /dev/null`; do \
dir=`awk '/package/{gsub(/\./,"/",$$2);gsub(/;/,"",$$2);print $$2;exit}' $$GENERATED_R_FILE`; \
mkdir -p $(TARGET_COMMON_OUT_ROOT)/R/$$dir; \
$(ACP) -fp $$GENERATED_R_FILE $(TARGET_COMMON_OUT_ROOT)/R/$$dir \
|| exit 31; \
- $(ACP) -fp $$GENERATED_R_FILE $@ || exit 32; \
+ $(ACP) -fp $$GENERATED_R_FILE $(2) || exit 32; \
done;
@# Ensure that the target file is always created, i.e. also in case we did not
@# enter the GENERATED_R_FILE-loop above. This avoids unnecessary rebuilding.
-$(hide) touch $@
+$(hide) touch $(2)
endef
###########################################################
@@ -2081,6 +2082,13 @@
$(PRIVATE_AAPT2_CFLAGS) --legacy
endef
+# TODO(b/74574557): use aapt2 compile --zip if it gets implemented
+define aapt2-compile-resource-zips
+@mkdir -p $(dir $@)
+$(ZIPSYNC) -d $@.contents -l $@.list $(PRIVATE_SOURCE_RES_ZIPS)
+$(hide) $(AAPT2) compile -o $@ --dir $@.contents $(PRIVATE_AAPT2_CFLAGS) --legacy
+endef
+
# Set up rule to compile one resource file with aapt2.
# Must be called with $(eval).
# $(1): the source file
@@ -2105,15 +2113,18 @@
define aapt2-link
@mkdir -p $(dir $@)
+rm -rf $(PRIVATE_JAVA_GEN_DIR)
+mkdir -p $(PRIVATE_JAVA_GEN_DIR)
$(call dump-words-to-file,$(PRIVATE_RES_FLAT),$(dir $@)aapt2-flat-list)
$(call dump-words-to-file,$(PRIVATE_OVERLAY_FLAT),$(dir $@)aapt2-flat-overlay-list)
$(hide) $(AAPT2) link -o $@ \
$(PRIVATE_AAPT_FLAGS) \
+ $(if $(PRIVATE_STATIC_LIBRARY_EXTRA_PACKAGES),$$(cat $(PRIVATE_STATIC_LIBRARY_EXTRA_PACKAGES))) \
$(addprefix --manifest ,$(PRIVATE_ANDROID_MANIFEST)) \
$(addprefix -I ,$(PRIVATE_AAPT_INCLUDES)) \
$(addprefix -I ,$(PRIVATE_SHARED_ANDROID_LIBRARIES)) \
$(addprefix -A ,$(PRIVATE_ASSET_DIR)) \
- $(addprefix --java ,$(PRIVATE_SOURCE_INTERMEDIATES_DIR)) \
+ $(addprefix --java ,$(PRIVATE_JAVA_GEN_DIR)) \
$(addprefix --proguard ,$(PRIVATE_PROGUARD_OPTIONS_FILE)) \
$(addprefix --min-sdk-version ,$(PRIVATE_DEFAULT_APP_TARGET_SDK)) \
$(addprefix --target-sdk-version ,$(PRIVATE_DEFAULT_APP_TARGET_SDK)) \
@@ -2126,6 +2137,8 @@
$(addprefix --rename-instrumentation-target-package ,$(PRIVATE_MANIFEST_INSTRUMENTATION_FOR)) \
-R \@$(dir $@)aapt2-flat-overlay-list \
\@$(dir $@)aapt2-flat-list
+$(SOONG_ZIP) -o $(PRIVATE_SRCJAR) -C $(PRIVATE_JAVA_GEN_DIR) -D $(PRIVATE_JAVA_GEN_DIR)
+$(EXTRACT_JAR_PACKAGES) -i $(PRIVATE_SRCJAR) -o $(PRIVATE_AAPT_EXTRA_PACKAGES) --prefix '--extra-packages '
endef
###########################################################
@@ -2184,58 +2197,79 @@
exit 1; \
fi; \
unzip -qo $$f -d $(2); \
+ rm -f $(2)/module-info.class; \
done
$(if $(PRIVATE_DONT_DELETE_JAR_META_INF),,$(hide) rm -rf $(2)/META-INF)
endef
-# Call jack
+# Return jar arguments to compress files in a given directory
+# $(1): directory
#
-define call-jack
- JACK_VERSION=$(PRIVATE_JACK_VERSION) $(JACK) $(DEFAULT_JACK_EXTRA_ARGS)
+# Returns an @-file argument that contains the output of a subshell
+# that looks like -C $(1) path/to/file1 -C $(1) path/to/file2
+# Also adds "-C out/empty ." which avoids errors in jar when
+# there are no files in the directory.
+define jar-args-sorted-files-in-directory
+ @<(find $(1) -type f | sort | $(JAR_ARGS) $(1); echo "-C $(EMPTY_DIRECTORY) .")
endef
-# Common definition to invoke javac on the host and target.
-#
+# append additional Java sources(resources/Proto sources, and etc) to $(1).
+define fetch-additional-java-source
+$(hide) if [ -d "$(PRIVATE_SOURCE_INTERMEDIATES_DIR)" ]; then \
+ find $(PRIVATE_SOURCE_INTERMEDIATES_DIR) -name '*.java' -and -not -name '.*' >> $(1); \
+fi
+$(if $(PRIVATE_HAS_PROTO_SOURCES), \
+ $(hide) find $(PRIVATE_PROTO_SOURCE_INTERMEDIATES_DIR) -name '*.java' -and -not -name '.*' >> $(1))
+endef
+
# Some historical notes:
# - below we write the list of java files to java-source-list to avoid argument
# list length problems with Cygwin
# - we filter out duplicate java file names because eclipse's compiler
# doesn't like them.
+define write-java-source-list
+@echo "$($(PRIVATE_PREFIX)DISPLAY) Java source list: $(PRIVATE_MODULE)"
+$(hide) rm -f $@
+$(call dump-words-to-file,$(sort $(PRIVATE_JAVA_SOURCES)),$@.tmp)
+$(call fetch-additional-java-source,$@.tmp)
+$(hide) tr ' ' '\n' < $@.tmp | $(NORMALIZE_PATH) | sort -u > $@
+endef
+
+# Common definition to invoke javac on the host and target.
#
# $(1): javac
-# $(2): bootclasspath
+# $(2): classpath_libs
define compile-java
$(hide) rm -f $@
$(hide) rm -rf $(PRIVATE_CLASS_INTERMEDIATES_DIR) $(PRIVATE_ANNO_INTERMEDIATES_DIR)
$(hide) mkdir -p $(dir $@)
$(hide) mkdir -p $(PRIVATE_CLASS_INTERMEDIATES_DIR) $(PRIVATE_ANNO_INTERMEDIATES_DIR)
-$(call unzip-jar-files,$(PRIVATE_STATIC_JAVA_LIBRARIES),$(PRIVATE_CLASS_INTERMEDIATES_DIR))
-$(call dump-words-to-file,$(PRIVATE_JAVA_SOURCES),$(PRIVATE_CLASS_INTERMEDIATES_DIR)/java-source-list)
-$(hide) if [ -d "$(PRIVATE_SOURCE_INTERMEDIATES_DIR)" ]; then \
- find $(PRIVATE_SOURCE_INTERMEDIATES_DIR) -name '*.java' -and -not -name '.*' >> $(PRIVATE_CLASS_INTERMEDIATES_DIR)/java-source-list; \
-fi
-$(if $(PRIVATE_HAS_PROTO_SOURCES), \
- $(hide) find $(PRIVATE_PROTO_SOURCE_INTERMEDIATES_DIR) -name '*.java' -and -not -name '.*' >> $(PRIVATE_CLASS_INTERMEDIATES_DIR)/java-source-list )
-$(if $(PRIVATE_HAS_RS_SOURCES), \
- $(hide) find $(PRIVATE_RS_SOURCE_INTERMEDIATES_DIR) -name '*.java' -and -not -name '.*' >> $(PRIVATE_CLASS_INTERMEDIATES_DIR)/java-source-list )
-$(hide) tr ' ' '\n' < $(PRIVATE_CLASS_INTERMEDIATES_DIR)/java-source-list \
- | $(NORMALIZE_PATH) | sort -u > $(PRIVATE_CLASS_INTERMEDIATES_DIR)/java-source-list-uniq
-$(hide) if [ -s $(PRIVATE_CLASS_INTERMEDIATES_DIR)/java-source-list-uniq ] ; then \
- $(SOONG_JAVAC_WRAPPER) $(1) -encoding UTF-8 \
+$(if $(PRIVATE_SRCJARS),\
+ $(ZIPSYNC) -d $(PRIVATE_SRCJAR_INTERMEDIATES_DIR) -l $(PRIVATE_SRCJAR_LIST_FILE) -f "*.java" $(PRIVATE_SRCJARS))
+$(hide) if [ -s $(PRIVATE_JAVA_SOURCE_LIST) $(if $(PRIVATE_SRCJARS),-o -s $(PRIVATE_SRCJAR_LIST_FILE) )] ; then \
+ $(SOONG_JAVAC_WRAPPER) $(JAVAC_WRAPPER) $(1) -encoding UTF-8 \
$(if $(findstring true,$(PRIVATE_WARNINGS_ENABLE)),$(xlint_unchecked),) \
- $(2) \
- $(addprefix -classpath ,$(strip \
- $(call normalize-path-list,$(PRIVATE_ALL_JAVA_LIBRARIES)))) \
+ $(if $(PRIVATE_USE_SYSTEM_MODULES), \
+ $(addprefix --system=,$(PRIVATE_SYSTEM_MODULES_DIR)), \
+ $(addprefix -bootclasspath ,$(strip \
+ $(call normalize-path-list,$(PRIVATE_BOOTCLASSPATH)) \
+ $(PRIVATE_EMPTY_BOOTCLASSPATH)))) \
+ $(if $(PRIVATE_USE_SYSTEM_MODULES), \
+ $(if $(PRIVATE_PATCH_MODULE), \
+ --patch-module=$(PRIVATE_PATCH_MODULE)=$(call normalize-path-list,. $(2)))) \
+ $(addprefix -classpath ,$(call normalize-path-list,$(strip \
+ $(if $(PRIVATE_USE_SYSTEM_MODULES), \
+ $(filter-out $(PRIVATE_SYSTEM_MODULES_LIBS),$(PRIVATE_BOOTCLASSPATH))) \
+ $(2)))) \
$(if $(findstring true,$(PRIVATE_WARNINGS_ENABLE)),$(xlint_unchecked),) \
- -extdirs "" -d $(PRIVATE_CLASS_INTERMEDIATES_DIR) -s $(PRIVATE_ANNO_INTERMEDIATES_DIR) \
+ -d $(PRIVATE_CLASS_INTERMEDIATES_DIR) -s $(PRIVATE_ANNO_INTERMEDIATES_DIR) \
$(PRIVATE_JAVACFLAGS) \
- \@$(PRIVATE_CLASS_INTERMEDIATES_DIR)/java-source-list-uniq \
+ \@$(PRIVATE_JAVA_SOURCE_LIST) \
+ $(if $(PRIVATE_SRCJARS),\@$(PRIVATE_SRCJAR_LIST_FILE)) \
|| ( rm -rf $(PRIVATE_CLASS_INTERMEDIATES_DIR) ; exit 41 ) \
fi
-$(if $(PRIVATE_JAVA_LAYERS_FILE), $(hide) build/tools/java-layers.py \
- $(PRIVATE_JAVA_LAYERS_FILE) \@$(PRIVATE_CLASS_INTERMEDIATES_DIR)/java-source-list-uniq,)
-$(hide) rm -f $(PRIVATE_CLASS_INTERMEDIATES_DIR)/java-source-list
-$(hide) rm -f $(PRIVATE_CLASS_INTERMEDIATES_DIR)/java-source-list-uniq
+$(if $(PRIVATE_JAVA_LAYERS_FILE), $(hide) build/make/tools/java-layers.py \
+ $(PRIVATE_JAVA_LAYERS_FILE) @$(PRIVATE_JAVA_SOURCE_LIST),)
$(if $(PRIVATE_JAR_EXCLUDE_FILES), $(hide) find $(PRIVATE_CLASS_INTERMEDIATES_DIR) \
-name $(word 1, $(PRIVATE_JAR_EXCLUDE_FILES)) \
$(addprefix -o -name , $(wordlist 2, 999, $(PRIVATE_JAR_EXCLUDE_FILES))) \
@@ -2248,153 +2282,32 @@
$(if $(PRIVATE_JAR_EXCLUDE_PACKAGES), $(hide) rm -rf \
$(foreach pkg, $(PRIVATE_JAR_EXCLUDE_PACKAGES), \
$(PRIVATE_CLASS_INTERMEDIATES_DIR)/$(subst .,/,$(pkg))))
-$(if $(PRIVATE_JAR_MANIFEST), \
- $(hide) sed -e "s/%BUILD_NUMBER%/$(BUILD_NUMBER_FROM_FILE)/" \
- $(PRIVATE_JAR_MANIFEST) > $(dir $@)/manifest.mf && \
- $(JAR) -cfm $@ $(dir $@)/manifest.mf \
- -C $(PRIVATE_CLASS_INTERMEDIATES_DIR) ., \
- $(hide) $(JAR) -cf $@ -C $(PRIVATE_CLASS_INTERMEDIATES_DIR) .)
+$(hide) $(JAR) -cf $@ $(call jar-args-sorted-files-in-directory,$(PRIVATE_CLASS_INTERMEDIATES_DIR))
$(if $(PRIVATE_EXTRA_JAR_ARGS),$(call add-java-resources-to,$@))
endef
-define transform-java-to-classes.jar
-@echo "$($(PRIVATE_PREFIX)DISPLAY) Java: $(PRIVATE_MODULE) ($(PRIVATE_CLASS_INTERMEDIATES_DIR))"
-$(call compile-java,$(TARGET_JAVAC),$(PRIVATE_BOOTCLASSPATH))
-endef
-
-# Invoke Jack to compile java from source to dex and jack files.
-#
-# Some historical notes:
-# - below we write the list of java files to java-source-list to avoid argument
-# list length problems with Cygwin
-# - we filter out duplicate java file names because Jack doesn't like them.
-define jack-java-to-dex
-$(hide) rm -f $@
-$(hide) rm -f $(PRIVATE_CLASSES_JACK)
-$(hide) rm -rf $(PRIVATE_JACK_INTERMEDIATES_DIR)
-$(hide) mkdir -p $(dir $@)
-$(hide) mkdir -p $(dir $(PRIVATE_CLASSES_JACK))
-$(hide) mkdir -p $(PRIVATE_JACK_INTERMEDIATES_DIR)
-$(if $(PRIVATE_JACK_INCREMENTAL_DIR),$(hide) mkdir -p $(PRIVATE_JACK_INCREMENTAL_DIR))
-$(call dump-words-to-file,$(PRIVATE_JAVA_SOURCES),$(PRIVATE_JACK_INTERMEDIATES_DIR)/java-source-list)
-$(if $(PRIVATE_SOURCE_INTERMEDIATES_DIR), \
- $(hide) if [ -d "$(PRIVATE_SOURCE_INTERMEDIATES_DIR)" ]; then \
- find $(PRIVATE_SOURCE_INTERMEDIATES_DIR) -name '*.java' >> $(PRIVATE_JACK_INTERMEDIATES_DIR)/java-source-list; \
- fi)
-$(if $(PRIVATE_HAS_PROTO_SOURCES), \
- $(hide) find $(PRIVATE_PROTO_SOURCE_INTERMEDIATES_DIR) -name '*.java' >> $(PRIVATE_JACK_INTERMEDIATES_DIR)/java-source-list )
-$(if $(PRIVATE_HAS_RS_SOURCES), \
- $(hide) find $(PRIVATE_RS_SOURCE_INTERMEDIATES_DIR) -name '*.java' >> $(PRIVATE_JACK_INTERMEDIATES_DIR)/java-source-list )
-$(hide) tr ' ' '\n' < $(PRIVATE_JACK_INTERMEDIATES_DIR)/java-source-list \
- | $(NORMALIZE_PATH) | sort -u > $(PRIVATE_JACK_INTERMEDIATES_DIR)/java-source-list-uniq
-$(if $(PRIVATE_JACK_PROGUARD_FLAGS), \
- $(hide) echo -basedirectory $(CURDIR) > $@.flags; \
- echo $(PRIVATE_JACK_PROGUARD_FLAGS) >> $@.flags; \
-)
-$(if $(PRIVATE_EXTRA_JAR_ARGS),
- $(hide) mkdir -p $@.res.tmp
- $(hide) $(call create-empty-package-at,$@.res.tmp.zip)
- $(hide) $(call add-java-resources-to,$@.res.tmp.zip)
- $(hide) unzip -qo $@.res.tmp.zip -d $@.res.tmp
- $(hide) rm $@.res.tmp.zip)
-$(if $(PRIVATE_JACK_IMPORT_JAR),
- $(hide) mkdir -p $@.tmpjill.res
- $(hide) unzip -qo $(PRIVATE_JACK_IMPORT_JAR) -d $@.tmpjill.res
- $(hide) find $@.tmpjill.res -iname "*.class" -delete)
-$(hide) if [ -s $(PRIVATE_JACK_INTERMEDIATES_DIR)/java-source-list-uniq ] ; then \
- export tmpEcjArg="@$(PRIVATE_JACK_INTERMEDIATES_DIR)/java-source-list-uniq"; \
-else \
- export tmpEcjArg=""; \
-fi; \
-$(call call-jack) \
- $(strip $(PRIVATE_JACK_FLAGS)) \
- $(strip $(PRIVATE_JACK_COVERAGE_OPTIONS)) \
- $(if $(NO_OPTIMIZE_DX), \
- -D jack.dex.optimize="false") \
- $(if $(PRIVATE_RMTYPEDEFS), \
- -D jack.android.remove-typedef="true") \
- $(if $(PRIVATE_JACK_IMPORT_JAR), \
- --import $(PRIVATE_JACK_IMPORT_JAR) --import-resource $@.tmpjill.res) \
+define transform-java-to-header.jar
+@echo "$($(PRIVATE_PREFIX)DISPLAY) Turbine: $(PRIVATE_MODULE)"
+@mkdir -p $(dir $@)
+@rm -rf $(dir $@)/classes-turbine
+@mkdir $(dir $@)/classes-turbine
+$(hide) if [ -s $(PRIVATE_JAVA_SOURCE_LIST) -o -n "$(PRIVATE_SRCJARS)" ] ; then \
+ $(JAVA) -jar $(TURBINE) \
+ --output $@.premerged --temp_dir $(dir $@)/classes-turbine \
+ --sources \@$(PRIVATE_JAVA_SOURCE_LIST) --source_jars $(PRIVATE_SRCJARS) \
+ --javacopts $(PRIVATE_JAVACFLAGS) $(COMMON_JDK_FLAGS) \
+ $(addprefix --bootclasspath ,$(strip \
+ $(call normalize-path-list,$(PRIVATE_BOOTCLASSPATH)) \
+ $(PRIVATE_EMPTY_BOOTCLASSPATH))) \
$(addprefix --classpath ,$(strip \
- $(call normalize-path-list,$(PRIVATE_JACK_SHARED_LIBRARIES)))) \
- $(addprefix --import ,$(call reverse-list,$(PRIVATE_STATIC_JACK_LIBRARIES))) \
- $(addprefix --pluginpath ,$(strip \
- $(call normalize-path-list,$(PRIVATE_JACK_PLUGIN_PATH)))) \
- $(if $(PRIVATE_JACK_PLUGIN),--plugin $(call normalize-comma-list,$(PRIVATE_JACK_PLUGIN))) \
- $(if $(PRIVATE_EXTRA_JAR_ARGS),--import-resource $@.res.tmp) \
- -D jack.android.min-api-level=$(PRIVATE_JACK_MIN_SDK_VERSION) \
- -D jack.import.resource.policy=keep-first \
- -D jack.import.type.policy=keep-first \
- --output-jack $(PRIVATE_CLASSES_JACK) \
- $(if $(PRIVATE_JACK_INCREMENTAL_DIR),--incremental-folder $(PRIVATE_JACK_INCREMENTAL_DIR)) \
- --output-dex $(PRIVATE_JACK_INTERMEDIATES_DIR) \
- $(addprefix --config-jarjar ,$(strip $(PRIVATE_JARJAR_RULES))) \
- $(if $(PRIVATE_JACK_PROGUARD_FLAGS),--config-proguard $@.flags) \
- $$tmpEcjArg \
- || ( rm -rf $(PRIVATE_CLASSES_JACK); exit 41 )
-$(hide) mv $(PRIVATE_JACK_INTERMEDIATES_DIR)/classes*.dex $(dir $@)
-$(hide) rm -f $(PRIVATE_JACK_INTERMEDIATES_DIR)/java-source-list
-$(if $(PRIVATE_EXTRA_JAR_ARGS),$(hide) rm -rf $@.res.tmp)
-$(hide) mv $(PRIVATE_JACK_INTERMEDIATES_DIR)/java-source-list-uniq $(PRIVATE_JACK_INTERMEDIATES_DIR).java-source-list
-$(if $(PRIVATE_JAR_PACKAGES), $(hide) echo unsupported options PRIVATE_JAR_PACKAGES in $@; exit 53)
-$(if $(PRIVATE_JAR_EXCLUDE_PACKAGES), $(hide) echo unsupported options JAR_EXCLUDE_PACKAGES in $@; exit 53)
-$(if $(PRIVATE_JAR_MANIFEST), $(hide) echo unsupported options JAR_MANIFEST in $@; exit 53)
-endef
-
-# Invoke Jack to compile java source just to check it compiles correctly.
-#
-# Some historical notes:
-# - below we write the list of java files to java-source-list to avoid argument
-# list length problems with Cygwin
-# - we filter out duplicate java file names because Jack doesn't like them.
-define jack-check-java
-$(hide) rm -f $@
-$(hide) rm -f $@.java-source-list
-$(hide) rm -f $@.java-source-list-uniq
-$(hide) mkdir -p $(dir $@)
-$(if $(PRIVATE_JACK_INCREMENTAL_DIR),$(hide) mkdir -p $(PRIVATE_JACK_INCREMENTAL_DIR))
-$(call dump-words-to-file,$(PRIVATE_JAVA_SOURCES),$@.java-source-list)
-$(hide) if [ -d "$(PRIVATE_SOURCE_INTERMEDIATES_DIR)" ]; then \
- find $(PRIVATE_SOURCE_INTERMEDIATES_DIR) -name '*.java' >> $@.java-source-list; \
+ $(call normalize-path-list,$(PRIVATE_ALL_JAVA_HEADER_LIBRARIES)))) \
+ || ( rm -rf $(dir $@)/classes-turbine ; exit 41 ) && \
+ $(MERGE_ZIPS) -j --ignore-duplicates -stripDir META-INF $@.tmp $@.premerged $(call reverse-list,$(PRIVATE_STATIC_JAVA_HEADER_LIBRARIES)) ; \
+else \
+ $(MERGE_ZIPS) -j --ignore-duplicates -stripDir META-INF $@.tmp $(call reverse-list,$(PRIVATE_STATIC_JAVA_HEADER_LIBRARIES)) ; \
fi
-$(if $(PRIVATE_HAS_PROTO_SOURCES), \
- $(hide) find $(PRIVATE_PROTO_SOURCE_INTERMEDIATES_DIR) -name '*.java' >> $@.java-source-list )
-$(if $(PRIVATE_HAS_RS_SOURCES), \
- $(hide) find $(PRIVATE_RS_SOURCE_INTERMEDIATES_DIR) -name '*.java' >> $@.java-source-list )
-$(hide) tr ' ' '\n' < $@.java-source-list \
- | sort -u > $@.java-source-list-uniq
-$(hide) if [ -s $@.java-source-list-uniq ] ; then \
- $(call call-jack,$(PRIVATE_JACK_EXTRA_ARGS)) \
- $(strip $(PRIVATE_JACK_FLAGS)) \
- $(strip $(PRIVATE_JACK_DEBUG_FLAGS)) \
- $(addprefix --classpath ,$(strip \
- $(call normalize-path-list,$(call reverse-list,$(PRIVATE_STATIC_JACK_LIBRARIES)) $(PRIVATE_JACK_SHARED_LIBRARIES)))) \
- -D jack.import.resource.policy=keep-first \
- -D jack.android.min-api-level=$(PRIVATE_JACK_MIN_SDK_VERSION) \
- -D jack.import.type.policy=keep-first \
- $(if $(PRIVATE_JACK_INCREMENTAL_DIR),--incremental-folder $(PRIVATE_JACK_INCREMENTAL_DIR)) \
- @$@.java-source-list-uniq; \
-fi
-touch $@
-endef
-
-define transform-jar-to-jack
- $(hide) mkdir -p $(dir $@)
- $(hide) mkdir -p $@.tmpjill.res
- $(hide) unzip -qo $< -d $@.tmpjill.res
- $(hide) find $@.tmpjill.res -iname "*.class" -delete
- $(hide) $(call call-jack) \
- $(PRIVATE_JACK_FLAGS) \
- $(addprefix --pluginpath ,$(strip \
- $(call normalize-path-list,$(PRIVATE_JACK_PLUGIN_PATH)))) \
- $(if $(PRIVATE_JACK_PLUGIN),--plugin $(call normalize-comma-list,$(PRIVATE_JACK_PLUGIN))) \
- -D jack.import.resource.policy=keep-first \
- -D jack.import.type.policy=keep-first \
- -D jack.android.min-api-level=$(PRIVATE_JACK_MIN_SDK_VERSION) \
- --import $< \
- --import-resource $@.tmpjill.res \
- --output-jack $@
- $(hide) rm -rf $@.tmpjill.res
+$(hide) $(ZIPTIME) $@.tmp
+$(hide) $(call commit-change-for-toc,$@)
endef
# Moves $1.tmp to $1 if necessary. This is designed to be used with
@@ -2409,26 +2322,6 @@
fi
endef
-# b/37756495
-IJAR_ASAN_OPTIONS := ASAN_OPTIONS=detect_leaks=0
-
-## Rule to create a table of contents from a .jar file.
-## Must be called with $(eval).
-# $(1): A .jar file
-define _transform-jar-to-toc
-$1.toc: $1 | $(IJAR)
- @echo Generating TOC: $$@
- $(hide) $(IJAR_ASAN_OPTIONS) $(IJAR) $$< $$@.tmp
- $$(call commit-change-for-toc,$$@)
-endef
-
-## Define a rule which generates .jar.toc and mark it as .KATI_RESTAT.
-# $(1): A .jar file
-define define-jar-to-toc-rule
-$(eval $(call _transform-jar-to-toc,$1))\
-$(eval .KATI_RESTAT: $1.toc)
-endef
-
ifeq (,$(TARGET_BUILD_APPS))
## Rule to create a table of contents from a .dex file.
@@ -2458,75 +2351,6 @@
endif # TARGET_BUILD_APPS
-# Invoke Jack to compile java from source to jack files without shrink or obfuscation.
-#
-# Some historical notes:
-# - below we write the list of java files to java-source-list to avoid argument
-# list length problems with Cygwin
-# - we filter out duplicate java file names because Jack doesn't like them.
-define java-to-jack
-$(hide) rm -f $@
-$(hide) rm -rf $(PRIVATE_JACK_INTERMEDIATES_DIR)
-$(hide) mkdir -p $(dir $@)
-$(hide) mkdir -p $(PRIVATE_JACK_INTERMEDIATES_DIR)
-$(if $(PRIVATE_JACK_INCREMENTAL_DIR),$(hide) mkdir -p $(PRIVATE_JACK_INCREMENTAL_DIR))
-$(call dump-words-to-file,$(PRIVATE_JAVA_SOURCES),$(PRIVATE_JACK_INTERMEDIATES_DIR)/java-source-list)
-$(hide) if [ -d "$(PRIVATE_SOURCE_INTERMEDIATES_DIR)" ]; then \
- find $(PRIVATE_SOURCE_INTERMEDIATES_DIR) -name '*.java' >> $(PRIVATE_JACK_INTERMEDIATES_DIR)/java-source-list; \
-fi
-$(if $(PRIVATE_HAS_PROTO_SOURCES), \
- $(hide) find $(PRIVATE_PROTO_SOURCE_INTERMEDIATES_DIR) -name '*.java' >> $(PRIVATE_JACK_INTERMEDIATES_DIR)/java-source-list )
-$(if $(PRIVATE_HAS_RS_SOURCES), \
- $(hide) find $(PRIVATE_RS_SOURCE_INTERMEDIATES_DIR) -name '*.java' >> $(PRIVATE_JACK_INTERMEDIATES_DIR)/java-source-list )
-$(hide) tr ' ' '\n' < $(PRIVATE_JACK_INTERMEDIATES_DIR)/java-source-list \
- | $(NORMALIZE_PATH) | sort -u > $(PRIVATE_JACK_INTERMEDIATES_DIR)/java-source-list-uniq
-$(if $(PRIVATE_JACK_PROGUARD_FLAGS), \
- $(hide) echo -basedirectory $(CURDIR) > $@.flags; \
- echo $(PRIVATE_JACK_PROGUARD_FLAGS) >> $@.flags; \
-)
-$(if $(PRIVATE_EXTRA_JAR_ARGS),
- $(hide) mkdir -p $@.res.tmp
- $(hide) $(call create-empty-package-at,$@.res.tmp.zip)
- $(hide) $(call add-java-resources-to,$@.res.tmp.zip)
- $(hide) unzip -qo $@.res.tmp.zip -d $@.res.tmp
- $(hide) rm $@.res.tmp.zip)
-$(hide) if [ -s $(PRIVATE_JACK_INTERMEDIATES_DIR)/java-source-list-uniq ] ; then \
- export tmpEcjArg="@$(PRIVATE_JACK_INTERMEDIATES_DIR)/java-source-list-uniq"; \
-else \
- export tmpEcjArg=""; \
-fi; \
-$(call call-jack) \
- $(strip $(PRIVATE_JACK_FLAGS)) \
- $(if $(NO_OPTIMIZE_DX), \
- -D jack.dex.optimize="false") \
- $(addprefix --classpath ,$(strip \
- $(call normalize-path-list,$(PRIVATE_JACK_SHARED_LIBRARIES)))) \
- $(addprefix --import ,$(call reverse-list,$(PRIVATE_STATIC_JACK_LIBRARIES))) \
- $(addprefix --pluginpath ,$(strip \
- $(call normalize-path-list,$(PRIVATE_JACK_PLUGIN_PATH)))) \
- $(if $(PRIVATE_JACK_PLUGIN),--plugin $(call normalize-comma-list,$(PRIVATE_JACK_PLUGIN))) \
- $(if $(PRIVATE_EXTRA_JAR_ARGS),--import-resource $@.res.tmp) \
- -D jack.import.resource.policy=keep-first \
- -D jack.import.type.policy=keep-first \
- -D jack.android.min-api-level=$(PRIVATE_JACK_MIN_SDK_VERSION) \
- $(if $(PRIVATE_JACK_INCREMENTAL_DIR),--incremental-folder $(PRIVATE_JACK_INCREMENTAL_DIR)) \
- --output-jack $@ \
- $(addprefix --config-jarjar ,$(strip $(PRIVATE_JARJAR_RULES))) \
- $(if $(PRIVATE_JACK_PROGUARD_FLAGS),--config-proguard $@.flags) \
- $$tmpEcjArg \
- || ( rm -f $@ ; exit 41 )
-$(hide) rm -f $(PRIVATE_JACK_INTERMEDIATES_DIR)/java-source-list
-$(if $(PRIVATE_EXTRA_JAR_ARGS),$(hide) rm -rf $@.res.tmp)
-$(hide) mv $(PRIVATE_JACK_INTERMEDIATES_DIR)/java-source-list-uniq $(PRIVATE_JACK_INTERMEDIATES_DIR).java-source-list
-$(if $(PRIVATE_JAR_PACKAGES), $(hide) echo unsupported options PRIVATE_JAR_PACKAGES in $@; exit 53)
-$(if $(PRIVATE_JAR_EXCLUDE_PACKAGES), $(hide) echo unsupported options JAR_EXCLUDE_PACKAGES in $@; exit 53)
-$(if $(PRIVATE_JAR_MANIFEST), $(hide) echo unsupported options JAR_MANIFEST in $@; exit 53)
-endef
-
-define desugar-classpath
-$(filter-out -classpath -bootclasspath "",$(subst :,$(space),$(1)))
-endef
-
# Takes an sdk version that might be PLATFORM_VERSION_CODENAME (for example P),
# returns a number greater than the highest existing sdk version if it is, or
# the input if it is not.
@@ -2542,12 +2366,12 @@
@rm -rf $(dir $@)/desugar_dumped_classes
@mkdir $(dir $@)/desugar_dumped_classes
$(hide) $(JAVA) \
- $(if $(EXPERIMENTAL_USE_OPENJDK9),--add-opens java.base/java.lang.invoke=ALL-UNNAMED,) \
+ $(if $(USE_OPENJDK9),--add-opens java.base/java.lang.invoke=ALL-UNNAMED,) \
-Djdk.internal.lambda.dumpProxyClasses=$(abspath $(dir $@))/desugar_dumped_classes \
-jar $(DESUGAR) \
- $(addprefix --bootclasspath_entry ,$(call desugar-bootclasspath,$(PRIVATE_BOOTCLASSPATH))) \
- $(addprefix --classpath_entry ,$(PRIVATE_ALL_JAVA_LIBRARIES)) \
- --min_sdk_version $(call codename-or-sdk-to-sdk,$(PRIVATE_DEFAULT_APP_TARGET_SDK)) \
+ $(addprefix --bootclasspath_entry ,$(PRIVATE_BOOTCLASSPATH)) \
+ $(addprefix --classpath_entry ,$(PRIVATE_SHARED_JAVA_HEADER_LIBRARIES)) \
+ --min_sdk_version $(call codename-or-sdk-to-sdk,$(PRIVATE_MIN_SDK_VERSION)) \
--allow_empty_bootclasspath \
$(if $(filter --core-library,$(PRIVATE_DX_FLAGS)),--core_library) \
-i $< -o $@.tmp
@@ -2561,7 +2385,7 @@
$(hide) rm -f $(dir $@)classes*.dex
$(hide) $(DX_COMMAND) \
--dex --output=$(dir $@) \
- --min-sdk-version=$(call codename-or-sdk-to-sdk,$(PRIVATE_DEFAULT_APP_TARGET_SDK)) \
+ --min-sdk-version=$(PRIVATE_MIN_SDK_VERSION) \
$(if $(NO_OPTIMIZE_DX), \
--no-optimize) \
$(if $(GENERATE_DEX_DEBUG), \
@@ -2572,6 +2396,21 @@
$<
endef
+
+define transform-classes-d8.jar-to-dex
+@echo "target Dex: $(PRIVATE_MODULE)"
+@mkdir -p $(dir $@)
+$(hide) rm -f $(dir $@)classes*.dex $(dir $@)d8_input.jar
+$(hide) $(ZIP2ZIP) -j -i $< -o $(dir $@)d8_input.jar "**/*.class"
+$(hide) $(DX_COMMAND) \
+ --output $(dir $@) \
+ --min-api $(PRIVATE_MIN_SDK_VERSION) \
+ $(subst --main-dex-list=, --main-dex-list , \
+ $(filter-out --core-library --multi-dex --minimal-main-dex,$(PRIVATE_DX_FLAGS))) \
+ $(dir $@)d8_input.jar
+$(hide) rm -f $(dir $@)d8_input.jar
+endef
+
# Create a mostly-empty .jar file that we'll add to later.
# The MacOS jar tool doesn't like creating empty jar files,
# so we need to give it something.
@@ -2628,6 +2467,8 @@
$(addprefix --rename-instrumentation-target-package , $(PRIVATE_MANIFEST_INSTRUMENTATION_FOR)) \
--skip-symbols-without-default-localization \
-F $@
+# So that we re-run aapt when the list of input files change
+$(hide) echo $(PRIVATE_RESOURCE_LIST) >/dev/null
endef
# We need the extra blank line, so that the command will be on a separate line.
@@ -2677,17 +2518,15 @@
@rm -f $(1).jar-arg-list
endef
-# Add resources carried by static Jack libraries.
-#
-define add-carried-jack-resources
- $(hide) if [ -d $(PRIVATE_JACK_INTERMEDIATES_DIR) ] ; then \
- find $(PRIVATE_JACK_INTERMEDIATES_DIR) -type f | sort \
- | sed -e "s?^$(PRIVATE_JACK_INTERMEDIATES_DIR)/? -C \"$(PRIVATE_JACK_INTERMEDIATES_DIR)\" \"?" -e "s/$$/\"/" \
- > $(dir $@)jack_res_jar_flags; \
- if [ -s $(dir $@)jack_res_jar_flags ] ; then \
- $(JAR) uf $@ @$(dir $@)jack_res_jar_flags; \
- fi; \
-fi
+# Add resources (non .class files) from a jar to a package
+# $(1): the package file
+# $(2): the jar file
+# $(3): temporary directory
+define add-jar-resources-to-package
+ rm -rf $(3)
+ mkdir -p $(3)
+ unzip -qo $(2) -d $(3) $$(zipinfo -1 $(2) | grep -v -E "\.class$$")
+ $(JAR) uf $(1) $(call jar-args-sorted-files-in-directory,$(3))
endef
# Sign a package using the specified key/cert.
@@ -2696,14 +2535,10 @@
$(call sign-package-arg,$@)
endef
-# signapk uses internal APIs from sun.security.{pkcs,x509}; see http://b/37137869
# $(1): the package file we are signing.
define sign-package-arg
$(hide) mv $(1) $(1).unsigned
-$(hide) $(JAVA) -Djava.library.path=$(SIGNAPK_JNI_LIBRARY_PATH) \
- $(if $(EXPERIMENTAL_USE_OPENJDK9),--add-exports java.base/sun.security.pkcs=ALL-UNNAMED,) \
- $(if $(EXPERIMENTAL_USE_OPENJDK9),--add-exports java.base/sun.security.x509=ALL-UNNAMED,) \
- -jar $(SIGNAPK_JAR) \
+$(hide) $(JAVA) -Djava.library.path=$(SIGNAPK_JNI_LIBRARY_PATH) -jar $(SIGNAPK_JAR) \
$(PRIVATE_CERTIFICATE) $(PRIVATE_PRIVATE_KEY) \
$(PRIVATE_ADDITIONAL_CERTIFICATES) $(1).unsigned $(1).signed
$(hide) mv $(1).signed $(1)
@@ -2738,14 +2573,27 @@
$(hide) $(ZIPTIME) $@
endef
+# Uncompress dex files embedded in an apk.
+#
+define uncompress-dexs
+$(hide) if (zipinfo $@ '*.dex' 2>/dev/null | grep -v ' stor ' >/dev/null) ; then \
+ tmpdir=$@.tmpdir; \
+ rm -rf $$tmpdir && mkdir $$tmpdir; \
+ unzip -q $@ '*.dex' -d $$tmpdir && \
+ zip -qd $@ '*.dex' && \
+ ( cd $$tmpdir && find . -type f | sort | zip -qD -X -0 ../$(notdir $@) -@ ) && \
+ rm -rf $$tmpdir; \
+ fi
+endef
+
# Uncompress shared libraries embedded in an apk.
#
define uncompress-shared-libs
$(hide) if (zipinfo $@ $(PRIVATE_EMBEDDED_JNI_LIBS) 2>/dev/null | grep -v ' stor ' >/dev/null) ; then \
rm -rf $(dir $@)uncompressedlibs && mkdir $(dir $@)uncompressedlibs; \
- unzip $@ $(PRIVATE_EMBEDDED_JNI_LIBS) -d $(dir $@)uncompressedlibs && \
- zip -d $@ 'lib/*.so' && \
- ( cd $(dir $@)uncompressedlibs && find lib -type f | sort | zip -D -X -0 ../$(notdir $@) -@ ) && \
+ unzip -q $@ $(PRIVATE_EMBEDDED_JNI_LIBS) -d $(dir $@)uncompressedlibs && \
+ zip -qd $@ 'lib/*.so' && \
+ ( cd $(dir $@)uncompressedlibs && find lib -type f | sort | zip -qD -X -0 ../$(notdir $@) -@ ) && \
rm -rf $(dir $@)uncompressedlibs; \
fi
endef
@@ -2757,8 +2605,15 @@
# Note: we intentionally don't clean PRIVATE_CLASS_INTERMEDIATES_DIR
# in transform-java-to-classes for the sake of vm-tests.
define transform-host-java-to-package
-@echo "$($(PRIVATE_PREFIX)DISPLAY) Java: $(PRIVATE_MODULE) ($(PRIVATE_CLASS_INTERMEDIATES_DIR))"
-$(call compile-java,$(HOST_JAVAC),$(PRIVATE_BOOTCLASSPATH))
+@echo "Host Java: $(PRIVATE_MODULE) ($(PRIVATE_CLASS_INTERMEDIATES_DIR))"
+$(call compile-java,$(HOST_JAVAC),$(PRIVATE_ALL_JAVA_LIBRARIES))
+endef
+
+# Note: we intentionally don't clean PRIVATE_CLASS_INTERMEDIATES_DIR
+# in transform-java-to-classes for the sake of vm-tests.
+define transform-host-java-to-dalvik-package
+@echo "Dalvik Java: $(PRIVATE_MODULE) ($(PRIVATE_CLASS_INTERMEDIATES_DIR))"
+$(call compile-java,$(HOST_JAVAC),$(PRIVATE_ALL_JAVA_HEADER_LIBRARIES))
endef
###########################################################
@@ -2783,6 +2638,14 @@
$$(copy-file-to-target)
endef
+define copy-and-uncompress-dexs
+$(2): $(1) $(ZIPALIGN)
+ @echo "Uncompress dexs in: $$@"
+ $$(copy-file-to-target)
+ $$(uncompress-dexs)
+ $$(align-package)
+endef
+
# Copies many files.
# $(1): The files to copy. Each entry is a ':' separated src:dst pair
# Evaluates to the list of the dst files (ie suitable for a dependency list)
@@ -2799,9 +2662,9 @@
# $(1): source file
# $(2): destination file, must end with .xml.
define copy-xml-file-checked
-$(2): $(1)
+$(2): $(1) $(XMLLINT)
@echo "Copy xml: $$@"
- $(hide) xmllint $$< >/dev/null # Don't print the xml file to stdout.
+ $(hide) $(XMLLINT) $$< >/dev/null # Don't print the xml file to stdout.
$$(copy-file-to-target)
endef
@@ -2822,7 +2685,7 @@
define copy-file-to-target
@mkdir -p $(dir $@)
$(hide) rm -f $@
-$(hide) cp $< $@
+$(hide) cp "$<" "$@"
endef
# The same as copy-file-to-target, but use the local
@@ -2830,7 +2693,7 @@
define copy-file-to-target-with-cp
@mkdir -p $(dir $@)
$(hide) rm -f $@
-$(hide) cp -p $< $@
+$(hide) cp -p "$<" "$@"
endef
# The same as copy-file-to-target, but strip out "# comment"-style
@@ -2898,15 +2761,90 @@
$(hide) ln -sf $(2) $$@
endef
+# Copy an apk to a target location while removing classes*.dex
+# $(1): source file
+# $(2): destination file
+# $(3): LOCAL_DEX_PREOPT, if nostripping then leave classes*.dex
+define dexpreopt-copy-jar
+$(2): $(1)
+ @echo "Copy: $$@"
+ $$(copy-file-to-target)
+ $(if $(filter nostripping,$(3)),,$$(call dexpreopt-remove-classes.dex,$$@))
+endef
+
+# $(1): the .jar or .apk to remove classes.dex. Note that if all dex files
+# are uncompressed in the archive, then dexopt will not do a copy of the dex
+# files and we should not strip.
+define dexpreopt-remove-classes.dex
+$(hide) if (zipinfo $1 '*.dex' 2>/dev/null | grep -v ' stor ' >/dev/null) ; then \
+zip --quiet --delete $(1) classes.dex; \
+dex_index=2; \
+while zip --quiet --delete $(1) classes$${dex_index}.dex > /dev/null; do \
+ let dex_index=dex_index+1; \
+done \
+fi
+endef
+
+define hiddenapi-copy-dex-files
+$(2): $(1) $(HIDDENAPI) $(INTERNAL_PLATFORM_HIDDENAPI_LIGHT_GREYLIST) \
+ $(INTERNAL_PLATFORM_HIDDENAPI_DARK_GREYLIST) $(INTERNAL_PLATFORM_HIDDENAPI_BLACKLIST)
+ @rm -rf $(dir $(2))
+ @mkdir -p $(dir $(2))
+ find $(dir $(1)) -maxdepth 1 -name "classes*.dex" | sort | \
+ xargs -I{} cp -f {} $(dir $(2))
+ find $(dir $(2)) -name "classes*.dex" | sort | sed 's/^/--dex=/' | \
+ xargs $(HIDDENAPI) --light-greylist=$(INTERNAL_PLATFORM_HIDDENAPI_LIGHT_GREYLIST) \
+ --dark-greylist=$(INTERNAL_PLATFORM_HIDDENAPI_DARK_GREYLIST) \
+ --blacklist=$(INTERNAL_PLATFORM_HIDDENAPI_BLACKLIST)
+endef
+
+define hiddenapi-copy-soong-jar
+$(2): PRIVATE_FOLDER := $(dir $(2))dex-hiddenapi
+$(2): $(1) $(HIDDENAPI) $(SOONG_ZIP) $(MERGE_ZIPS) $(INTERNAL_PLATFORM_HIDDENAPI_LIGHT_GREYLIST) \
+ $(INTERNAL_PLATFORM_HIDDENAPI_DARK_GREYLIST) $(INTERNAL_PLATFORM_HIDDENAPI_BLACKLIST)
+ @echo "Hidden API: $$@"
+ $$(copy-file-to-target)
+ @rm -rf $${PRIVATE_FOLDER}
+ @mkdir -p $${PRIVATE_FOLDER}
+ unzip -q $(2) 'classes*.dex' -d $${PRIVATE_FOLDER}
+ find $${PRIVATE_FOLDER} -name "classes*.dex" | sort | sed 's/^/--dex=/' | \
+ xargs $(HIDDENAPI) --light-greylist=$(INTERNAL_PLATFORM_HIDDENAPI_LIGHT_GREYLIST) \
+ --dark-greylist=$(INTERNAL_PLATFORM_HIDDENAPI_DARK_GREYLIST) \
+ --blacklist=$(INTERNAL_PLATFORM_HIDDENAPI_BLACKLIST)
+ $(SOONG_ZIP) -o $${PRIVATE_FOLDER}/classes.dex.jar -C $${PRIVATE_FOLDER} -D $${PRIVATE_FOLDER}
+ $(MERGE_ZIPS) -D -zipToNotStrip $${PRIVATE_FOLDER}/classes.dex.jar -stripFile "classes*.dex" \
+ $(2) $${PRIVATE_FOLDER}/classes.dex.jar $(1)
+endef
+
###########################################################
## Commands to call Proguard
###########################################################
+ifdef TARGET_OPENJDK9
+define transform-jar-to-proguard
+@echo Skipping Proguard: $< $@
+$(hide) cp '$<' $@
+endef
+else
define transform-jar-to-proguard
@echo Proguard: $@
-$(hide) $(PROGUARD) -injars '$<$(PRIVATE_PROGUARD_INJAR_FILTERS)' \
- -outjars $@ $(PRIVATE_PROGUARD_FLAGS) \
+$(hide) $(PROGUARD) -injars $< -outjars $@ $(PRIVATE_PROGUARD_FLAGS) \
$(addprefix -injars , $(PRIVATE_EXTRA_INPUT_JAR))
endef
+endif
+
+
+###########################################################
+## Commands to call R8
+###########################################################
+define transform-jar-to-dex-r8
+@echo R8: $@
+$(hide) $(R8_COMPAT_PROGUARD) -injars '$<' \
+ --min-api $(PRIVATE_MIN_SDK_VERSION) \
+ --force-proguard-compatibility --output $(subst classes.dex,,$@) \
+ $(PRIVATE_PROGUARD_FLAGS) \
+ $(addprefix -injars , $(PRIVATE_EXTRA_INPUT_JAR)) \
+ $(PRIVATE_DX_FLAGS)
+endef
###########################################################
## Stuff source generated from one-off tools
@@ -2928,39 +2866,16 @@
$(error HOST_OS must define get-file-size)
endif
-# Convert a partition data size (eg, as reported in /proc/mtd) to the
-# size of the image used to flash that partition (which includes a
-# spare area for each page).
-# $(1): the partition data size
-define image-size-from-data-size
-$(strip $(eval _isfds_value := $$(shell echo $$$$(($(1) / $(BOARD_NAND_PAGE_SIZE) * \
- ($(BOARD_NAND_PAGE_SIZE)+$(BOARD_NAND_SPARE_SIZE))))))\
-$(if $(filter 0, $(_isfds_value)),$(shell echo $$(($(BOARD_NAND_PAGE_SIZE)+$(BOARD_NAND_SPARE_SIZE)))),$(_isfds_value))\
-$(eval _isfds_value :=))
-endef
-
# $(1): The file(s) to check (often $@)
-# $(2): The maximum total image size, in decimal bytes.
-# Make sure to take into account any reserved space needed for the FS.
-#
-# If $(2) is empty, evaluates to "true"
-#
-# Reserve bad blocks. Make sure that MAX(1% of partition size, 2 blocks)
-# is left over after the image has been flashed. Round the 1% up to the
-# next whole flash block size.
-define assert-max-file-size
+# $(2): The partition size.
+define assert-max-image-size
$(if $(2), \
size=$$(for i in $(1); do $(call get-file-size,$$i); echo +; done; echo 0); \
total=$$(( $$( echo "$$size" ) )); \
printname=$$(echo -n "$(1)" | tr " " +); \
- img_blocksize=$(call image-size-from-data-size,$(BOARD_FLASH_BLOCK_SIZE)); \
- twoblocks=$$((img_blocksize * 2)); \
- onepct=$$((((($(2) / 100) - 1) / img_blocksize + 1) * img_blocksize)); \
- reserve=$$((twoblocks > onepct ? twoblocks : onepct)); \
- maxsize=$$(($(2) - reserve)); \
- echo "$$printname maxsize=$$maxsize blocksize=$$img_blocksize total=$$total reserve=$$reserve"; \
+ maxsize=$$(($(2))); \
if [ "$$total" -gt "$$maxsize" ]; then \
- echo "error: $$printname too large ($$total > [$(2) - $$reserve])"; \
+ echo "error: $$printname too large ($$total > $$maxsize)"; \
false; \
elif [ "$$total" -gt $$((maxsize - 32768)) ]; then \
echo "WARNING: $$printname approaching size limit ($$total now; limit $$maxsize)"; \
@@ -2970,17 +2885,6 @@
)
endef
-# Like assert-max-file-size, but the second argument is a partition
-# size, which we'll convert to a max image size before checking it
-# against the files.
-#
-# $(1): The file(s) to check (often $@)
-# $(2): The partition size.
-define assert-max-image-size
-$(if $(2), \
- $(call assert-max-file-size,$(1),$(call image-size-from-data-size,$(2))))
-endef
-
###########################################################
## Define device-specific radio files
@@ -3157,9 +3061,11 @@
HOST_DALVIK_JAVA_LIBRARY \
HOST_DALVIK_STATIC_JAVA_LIBRARY \
base_rules \
- HEADER_LIBRARY
+ HEADER_LIBRARY \
+ HOST_TEST_CONFIG \
+ TARGET_TEST_CONFIG
-$(foreach $(s),$(STATS.MODULE_TYPE),$(eval STATS.MODULE_TYPE.$(s) :=))
+$(foreach s,$(STATS.MODULE_TYPE),$(eval STATS.MODULE_TYPE.$(s) :=))
define record-module-type
$(strip $(if $(LOCAL_RECORDED_MODULE_TYPE),,
$(if $(filter-out $(SOONG_ANDROID_MK),$(LOCAL_MODULE_MAKEFILE)),
@@ -3189,7 +3095,7 @@
define create-suite-dependencies
$(foreach suite, $(LOCAL_COMPATIBILITY_SUITE), \
$(eval COMPATIBILITY.$(suite).FILES := \
- $(COMPATIBILITY.$(suite).FILES) $(foreach f,$(my_compat_dist_$(suite)),$(call word-colon,2,$(f))))) \
+ $$(COMPATIBILITY.$(suite).FILES) $$(foreach f,$$(my_compat_dist_$(suite)),$$(call word-colon,2,$$(f))))) \
$(eval $(my_all_targets) : $(call copy-many-files, \
$(sort $(foreach suite,$(LOCAL_COMPATIBILITY_SUITE),$(my_compat_dist_$(suite))))))
endef
@@ -3330,6 +3236,122 @@
endif
###########################################################
+## Given a filepath, returns nonempty if the path cannot be
+## validated to be contained in the current directory
+## This is, this function checks for '/' and '..'
+##
+## $(1): path to validate
+define try-validate-path-is-subdir
+$(strip
+ $(if $(filter /%,$(1)),
+ $(1) starts with a slash
+ )
+ $(if $(filter ../%,$(call clean-path,$(1))),
+ $(1) escapes its parent using '..'
+ )
+ $(if $(strip $(1)),
+ ,
+ '$(1)' is empty
+ )
+)
+endef
+
+define validate-path-is-subdir
+$(if $(call try-validate-path-is-subdir,$(1)),
+ $(call pretty-error, Illegal path: $(call try-validate-path-is-subdir,$(1)))
+)
+endef
+
+###########################################################
+## Given a space-delimited list of filepaths, returns
+## nonempty if any cannot be validated to be contained in
+## the current directory
+##
+## $(1): path list to validate
+define try-validate-paths-are-subdirs
+$(strip \
+ $(foreach my_path,$(1),\
+ $(call try-validate-path-is-subdir,$(my_path))\
+ )
+)
+endef
+
+define validate-paths-are-subdirs
+$(if $(call try-validate-paths-are-subdirs,$(1)),
+ $(call pretty-error,Illegal paths:\'$(call try-validate-paths-are-subdirs,$(1))\')
+)
+endef
+
+###########################################################
+## Tests of try-validate-path-is-subdir
+## and try-validate-paths-are-subdirs
+define test-validate-paths-are-subdirs
+$(eval my_error := $(call try-validate-path-is-subdir,/tmp)) \
+$(if $(call streq,$(my_error),/tmp starts with a slash),
+,
+ $(error incorrect error message for path /tmp. Got '$(my_error)')
+) \
+$(eval my_error := $(call try-validate-path-is-subdir,../sibling)) \
+$(if $(call streq,$(my_error),../sibling escapes its parent using '..'),
+,
+ $(error incorrect error message for path ../sibling. Got '$(my_error)')
+) \
+$(eval my_error := $(call try-validate-path-is-subdir,child/../../sibling)) \
+$(if $(call streq,$(my_error),child/../../sibling escapes its parent using '..'),
+,
+ $(error incorrect error message for path child/../../sibling. Got '$(my_error)')
+) \
+$(eval my_error := $(call try-validate-path-is-subdir,)) \
+$(if $(call streq,$(my_error),'' is empty),
+,
+ $(error incorrect error message for empty path ''. Got '$(my_error)')
+) \
+$(eval my_error := $(call try-validate-path-is-subdir,subdir/subsubdir)) \
+$(if $(call streq,$(my_error),),
+,
+ $(error rejected valid path 'subdir/subsubdir'. Got '$(my_error)')
+)
+
+$(eval my_error := $(call try-validate-paths-are-subdirs,a/b /c/d e/f))
+$(if $(call streq,$(my_error),/c/d starts with a slash),
+,
+ $(error incorrect error message for path list 'a/b /c/d e/f'. Got '$(my_error)')
+)
+$(eval my_error := $(call try-validate-paths-are-subdirs,a/b c/d))
+$(if $(call streq,$(my_error),),
+,
+ $(error rejected valid path list 'a/b c/d'. Got '$(my_error)')
+)
+endef
+# run test
+$(strip $(call test-validate-paths-are-subdirs))
+
+###########################################################
+## Validate jacoco class filters and convert them to
+## file arguments
+## Jacoco class filters are comma-separated lists of class
+## files (android.app.Application), and may have '*' as the
+## last character to match all classes in a package
+## including subpackages.
+define jacoco-class-filter-to-file-args
+$(strip $(call jacoco-validate-file-args,\
+ $(subst $(comma),$(space),\
+ $(subst .,/,\
+ $(strip $(1))))))
+endef
+
+define jacoco-validate-file-args
+$(strip $(1)\
+ $(call validate-paths-are-subdirs,$(1))
+ $(foreach arg,$(1),\
+ $(if $(findstring ?,$(arg)),$(call pretty-error,\
+ '?' filters are not supported in LOCAL_JACK_COVERAGE_INCLUDE_FILTER or LOCAL_JACK_COVERAGE_EXCLUDE_FILTER))\
+ $(if $(findstring *,$(patsubst %*,%,$(arg))),$(call pretty-error,\
+ '*' is only supported at the end of a filter in LOCAL_JACK_COVERAGE_INCLUDE_FILTER or LOCAL_JACK_COVERAGE_EXCLUDE_FILTER))\
+ ))
+endef
+
+###########################################################
## Other includes
###########################################################
@@ -3409,3 +3431,43 @@
$(eval ALL_MODULES.$(enforce_rro_source_module).REQUIRED += $(enforce_rro_module)) \
)
endef
+
+###########################################################
+## Find system_$(VER) in LOCAL_SDK_VERSION
+##
+## $(1): LOCAL_SDK_VERSION
+###########################################################
+define has-system-sdk-version
+$(filter system_%,$(1))
+endef
+
+###########################################################
+## Get numerical version in LOCAL_SDK_VERSION
+##
+## $(1): LOCAL_SDK_VERSION
+###########################################################
+define get-numeric-sdk-version
+$(filter-out current,\
+ $(if $(call has-system-sdk-version,$(1)),$(patsubst system_%,%,$(1)),$(1)))
+endef
+
+# Convert to lower case without requiring a shell, which isn't cacheable.
+to-lower=$(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))))))))))))))))))))))))))
+
+# Convert to upper case without requiring a shell, which isn't cacheable.
+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
+lower := abcdefghijklmnopqrstuvwxyz-_
+upper := ABCDEFGHIJKLMNOPQRSTUVWXYZ-_
+
+ifneq ($(lower),$(call to-lower,$(upper)))
+ $(error to-lower sanity check failure)
+endif
+
+ifneq ($(upper),$(call to-upper,$(lower)))
+ $(error to-upper sanity check failure)
+endif
+
+lower :=
+upper :=
diff --git a/core/dex_preopt.mk b/core/dex_preopt.mk
index 8e496a7..7298bde 100644
--- a/core/dex_preopt.mk
+++ b/core/dex_preopt.mk
@@ -24,34 +24,42 @@
SYSTEM_OTHER_ODEX_FILTER ?= app/% priv-app/%
# Method returning whether the install path $(1) should be for system_other.
+# Under SANITIZE_LITE, we do not want system_other. Just put things under /data/asan.
+ifeq ($(SANITIZE_LITE),true)
+install-on-system-other =
+else
install-on-system-other = $(filter-out $(PRODUCT_DEXPREOPT_SPEED_APPS) $(PRODUCT_SYSTEM_SERVER_APPS),$(basename $(notdir $(filter $(foreach f,$(SYSTEM_OTHER_ODEX_FILTER),$(TARGET_OUT)/$(f)),$(1)))))
+endif
# The default values for pre-opting: always preopt PIC.
# Conditional to building on linux, as dex2oat currently does not work on darwin.
ifeq ($(HOST_OS),linux)
WITH_DEXPREOPT ?= true
-# For an eng build only pre-opt the boot image and system server. This gives reasonable performance
-# and still allows a simple workflow: building in frameworks/base and syncing.
ifeq (eng,$(TARGET_BUILD_VARIANT))
+ # Don't strip for quick development turnarounds.
+ DEX_PREOPT_DEFAULT := nostripping
+ # For an eng build only pre-opt the boot image and system server. This gives reasonable performance
+ # and still allows a simple workflow: building in frameworks/base and syncing.
WITH_DEXPREOPT_BOOT_IMG_AND_SYSTEM_SERVER_ONLY ?= true
endif
-# Add mini-debug-info to the boot classpath unless explicitly asked not to.
+ # Add mini-debug-info to the boot classpath unless explicitly asked not to.
ifneq (false,$(WITH_DEXPREOPT_DEBUG_INFO))
PRODUCT_DEX_PREOPT_BOOT_FLAGS += --generate-mini-debug-info
endif
+
+ # Non eng linux builds must have preopt enabled so that system server doesn't run as interpreter
+ # only. b/74209329
+ ifeq (,$(filter eng, $(TARGET_BUILD_VARIANT)))
+ ifneq (true,$(WITH_DEXPREOPT))
+ ifneq (true,$(WITH_DEXPREOPT_BOOT_IMG_AND_SYSTEM_SERVER_ONLY))
+ $(call pretty-error, DEXPREOPT must be enabled for user and userdebug builds)
+ endif
+ endif
+ endif
endif
GLOBAL_DEXPREOPT_FLAGS :=
-# $(1): the .jar or .apk to remove classes.dex
-define dexpreopt-remove-classes.dex
-$(hide) zip --quiet --delete $(1) classes.dex; \
-dex_index=2; \
-while zip --quiet --delete $(1) classes$${dex_index}.dex > /dev/null; do \
- let dex_index=dex_index+1; \
-done
-endef
-
# Special rules for building stripped boot jars that override java_library.mk rules
# $(1): boot jar module name
@@ -59,11 +67,7 @@
_dbj_jar_no_dex := $(DEXPREOPT_BOOT_JAR_DIR_FULL_PATH)/$(1)_nodex.jar
_dbj_src_jar := $(call intermediates-dir-for,JAVA_LIBRARIES,$(1),,COMMON)/javalib.jar
-$$(_dbj_jar_no_dex) : $$(_dbj_src_jar)
- $$(call copy-file-to-target)
-ifneq ($(DEX_PREOPT_DEFAULT),nostripping)
- $$(call dexpreopt-remove-classes.dex,$$@)
-endif
+$(call dexpreopt-copy-jar,$$(_dbj_src_jar),$$(_dbj_jar_no_dex),$(DEX_PREOPT_DEFAULT))
_dbj_jar_no_dex :=
_dbj_src_jar :=
@@ -85,3 +89,20 @@
ifdef TARGET_2ND_ARCH
$(TARGET_2ND_ARCH_VAR_PREFIX)DEXPREOPT_ONE_FILE_DEPENDENCY_BUILT_BOOT_PREOPT := $($(TARGET_2ND_ARCH_VAR_PREFIX)DEFAULT_DEX_PREOPT_BUILT_IMAGE_FILENAME)
endif # TARGET_2ND_ARCH
+
+ifeq ($(PRODUCT_DIST_BOOT_AND_SYSTEM_JARS),true)
+boot_profile_jars_zip := $(PRODUCT_OUT)/boot_profile_jars.zip
+all_boot_jars := \
+ $(foreach m,$(DEXPREOPT_BOOT_JARS_MODULES),$(PRODUCT_OUT)/system/framework/$(m).jar) \
+ $(foreach m,$(PRODUCT_SYSTEM_SERVER_JARS),$(PRODUCT_OUT)/system/framework/$(m).jar)
+
+$(boot_profile_jars_zip): PRIVATE_JARS := $(all_boot_jars)
+$(boot_profile_jars_zip): $(all_boot_jars) $(SOONG_ZIP)
+ echo "Create boot profiles package: $@"
+ rm -f $@
+ $(SOONG_ZIP) -o $@ -C $(PRODUCT_OUT) $(PRIVATE_JARS)
+
+droidcore: $(boot_profile_jars_zip)
+
+$(call dist-for-goals, droidcore, $(boot_profile_jars_zip))
+endif
diff --git a/core/dex_preopt_libart.mk b/core/dex_preopt_libart.mk
index 9616036..9c4d55d 100644
--- a/core/dex_preopt_libart.mk
+++ b/core/dex_preopt_libart.mk
@@ -7,15 +7,14 @@
# Set USE_DEX2OAT_DEBUG to false for only building non-debug versions.
ifeq ($(USE_DEX2OAT_DEBUG),false)
DEX2OAT := $(HOST_OUT_EXECUTABLES)/dex2oat$(HOST_EXECUTABLE_SUFFIX)
+PATCHOAT := $(HOST_OUT_EXECUTABLES)/patchoat$(HOST_EXECUTABLE_SUFFIX)
else
DEX2OAT := $(HOST_OUT_EXECUTABLES)/dex2oatd$(HOST_EXECUTABLE_SUFFIX)
+PATCHOAT := $(HOST_OUT_EXECUTABLES)/patchoatd$(HOST_EXECUTABLE_SUFFIX)
endif
-# Pass special class loader context to skip the classpath and collision check.
-# Should modify build system to pass used libraries properly later.
-DEX2OAT_CLASS_LOADER_CONTEXT := "&"
-
DEX2OAT_DEPENDENCY += $(DEX2OAT)
+PATCHOAT_DEPENDENCY += $(PATCHOAT)
# Use the first preloaded-classes file in PRODUCT_COPY_FILES.
PRELOADED_CLASSES := $(call word-colon,1,$(firstword \
@@ -30,7 +29,9 @@
$(filter %system/etc/dirty-image-objects,$(PRODUCT_COPY_FILES))))
define get-product-default-property
-$(strip $(patsubst $(1)=%,%,$(filter $(1)=%,$(PRODUCT_DEFAULT_PROPERTY_OVERRIDES))))
+$(strip \
+ $(eval _prop := $(patsubst $(1)=%,%,$(filter $(1)=%,$(PRODUCT_DEFAULT_PROPERTY_OVERRIDES))))\
+ $(if $(_prop),$(_prop),$(patsubst $(1)=%,%,$(filter $(1)=%,$(PRODUCT_SYSTEM_DEFAULT_PROPERTIES)))))
endef
DEX2OAT_IMAGE_XMS := $(call get-product-default-property,dalvik.vm.image-dex2oat-Xms)
@@ -89,14 +90,19 @@
# is converted into to boot.art (to match the legacy assumption that boot.art
# exists), and the rest are converted to boot-<name>.art.
# In addition, each .art file has an associated .oat file.
-LIBART_TARGET_BOOT_ART_EXTRA_FILES := $(foreach jar,$(wordlist 2,999,$(LIBART_TARGET_BOOT_JARS)),boot-$(jar).art boot-$(jar).oat boot-$(jar).vdex)
-LIBART_TARGET_BOOT_ART_EXTRA_FILES += boot.oat boot.vdex
+LIBART_TARGET_BOOT_ART_EXTRA_FILES := $(foreach jar,$(wordlist 2,999,$(LIBART_TARGET_BOOT_JARS)),boot-$(jar).art boot-$(jar).art.rel boot-$(jar).oat)
+LIBART_TARGET_BOOT_ART_EXTRA_FILES += boot.art.rel boot.oat
+LIBART_TARGET_BOOT_ART_VDEX_FILES := $(foreach jar,$(wordlist 2,999,$(LIBART_TARGET_BOOT_JARS)),boot-$(jar).vdex)
+LIBART_TARGET_BOOT_ART_VDEX_FILES += boot.vdex
# If we use a boot image profile.
my_use_profile_for_boot_image := $(PRODUCT_USE_PROFILE_FOR_BOOT_IMAGE)
ifeq (,$(my_use_profile_for_boot_image))
-# If not set, use the default.
-my_use_profile_for_boot_image := false
+# If not set, set the default to true if we are not a PDK build. PDK builds
+# can't build the profile since they don't have frameworks/base.
+ifneq (true,$(TARGET_BUILD_PDK))
+my_use_profile_for_boot_image := true
+endif
endif
ifeq (true,$(my_use_profile_for_boot_image))
@@ -128,6 +134,8 @@
endif
+LIBART_TARGET_BOOT_ART_VDEX_INSTALLED_SHARED_FILES := $(addprefix $(PRODUCT_OUT)/$(DEXPREOPT_BOOT_JAR_DIR)/,$(LIBART_TARGET_BOOT_ART_VDEX_FILES))
+
my_2nd_arch_prefix :=
include $(BUILD_SYSTEM)/dex_preopt_libart_boot.mk
@@ -135,22 +143,50 @@
ifdef TARGET_2ND_ARCH
my_2nd_arch_prefix := $(TARGET_2ND_ARCH_VAR_PREFIX)
include $(BUILD_SYSTEM)/dex_preopt_libart_boot.mk
-my_2nd_arch_prefix :=
endif
endif
+# Copy shared vdex to the directory and create corresponding symlinks in primary and secondary arch.
+$(LIBART_TARGET_BOOT_ART_VDEX_INSTALLED_SHARED_FILES) : PRIMARY_ARCH_DIR := $(dir $(DEFAULT_DEX_PREOPT_INSTALLED_IMAGE))
+$(LIBART_TARGET_BOOT_ART_VDEX_INSTALLED_SHARED_FILES) : SECOND_ARCH_DIR := $(dir $($(my_2nd_arch_prefix)DEFAULT_DEX_PREOPT_INSTALLED_IMAGE))
+$(LIBART_TARGET_BOOT_ART_VDEX_INSTALLED_SHARED_FILES) : $(DEFAULT_DEX_PREOPT_BUILT_IMAGE_FILENAME)
+ @echo "Install: $@"
+ @mkdir -p $(dir $@)
+ @rm -f $@
+ $(hide) cp "$(dir $<)$(notdir $@)" "$@"
+ # Make symlink for both the archs. In the case its single arch the symlink will just get overridden.
+ @mkdir -p $(PRIMARY_ARCH_DIR)
+ $(hide) ln -sf /$(DEXPREOPT_BOOT_JAR_DIR)/$(notdir $@) $(PRIMARY_ARCH_DIR)$(notdir $@)
+ @mkdir -p $(SECOND_ARCH_DIR)
+ $(hide) ln -sf /$(DEXPREOPT_BOOT_JAR_DIR)/$(notdir $@) $(SECOND_ARCH_DIR)$(notdir $@)
+
+my_2nd_arch_prefix :=
########################################################################
# For a single jar or APK
# $(1): the input .jar or .apk file
# $(2): the output .odex file
+# In the case where LOCAL_ENFORCE_USES_LIBRARIES is true, PRIVATE_DEX2OAT_CLASS_LOADER_CONTEXT
+# contains the normalized path list of the libraries. This makes it easier to conditionally prepend
+# org.apache.http.legacy.boot based on the SDK level if required.
define dex2oat-one-file
$(hide) rm -f $(2)
$(hide) mkdir -p $(dir $(2))
-$(hide) ANDROID_LOG_TAGS="*:e" $(DEX2OAT) \
+stored_class_loader_context_libs=$(PRIVATE_DEX2OAT_STORED_CLASS_LOADER_CONTEXT_LIBS) && \
+class_loader_context_arg=--class-loader-context=$(PRIVATE_DEX2OAT_CLASS_LOADER_CONTEXT) && \
+class_loader_context=$(PRIVATE_DEX2OAT_CLASS_LOADER_CONTEXT) && \
+stored_class_loader_context_arg="" && \
+uses_library_names="$(PRIVATE_USES_LIBRARY_NAMES)" && \
+optional_uses_library_names="$(PRIVATE_OPTIONAL_USES_LIBRARY_NAMES)" && \
+$(if $(PRIVATE_ENFORCE_USES_LIBRARIES), \
+source build/make/core/verify_uses_libraries.sh "$(1)" && \
+source build/make/core/construct_context.sh "$(PRIVATE_CONDITIONAL_USES_LIBRARIES_HOST)" "$(PRIVATE_CONDITIONAL_USES_LIBRARIES_TARGET)" && \
+,) \
+ANDROID_LOG_TAGS="*:e" $(DEX2OAT) \
--runtime-arg -Xms$(DEX2OAT_XMS) --runtime-arg -Xmx$(DEX2OAT_XMX) \
- --class-loader-context=$(DEX2OAT_CLASS_LOADER_CONTEXT) \
+ $${class_loader_context_arg} \
+ $${stored_class_loader_context_arg} \
--boot-image=$(PRIVATE_DEX_PREOPT_IMAGE_LOCATION) \
--dex-file=$(1) \
--dex-location=$(PRIVATE_DEX_LOCATION) \
diff --git a/core/dex_preopt_libart_boot.mk b/core/dex_preopt_libart_boot.mk
index e3eb9ef..a5e7e88 100644
--- a/core/dex_preopt_libart_boot.mk
+++ b/core/dex_preopt_libart_boot.mk
@@ -30,6 +30,8 @@
$(my_2nd_arch_prefix)DEFAULT_DEX_PREOPT_INSTALLED_IMAGE := $(PRODUCT_OUT)$($(my_2nd_arch_prefix)LIBART_BOOT_IMAGE_FILENAME)
$(my_2nd_arch_prefix)LIBART_TARGET_BOOT_ART_EXTRA_INSTALLED_FILES := $(addprefix $(dir $($(my_2nd_arch_prefix)DEFAULT_DEX_PREOPT_INSTALLED_IMAGE)),\
$(LIBART_TARGET_BOOT_ART_EXTRA_FILES))
+$(my_2nd_arch_prefix)LIBART_TARGET_BOOT_ART_VDEX_INSTALLED_FILES := $(addprefix $(dir $($(my_2nd_arch_prefix)DEFAULT_DEX_PREOPT_INSTALLED_IMAGE)),\
+ $(LIBART_TARGET_BOOT_ART_VDEX_FILES))
# If we have a compiled-classes file, create a parameter.
COMPILED_CLASSES_FLAGS :=
@@ -45,7 +47,7 @@
# The rule to install boot.art
# Depends on installed boot.oat, boot-*.art, boot-*.oat
-$($(my_2nd_arch_prefix)DEFAULT_DEX_PREOPT_INSTALLED_IMAGE) : $($(my_2nd_arch_prefix)DEFAULT_DEX_PREOPT_BUILT_IMAGE_FILENAME) | $(ACP) $($(my_2nd_arch_prefix)LIBART_TARGET_BOOT_ART_EXTRA_INSTALLED_FILES)
+$($(my_2nd_arch_prefix)DEFAULT_DEX_PREOPT_INSTALLED_IMAGE) : $($(my_2nd_arch_prefix)DEFAULT_DEX_PREOPT_BUILT_IMAGE_FILENAME) | $(ACP) $($(my_2nd_arch_prefix)LIBART_TARGET_BOOT_ART_EXTRA_INSTALLED_FILES) $($(my_2nd_arch_prefix)LIBART_TARGET_BOOT_ART_VDEX_INSTALLED_SHARED_FILES)
@echo "Install: $@"
$(copy-file-to-target)
@@ -65,17 +67,42 @@
my_boot_image_flags += --profile-file=$(my_out_boot_image_profile_location)
endif
+ifneq (addresstrue,$(SANITIZE_TARGET)$(SANITIZE_LITE))
+# Skip recompiling the boot image for the second sanitization phase. We'll get separate paths
+# and invalidate first-stage artifacts which are crucial to SANITIZE_LITE builds.
+# Note: this is technically incorrect. Compiled code contains stack checks which may depend
+# on ASAN settings.
+
+# Use ANDROID_LOG_TAGS to suppress most logging by default...
+ifeq (,$(ART_BOOT_IMAGE_EXTRA_ARGS))
+DEX2OAT_BOOT_IMAGE_LOG_TAGS := ANDROID_LOG_TAGS="*:e"
+else
+# ...unless the boot image is generated specifically for testing, then allow all logging.
+DEX2OAT_BOOT_IMAGE_LOG_TAGS := ANDROID_LOG_TAGS="*:v"
+endif
+
+# An additional message to print on dex2oat failure.
+DEX2OAT_FAILURE_MESSAGE := ERROR: Dex2oat failed to compile a boot image.
+DEX2OAT_FAILURE_MESSAGE += It is likely that the boot classpath is inconsistent.
+ifeq ($(ONE_SHOT_MAKEFILE),)
+ DEX2OAT_FAILURE_MESSAGE += Rebuild with ART_BOOT_IMAGE_EXTRA_ARGS="--runtime-arg -verbose:verifier" to see verification errors.
+else
+ DEX2OAT_FAILURE_MESSAGE += Build with m, mma, or mmma instead of mm or mmm to remedy the situation.
+endif
+
$($(my_2nd_arch_prefix)DEFAULT_DEX_PREOPT_BUILT_IMAGE_FILENAME): PRIVATE_BOOT_IMAGE_FLAGS := $(my_boot_image_flags)
$($(my_2nd_arch_prefix)DEFAULT_DEX_PREOPT_BUILT_IMAGE_FILENAME): PRIVATE_2ND_ARCH_VAR_PREFIX := $(my_2nd_arch_prefix)
+$($(my_2nd_arch_prefix)DEFAULT_DEX_PREOPT_BUILT_IMAGE_FILENAME): PRIVATE_IMAGE_LOCATION := $($(my_2nd_arch_prefix)DEFAULT_DEX_PREOPT_BUILT_IMAGE_LOCATION)
# Use dex2oat debug version for better error reporting
-$($(my_2nd_arch_prefix)DEFAULT_DEX_PREOPT_BUILT_IMAGE_FILENAME) : $(LIBART_TARGET_BOOT_DEX_FILES) $(PRELOADED_CLASSES) $(COMPILED_CLASSES) $(DIRTY_IMAGE_OBJECTS) $(DEX2OAT_DEPENDENCY) $(my_out_boot_image_profile_location)
+$($(my_2nd_arch_prefix)DEFAULT_DEX_PREOPT_BUILT_IMAGE_FILENAME) : $(LIBART_TARGET_BOOT_DEX_FILES) $(PRELOADED_CLASSES) $(COMPILED_CLASSES) $(DIRTY_IMAGE_OBJECTS) $(DEX2OAT_DEPENDENCY) $(PATCHOAT_DEPENDENCY) $(my_out_boot_image_profile_location)
@echo "target dex2oat: $@"
@mkdir -p $(dir $@)
@mkdir -p $(dir $($(PRIVATE_2ND_ARCH_VAR_PREFIX)LIBART_TARGET_BOOT_OAT_UNSTRIPPED))
- @rm -f $(dir $@)/*.art $(dir $@)/*.oat
+ @rm -f $(dir $@)/*.art $(dir $@)/*.oat $(dir $@)/*.art.rel
@rm -f $(dir $($(PRIVATE_2ND_ARCH_VAR_PREFIX)LIBART_TARGET_BOOT_OAT_UNSTRIPPED))/*.art
@rm -f $(dir $($(PRIVATE_2ND_ARCH_VAR_PREFIX)LIBART_TARGET_BOOT_OAT_UNSTRIPPED))/*.oat
- $(DEX2OAT) --runtime-arg -Xms$(DEX2OAT_IMAGE_XMS) \
+ @rm -f $(dir $($(PRIVATE_2ND_ARCH_VAR_PREFIX)LIBART_TARGET_BOOT_OAT_UNSTRIPPED))/*.art.rel
+ $(hide) $(DEX2OAT_BOOT_IMAGE_LOG_TAGS) $(DEX2OAT) --runtime-arg -Xms$(DEX2OAT_IMAGE_XMS) \
--runtime-arg -Xmx$(DEX2OAT_IMAGE_XMX) \
$(PRIVATE_BOOT_IMAGE_FLAGS) \
$(addprefix --dex-file=,$(LIBART_TARGET_BOOT_DEX_FILES)) \
@@ -91,4 +118,14 @@
--runtime-arg -Xnorelocate --compile-pic \
--no-generate-debug-info --generate-build-id \
--multi-image --no-inline-from=core-oj.jar \
- $(PRODUCT_DEX_PREOPT_BOOT_FLAGS) $(GLOBAL_DEXPREOPT_FLAGS) $(ART_BOOT_IMAGE_EXTRA_ARGS)
+ --abort-on-hard-verifier-error \
+ --abort-on-soft-verifier-error \
+ $(PRODUCT_DEX_PREOPT_BOOT_FLAGS) $(GLOBAL_DEXPREOPT_FLAGS) $(ART_BOOT_IMAGE_EXTRA_ARGS) \
+ || ( echo "$(DEX2OAT_FAILURE_MESSAGE)" ; false ) && \
+ $(DEX2OAT_BOOT_IMAGE_LOG_TAGS) ANDROID_ROOT=$(PRODUCT_OUT)/system ANDROID_DATA=$(dir $@) $(PATCHOAT) \
+ --input-image-location=$(PRIVATE_IMAGE_LOCATION) \
+ --output-image-relocation-directory=$(dir $@) \
+ --instruction-set=$($(PRIVATE_2ND_ARCH_VAR_PREFIX)DEX2OAT_TARGET_ARCH) \
+ --base-offset-delta=0x10000000
+
+endif
diff --git a/core/dex_preopt_odex_install.mk b/core/dex_preopt_odex_install.mk
index 235f4bc..ce91759 100644
--- a/core/dex_preopt_odex_install.mk
+++ b/core/dex_preopt_odex_install.mk
@@ -1,6 +1,20 @@
# dexpreopt_odex_install.mk is used to define odex creation rules for JARs and APKs
# This file depends on variables set in base_rules.mk
-# Output variables: LOCAL_DEX_PREOPT, built_odex, dexpreopt_boot_jar_module
+# Output variables: LOCAL_DEX_PREOPT, LOCAL_UNCOMPRESS_DEX, built_odex,
+# dexpreopt_boot_jar_module
+
+# We explicitly uncompress APKs of privileged apps, and used by
+# privileged apps
+LOCAL_UNCOMPRESS_DEX := false
+ifneq (true,$(DONT_UNCOMPRESS_PRIV_APPS_DEXS))
+ifeq (true,$(LOCAL_PRIVILEGED_MODULE))
+ LOCAL_UNCOMPRESS_DEX := true
+else
+ ifneq (,$(filter $(PRODUCT_LOADED_BY_PRIVILEGED_MODULES), $(LOCAL_MODULE)))
+ LOCAL_UNCOMPRESS_DEX := true
+ endif # PRODUCT_LOADED_BY_PRIVILEGED_MODULES
+endif # LOCAL_PRIVILEGED_MODULE
+endif # DONT_UNCOMPRESS_PRIV_APPS_DEXS
# Setting LOCAL_DEX_PREOPT based on WITH_DEXPREOPT, LOCAL_DEX_PREOPT, etc
LOCAL_DEX_PREOPT := $(strip $(LOCAL_DEX_PREOPT))
@@ -30,7 +44,7 @@
ifdef LOCAL_UNINSTALLABLE_MODULE
LOCAL_DEX_PREOPT :=
endif
-ifeq (,$(strip $(built_dex)$(my_prebuilt_src_file))) # contains no java code
+ifeq (,$(strip $(built_dex)$(my_prebuilt_src_file)$(LOCAL_SOONG_DEX_JAR))) # contains no java code
LOCAL_DEX_PREOPT :=
endif
# if WITH_DEXPREOPT_BOOT_IMG_AND_SYSTEM_SERVER_ONLY=true and module is not in boot class path skip
@@ -46,14 +60,27 @@
endif
endif
-# if installing into system, and odex are being installed into system_other, don't strip
-ifeq ($(BOARD_USES_SYSTEM_OTHER_ODEX),true)
ifeq ($(LOCAL_DEX_PREOPT),true)
+
+# Don't strip with dexes we explicitly uncompress (dexopt will not store the dex code).
+ifeq ($(LOCAL_UNCOMPRESS_DEX),true)
+LOCAL_DEX_PREOPT := nostripping
+endif # LOCAL_UNCOMPRESS_DEX
+
+# system_other isn't there for an OTA, so don't strip
+# if module is on system, and odex is on system_other.
+ifeq ($(BOARD_USES_SYSTEM_OTHER_ODEX),true)
ifneq ($(call install-on-system-other, $(my_module_path)),)
LOCAL_DEX_PREOPT := nostripping
-endif
-endif
-endif
+endif # install-on-system-other
+endif # BOARD_USES_SYSTEM_OTHER_ODEX
+
+# We also don't strip if all dexs are uncompressed (dexopt will not store the dex code),
+# but that requires to inspect the source file, which is too early at this point (as we
+# don't know if the source file will actually be used).
+# See dexpreopt-remove-classes.dex.
+
+endif # LOCAL_DEX_PREOPT
built_odex :=
built_vdex :=
@@ -64,32 +91,39 @@
built_installed_odex :=
built_installed_vdex :=
built_installed_art :=
+my_process_profile :=
+my_profile_is_text_listing :=
ifeq (false,$(WITH_DEX_PREOPT_GENERATE_PROFILE))
LOCAL_DEX_PREOPT_GENERATE_PROFILE := false
endif
ifndef LOCAL_DEX_PREOPT_GENERATE_PROFILE
+
+
# If LOCAL_DEX_PREOPT_GENERATE_PROFILE is not defined, default it based on the existence of the
# profile class listing. TODO: Use product specific directory here.
my_classes_directory := $(PRODUCT_DEX_PREOPT_PROFILE_DIR)
-LOCAL_DEX_PREOPT_PROFILE_CLASS_LISTING := $(my_classes_directory)/$(LOCAL_MODULE).prof.txt
-ifneq (,$(wildcard $(LOCAL_DEX_PREOPT_PROFILE_CLASS_LISTING)))
-# Profile listing exists, use it to generate the profile.
-LOCAL_DEX_PREOPT_GENERATE_PROFILE := true
-endif
-endif
+LOCAL_DEX_PREOPT_PROFILE := $(my_classes_directory)/$(LOCAL_MODULE).prof
-ifeq (true,$(LOCAL_DEX_PREOPT_GENERATE_PROFILE))
-
-ifdef LOCAL_VENDOR_MODULE
-$(call pretty-error, Internal error: profiles are not supported for vendor modules)
+ifneq (,$(wildcard $(LOCAL_DEX_PREOPT_PROFILE)))
+my_process_profile := true
+my_profile_is_text_listing := false
+endif
else
+my_process_profile := $(LOCAL_DEX_PREOPT_GENERATE_PROFILE)
+my_profile_is_text_listing := true
+LOCAL_DEX_PREOPT_PROFILE := $(LOCAL_DEX_PREOPT_PROFILE_CLASS_LISTING)
+endif
+
+ifeq (true,$(my_process_profile))
+
+ifeq (,$(LOCAL_DEX_PREOPT_APP_IMAGE))
LOCAL_DEX_PREOPT_APP_IMAGE := true
endif
-ifndef LOCAL_DEX_PREOPT_PROFILE_CLASS_LISTING
-$(call pretty-error,Must have specified class listing (LOCAL_DEX_PREOPT_PROFILE_CLASS_LISTING))
+ifndef LOCAL_DEX_PREOPT_PROFILE
+$(call pretty-error,Must have specified class listing (LOCAL_DEX_PREOPT_PROFILE))
endif
ifeq (,$(dex_preopt_profile_src_file))
$(call pretty-error, Internal error: dex_preopt_profile_src_file must be set)
@@ -100,20 +134,40 @@
my_dex_location := $(patsubst %.gz,%,$(my_dex_location))
$(my_built_profile): PRIVATE_BUILT_MODULE := $(dex_preopt_profile_src_file)
$(my_built_profile): PRIVATE_DEX_LOCATION := $(my_dex_location)
-$(my_built_profile): PRIVATE_SOURCE_CLASSES := $(LOCAL_DEX_PREOPT_PROFILE_CLASS_LISTING)
-$(my_built_profile): $(LOCAL_DEX_PREOPT_PROFILE_CLASS_LISTING)
+$(my_built_profile): PRIVATE_SOURCE_CLASSES := $(LOCAL_DEX_PREOPT_PROFILE)
+$(my_built_profile): $(LOCAL_DEX_PREOPT_PROFILE)
$(my_built_profile): $(PROFMAN)
$(my_built_profile): $(dex_preopt_profile_src_file)
-$(my_built_profile):
+ifeq (true,$(my_profile_is_text_listing))
+# The profile is a test listing of classes (used for framework jars).
+# We need to generate the actual binary profile before being able to compile.
$(hide) mkdir -p $(dir $@)
ANDROID_LOG_TAGS="*:e" $(PROFMAN) \
--create-profile-from=$(PRIVATE_SOURCE_CLASSES) \
--apk=$(PRIVATE_BUILT_MODULE) \
--dex-location=$(PRIVATE_DEX_LOCATION) \
--reference-profile-file=$@
-dex_preopt_profile_src_file:=
-# Remove compressed APK extension.
+else
+# The profile is binary profile (used for apps). Run it through profman to
+# ensure the profile keys match the apk.
+$(my_built_profile):
+ $(hide) mkdir -p $(dir $@)
+ touch $@
+ ANDROID_LOG_TAGS="*:i" $(PROFMAN) \
+ --copy-and-update-profile-key \
+ --profile-file=$(PRIVATE_SOURCE_CLASSES) \
+ --apk=$(PRIVATE_BUILT_MODULE) \
+ --dex-location=$(PRIVATE_DEX_LOCATION) \
+ --reference-profile-file=$@ \
+ || echo "Profile out of date for $(PRIVATE_BUILT_MODULE)"
+endif
+
+my_profile_is_text_listing :=
+dex_preopt_profile_src_file :=
+
+# Remove compressed APK extension.
my_installed_profile := $(patsubst %.gz,%,$(LOCAL_INSTALLED_MODULE)).prof
+
# my_installed_profile := $(LOCAL_INSTALLED_MODULE).prof
$(eval $(call copy-one-file,$(my_built_profile),$(my_installed_profile)))
build_installed_profile:=$(my_built_profile):$(my_installed_profile)
@@ -125,6 +179,12 @@
ifdef LOCAL_DEX_PREOPT
dexpreopt_boot_jar_module := $(filter $(DEXPREOPT_BOOT_JARS_MODULES),$(LOCAL_MODULE))
+
+# Filter org.apache.http.legacy.boot.
+ifeq ($(dexpreopt_boot_jar_module),org.apache.http.legacy.boot)
+dexpreopt_boot_jar_module :=
+endif
+
ifdef dexpreopt_boot_jar_module
# 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.
@@ -178,7 +238,7 @@
installed_art := $(strip $(installed_art))
ifdef built_odex
-ifeq (true,$(LOCAL_DEX_PREOPT_GENERATE_PROFILE))
+ifeq (true,$(my_process_profile))
$(built_odex): $(my_built_profile)
$(built_odex): PRIVATE_PROFILE_PREOPT_FLAGS := --profile-file=$(my_built_profile)
else
@@ -197,6 +257,12 @@
my_system_server_compiler_filter := speed
endif
+my_default_compiler_filter := $(PRODUCT_DEX_PREOPT_DEFAULT_COMPILER_FILTER)
+ifeq (,$(my_default_compiler_filter))
+# If no default compiler filter is specified, default to 'quicken' to save on storage.
+my_default_compiler_filter := quicken
+endif
+
ifeq (,$(filter --compiler-filter=%, $(LOCAL_DEX_PREOPT_FLAGS)))
ifneq (,$(filter $(PRODUCT_SYSTEM_SERVER_JARS),$(LOCAL_MODULE)))
# Jars of system server, use the product option if it is set, speed otherwise.
@@ -207,45 +273,107 @@
# 'speed' compiler filter.
LOCAL_DEX_PREOPT_FLAGS += --compiler-filter=speed
else
- ifeq (true,$(LOCAL_DEX_PREOPT_GENERATE_PROFILE))
+ ifeq (true,$(my_process_profile))
# For non system server jars, use speed-profile when we have a profile.
LOCAL_DEX_PREOPT_FLAGS += --compiler-filter=speed-profile
else
- # If no compiler filter is specified, default to 'quicken' to save on storage.
- LOCAL_DEX_PREOPT_FLAGS += --compiler-filter=quicken
+ LOCAL_DEX_PREOPT_FLAGS += --compiler-filter=$(my_default_compiler_filter)
endif
endif
endif
endif
-# PRODUCT_SYSTEM_SERVER_DEBUG_INFO overrides WITH_DEXPREOPT_DEBUG_INFO.
-my_system_server_debug_info := $(PRODUCT_SYSTEM_SERVER_DEBUG_INFO)
-ifeq (,$(filter eng, $(TARGET_BUILD_VARIANT)))
-# Only enable for non-eng builds.
-ifeq (,$(my_system_server_debug_info))
-my_system_server_debug_info := true
-endif
+my_generate_dm := $(PRODUCT_DEX_PREOPT_GENERATE_DM_FILES)
+ifeq (,$(filter $(LOCAL_DEX_PREOPT_FLAGS),--compiler-filter=verify))
+# Generating DM files only makes sense for verify, avoid doing for non verify compiler filter APKs.
+my_generate_dm := false
endif
-ifeq (true, $(my_system_server_debug_info))
- ifneq (,$(filter $(PRODUCT_SYSTEM_SERVER_JARS),$(LOCAL_MODULE)))
- LOCAL_DEX_PREOPT_FLAGS += --generate-mini-debug-info
+# No reason to use a dm file if the dex is already uncompressed.
+ifeq ($(LOCAL_UNCOMPRESS_DEX),true)
+my_generate_dm := false
+endif
+
+ifeq (true,$(my_generate_dm))
+LOCAL_DEX_PREOPT_FLAGS += --copy-dex-files=false
+LOCAL_DEX_PREOPT := nostripping
+my_built_dm := $(dir $(LOCAL_BUILT_MODULE))generated.dm
+my_installed_dm := $(patsubst %.apk,%,$(LOCAL_INSTALLED_MODULE)).dm
+my_copied_vdex := $(dir $(LOCAL_BUILT_MODULE))primary.vdex
+$(eval $(call copy-one-file,$(built_vdex),$(my_copied_vdex)))
+$(my_built_dm): PRIVATE_INPUT_VDEX := $(my_copied_vdex)
+$(my_built_dm): $(my_copied_vdex) $(ZIPTIME)
+ $(hide) mkdir -p $(dir $@)
+ $(hide) rm -f $@
+ $(hide) zip -qD -j -X -9 $@ $(PRIVATE_INPUT_VDEX)
+ $(ZIPTIME) $@
+$(eval $(call copy-one-file,$(my_built_dm),$(my_installed_dm)))
+endif
+
+# By default, emit debug info.
+my_dexpreopt_debug_info := true
+# If the global setting suppresses mini-debug-info, disable it.
+ifeq (false,$(WITH_DEXPREOPT_DEBUG_INFO))
+ my_dexpreopt_debug_info := false
+endif
+
+# PRODUCT_SYSTEM_SERVER_DEBUG_INFO overrides WITH_DEXPREOPT_DEBUG_INFO.
+# PRODUCT_OTHER_JAVA_DEBUG_INFO overrides WITH_DEXPREOPT_DEBUG_INFO.
+ifneq (,$(filter $(PRODUCT_SYSTEM_SERVER_JARS),$(LOCAL_MODULE)))
+ ifeq (true,$(PRODUCT_SYSTEM_SERVER_DEBUG_INFO))
+ my_dexpreopt_debug_info := true
+ else ifeq (false,$(PRODUCT_SYSTEM_SERVER_DEBUG_INFO))
+ my_dexpreopt_debug_info := false
+ endif
+else
+ ifeq (true,$(PRODUCT_OTHER_JAVA_DEBUG_INFO))
+ my_dexpreopt_debug_info := true
+ else ifeq (false,$(PRODUCT_OTHER_JAVA_DEBUG_INFO))
+ my_dexpreopt_debug_info := false
endif
endif
+# Never enable on eng.
+ifeq (eng,$(filter eng, $(TARGET_BUILD_VARIANT)))
+my_dexpreopt_debug_info := false
+endif
+
+# Add dex2oat flag for debug-info/no-debug-info.
+ifeq (true,$(my_dexpreopt_debug_info))
+ LOCAL_DEX_PREOPT_FLAGS += --generate-mini-debug-info
+else ifeq (false,$(my_dexpreopt_debug_info))
+ LOCAL_DEX_PREOPT_FLAGS += --no-generate-mini-debug-info
+endif
+
+# Set the compiler reason to 'prebuilt' to identify the oat files produced
+# during the build, as opposed to compiled on the device.
+LOCAL_DEX_PREOPT_FLAGS += --compilation-reason=prebuilt
+
$(built_odex): PRIVATE_DEX_PREOPT_FLAGS := $(LOCAL_DEX_PREOPT_FLAGS)
$(built_vdex): $(built_odex)
$(built_art): $(built_odex)
endif
-# Add the installed_odex to the list of installed files for this module.
-ALL_MODULES.$(my_register_name).INSTALLED += $(installed_odex)
-ALL_MODULES.$(my_register_name).INSTALLED += $(installed_vdex)
-ALL_MODULES.$(my_register_name).INSTALLED += $(installed_art)
+ifneq (true,$(my_generate_dm))
+ # Add the installed_odex to the list of installed files for this module if we aren't generating a
+ # dm file.
+ ALL_MODULES.$(my_register_name).INSTALLED += $(installed_odex)
+ ALL_MODULES.$(my_register_name).INSTALLED += $(installed_vdex)
+ ALL_MODULES.$(my_register_name).INSTALLED += $(installed_art)
-ALL_MODULES.$(my_register_name).BUILT_INSTALLED += $(built_installed_odex)
-ALL_MODULES.$(my_register_name).BUILT_INSTALLED += $(built_installed_vdex)
-ALL_MODULES.$(my_register_name).BUILT_INSTALLED += $(built_installed_art)
+ ALL_MODULES.$(my_register_name).BUILT_INSTALLED += $(built_installed_odex)
+ ALL_MODULES.$(my_register_name).BUILT_INSTALLED += $(built_installed_vdex)
+ ALL_MODULES.$(my_register_name).BUILT_INSTALLED += $(built_installed_art)
+
+ # Make sure to install the .odex and .vdex when you run "make <module_name>"
+ $(my_all_targets): $(installed_odex) $(installed_vdex) $(installed_art)
+else
+ ALL_MODULES.$(my_register_name).INSTALLED += $(my_installed_dm)
+ ALL_MODULES.$(my_register_name).BUILT_INSTALLED += $(my_built_dm) $(my_installed_dm)
+
+ # Make sure to install the .dm when you run "make <module_name>"
+ $(my_all_targets): $(installed_dm)
+endif
# Record dex-preopt config.
DEXPREOPT.$(LOCAL_MODULE).DEX_PREOPT := $(LOCAL_DEX_PREOPT)
@@ -259,14 +387,12 @@
DEXPREOPT.MODULES.$(LOCAL_MODULE_CLASS) := $(sort \
$(DEXPREOPT.MODULES.$(LOCAL_MODULE_CLASS)) $(LOCAL_MODULE))
-
-# Make sure to install the .odex and .vdex when you run "make <module_name>"
-$(my_all_targets): $(installed_odex) $(installed_vdex) $(installed_art)
-
endif # LOCAL_DEX_PREOPT
# Profile doesn't depend on LOCAL_DEX_PREOPT.
ALL_MODULES.$(my_register_name).INSTALLED += $(my_installed_profile)
ALL_MODULES.$(my_register_name).BUILT_INSTALLED += $(build_installed_profile)
+my_process_profile :=
+
$(my_all_targets): $(my_installed_profile)
diff --git a/core/distdir.mk b/core/distdir.mk
index 89c5966..c074186 100644
--- a/core/distdir.mk
+++ b/core/distdir.mk
@@ -17,9 +17,6 @@
# When specifying "dist", the user has asked that we copy the important
# files from this build into DIST_DIR.
-dist_goal := $(strip $(filter dist,$(MAKECMDGOALS)))
-MAKECMDGOALS := $(strip $(filter-out dist,$(MAKECMDGOALS)))
-
ifdef dist_goal
# $(1): source file
diff --git a/core/dpi_specific_apk.mk b/core/dpi_specific_apk.mk
index 1b0be07..f32daf5 100644
--- a/core/dpi_specific_apk.mk
+++ b/core/dpi_specific_apk.mk
@@ -9,7 +9,7 @@
# Set up all the target-specific variables.
$(built_dpi_apk): PRIVATE_MODULE := $(dpi_apk_name)
-$(built_dpi_apk): PRIVATE_AAPT_FLAGS := $(LOCAL_AAPT_FLAGS) $(PRODUCT_AAPT_FLAGS) $($(LOCAL_PACKAGE_NAME)_aapt_flags_$(my_dpi))
+$(built_dpi_apk): PRIVATE_AAPT_FLAGS := $(LOCAL_AAPT_FLAGS) --pseudo-localize $($(LOCAL_PACKAGE_NAME)_aapt_flags_$(my_dpi))
# Clear PRIVATE_PRODUCT_AAPT_CONFIG to include everything by default.
$(built_dpi_apk): PRIVATE_PRODUCT_AAPT_CONFIG :=
$(built_dpi_apk): PRIVATE_PRODUCT_AAPT_PREF_CONFIG := $(my_dpi)
@@ -17,8 +17,9 @@
$(built_dpi_apk): PRIVATE_RESOURCE_DIR := $(LOCAL_RESOURCE_DIR)
$(built_dpi_apk): PRIVATE_ASSET_DIR := $(LOCAL_ASSET_DIR)
$(built_dpi_apk): PRIVATE_AAPT_INCLUDES := $(all_library_res_package_exports)
-ifneq (,$(filter-out current system_current test_current, $(LOCAL_SDK_VERSION)))
-$(built_dpi_apk): PRIVATE_DEFAULT_APP_TARGET_SDK := $(LOCAL_SDK_VERSION)
+$(built_dpi_apk): PRIVATE_RESOURCE_LIST := $(all_res_assets)
+ifneq (,$(filter-out current system_current test_current core_current, $(LOCAL_SDK_VERSION)))
+$(built_dpi_apk): PRIVATE_DEFAULT_APP_TARGET_SDK := $(call get-numeric-sdk-version,$(LOCAL_SDK_VERSION))
else
$(built_dpi_apk): PRIVATE_DEFAULT_APP_TARGET_SDK := $(DEFAULT_APP_TARGET_SDK)
endif
@@ -34,12 +35,8 @@
$(built_dpi_apk): PRIVATE_SOURCE_ARCHIVE :=
ifneq ($(full_classes_jar),)
$(built_dpi_apk): PRIVATE_DEX_FILE := $(built_dex)
-ifndef LOCAL_JACK_ENABLED
# Use the jarjar processed arhive as the initial package file.
$(built_dpi_apk): PRIVATE_SOURCE_ARCHIVE := $(full_classes_pre_proguard_jar)
-else
-$(built_dpi_apk): PRIVATE_JACK_INTERMEDIATES_DIR := $(intermediates.COMMON)/jack-rsc
-endif # LOCAL_JACK_ENABLED
$(built_dpi_apk): $(built_dex)
else
$(built_dpi_apk): PRIVATE_DEX_FILE :=
@@ -64,9 +61,6 @@
$(if $(PRIVATE_EXTRA_JAR_ARGS),$(call add-java-resources-to,$@))
else
$(add-dex-to-package)
-ifdef LOCAL_JACK_ENABLED
- $(add-carried-jack-resources)
-endif
endif
$(sign-package)
diff --git a/core/droiddoc.mk b/core/droiddoc.mk
index 94e282d..bcd2002 100644
--- a/core/droiddoc.mk
+++ b/core/droiddoc.mk
@@ -15,12 +15,9 @@
#
$(call record-module-type,DROIDDOC)
-##
-##
-## Common to both droiddoc and javadoc
-##
-##
-
+###########################################################
+## Common logic to both droiddoc and javadoc
+###########################################################
LOCAL_IS_HOST_MODULE := $(call true-or-empty,$(LOCAL_IS_HOST_MODULE))
ifeq ($(LOCAL_IS_HOST_MODULE),true)
my_prefix := HOST_
@@ -54,10 +51,10 @@
endif
ifeq ($(LOCAL_IS_HOST_MODULE),true)
+
$(full_target): PRIVATE_BOOTCLASSPATH :=
full_java_libs := $(addprefix $(HOST_OUT_JAVA_LIBRARIES)/,\
$(addsuffix $(COMMON_JAVA_PACKAGE_SUFFIX),$(LOCAL_JAVA_LIBRARIES)))
-full_java_lib_deps := $(full_java_libs)
else
@@ -72,30 +69,43 @@
else ifeq ($(LOCAL_SDK_VERSION)$(TARGET_BUILD_APPS),test_current)
LOCAL_JAVA_LIBRARIES := android_test_stubs_current $(LOCAL_JAVA_LIBRARIES)
$(full_target): PRIVATE_BOOTCLASSPATH := $(call java-lib-files, android_test_stubs_current)
+ else ifeq ($(LOCAL_SDK_VERSION)$(TARGET_BUILD_APPS),core_current)
+ LOCAL_JAVA_LIBRARIES := core.current.stubs $(LOCAL_JAVA_LIBRARIES)
+ $(full_target): PRIVATE_BOOTCLASSPATH := $(call java-lib-files, core.current.stubs)
else
- LOCAL_JAVA_LIBRARIES := sdk_v$(LOCAL_SDK_VERSION) $(LOCAL_JAVA_LIBRARIES)
- $(full_target): PRIVATE_BOOTCLASSPATH := $(call java-lib-files, sdk_v$(LOCAL_SDK_VERSION))
+ # core_<ver> is subset of <ver>. Instead of defining a prebuilt lib for core_<ver>,
+ # use the stub for <ver> when building for apps.
+ _version := $(patsubst core_%,%,$(LOCAL_SDK_VERSION))
+ LOCAL_JAVA_LIBRARIES := sdk_v$(_version) $(LOCAL_JAVA_LIBRARIES)
+ $(full_target): PRIVATE_BOOTCLASSPATH := $(call java-lib-files, sdk_v$(_version))
+ _version :=
endif
else
- LOCAL_JAVA_LIBRARIES := core-oj core-libart ext framework $(LOCAL_JAVA_LIBRARIES)
+ ifeq ($(LOCAL_NO_STANDARD_LIBRARIES),true)
+ LOCAL_JAVA_LIBRARIES := core-oj core-libart
+ else
+ LOCAL_JAVA_LIBRARIES := core-oj core-libart ext framework $(LOCAL_JAVA_LIBRARIES)
+ endif
$(full_target): PRIVATE_BOOTCLASSPATH := $(call java-lib-files, core-oj):$(call java-lib-files, core-libart)
endif # LOCAL_SDK_VERSION
LOCAL_JAVA_LIBRARIES := $(sort $(LOCAL_JAVA_LIBRARIES))
full_java_libs := $(call java-lib-files,$(LOCAL_JAVA_LIBRARIES)) $(LOCAL_CLASSPATH)
-full_java_lib_deps := $(call java-lib-deps,$(LOCAL_JAVA_LIBRARIES)) $(LOCAL_CLASSPATH)
endif # !LOCAL_IS_HOST_MODULE
-$(full_target): PRIVATE_CLASSPATH := $(subst $(space),:,$(full_java_libs))
-
+$(full_target): PRIVATE_CLASSPATH := $(call normalize-path-list,$(full_java_libs))
intermediates.COMMON := $(call local-intermediates-dir,COMMON)
$(full_target): PRIVATE_SOURCE_PATH := $(call normalize-path-list,$(LOCAL_DROIDDOC_SOURCE_PATH))
$(full_target): PRIVATE_JAVA_FILES := $(filter %.java,$(full_src_files))
$(full_target): PRIVATE_JAVA_FILES += $(addprefix $($(my_prefix)OUT_COMMON_INTERMEDIATES)/, $(filter %.java,$(LOCAL_INTERMEDIATE_SOURCES)))
+$(full_target): PRIVATE_JAVA_FILES += $(filter %.java,$(LOCAL_GENERATED_SOURCES))
+$(full_target): PRIVATE_SRCJARS := $(LOCAL_SRCJARS)
$(full_target): PRIVATE_SOURCE_INTERMEDIATES_DIR := $(intermediates.COMMON)/src
+$(full_target): PRIVATE_SRCJAR_INTERMEDIATES_DIR := $(intermediates.COMMON)/srcjars
$(full_target): PRIVATE_SRC_LIST_FILE := $(intermediates.COMMON)/droiddoc-src-list
+$(full_target): PRIVATE_SRCJAR_LIST_FILE := $(intermediates.COMMON)/droiddoc-srcjar-list
ifneq ($(strip $(LOCAL_ADDITIONAL_JAVA_DIR)),)
$(full_target): PRIVATE_ADDITIONAL_JAVA_DIR := $(LOCAL_ADDITIONAL_JAVA_DIR)
@@ -104,6 +114,7 @@
$(full_target): PRIVATE_OUT_DIR := $(out_dir)
$(full_target): PRIVATE_DROIDDOC_OPTIONS := $(LOCAL_DROIDDOC_OPTIONS)
$(full_target): PRIVATE_STUB_OUT_DIR := $(LOCAL_DROIDDOC_STUB_OUT_DIR)
+$(full_target): PRIVATE_METALAVA_DOCS_STUB_OUT_DIR := $(LOCAL_DROIDDOC_METALAVA_DOCS_STUB_OUT_DIR)
# Lists the input files for the doc build into a text file
# suitable for the @ syntax of javadoc.
@@ -116,18 +127,10 @@
$(hide) for d in $(3) ; do find $$d -name '*.java' -and -not -name '.*' >> $(1) 2> /dev/null ; done ; true
endef
-ifeq (a,b)
-$(full_target): PRIVATE_PROFILING_OPTIONS := \
- -J-agentlib:jprofilerti=port=8849 -J-Xbootclasspath/a:/Applications/jprofiler5/bin/agent.jar
-endif
-
-
+###########################################################
+## Logic for droiddoc only
+###########################################################
ifneq ($(strip $(LOCAL_DROIDDOC_USE_STANDARD_DOCLET)),true)
-##
-##
-## droiddoc only
-##
-##
droiddoc_templates := \
$(sort $(shell find $(LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR) -type f $(if $(ALLOW_MISSING_DEPENDENCIES),2>/dev/null)))
@@ -138,10 +141,6 @@
endif
endif
-droiddoc := \
- $(HOST_JDK_TOOLS_JAR) \
- $(HOST_OUT_JAVA_LIBRARIES)/doclava$(COMMON_JAVA_PACKAGE_SUFFIX)
-
$(full_target): PRIVATE_DOCLETPATH := $(HOST_OUT_JAVA_LIBRARIES)/jsilver$(COMMON_JAVA_PACKAGE_SUFFIX):$(HOST_OUT_JAVA_LIBRARIES)/doclava$(COMMON_JAVA_PACKAGE_SUFFIX)
$(full_target): PRIVATE_CURRENT_BUILD := -hdf page.build $(BUILD_ID)-$(BUILD_NUMBER_FROM_FILE)
$(full_target): PRIVATE_CURRENT_TIME := -hdf page.now "$$($(DATE_FROM_FILE) "+%d %b %Y %k:%M")"
@@ -163,60 +162,162 @@
$(full_target): PRIVATE_ADDITIONAL_HTML_DIR :=
endif
-# TODO: not clear if this is used any more
+# TODO(nanzhang): Remove it if this is not used any more
$(full_target): PRIVATE_LOCAL_PATH := $(LOCAL_PATH)
+ifeq ($(strip $(LOCAL_DROIDDOC_USE_METALAVA)),true)
+ifneq ($(LOCAL_DROIDDOC_METALAVA_PREVIOUS_API),)
+$(full_target): PRIVATE_DROIDDOC_METALAVA_PREVIOUS_API := --previous-api $(LOCAL_DROIDDOC_METALAVA_PREVIOUS_API)
+else
+$(full_target): PRIVATE_DROIDDOC_METALAVA_PREVIOUS_API :=
+endif #!LOCAL_DROIDDOC_METALAVA_PREVIOUS_API
+
+metalava_annotations_deps :=
+ifeq ($(strip $(LOCAL_DROIDDOC_METALAVA_ANNOTATIONS_ENABLED)),true)
+ifeq ($(LOCAL_DROIDDOC_METALAVA_PREVIOUS_API),)
+$(error $(LOCAL_PATH): LOCAL_DROIDDOC_METALAVA_PREVIOUS_API has to be non-empty if metalava annotations was enabled!)
+endif
+ifeq ($(LOCAL_DROIDDOC_METALAVA_MERGE_ANNOTATIONS_DIR),)
+$(error $(LOCAL_PATH): LOCAL_DROIDDOC_METALAVA_MERGE_ANNOTATIONS_DIR has to be non-empty if metalava annotations was enabled!)
+endif
+
+$(full_target): PRIVATE_DROIDDOC_METALAVA_ANNOTATIONS := --include-annotations --migrate-nullness \
+ --extract-annotations $(TARGET_OUT_COMMON_INTERMEDIATES)/PACKAGING/$(LOCAL_MODULE)_annotations.zip \
+ --merge-annotations $(LOCAL_DROIDDOC_METALAVA_MERGE_ANNOTATIONS_DIR) \
+ --hide HiddenTypedefConstant --hide SuperfluousPrefix --hide AnnotationExtraction
+metalava_annotations_deps := $(sort $(shell find $(LOCAL_DROIDDOC_METALAVA_MERGE_ANNOTATIONS_DIR) -type f))
+else
+$(full_target): PRIVATE_DROIDDOC_METALAVA_ANNOTATIONS :=
+endif #LOCAL_DROIDDOC_METALAVA_ANNOTATIONS_ENABLED=true
+
+ifneq (,$(filter --generate-documentation,$(LOCAL_DROIDDOC_OPTIONS)))
+
+pos = $(if $(findstring $1,$2),$(call pos,$1,$(wordlist 2,$(words $2),$2),x $3),$3)
+metalava_args := $(wordlist 1, $(words $(call pos,--generate-documentation,$(LOCAL_DROIDDOC_OPTIONS))), \
+ $(LOCAL_DROIDDOC_OPTIONS))
+remaining_args := $(wordlist $(words $(call pos,--generate-documentation,$(LOCAL_DROIDDOC_OPTIONS))), \
+ $(words $(LOCAL_DROIDDOC_OPTIONS)), $(LOCAL_DROIDDOC_OPTIONS))
+doclava_args := $(wordlist 2, $(words $(remaining_args)), $(remaining_args))
+
+$(full_target): \
+ $(full_src_files) $(LOCAL_GENERATED_SOURCES) \
+ $(droiddoc_templates) \
+ $(HOST_JDK_TOOLS_JAR) \
+ $(HOST_OUT_JAVA_LIBRARIES)/jsilver$(COMMON_JAVA_PACKAGE_SUFFIX) \
+ $(HOST_OUT_JAVA_LIBRARIES)/doclava$(COMMON_JAVA_PACKAGE_SUFFIX) \
+ $(HOST_OUT_JAVA_LIBRARIES)/metalava$(COMMON_JAVA_PACKAGE_SUFFIX) \
+ $(html_dir_files) \
+ $(full_java_libs) \
+ $(ZIPSYNC) \
+ $(LOCAL_SRCJARS) \
+ $(LOCAL_ADDITIONAL_DEPENDENCIES) \
+ $(LOCAL_DROIDDOC_METALAVA_PREVIOUS_API) \
+ $(metalava_annotations_deps)
+ @echo metalava based docs: $(PRIVATE_OUT_DIR)
+ $(hide) mkdir -p $(dir $@)
+ $(hide) rm -rf $(PRIVATE_STUB_OUT_DIR)
+ $(hide) rm -rf $(PRIVATE_METALAVA_DOCS_STUB_OUT_DIR)
+ $(call prepare-doc-source-list,$(PRIVATE_SRC_LIST_FILE),$(PRIVATE_JAVA_FILES), \
+ $(PRIVATE_SOURCE_INTERMEDIATES_DIR) $(PRIVATE_ADDITIONAL_JAVA_DIR))
+ $(ZIPSYNC) -d $(PRIVATE_SRCJAR_INTERMEDIATES_DIR) -l $(PRIVATE_SRCJAR_LIST_FILE) -f "*.java" $(PRIVATE_SRCJARS)
+ $(hide) ( \
+ $(JAVA) -jar $(HOST_OUT_JAVA_LIBRARIES)/metalava$(COMMON_JAVA_PACKAGE_SUFFIX) \
+ -encoding UTF-8 -source 1.8 \@$(PRIVATE_SRC_LIST_FILE) \@$(PRIVATE_SRCJAR_LIST_FILE) \
+ $(addprefix -bootclasspath ,$(PRIVATE_BOOTCLASSPATH)) \
+ $(addprefix -classpath ,$(PRIVATE_CLASSPATH)) \
+ --sourcepath $(PRIVATE_SOURCE_PATH) \
+ --no-banner --color --quiet \
+ $(addprefix --stubs ,$(PRIVATE_STUB_OUT_DIR)) \
+ $(addprefix --doc-stubs ,$(PRIVATE_METALAVA_DOCS_STUB_OUT_DIR)) \
+ --write-stubs-source-list $(intermediates.COMMON)/stubs-src-list \
+ $(metalava_args) $(PRIVATE_DROIDDOC_METALAVA_PREVIOUS_API) $(PRIVATE_DROIDDOC_METALAVA_ANNOTATIONS) \
+ $(JAVADOC) -encoding UTF-8 -source 1.8 STUBS_SOURCE_LIST \
+ -J-Xmx1600m -J-XX:-OmitStackTraceInFastThrow -XDignore.symbol.file \
+ -quiet -doclet com.google.doclava.Doclava -docletpath $(PRIVATE_DOCLETPATH) \
+ -templatedir $(PRIVATE_CUSTOM_TEMPLATE_DIR) \
+ $(PRIVATE_DROIDDOC_HTML_DIR) $(PRIVATE_ADDITIONAL_HTML_DIR) \
+ $(addprefix -bootclasspath ,$(PRIVATE_BOOTCLASSPATH)) \
+ $(addprefix -classpath ,$(PRIVATE_CLASSPATH)) \
+ -sourcepath $(PRIVATE_SOURCE_PATH) \
+ -d $(PRIVATE_OUT_DIR) \
+ $(PRIVATE_CURRENT_BUILD) $(PRIVATE_CURRENT_TIME) $(doclava_args) \
+ && touch -f $@ ) || (rm -rf $(PRIVATE_OUT_DIR) $(PRIVATE_SRC_LIST_FILE); exit 45)
+else
+# no docs generation
+$(full_target): \
+ $(full_src_files) $(LOCAL_GENERATED_SOURCES) \
+ $(full_java_libs) \
+ $(HOST_OUT_JAVA_LIBRARIES)/metalava$(COMMON_JAVA_PACKAGE_SUFFIX) \
+ $(ZIPSYNC) \
+ $(LOCAL_SRCJARS) \
+ $(LOCAL_ADDITIONAL_DEPENDENCIES)
+ @echo metalava based stubs: $@
+ $(hide) mkdir -p $(dir $@)
+ $(hide) rm -rf $(PRIVATE_STUB_OUT_DIR)
+ $(call prepare-doc-source-list,$(PRIVATE_SRC_LIST_FILE),$(PRIVATE_JAVA_FILES), \
+ $(PRIVATE_SOURCE_INTERMEDIATES_DIR) $(PRIVATE_ADDITIONAL_JAVA_DIR))
+ $(ZIPSYNC) -d $(PRIVATE_SRCJAR_INTERMEDIATES_DIR) -l $(PRIVATE_SRCJAR_LIST_FILE) -f "*.java" $(PRIVATE_SRCJARS)
+ $(hide) ( \
+ $(JAVA) -jar $(HOST_OUT_JAVA_LIBRARIES)/metalava$(COMMON_JAVA_PACKAGE_SUFFIX) \
+ -encoding UTF-8 -source 1.8 \@$(PRIVATE_SRC_LIST_FILE) \@$(PRIVATE_SRCJAR_LIST_FILE) \
+ $(addprefix -bootclasspath ,$(PRIVATE_BOOTCLASSPATH)) \
+ $(addprefix -classpath ,$(PRIVATE_CLASSPATH)) \
+ --sourcepath $(PRIVATE_SOURCE_PATH) \
+ $(PRIVATE_DROIDDOC_OPTIONS) $(PRIVATE_DROIDDOC_METALAVA_PREVIOUS_API) $(PRIVATE_DROIDDOC_METALAVA_ANNOTATIONS) \
+ --no-banner --color --quiet \
+ $(addprefix --stubs ,$(PRIVATE_STUB_OUT_DIR)) \
+ && touch -f $@ ) || (rm -rf $(PRIVATE_SRC_LIST_FILE); exit 45)
+
+endif # stubs + docs generation
+ifeq ($(strip $(LOCAL_DROIDDOC_METALAVA_ANNOTATIONS_ENABLED)),true)
+$(TARGET_OUT_COMMON_INTERMEDIATES)/PACKAGING/$(LOCAL_MODULE)_annotations.zip: $(full_target)
+endif
+
+else # doclava based droiddoc generation
+
# TODO(tobiast): Clean this up once we move to -source 1.9.
# OpenJDK 9 does not have the concept of a "boot classpath" so we should
# then rename PRIVATE_BOOTCLASSPATH to PRIVATE_MODULE or similar. For now,
# keep -bootclasspath here since it works in combination with -source 1.8.
$(full_target): \
- $(full_src_files) \
+ $(full_src_files) $(LOCAL_GENERATED_SOURCES) \
$(droiddoc_templates) \
- $(droiddoc) \
+ $(HOST_JDK_TOOLS_JAR) \
+ $(HOST_OUT_JAVA_LIBRARIES)/jsilver$(COMMON_JAVA_PACKAGE_SUFFIX) \
+ $(HOST_OUT_JAVA_LIBRARIES)/doclava$(COMMON_JAVA_PACKAGE_SUFFIX) \
$(html_dir_files) \
- $(full_java_lib_deps) \
+ $(full_java_libs) \
+ $(ZIPSYNC) \
+ $(LOCAL_SRCJARS) \
$(LOCAL_ADDITIONAL_DEPENDENCIES)
@echo Docs droiddoc: $(PRIVATE_OUT_DIR)
$(hide) mkdir -p $(dir $@)
- $(addprefix $(hide) rm -rf ,$(PRIVATE_STUB_OUT_DIR))
+ $(hide) rm -rf $(PRIVATE_STUB_OUT_DIR)
$(call prepare-doc-source-list,$(PRIVATE_SRC_LIST_FILE),$(PRIVATE_JAVA_FILES), \
$(PRIVATE_SOURCE_INTERMEDIATES_DIR) $(PRIVATE_ADDITIONAL_JAVA_DIR))
+ $(ZIPSYNC) -d $(PRIVATE_SRCJAR_INTERMEDIATES_DIR) -l $(PRIVATE_SRCJAR_LIST_FILE) -f "*.java" $(PRIVATE_SRCJARS)
$(hide) ( \
$(JAVADOC) \
- -encoding UTF-8 \
- -source 1.8 \
- \@$(PRIVATE_SRC_LIST_FILE) \
- -J-Xmx1600m \
- -J-XX:-OmitStackTraceInFastThrow \
- -XDignore.symbol.file \
- $(PRIVATE_PROFILING_OPTIONS) \
- -quiet \
- -doclet com.google.doclava.Doclava \
- -docletpath $(PRIVATE_DOCLETPATH) \
+ -encoding UTF-8 -source 1.8 \@$(PRIVATE_SRC_LIST_FILE) \@$(PRIVATE_SRCJAR_LIST_FILE) \
+ -J-Xmx1600m -J-XX:-OmitStackTraceInFastThrow -XDignore.symbol.file \
+ -quiet -doclet com.google.doclava.Doclava -docletpath $(PRIVATE_DOCLETPATH) \
-templatedir $(PRIVATE_CUSTOM_TEMPLATE_DIR) \
- $(PRIVATE_DROIDDOC_HTML_DIR) \
- $(PRIVATE_ADDITIONAL_HTML_DIR) \
+ $(PRIVATE_DROIDDOC_HTML_DIR) $(PRIVATE_ADDITIONAL_HTML_DIR) \
$(addprefix -bootclasspath ,$(PRIVATE_BOOTCLASSPATH)) \
$(addprefix -classpath ,$(PRIVATE_CLASSPATH)) \
-sourcepath $(PRIVATE_SOURCE_PATH)$(addprefix :,$(PRIVATE_CLASSPATH)) \
-d $(PRIVATE_OUT_DIR) \
- $(PRIVATE_CURRENT_BUILD) $(PRIVATE_CURRENT_TIME) \
- $(PRIVATE_DROIDDOC_OPTIONS) \
+ $(PRIVATE_CURRENT_BUILD) $(PRIVATE_CURRENT_TIME) $(PRIVATE_DROIDDOC_OPTIONS) \
$(addprefix -stubs ,$(PRIVATE_STUB_OUT_DIR)) \
- && touch -f $@ \
- ) || (rm -rf $(PRIVATE_OUT_DIR) $(PRIVATE_SRC_LIST_FILE); exit 45)
-
-
+ && touch -f $@ ) || (rm -rf $(PRIVATE_OUT_DIR) $(PRIVATE_SRC_LIST_FILE); exit 45)
+endif #LOCAL_DROIDDOC_USE_METALAVA
else
-##
-##
-## standard doclet only
-##
-##
-ifneq ($(EXPERIMENTAL_USE_OPENJDK9),)
+###########################################################
+## Logic for javadoc only
+###########################################################
+ifdef USE_OPENJDK9
# For OpenJDK 9 we use --patch-module to define the core libraries code.
# TODO(tobiast): Reorganize this when adding proper support for OpenJDK 9
# modules. Here we treat all code in core libraries as being in java.base
@@ -226,37 +327,22 @@
# For OpenJDK 8 we can use -bootclasspath to define the core libraries code.
$(full_target): PRIVATE_BOOTCLASSPATH_ARG := $(addprefix -bootclasspath ,$(PRIVATE_BOOTCLASSPATH))
endif
-
-$(full_target): $(full_src_files) $(full_java_lib_deps)
+$(full_target): $(full_src_files) $(LOCAL_GENERATED_SOURCES) $(full_java_libs) $(ZIPSYNC) $(LOCAL_SRCJARS) $(LOCAL_ADDITIONAL_DEPENDENCIES)
@echo Docs javadoc: $(PRIVATE_OUT_DIR)
@mkdir -p $(dir $@)
$(call prepare-doc-source-list,$(PRIVATE_SRC_LIST_FILE),$(PRIVATE_JAVA_FILES), \
$(PRIVATE_SOURCE_INTERMEDIATES_DIR) $(PRIVATE_ADDITIONAL_JAVA_DIR))
+ $(ZIPSYNC) -d $(PRIVATE_SRCJAR_INTERMEDIATES_DIR) -l $(PRIVATE_SRCJAR_LIST_FILE) -f "*.java" $(PRIVATE_SRCJARS)
$(hide) ( \
- $(JAVADOC) \
- -encoding UTF-8 \
- $(PRIVATE_DROIDDOC_OPTIONS) \
- \@$(PRIVATE_SRC_LIST_FILE) \
- -J-Xmx1024m \
- -XDignore.symbol.file \
- -Xdoclint:none \
- $(PRIVATE_PROFILING_OPTIONS) \
- $(addprefix -classpath ,$(PRIVATE_CLASSPATH)) \
- $(PRIVATE_BOOTCLASSPATH_ARG) \
- -sourcepath $(PRIVATE_SOURCE_PATH)$(addprefix :,$(PRIVATE_CLASSPATH)) \
+ $(JAVADOC) -encoding UTF-8 \@$(PRIVATE_SRC_LIST_FILE) \@$(PRIVATE_SRCJAR_LIST_FILE) \
+ $(PRIVATE_DROIDDOC_OPTIONS) -J-Xmx1024m -XDignore.symbol.file -Xdoclint:none -quiet \
+ $(addprefix -classpath ,$(PRIVATE_CLASSPATH)) $(PRIVATE_BOOTCLASSPATH_ARG) \
+ -sourcepath $(PRIVATE_SOURCE_PATH) \
-d $(PRIVATE_OUT_DIR) \
- -quiet \
&& touch -f $@ \
) || (rm -rf $(PRIVATE_OUT_DIR) $(PRIVATE_SRC_LIST_FILE); exit 45)
-
-endif
-##
-##
-## Common to both droiddoc and javadoc
-##
-##
-
+endif # !LOCAL_DROIDDOC_USE_STANDARD_DOCLET
ALL_DOCS += $(full_target)
@@ -278,4 +364,4 @@
$(call dist-for-goals,docs,$(out_zip))
-endif
+endif #!LOCAL_UNINSTALLABLE_MODULE
diff --git a/core/dumpvar.mk b/core/dumpvar.mk
index acae48e..59efb04 100644
--- a/core/dumpvar.mk
+++ b/core/dumpvar.mk
@@ -1,37 +1,3 @@
-
-# List of variables we want to print in the build banner.
-print_build_config_vars := \
- PLATFORM_VERSION_CODENAME \
- PLATFORM_VERSION \
- TARGET_PRODUCT \
- TARGET_BUILD_VARIANT \
- TARGET_BUILD_TYPE \
- TARGET_PLATFORM_VERSION \
- TARGET_BUILD_APPS \
- TARGET_ARCH \
- TARGET_ARCH_VARIANT \
- TARGET_CPU_VARIANT \
- TARGET_2ND_ARCH \
- TARGET_2ND_ARCH_VARIANT \
- TARGET_2ND_CPU_VARIANT \
- HOST_ARCH \
- HOST_2ND_ARCH \
- HOST_OS \
- HOST_OS_EXTRA \
- HOST_CROSS_OS \
- HOST_CROSS_ARCH \
- HOST_CROSS_2ND_ARCH \
- HOST_BUILD_TYPE \
- BUILD_ID \
- OUT_DIR \
- AUX_OS_VARIANT_LIST
-
-ifeq ($(TARGET_BUILD_PDK),true)
-print_build_config_vars += \
- TARGET_BUILD_PDK \
- PDK_FUSION_PLATFORM_ZIP
-endif
-
# ---------------------------------------------------------------
# the setpath shell function in envsetup.sh uses this to figure out
# what to add to the path given the config we have chosen.
@@ -52,79 +18,14 @@
ANDROID_PREBUILTS := prebuilt/$(HOST_PREBUILT_TAG)
ANDROID_GCC_PREBUILTS := prebuilts/gcc/$(HOST_PREBUILT_TAG)
-# The "dumpvar" stuff lets you say something like
-#
-# CALLED_FROM_SETUP=true \
-# make -f config/envsetup.make dumpvar-TARGET_OUT
-# or
-# CALLED_FROM_SETUP=true \
-# make -f config/envsetup.make dumpvar-abs-HOST_OUT_EXECUTABLES
-#
-# The plain (non-abs) version just dumps the value of the named variable.
-# The "abs" version will treat the variable as a path, and dumps an
-# absolute path to it.
-#
-dumpvar_goals := \
- $(strip $(patsubst dumpvar-%,%,$(filter dumpvar-%,$(MAKECMDGOALS))))
-ifdef dumpvar_goals
-
- ifneq ($(words $(dumpvar_goals)),1)
- $(error Only one "dumpvar-" goal allowed. Saw "$(MAKECMDGOALS)")
- endif
-
- # If the goal is of the form "dumpvar-abs-VARNAME", then
- # treat VARNAME as a path and return the absolute path to it.
- absolute_dumpvar := $(strip $(filter abs-%,$(dumpvar_goals)))
- ifdef absolute_dumpvar
- dumpvar_goals := $(patsubst abs-%,%,$(dumpvar_goals))
- DUMPVAR_VALUE := $(abspath $($(dumpvar_goals)))
- dumpvar_target := dumpvar-abs-$(dumpvar_goals)
- else
- DUMPVAR_VALUE := $($(dumpvar_goals))
- dumpvar_target := dumpvar-$(dumpvar_goals)
- endif
-
-.PHONY: $(dumpvar_target)
-$(dumpvar_target):
- @echo $(DUMPVAR_VALUE)
-
-endif # dumpvar_goals
-
-ifneq ($(dumpvar_goals),report_config)
-PRINT_BUILD_CONFIG:=
-endif
-
-ifneq ($(filter report_config,$(DUMP_MANY_VARS)),)
-# Construct the shell commands that print the config banner.
-report_config_sh := echo '============================================';
-report_config_sh += $(foreach v,$(print_build_config_vars),echo '$v=$($(v))';)
-report_config_sh += echo '============================================';
-endif
-
# Dump mulitple variables to "<var>=<value>" pairs, one per line.
# The output may be executed as bash script.
# Input variables:
# DUMP_MANY_VARS: the list of variable names.
# DUMP_VAR_PREFIX: an optional prefix of the variable name added to the output.
-# DUMP_MANY_ABS_VARS: the list of abs variable names.
-# DUMP_ABS_VAR_PREFIX: an optional prefix of the abs variable name added to the output.
.PHONY: dump-many-vars
dump-many-vars :
- @$(foreach v, $(filter-out report_config, $(DUMP_MANY_VARS)),\
+ @$(foreach v, $(DUMP_MANY_VARS),\
echo "$(DUMP_VAR_PREFIX)$(v)='$($(v))'";)
-ifneq ($(filter report_config, $(DUMP_MANY_VARS)),)
- @# Construct a special variable for report_config.
- @# Escape \` to defer the execution of report_config_sh to preserve the line breaks.
- @echo "$(DUMP_VAR_PREFIX)report_config=\`$(report_config_sh)\`"
-endif
- @$(foreach v, $(sort $(DUMP_MANY_ABS_VARS)),\
- echo "$(DUMP_ABS_VAR_PREFIX)$(v)='$(abspath $($(v)))'";)
endif # CALLED_FROM_SETUP
-
-ifneq ($(PRINT_BUILD_CONFIG),)
-$(info ============================================)
-$(foreach v, $(print_build_config_vars),\
- $(info $v=$($(v))))
-$(info ============================================)
-endif
diff --git a/core/dynamic_binary.mk b/core/dynamic_binary.mk
index 949793b..f44b8a8 100644
--- a/core/dynamic_binary.mk
+++ b/core/dynamic_binary.mk
@@ -99,10 +99,15 @@
my_breakpad_path := $(TARGET_OUT_BREAKPAD)/$(patsubst $(PRODUCT_OUT)/%,%,$(my_module_path))
breakpad_input := $(relocation_packer_output)
breakpad_output := $(my_breakpad_path)/$(my_installed_module_stem).sym
-$(breakpad_output) : $(breakpad_input) | $(BREAKPAD_DUMP_SYMS)
+$(breakpad_output) : $(breakpad_input) | $(BREAKPAD_DUMP_SYMS) $(PRIVATE_READELF)
@echo "target breakpad: $(PRIVATE_MODULE) ($@)"
@mkdir -p $(dir $@)
- $(hide) $(BREAKPAD_DUMP_SYMS) -c $< > $@
+ $(hide) if $(PRIVATE_READELF) -S $< > /dev/null 2>&1 ; then \
+ $(BREAKPAD_DUMP_SYMS) -c $< > $@ ; \
+ else \
+ echo "skipped for non-elf file."; \
+ touch $@; \
+ fi
$(LOCAL_BUILT_MODULE) : $(breakpad_output)
endif
diff --git a/core/empty_test_config.xml b/core/empty_test_config.xml
new file mode 100644
index 0000000..7c9daff
--- /dev/null
+++ b/core/empty_test_config.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<!-- No AndroidTest.xml was provided and the manifest does not include
+ instrumentation, hence this apk is not instrumentable.
+-->
+<configuration description="Empty Configuration" />
diff --git a/core/envsetup.mk b/core/envsetup.mk
index 46066e3..700189e 100644
--- a/core/envsetup.mk
+++ b/core/envsetup.mk
@@ -97,8 +97,6 @@
# compiles except for arm/mips, so the HOST is whatever we are
# running on
-UNAME := $(shell uname -sm)
-
# HOST_OS
ifneq (,$(findstring Linux,$(UNAME)))
HOST_OS := linux
@@ -110,7 +108,15 @@
HOST_OS := darwin
endif
-HOST_OS_EXTRA:=$(shell python -c "import platform; print(platform.platform())")
+HOST_OS_EXTRA := $(shell uname -rsm)
+ifeq ($(HOST_OS),linux)
+ ifneq ($(wildcard /etc/os-release),)
+ HOST_OS_EXTRA += $(shell source /etc/os-release; echo $$PRETTY_NAME)
+ endif
+else ifeq ($(HOST_OS),darwin)
+ HOST_OS_EXTRA += $(shell sw_vers -productVersion)
+endif
+HOST_OS_EXTRA := $(subst $(space),-,$(HOST_OS_EXTRA))
# BUILD_OS is the real host doing the build.
BUILD_OS := $(HOST_OS)
@@ -118,11 +124,13 @@
HOST_CROSS_OS :=
# We can cross-build Windows binaries 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
+endif
ifeq ($(HOST_OS),)
$(error Unable to determine HOST_OS from uname -sm: $(UNAME)!)
@@ -171,6 +179,7 @@
TARGET_COPY_OUT_ASAN := $(TARGET_COPY_OUT_DATA)/asan
TARGET_COPY_OUT_OEM := oem
TARGET_COPY_OUT_ODM := odm
+TARGET_COPY_OUT_PRODUCT := product
TARGET_COPY_OUT_ROOT := root
TARGET_COPY_OUT_RECOVERY := recovery
@@ -190,10 +199,29 @@
TARGET_COPY_OUT_VENDOR := $(_vendor_path_placeholder)
###########################################
+###########################################
+# Define TARGET_COPY_OUT_PRODUCT to a placeholder, for at this point
+# we don't know if the device wants to build a separate product.img
+# or just build product stuff into system.img.
+# A device can set up TARGET_COPY_OUT_PRODUCT to "product" in its
+# BoardConfig.mk.
+# We'll substitute with the real value after loading BoardConfig.mk.
+_product_path_placeholder := ||PRODUCT-PATH-PH||
+TARGET_COPY_OUT_PRODUCT := $(_product_path_placeholder)
+###########################################
+
#################################################################
# Set up minimal BOOTCLASSPATH list of jars to build/execute
# java code with dalvikvm/art.
TARGET_CORE_JARS := core-oj core-libart conscrypt okhttp bouncycastle apache-xml
+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.
+ TARGET_CORE_JARS += jacocoagent
+ endif # EMMA_INSTRUMENT_STATIC
+endif # EMMA_INSTRUMENT
HOST_CORE_JARS := $(addsuffix -hostdex,$(TARGET_CORE_JARS))
#################################################################
@@ -257,6 +285,29 @@
else ifdef BOARD_USES_VENDORIMAGE
$(error TARGET_COPY_OUT_VENDOR must be set to 'vendor' to use a vendor image)
endif
+
+###########################################
+# Now we can substitute with the real value of TARGET_COPY_OUT_PRODUCT
+ifeq ($(TARGET_COPY_OUT_PRODUCT),$(_product_path_placeholder))
+TARGET_COPY_OUT_PRODUCT := system/product
+else ifeq ($(filter product system/product,$(TARGET_COPY_OUT_PRODUCT)),)
+$(error TARGET_COPY_OUT_PRODUCT must be either 'product' or 'system/product', seeing '$(TARGET_COPY_OUT_PRODUCT)'.)
+endif
+PRODUCT_COPY_FILES := $(subst $(_product_path_placeholder),$(TARGET_COPY_OUT_PRODUCT),$(PRODUCT_COPY_FILES))
+
+BOARD_USES_PRODUCTIMAGE :=
+ifdef BOARD_PREBUILT_PRODUCTIMAGE
+BOARD_USES_PRODUCTIMAGE := true
+endif
+ifdef BOARD_PRODUCTIMAGE_FILE_SYSTEM_TYPE
+BOARD_USES_PRODUCTIMAGE := true
+endif
+ifeq ($(TARGET_COPY_OUT_PRODUCT),product)
+BOARD_USES_PRODUCTIMAGE := true
+else ifdef BOARD_USES_PRODUCTIMAGE
+$(error TARGET_COPY_OUT_PRODUCT must be set to 'product' to use a product image)
+endif
+
###########################################
# Ensure that only TARGET_RECOVERY_UPDATER_LIBS *or* AB_OTA_UPDATER is set.
TARGET_RECOVERY_UPDATER_LIBS ?=
@@ -269,6 +320,11 @@
endif
# Check BOARD_VNDK_VERSION
+define check_vndk_version
+ $(eval vndk_path := prebuilts/vndk/v$(1)) \
+ $(if $(wildcard $(vndk_path)/*/Android.bp),,$(error VNDK version $(1) not found))
+endef
+
ifdef BOARD_VNDK_VERSION
ifneq ($(BOARD_VNDK_VERSION),current)
$(error BOARD_VNDK_VERSION: Only "current" is implemented)
@@ -279,6 +335,17 @@
TARGET_VENDOR_TEST_SUFFIX :=
endif
+ifdef PRODUCT_EXTRA_VNDK_VERSIONS
+ $(foreach v,$(PRODUCT_EXTRA_VNDK_VERSIONS),$(call check_vndk_version,$(v)))
+endif
+
+# Ensure that BOARD_SYSTEMSDK_VERSIONS are all within PLATFORM_SYSTEMSDK_VERSIONS
+_unsupported_systemsdk_versions := $(filter-out $(PLATFORM_SYSTEMSDK_VERSIONS),$(BOARD_SYSTEMSDK_VERSIONS))
+ifneq (,$(_unsupported_systemsdk_versions))
+ $(error System SDK versions '$(_unsupported_systemsdk_versions)' in BOARD_SYSTEMSDK_VERSIONS are not supported.\
+ Supported versions are $(PLATFORM_SYSTEMSDK_VERSIONS))
+endif
+
# ---------------------------------------------------------------
# Set up configuration for target machine.
# The following must be set:
@@ -309,29 +376,17 @@
SOONG_OUT_DIR := $(OUT_DIR)/soong
-DEBUG_OUT_DIR := $(OUT_DIR)/debug
+TARGET_OUT_ROOT := $(OUT_DIR)/target
-# Move the host or target under the debug/ directory
-# if necessary.
-TARGET_OUT_ROOT_release := $(OUT_DIR)/target
-TARGET_OUT_ROOT_debug := $(DEBUG_OUT_DIR)/target
-TARGET_OUT_ROOT := $(TARGET_OUT_ROOT_$(TARGET_BUILD_TYPE))
-
-HOST_OUT_ROOT_release := $(OUT_DIR)/host
-HOST_OUT_ROOT_debug := $(DEBUG_OUT_DIR)/host
-HOST_OUT_ROOT := $(HOST_OUT_ROOT_$(HOST_BUILD_TYPE))
+HOST_OUT_ROOT := $(OUT_DIR)/host
# We want to avoid two host bin directories in multilib build.
-HOST_OUT_release := $(HOST_OUT_ROOT_release)/$(HOST_OS)-$(HOST_PREBUILT_ARCH)
-HOST_OUT_debug := $(HOST_OUT_ROOT_debug)/$(HOST_OS)-$(HOST_PREBUILT_ARCH)
-HOST_OUT := $(HOST_OUT_$(HOST_BUILD_TYPE))
+HOST_OUT := $(HOST_OUT_ROOT)/$(HOST_OS)-$(HOST_PREBUILT_ARCH)
SOONG_HOST_OUT := $(SOONG_OUT_DIR)/host/$(HOST_OS)-$(HOST_PREBUILT_ARCH)
# TODO: remove
BUILD_OUT := $(HOST_OUT)
-HOST_CROSS_OUT_release := $(HOST_OUT_ROOT_release)/windows-$(HOST_PREBUILT_ARCH)
-HOST_CROSS_OUT_debug := $(HOST_OUT_ROOT_debug)/windows-$(HOST_PREBUILT_ARCH)
-HOST_CROSS_OUT := $(HOST_CROSS_OUT_$(HOST_BUILD_TYPE))
+HOST_CROSS_OUT := $(HOST_OUT_ROOT)/windows-$(HOST_PREBUILT_ARCH)
TARGET_PRODUCT_OUT_ROOT := $(TARGET_OUT_ROOT)/product
@@ -341,6 +396,7 @@
PRODUCT_OUT := $(TARGET_PRODUCT_OUT_ROOT)/$(TARGET_DEVICE)
OUT_DOCS := $(TARGET_COMMON_OUT_ROOT)/docs
+OUT_NDK_DOCS := $(TARGET_COMMON_OUT_ROOT)/ndk-docs
BUILD_OUT_EXECUTABLES := $(BUILD_OUT)/bin
SOONG_HOST_OUT_EXECUTABLES := $(SOONG_HOST_OUT)/bin
@@ -352,12 +408,13 @@
HOST_OUT_SDK_ADDON := $(HOST_OUT)/sdk_addon
HOST_OUT_NATIVE_TESTS := $(HOST_OUT)/nativetest64
HOST_OUT_COVERAGE := $(HOST_OUT)/coverage
+HOST_OUT_TESTCASES := $(HOST_OUT)/testcases
HOST_CROSS_OUT_EXECUTABLES := $(HOST_CROSS_OUT)/bin
HOST_CROSS_OUT_SHARED_LIBRARIES := $(HOST_CROSS_OUT)/lib
HOST_CROSS_OUT_NATIVE_TESTS := $(HOST_CROSS_OUT)/nativetest
HOST_CROSS_OUT_COVERAGE := $(HOST_CROSS_OUT)/coverage
-HOST_OUT_TESTCASES := $(HOST_OUT)/testcases
+HOST_CROSS_OUT_TESTCASES := $(HOST_CROSS_OUT)/testcases
HOST_OUT_INTERMEDIATES := $(HOST_OUT)/obj
HOST_OUT_INTERMEDIATE_LIBRARIES := $(HOST_OUT_INTERMEDIATES)/lib
@@ -377,6 +434,8 @@
HOST_CROSS_OUT_GEN := $(HOST_CROSS_OUT)/gen
+HOST_OUT_TEST_CONFIG := $(HOST_OUT)/test_config
+
# Out for HOST_2ND_ARCH
HOST_2ND_ARCH_VAR_PREFIX := 2ND_
HOST_2ND_ARCH_MODULE_SUFFIX := _32
@@ -421,8 +480,16 @@
TARGET_OUT := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_SYSTEM)
ifneq ($(filter address,$(SANITIZE_TARGET)),)
target_out_shared_libraries_base := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_ASAN)/system
+ifeq ($(SANITIZE_LITE),true)
+# When using SANITIZE_LITE, APKs must not be packaged with sanitized libraries, as they will not
+# work with unsanitized app_process. For simplicity, generate APKs into /data/asan/.
+target_out_app_base := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_ASAN)/system
+else
+target_out_app_base := $(TARGET_OUT)
+endif
else
target_out_shared_libraries_base := $(TARGET_OUT)
+target_out_app_base := $(TARGET_OUT)
endif
TARGET_OUT_EXECUTABLES := $(TARGET_OUT)/bin
@@ -436,16 +503,23 @@
endif
TARGET_OUT_RENDERSCRIPT_BITCODE := $(TARGET_OUT_SHARED_LIBRARIES)
TARGET_OUT_JAVA_LIBRARIES := $(TARGET_OUT)/framework
-TARGET_OUT_APPS := $(TARGET_OUT)/app
-TARGET_OUT_APPS_PRIVILEGED := $(TARGET_OUT)/priv-app
+TARGET_OUT_APPS := $(target_out_app_base)/app
+TARGET_OUT_APPS_PRIVILEGED := $(target_out_app_base)/priv-app
TARGET_OUT_KEYLAYOUT := $(TARGET_OUT)/usr/keylayout
TARGET_OUT_KEYCHARS := $(TARGET_OUT)/usr/keychars
TARGET_OUT_ETC := $(TARGET_OUT)/etc
TARGET_OUT_NOTICE_FILES := $(TARGET_OUT_INTERMEDIATES)/NOTICE_FILES
TARGET_OUT_FAKE := $(PRODUCT_OUT)/fake_packages
TARGET_OUT_TESTCASES := $(PRODUCT_OUT)/testcases
+TARGET_OUT_TEST_CONFIG := $(PRODUCT_OUT)/test_config
+ifeq ($(SANITIZE_LITE),true)
+# When using SANITIZE_LITE, APKs must not be packaged with sanitized libraries, as they will not
+# work with unsanitized app_process. For simplicity, generate APKs into /data/asan/.
+TARGET_OUT_SYSTEM_OTHER := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_ASAN)/$(TARGET_COPY_OUT_SYSTEM_OTHER)
+else
TARGET_OUT_SYSTEM_OTHER := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_SYSTEM_OTHER)
+endif
# Out for TARGET_2ND_ARCH
TARGET_2ND_ARCH_VAR_PREFIX := $(HOST_2ND_ARCH_VAR_PREFIX)
@@ -514,8 +588,16 @@
TARGET_OUT_VENDOR := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_VENDOR)
ifneq ($(filter address,$(SANITIZE_TARGET)),)
target_out_vendor_shared_libraries_base := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_ASAN)/vendor
+ifeq ($(SANITIZE_LITE),true)
+# When using SANITIZE_LITE, APKs must not be packaged with sanitized libraries, as they will not
+# work with unsanitized app_process. For simplicity, generate APKs into /data/asan/.
+target_out_vendor_app_base := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_ASAN)/vendor
+else
+target_out_vendor_app_base := $(TARGET_OUT_VENDOR)
+endif
else
target_out_vendor_shared_libraries_base := $(TARGET_OUT_VENDOR)
+target_out_vendor_app_base := $(TARGET_OUT_VENDOR)
endif
TARGET_OUT_VENDOR_EXECUTABLES := $(TARGET_OUT_VENDOR)/bin
@@ -527,8 +609,8 @@
endif
TARGET_OUT_VENDOR_RENDERSCRIPT_BITCODE := $(TARGET_OUT_VENDOR_SHARED_LIBRARIES)
TARGET_OUT_VENDOR_JAVA_LIBRARIES := $(TARGET_OUT_VENDOR)/framework
-TARGET_OUT_VENDOR_APPS := $(TARGET_OUT_VENDOR)/app
-TARGET_OUT_VENDOR_APPS_PRIVILEGED := $(TARGET_OUT_VENDOR)/priv-app
+TARGET_OUT_VENDOR_APPS := $(target_out_vendor_app_base)/app
+TARGET_OUT_VENDOR_APPS_PRIVILEGED := $(target_out_vendor_app_base)/priv-app
TARGET_OUT_VENDOR_ETC := $(TARGET_OUT_VENDOR)/etc
$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_VENDOR_EXECUTABLES := $(TARGET_OUT_VENDOR_EXECUTABLES)
@@ -579,6 +661,39 @@
endif
$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_ODM_APPS := $(TARGET_OUT_ODM_APPS)
+TARGET_OUT_PRODUCT := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_PRODUCT)
+ifneq ($(filter address,$(SANITIZE_TARGET)),)
+target_out_product_shared_libraries_base := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_ASAN)/product
+ifeq ($(SANITIZE_LITE),true)
+# When using SANITIZE_LITE, APKs must not be packaged with sanitized libraries, as they will not
+# work with unsanitized app_process. For simplicity, generate APKs into /data/asan/.
+target_out_product_app_base := $(PRODUCT_OUT)/$(TARGET_COPY_OUT_ASAN)/product
+else
+target_out_product_app_base := $(TARGET_OUT_PRODUCT)
+endif
+else
+target_out_product_shared_libraries_base := $(TARGET_OUT_PRODUCT)
+target_out_product_app_base := $(TARGET_OUT_PRODUCT)
+endif
+
+ifeq ($(TARGET_IS_64_BIT),true)
+TARGET_OUT_PRODUCT_SHARED_LIBRARIES := $(target_out_product_shared_libraries_base)/lib64
+else
+TARGET_OUT_PRODUCT_SHARED_LIBRARIES := $(target_out_product_shared_libraries_base)/lib
+endif
+TARGET_OUT_PRODUCT_JAVA_LIBRARIES:= $(TARGET_OUT_PRODUCT)/framework
+TARGET_OUT_PRODUCT_APPS := $(target_out_product_app_base)/app
+TARGET_OUT_PRODUCT_APPS_PRIVILEGED := $(target_out_product_app_base)/priv-app
+TARGET_OUT_PRODUCT_ETC := $(TARGET_OUT_PRODUCT)/etc
+
+ifeq ($(TARGET_TRANSLATE_2ND_ARCH),true)
+$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_PRODUCT_SHARED_LIBRARIES := $(target_out_product_shared_libraries_base)/lib/$(TARGET_2ND_ARCH)
+else
+$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_PRODUCT_SHARED_LIBRARIES := $(target_out_product_shared_libraries_base)/lib
+endif
+$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_PRODUCT_APPS := $(TARGET_OUT_PRODUCT_APPS)
+$(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_PRODUCT_APPS_PRIVILEGED := $(TARGET_OUT_PRODUCT_APPS_PRIVILEGED)
+
TARGET_OUT_BREAKPAD := $(PRODUCT_OUT)/breakpad
TARGET_OUT_UNSTRIPPED := $(PRODUCT_OUT)/symbols
@@ -615,16 +730,6 @@
DIST_DIR := $(OUT_DIR)/dist
endif
-ifndef KATI
+ifeq ($(CALLED_FROM_SETUP),true)
PRINT_BUILD_CONFIG ?= true
endif
-
-ifeq ($(USE_CLANG_PLATFORM_BUILD),)
-USE_CLANG_PLATFORM_BUILD := true
-endif
-
-ifneq ($(USE_CLANG_PLATFORM_BUILD),true)
-ifneq ($(USE_CLANG_PLATFORM_BUILD),false)
-$(error USE_CLANG_PLATFORM_BUILD must be true or false)
-endif
-endif
diff --git a/core/executable_internal.mk b/core/executable_internal.mk
index 3509bd2..4a62fbf 100644
--- a/core/executable_internal.mk
+++ b/core/executable_internal.mk
@@ -12,7 +12,9 @@
LOCAL_MODULE_SUFFIX := $(TARGET_EXECUTABLE_SUFFIX)
endif
+ifdef target-executable-hook
$(call target-executable-hook)
+endif
skip_build_from_source :=
ifdef LOCAL_PREBUILT_MODULE_FILE
@@ -76,4 +78,39 @@
$(PRIVATE_POST_LINK_CMD)
endif
+ifeq ($(my_native_coverage),true)
+gcno_suffix := .gcnodir
+
+built_whole_gcno_libraries := \
+ $(foreach lib,$(my_whole_static_libraries), \
+ $(call intermediates-dir-for, \
+ STATIC_LIBRARIES,$(lib),$(my_kind),,$(LOCAL_2ND_ARCH_VAR_PREFIX), \
+ $(my_host_cross))/$(lib)$(gcno_suffix))
+
+built_static_gcno_libraries := \
+ $(foreach lib,$(my_static_libraries), \
+ $(call intermediates-dir-for, \
+ STATIC_LIBRARIES,$(lib),$(my_kind),,$(LOCAL_2ND_ARCH_VAR_PREFIX), \
+ $(my_host_cross))/$(lib)$(gcno_suffix))
+
+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
+
+GCNO_ARCHIVE := $(my_installed_module_stem)$(gcno_suffix)
+
+$(intermediates)/$(GCNO_ARCHIVE) : PRIVATE_ALL_OBJECTS := $(strip $(LOCAL_GCNO_FILES))
+$(intermediates)/$(GCNO_ARCHIVE) : PRIVATE_ALL_WHOLE_STATIC_LIBRARIES := $(strip $(built_whole_gcno_libraries)) $(strip $(built_static_gcno_libraries))
+$(intermediates)/$(GCNO_ARCHIVE) : PRIVATE_INTERMEDIATES_DIR := $(intermediates)
+$(intermediates)/$(GCNO_ARCHIVE) : $(LOCAL_GCNO_FILES) $(built_whole_gcno_libraries) $(built_static_gcno_libraries)
+ $(transform-o-to-static-lib)
+
+$(my_coverage_path)/$(GCNO_ARCHIVE) : $(intermediates)/$(GCNO_ARCHIVE)
+ $(copy-file-to-target)
+
+$(LOCAL_BUILT_MODULE): $(my_coverage_path)/$(GCNO_ARCHIVE)
+endif
+
endif # skip_build_from_source
diff --git a/core/find-jdk-tools-jar.sh b/core/find-jdk-tools-jar.sh
deleted file mode 100755
index ac0b3b6..0000000
--- a/core/find-jdk-tools-jar.sh
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/bin/sh
-if [ "x$ANDROID_JAVA_HOME" != x ] && [ -e "$ANDROID_JAVA_HOME/lib/tools.jar" ] ; then
- echo $ANDROID_JAVA_HOME/lib/tools.jar
-else
- JAVAC=$(realpath $(which javac) 2>/dev/null)
- if [ -z "$JAVAC" ]; then
- JAVAC=$(readlink -f $(which javac) 2>/dev/null)
- fi
- if [ -z "$JAVAC" ]; then
- JAVAC=$(which javac)
- fi
- if [ -z "$JAVAC" ] ; then
- exit 1
- fi
- while [ -L "$JAVAC" ] ; do
- LSLINE=$(ls -l "$JAVAC")
- JAVAC=$(echo -n "$LSLINE" | sed -e "s/.* -> //")
- done
- echo $JAVAC | sed -e 's:\(.*\)/javac$:\1/../lib/tools.jar:'
-fi
diff --git a/core/fuzz_test.mk b/core/fuzz_test.mk
index 4d41871..2cc2e2c 100644
--- a/core/fuzz_test.mk
+++ b/core/fuzz_test.mk
@@ -8,8 +8,50 @@
$(error $(LOCAL_PATH): $(LOCAL_MODULE): NDK fuzz tests are not supported.)
endif
-LOCAL_CFLAGS += -fsanitize-coverage=trace-pc-guard
+my_fuzzer:=libFuzzer
+ifdef LOCAL_FUZZ_ENGINE
+ my_fuzzer:=$(LOCAL_FUZZ_ENGINE)
+else ifdef TARGET_FUZZ_ENGINE
+ my_fuzzer:=$(TARGET_FUZZ_ENGINE)
+endif
+
+
+LOCAL_CFLAGS += -fsanitize-coverage=trace-pc-guard,indirect-calls,trace-cmp
+
+ifeq ($(my_fuzzer),libFuzzer)
LOCAL_STATIC_LIBRARIES += libFuzzer
+else ifeq ($(my_fuzzer),honggfuzz)
+LOCAL_STATIC_LIBRARIES += honggfuzz_libhfuzz
+LOCAL_REQUIRED_MODULES += honggfuzz
+LOCAL_LDFLAGS += \
+ "-Wl,--wrap=strcmp" \
+ "-Wl,--wrap=strcasecmp" \
+ "-Wl,--wrap=strncmp" \
+ "-Wl,--wrap=strncasecmp" \
+ "-Wl,--wrap=strstr" \
+ "-Wl,--wrap=strcasestr" \
+ "-Wl,--wrap=memcmp" \
+ "-Wl,--wrap=bcmp" \
+ "-Wl,--wrap=memmem" \
+ "-Wl,--wrap=ap_cstr_casecmp" \
+ "-Wl,--wrap=ap_cstr_casecmpn" \
+ "-Wl,--wrap=ap_strcasestr" \
+ "-Wl,--wrap=apr_cstr_casecmp" \
+ "-Wl,--wrap=apr_cstr_casecmpn" \
+ "-Wl,--wrap=CRYPTO_memcmp" \
+ "-Wl,--wrap=OPENSSL_memcmp" \
+ "-Wl,--wrap=OPENSSL_strcasecmp" \
+ "-Wl,--wrap=OPENSSL_strncasecmp" \
+ "-Wl,--wrap=xmlStrncmp" \
+ "-Wl,--wrap=xmlStrcmp" \
+ "-Wl,--wrap=xmlStrEqual" \
+ "-Wl,--wrap=xmlStrcasecmp" \
+ "-Wl,--wrap=xmlStrncasecmp" \
+ "-Wl,--wrap=xmlStrstr" \
+ "-Wl,--wrap=xmlStrcasestr"
+else
+$(call pretty-error, Unknown fuzz engine $(my_fuzzer))
+endif
ifdef LOCAL_MODULE_PATH
$(error $(LOCAL_PATH): Do not set LOCAL_MODULE_PATH when building test $(LOCAL_MODULE))
@@ -32,4 +74,8 @@
endif
endif
+ifndef LOCAL_STRIP_MODULE
+LOCAL_STRIP_MODULE := keep_symbols
+endif
+
include $(BUILD_EXECUTABLE)
diff --git a/core/generate_enforce_rro.mk b/core/generate_enforce_rro.mk
index 579089c..62a8c8d 100644
--- a/core/generate_enforce_rro.mk
+++ b/core/generate_enforce_rro.mk
@@ -7,12 +7,12 @@
ifeq (true,$(enforce_rro_source_is_manifest_package_name))
$(rro_android_manifest_file): PRIVATE_PACKAGE_NAME := $(enforce_rro_source_manifest_package_info)
-$(rro_android_manifest_file): build/tools/generate-enforce-rro-android-manifest.py
- $(hide) build/tools/generate-enforce-rro-android-manifest.py -u -p $(PRIVATE_PACKAGE_NAME) -o $@
+$(rro_android_manifest_file): build/make/tools/generate-enforce-rro-android-manifest.py
+ $(hide) build/make/tools/generate-enforce-rro-android-manifest.py -u -p $(PRIVATE_PACKAGE_NAME) -o $@
else
$(rro_android_manifest_file): PRIVATE_SOURCE_MANIFEST_FILE := $(enforce_rro_source_manifest_package_info)
-$(rro_android_manifest_file): $(enforce_rro_source_manifest_package_info) build/tools/generate-enforce-rro-android-manifest.py
- $(hide) build/tools/generate-enforce-rro-android-manifest.py -p $(PRIVATE_SOURCE_MANIFEST_FILE) -o $@
+$(rro_android_manifest_file): $(enforce_rro_source_manifest_package_info) build/make/tools/generate-enforce-rro-android-manifest.py
+ $(hide) build/make/tools/generate-enforce-rro-android-manifest.py -p $(PRIVATE_SOURCE_MANIFEST_FILE) -o $@
endif
LOCAL_PATH:= $(intermediates)
diff --git a/core/help.mk b/core/help.mk
deleted file mode 100644
index c034e79..0000000
--- a/core/help.mk
+++ /dev/null
@@ -1,35 +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.
-#
-
-.PHONY: help
-help:
- @echo
- @echo "Common make targets:"
- @echo "----------------------------------------------------------------------------------"
- @echo "droid Default target"
- @echo "clean (aka clobber) equivalent to rm -rf out/"
- @echo "snod Quickly rebuild the system image from built packages"
- @echo "vnod Quickly rebuild the vendor image from built packages"
- @echo "offline-sdk-docs Generate the HTML for the developer SDK docs"
- @echo "doc-comment-check-docs Check HTML doc links & validity, without generating HTML"
- @echo "libandroid_runtime All the JNI framework stuff"
- @echo "framework All the java framework stuff"
- @echo "services The system server (Java) and friends"
- @echo "help You're reading it right now"
-
-.PHONY: out
-out:
- @echo "I'm sure you're nice and all, but no thanks."
diff --git a/core/host_dalvik_java_library.mk b/core/host_dalvik_java_library.mk
index 4f3069f..1ef0ccb 100644
--- a/core/host_dalvik_java_library.mk
+++ b/core/host_dalvik_java_library.mk
@@ -24,53 +24,39 @@
ifeq ($(HOST_OS),linux)
USE_CORE_LIB_BOOTCLASSPATH := true
-#################################
-include $(BUILD_SYSTEM)/configure_local_jack.mk
-#################################
-
#######################################
include $(BUILD_SYSTEM)/host_java_library_common.mk
#######################################
-ifdef LOCAL_JACK_ENABLED
-ifeq ($(LOCAL_IS_STATIC_JAVA_LIBRARY),true)
- # For static library, $(LOCAL_BUILT_MODULE) is $(full_classes_jack).
- LOCAL_BUILT_MODULE_STEM := classes.jack
-endif
-endif
-ifneq ($(LOCAL_NO_STANDARD_LIBRARIES),true)
- LOCAL_JAVA_LIBRARIES := core-oj-hostdex core-libart-hostdex $(LOCAL_JAVA_LIBRARIES)
-endif
-
+full_classes_turbine_jar := $(intermediates.COMMON)/classes-turbine.jar
+full_classes_header_jarjar := $(intermediates.COMMON)/classes-header-jarjar.jar
+full_classes_header_jar := $(intermediates.COMMON)/classes-header.jar
full_classes_compiled_jar := $(intermediates.COMMON)/classes-full-debug.jar
+full_classes_combined_jar := $(intermediates.COMMON)/classes-combined.jar
full_classes_desugar_jar := $(intermediates.COMMON)/desugar.classes.jar
full_classes_jarjar_jar := $(intermediates.COMMON)/classes-jarjar.jar
full_classes_jar := $(intermediates.COMMON)/classes.jar
-full_classes_jack := $(intermediates.COMMON)/classes.jack
-jack_check_timestamp := $(intermediates.COMMON)/jack.check.timestamp
built_dex := $(intermediates.COMMON)/classes.dex
+java_source_list_file := $(intermediates.COMMON)/java-source-list
LOCAL_INTERMEDIATE_TARGETS += \
+ $(full_classes_turbine_jar) \
$(full_classes_compiled_jar) \
+ $(full_classes_combined_jar) \
$(full_classes_desugar_jar) \
$(full_classes_jarjar_jar) \
- $(full_classes_jack) \
$(full_classes_jar) \
- $(jack_check_timestamp) \
- $(built_dex)
+ $(built_dex) \
+ $(java_source_list_file)
# See comment in java.mk
ifndef LOCAL_CHECKED_MODULE
-ifdef LOCAL_JACK_ENABLED
-LOCAL_CHECKED_MODULE := $(jack_check_timestamp)
-else
ifeq ($(LOCAL_IS_STATIC_JAVA_LIBRARY),true)
LOCAL_CHECKED_MODULE := $(full_classes_compiled_jar)
else
LOCAL_CHECKED_MODULE := $(built_dex)
endif
endif
-endif
#######################################
include $(BUILD_SYSTEM)/base_rules.mk
@@ -81,51 +67,113 @@
include $(BUILD_SYSTEM)/java_common.mk
+include $(BUILD_SYSTEM)/sdk_check.mk
+
$(cleantarget): PRIVATE_CLEAN_FILES += $(intermediates.COMMON)
-ifndef LOCAL_JACK_ENABLED
+# List of dependencies for anything that needs all java sources in place
+java_sources_deps := \
+ $(java_sources) \
+ $(java_resource_sources) \
+ $(proto_java_sources_file_stamp) \
+ $(LOCAL_SRCJARS) \
+ $(LOCAL_ADDITIONAL_DEPENDENCIES)
+
+$(java_source_list_file): $(java_sources_deps)
+ $(write-java-source-list)
$(full_classes_compiled_jar): PRIVATE_JAVA_LAYERS_FILE := $(layers_file)
-$(full_classes_compiled_jar): PRIVATE_JAVACFLAGS := $(GLOBAL_JAVAC_DEBUG_FLAGS) $(LOCAL_JAVACFLAGS) $(annotation_processor_flags)
+$(full_classes_compiled_jar): PRIVATE_JAVACFLAGS := $(LOCAL_JAVACFLAGS) $(annotation_processor_flags)
$(full_classes_compiled_jar): PRIVATE_JAR_EXCLUDE_FILES :=
$(full_classes_compiled_jar): PRIVATE_JAR_PACKAGES :=
$(full_classes_compiled_jar): PRIVATE_JAR_EXCLUDE_PACKAGES :=
+$(full_classes_compiled_jar): PRIVATE_SRCJARS := $(LOCAL_SRCJARS)
+$(full_classes_compiled_jar): PRIVATE_SRCJAR_LIST_FILE := $(intermediates.COMMON)/srcjar-list
+$(full_classes_compiled_jar): PRIVATE_SRCJAR_INTERMEDIATES_DIR := $(intermediates.COMMON)/srcjars
$(full_classes_compiled_jar): \
- $(java_sources) \
- $(java_resource_sources) \
- $(full_java_lib_deps) \
- $(jar_manifest_file) \
- $(proto_java_sources_file_stamp) \
- $(annotation_processor_deps) \
- $(NORMALIZE_PATH) \
- $(LOCAL_ADDITIONAL_DEPENDENCIES) \
- | $(SOONG_JAVAC_WRAPPER)
- $(transform-host-java-to-package)
+ $(java_source_list_file) \
+ $(java_sources_deps) \
+ $(full_java_header_libs) \
+ $(full_java_bootclasspath_libs) \
+ $(full_java_system_modules_deps) \
+ $(annotation_processor_deps) \
+ $(NORMALIZE_PATH) \
+ $(JAR_ARGS) \
+ $(ZIPSYNC) \
+ | $(SOONG_JAVAC_WRAPPER)
+ $(transform-host-java-to-dalvik-package)
-my_desugaring :=
-ifeq ($(LOCAL_JAVA_LANGUAGE_VERSION),1.8)
-my_desugaring := true
-$(full_classes_desugar_jar): PRIVATE_DX_FLAGS := $(LOCAL_DX_FLAGS)
-$(full_classes_desugar_jar): $(full_classes_compiled_jar) $(DESUGAR)
- $(desugar-classes-jar)
+ifneq ($(TURBINE_ENABLED),false)
+
+$(full_classes_turbine_jar): PRIVATE_JAVACFLAGS := $(LOCAL_JAVACFLAGS) $(annotation_processor_flags)
+$(full_classes_turbine_jar): PRIVATE_DONT_DELETE_JAR_META_INF := $(LOCAL_DONT_DELETE_JAR_META_INF)
+$(full_classes_turbine_jar): PRIVATE_SRCJARS := $(LOCAL_SRCJARS)
+$(full_classes_turbine_jar): \
+ $(java_source_list_file) \
+ $(java_sources_deps) \
+ $(full_java_header_libs) \
+ $(full_java_bootclasspath_libs) \
+ $(NORMALIZE_PATH) \
+ $(JAR_ARGS) \
+ $(ZIPTIME) \
+ | $(TURBINE) \
+ $(MERGE_ZIPS)
+ $(transform-java-to-header.jar)
+
+.KATI_RESTAT: $(full_classes_turbine_jar)
+
+# Run jarjar before generate classes-header.jar if necessary.
+ifneq ($(strip $(LOCAL_JARJAR_RULES)),)
+$(full_classes_header_jarjar): PRIVATE_JARJAR_RULES := $(LOCAL_JARJAR_RULES)
+$(full_classes_header_jarjar): $(full_classes_turbine_jar) $(LOCAL_JARJAR_RULES) | $(JARJAR)
+ @echo Header JarJar: $@
+ $(hide) $(JAVA) -jar $(JARJAR) process $(PRIVATE_JARJAR_RULES) $< $@
+else
+full_classes_header_jarjar := $(full_classes_turbine_jar)
endif
-ifndef my_desugaring
-full_classes_desugar_jar := $(full_classes_compiled_jar)
-endif
+$(eval $(call copy-one-file,$(full_classes_header_jarjar),$(full_classes_header_jar)))
+
+endif # TURBINE_ENABLED != false
+
+$(full_classes_combined_jar): PRIVATE_DONT_DELETE_JAR_META_INF := $(LOCAL_DONT_DELETE_JAR_META_INF)
+$(full_classes_combined_jar): $(full_classes_compiled_jar) \
+ $(jar_manifest_file) \
+ $(full_static_java_libs) | $(MERGE_ZIPS)
+ $(if $(PRIVATE_JAR_MANIFEST), $(hide) sed -e "s/%BUILD_NUMBER%/$(BUILD_NUMBER_FROM_FILE)/" \
+ $(PRIVATE_JAR_MANIFEST) > $(dir $@)/manifest.mf)
+ $(MERGE_ZIPS) -j --ignore-duplicates $(if $(PRIVATE_JAR_MANIFEST),-m $(dir $@)/manifest.mf) \
+ $(if $(PRIVATE_DONT_DELETE_JAR_META_INF),,-stripDir META-INF -zipToNotStrip $<) \
+ $@ $< $(call reverse-list,$(PRIVATE_STATIC_JAVA_LIBRARIES))
# Run jarjar if necessary, otherwise just copy the file.
ifneq ($(strip $(LOCAL_JARJAR_RULES)),)
$(full_classes_jarjar_jar): PRIVATE_JARJAR_RULES := $(LOCAL_JARJAR_RULES)
-$(full_classes_jarjar_jar): $(full_classes_desugar_jar) $(LOCAL_JARJAR_RULES) | $(JARJAR)
+$(full_classes_jarjar_jar): $(full_classes_combined_jar) $(LOCAL_JARJAR_RULES) | $(JARJAR)
@echo JarJar: $@
$(hide) $(JAVA) -jar $(JARJAR) process $(PRIVATE_JARJAR_RULES) $< $@
else
-full_classes_jarjar_jar := $(full_classes_desugar_jar)
+full_classes_jarjar_jar := $(full_classes_combined_jar)
endif
$(eval $(call copy-one-file,$(full_classes_jarjar_jar),$(full_classes_jar)))
+ifneq ($(USE_D8_DESUGAR),true)
+my_desugaring :=
+ifeq ($(LOCAL_JAVA_LANGUAGE_VERSION),1.8)
+my_desugaring := true
+$(full_classes_desugar_jar): PRIVATE_DX_FLAGS := $(LOCAL_DX_FLAGS)
+$(full_classes_desugar_jar): $(full_classes_jar) $(full_java_header_libs) $(DESUGAR)
+ $(desugar-classes-jar)
+endif
+else
+my_desugaring :=
+endif
+
+ifndef my_desugaring
+full_classes_desugar_jar := $(full_classes_jar)
+endif
+
ifeq ($(LOCAL_IS_STATIC_JAVA_LIBRARY),true)
# No dex; all we want are the .class files with resources.
$(LOCAL_BUILT_MODULE) : $(java_resource_sources)
@@ -136,8 +184,12 @@
else # !LOCAL_IS_STATIC_JAVA_LIBRARY
$(built_dex): PRIVATE_INTERMEDIATES_DIR := $(intermediates.COMMON)
$(built_dex): PRIVATE_DX_FLAGS := $(LOCAL_DX_FLAGS)
-$(built_dex): $(full_classes_jar) $(DX)
+$(built_dex): $(full_classes_desugar_jar) $(DX) $(ZIP2ZIP)
+ifneq ($(USE_D8_DESUGAR),true)
$(transform-classes.jar-to-dex)
+else
+ $(transform-classes-d8.jar-to-dex)
+endif
$(LOCAL_BUILT_MODULE): PRIVATE_DEX_FILE := $(built_dex)
$(LOCAL_BUILT_MODULE): PRIVATE_SOURCE_ARCHIVE := $(full_classes_jarjar_jar)
@@ -149,67 +201,23 @@
endif # !LOCAL_IS_STATIC_JAVA_LIBRARY
-ifneq (,$(filter-out current system_current test_current, $(LOCAL_SDK_VERSION)))
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_DEFAULT_APP_TARGET_SDK := $(LOCAL_SDK_VERSION)
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_SDK_VERSION := $(LOCAL_SDK_VERSION)
+ifneq (,$(filter-out current system_current test_current core_current, $(LOCAL_SDK_VERSION)))
+ my_default_app_target_sdk := $(call get-numeric-sdk-version,$(LOCAL_SDK_VERSION))
+ my_sdk_version := $(call get-numeric-sdk-version,$(LOCAL_SDK_VERSION))
else
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_DEFAULT_APP_TARGET_SDK := $(DEFAULT_APP_TARGET_SDK)
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_SDK_VERSION := $(PLATFORM_SDK_VERSION)
+ my_default_app_target_sdk := $(DEFAULT_APP_TARGET_SDK)
+ my_sdk_version := $(PLATFORM_SDK_VERSION)
endif
-else # LOCAL_JACK_ENABLED
-$(LOCAL_INTERMEDIATE_TARGETS): \
- PRIVATE_JACK_INTERMEDIATES_DIR := $(intermediates.COMMON)/jack-rsc
-
-ifeq ($(LOCAL_JACK_ENABLED),incremental)
-$(LOCAL_INTERMEDIATE_TARGETS): \
- PRIVATE_JACK_INCREMENTAL_DIR := $(intermediates.COMMON)/jack-incremental
+ifdef LOCAL_MIN_SDK_VERSION
+ my_min_sdk_version := $(LOCAL_MIN_SDK_VERSION)
else
-$(LOCAL_INTERMEDIATE_TARGETS): \
- PRIVATE_JACK_INCREMENTAL_DIR :=
+ my_min_sdk_version := $(call codename-or-sdk-to-sdk,$(my_default_app_target_sdk))
endif
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_JACK_FLAGS := $(GLOBAL_JAVAC_DEBUG_FLAGS) $(LOCAL_JACK_FLAGS)
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_JACK_VERSION := $(LOCAL_JACK_VERSION)
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_JACK_MIN_SDK_VERSION := $(PLATFORM_JACK_MIN_SDK_VERSION)
-jack_all_deps := $(java_sources) $(java_resource_sources) $(full_jack_deps) \
- $(jar_manifest_file) $(proto_java_sources_file_stamp) \
- $(LOCAL_ADDITIONAL_DEPENDENCIES) $(NORMALIZE_PATH) $(JACK_DEFAULT_ARGS) $(JACK)
-
-ifneq ($(LOCAL_IS_STATIC_JAVA_LIBRARY),true)
-$(built_dex): PRIVATE_CLASSES_JACK := $(full_classes_jack)
-$(built_dex): PRIVATE_JACK_PLUGIN_PATH := $(LOCAL_JACK_PLUGIN_PATH)
-$(built_dex): PRIVATE_JACK_PLUGIN := $(LOCAL_JACK_PLUGIN)
-$(built_dex): $(jack_all_deps) $(LOCAL_JACK_PLUGIN_PATH) | setup-jack-server
- @echo Building with Jack: $@
- $(jack-java-to-dex)
-
-# $(full_classes_jack) is just by-product of $(built_dex).
-# The dummy command was added because, without it, make misses the fact the $(built_dex) also
-# change $(full_classes_jack).
-$(full_classes_jack): $(built_dex)
- $(hide) touch $@
-
-$(LOCAL_BUILT_MODULE): PRIVATE_DEX_FILE := $(built_dex)
-$(LOCAL_BUILT_MODULE): $(built_dex) $(java_resource_sources)
- @echo "Host Jar: $(PRIVATE_MODULE) ($@)"
- $(create-empty-package)
- $(add-dex-to-package)
- $(add-carried-jack-resources)
-
-else # LOCAL_IS_STATIC_JAVA_LIBRARY
-$(full_classes_jack): PRIVATE_JACK_PLUGIN_PATH := $(LOCAL_JACK_PLUGIN_PATH)
-$(full_classes_jack): PRIVATE_JACK_PLUGIN := $(LOCAL_JACK_PLUGIN)
-$(full_classes_jack): $(jack_all_deps) $(LOCAL_JACK_PLUGIN_PATH) | setup-jack-server
- @echo Building with Jack: $@
- $(java-to-jack)
-
-endif # LOCAL_IS_STATIC_JAVA_LIBRARY
-
-$(jack_check_timestamp): $(jack_all_deps) | setup-jack-server
- @echo Checking build with Jack: $@
- $(jack-check-java)
-endif # LOCAL_JACK_ENABLED
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_DEFAULT_APP_TARGET_SDK := $(my_default_app_target_sdk)
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_SDK_VERSION := $(my_sdk_version)
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_MIN_SDK_VERSION := $(my_min_sdk_version)
USE_CORE_LIB_BOOTCLASSPATH :=
diff --git a/core/host_executable_internal.mk b/core/host_executable_internal.mk
index 19200fd..c4f9f66 100644
--- a/core/host_executable_internal.mk
+++ b/core/host_executable_internal.mk
@@ -12,7 +12,9 @@
LOCAL_MODULE_SUFFIX := $($(my_prefix)EXECUTABLE_SUFFIX)
endif
+ifdef host-executable-hook
$(call host-executable-hook)
+endif
skip_build_from_source :=
ifdef LOCAL_PREBUILT_MODULE_FILE
diff --git a/core/host_fuzz_test.mk b/core/host_fuzz_test.mk
index 8622911..556e02f 100644
--- a/core/host_fuzz_test.mk
+++ b/core/host_fuzz_test.mk
@@ -4,7 +4,7 @@
################################################
$(call record-module-type,HOST_FUZZ_TEST)
-LOCAL_CFLAGS += -fsanitize-coverage=trace-pc-guard
+LOCAL_CFLAGS += -fsanitize-coverage=trace-pc-guard,indirect-calls,trace-cmp
LOCAL_STATIC_LIBRARIES += libLLVMFuzzer
include $(BUILD_HOST_EXECUTABLE)
diff --git a/core/host_java_library.mk b/core/host_java_library.mk
index a68be6a..750254f 100644
--- a/core/host_java_library.mk
+++ b/core/host_java_library.mk
@@ -34,10 +34,15 @@
full_classes_compiled_jar := $(intermediates.COMMON)/classes-full-debug.jar
full_classes_jarjar_jar := $(intermediates.COMMON)/classes-jarjar.jar
full_classes_jar := $(intermediates.COMMON)/classes.jar
+java_source_list_file := $(intermediates.COMMON)/java-source-list
+full_classes_header_jar := $(intermediates.COMMON)/classes-header.jar
+full_classes_combined_jar := $(intermediates.COMMON)/classes-combined.jar
LOCAL_INTERMEDIATE_TARGETS += \
$(full_classes_compiled_jar) \
$(full_classes_jarjar_jar) \
+ $(java_source_list_file) \
+ $(full_classes_combined_jar)
#######################################
include $(BUILD_SYSTEM)/base_rules.mk
@@ -50,53 +55,73 @@
include $(BUILD_SYSTEM)/java_common.mk
# The layers file allows you to enforce a layering between java packages.
-# Run build/tools/java-layers.py for more details.
+# Run build/make/tools/java-layers.py for more details.
layers_file := $(addprefix $(LOCAL_PATH)/, $(LOCAL_JAVA_LAYERS_FILE))
-# If error prone is enabled then add LOCAL_ERROR_PRONE_FLAGS to LOCAL_JAVACFLAGS
-ifeq ($(RUN_ERROR_PRONE),true)
-LOCAL_JAVACFLAGS += $(LOCAL_ERROR_PRONE_FLAGS)
-endif
+# List of dependencies for anything that needs all java sources in place
+java_sources_deps := \
+ $(java_sources) \
+ $(java_resource_sources) \
+ $(proto_java_sources_file_stamp) \
+ $(LOCAL_SRCJARS) \
+ $(LOCAL_ADDITIONAL_DEPENDENCIES)
+
+$(java_source_list_file): $(java_sources_deps)
+ $(write-java-source-list)
$(full_classes_compiled_jar): PRIVATE_JAVA_LAYERS_FILE := $(layers_file)
-$(full_classes_compiled_jar): PRIVATE_JAVACFLAGS := $(GLOBAL_JAVAC_DEBUG_FLAGS) $(LOCAL_JAVACFLAGS) $(annotation_processor_flags)
+$(full_classes_compiled_jar): PRIVATE_JAVACFLAGS := $(LOCAL_JAVACFLAGS) $(annotation_processor_flags)
$(full_classes_compiled_jar): PRIVATE_JAR_EXCLUDE_FILES :=
$(full_classes_compiled_jar): PRIVATE_JAR_PACKAGES :=
$(full_classes_compiled_jar): PRIVATE_JAR_EXCLUDE_PACKAGES :=
+$(full_classes_compiled_jar): PRIVATE_SRCJARS := $(LOCAL_SRCJARS)
+$(full_classes_compiled_jar): PRIVATE_SRCJAR_LIST_FILE := $(intermediates.COMMON)/srcjar-list
+$(full_classes_compiled_jar): PRIVATE_SRCJAR_INTERMEDIATES_DIR := $(intermediates.COMMON)/srcjars
$(full_classes_compiled_jar): \
- $(java_sources) \
- $(java_resource_sources) \
- $(full_java_lib_deps) \
- $(jar_manifest_file) \
- $(proto_java_sources_file_stamp) \
- $(annotation_processor_deps) \
- $(NORMALIZE_PATH) \
- $(ZIPTIME) \
- $(LOCAL_ADDITIONAL_DEPENDENCIES) \
- | $(SOONG_JAVAC_WRAPPER)
+ $(java_source_list_file) \
+ $(java_sources_deps) \
+ $(full_java_libs) \
+ $(full_java_bootclasspath_libs) \
+ $(annotation_processor_deps) \
+ $(NORMALIZE_PATH) \
+ $(ZIPTIME) \
+ $(JAR_ARGS) \
+ $(ZIPSYNC) \
+ | $(SOONG_JAVAC_WRAPPER)
$(transform-host-java-to-package)
$(remove-timestamps-from-package)
javac-check : $(full_classes_compiled_jar)
javac-check-$(LOCAL_MODULE) : $(full_classes_compiled_jar)
+$(full_classes_combined_jar): $(full_classes_compiled_jar) \
+ $(jar_manifest_file) \
+ $(full_static_java_libs) | $(MERGE_ZIPS)
+ $(if $(PRIVATE_JAR_MANIFEST), $(hide) sed -e "s/%BUILD_NUMBER%/$(BUILD_NUMBER_FROM_FILE)/" \
+ $(PRIVATE_JAR_MANIFEST) > $(dir $@)/manifest.mf)
+ $(MERGE_ZIPS) -j --ignore-duplicates $(if $(PRIVATE_JAR_MANIFEST),-m $(dir $@)/manifest.mf) \
+ -stripDir META-INF -zipToNotStrip $< $@ $< $(call reverse-list,$(PRIVATE_STATIC_JAVA_LIBRARIES))
+
# Run jarjar if necessary, otherwise just copy the file.
ifneq ($(strip $(LOCAL_JARJAR_RULES)),)
$(full_classes_jarjar_jar): PRIVATE_JARJAR_RULES := $(LOCAL_JARJAR_RULES)
-$(full_classes_jarjar_jar): $(full_classes_compiled_jar) $(LOCAL_JARJAR_RULES) | $(JARJAR)
+$(full_classes_jarjar_jar): $(full_classes_combined_jar) $(LOCAL_JARJAR_RULES) | $(JARJAR)
@echo JarJar: $@
$(hide) $(JAVA) -jar $(JARJAR) process $(PRIVATE_JARJAR_RULES) $< $@
else
-full_classes_jarjar_jar := $(full_classes_compiled_jar)
+full_classes_jarjar_jar := $(full_classes_combined_jar)
endif
+#######################################
LOCAL_FULL_CLASSES_PRE_JACOCO_JAR := $(full_classes_jarjar_jar)
-#######################################
include $(BUILD_SYSTEM)/jacoco.mk
#######################################
$(eval $(call copy-one-file,$(LOCAL_FULL_CLASSES_JACOCO_JAR),$(LOCAL_BUILT_MODULE)))
$(eval $(call copy-one-file,$(LOCAL_FULL_CLASSES_JACOCO_JAR),$(full_classes_jar)))
+ifeq ($(TURBINE_ENABLED),false)
+$(eval $(call copy-one-file,$(LOCAL_FULL_CLASSES_JACOCO_JAR),$(full_classes_header_jar)))
+endif
diff --git a/core/host_java_library_common.mk b/core/host_java_library_common.mk
index 8df4b37..51e2d94 100644
--- a/core/host_java_library_common.mk
+++ b/core/host_java_library_common.mk
@@ -48,3 +48,8 @@
LOCAL_INTERMEDIATE_SOURCE_DIR := $(intermediates.COMMON)/src
LOCAL_JAVA_LIBRARIES := $(sort $(LOCAL_JAVA_LIBRARIES))
+
+# If error prone is enabled then add LOCAL_ERROR_PRONE_FLAGS to LOCAL_JAVACFLAGS
+ifeq ($(RUN_ERROR_PRONE),true)
+LOCAL_JAVACFLAGS += $(LOCAL_ERROR_PRONE_FLAGS)
+endif
diff --git a/core/host_shared_library_internal.mk b/core/host_shared_library_internal.mk
index bfbde21..0a3b317 100644
--- a/core/host_shared_library_internal.mk
+++ b/core/host_shared_library_internal.mk
@@ -20,7 +20,9 @@
$(error $(LOCAL_PATH): Cannot set module stem for a library)
endif
+ifdef host-shared-library-hook
$(call host-shared-library-hook)
+endif
skip_build_from_source :=
ifdef LOCAL_PREBUILT_MODULE_FILE
@@ -39,7 +41,7 @@
include $(BUILD_SYSTEM)/binary.mk
my_host_libprofile_rt := $($(LOCAL_2ND_ARCH_VAR_PREFIX)$(my_prefix)LIBPROFILE_RT)
-$(LOCAL_BUILD_MODULE): PRIVATE_HOST_LIBPROFILE_RT := $(my_host_libprofile_rt)
+$(LOCAL_BUILT_MODULE): PRIVATE_HOST_LIBPROFILE_RT := $(my_host_libprofile_rt)
$(LOCAL_BUILT_MODULE): \
$(all_objects) \
diff --git a/target/board/generic_armv5/BoardConfig.mk b/core/host_test_config.mk
similarity index 68%
copy from target/board/generic_armv5/BoardConfig.mk
copy to core/host_test_config.mk
index 016937a..b9975e5 100644
--- a/target/board/generic_armv5/BoardConfig.mk
+++ b/core/host_test_config.mk
@@ -1,5 +1,5 @@
#
-# Copyright (C) 2011 The Android Open Source Project
+# 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.
@@ -14,10 +14,12 @@
# limitations under the License.
#
-include build/target/board/generic/BoardConfig.mk
+#
+# Common rules for building a TradeFed test XML file for host side tests.
+#
-TARGET_ARCH_VARIANT := armv5te
-TARGET_CPU_ABI := armeabi
-TARGET_CPU_ABI2 :=
+$(call record-module-type,HOST_TEST_CONFIG)
-WITH_DEXPREOPT := false
+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
index ffb22c7..42e01e1 100644
--- a/core/host_test_internal.mk
+++ b/core/host_test_internal.mk
@@ -5,9 +5,7 @@
ifeq ($(LOCAL_GTEST),true)
LOCAL_CFLAGS_windows += -DGTEST_OS_WINDOWS
LOCAL_CFLAGS_linux += -DGTEST_OS_LINUX
- LOCAL_LDLIBS_linux += -lpthread
LOCAL_CFLAGS_darwin += -DGTEST_OS_MAC
- LOCAL_LDLIBS_darwin += -lpthread
LOCAL_CFLAGS += -DGTEST_HAS_STD_STRING -O0 -g
diff --git a/core/install_jni_libs.mk b/core/install_jni_libs.mk
index e88db40..b7d83dc 100644
--- a/core/install_jni_libs.mk
+++ b/core/install_jni_libs.mk
@@ -18,19 +18,9 @@
ifneq ($(filter tests samples, $(LOCAL_MODULE_TAGS)),)
my_embed_jni := true
endif
-ifeq ($(PRODUCT_FULL_TREBLE),true)
- ifeq ($(filter $(TARGET_OUT)/%, $(my_module_path)),)
- # If this app isn't to be installed to the system partition, and the device
- # is fully treble-ized then jni libs are embedded, Otherwise, access to the
- # directory where the lib is installed to (usually /vendor/lib) needs to be
- # allowed for system processes, which is a Treble violation.
- my_embed_jni := true
- endif
-else
- ifeq ($(filter $(TARGET_OUT)/% $(TARGET_OUT_VENDOR)/% $(TARGET_OUT_OEM)/%, $(my_module_path)),)
- # If this app isn't to be installed to system, vendor, or oem partitions.
- my_embed_jni := true
- endif
+ifeq ($(filter $(TARGET_OUT)/% $(TARGET_OUT_VENDOR)/% $(TARGET_OUT_OEM)/%, $(my_module_path)),)
+# If this app isn't to be installed to system partitions.
+my_embed_jni := true
endif
# If we're installing this APP as a compressed module, we include all JNI libraries
# in the compressed artifact, rather than as separate files on the partition in question.
diff --git a/core/install_jni_libs_internal.mk b/core/install_jni_libs_internal.mk
index b5f10cf..a99d88a 100644
--- a/core/install_jni_libs_internal.mk
+++ b/core/install_jni_libs_internal.mk
@@ -24,16 +24,11 @@
ifdef my_embed_jni
# App explicitly requires the prebuilt NDK stl shared libraies.
# The NDK stl shared libraries should never go to the system image.
-ifneq ($(filter $(LOCAL_NDK_STL_VARIANT), stlport_shared c++_shared),)
+ifeq ($(LOCAL_NDK_STL_VARIANT),c++_shared)
ifndef LOCAL_SDK_VERSION
$(error LOCAL_SDK_VERSION must be defined with LOCAL_NDK_STL_VARIANT, \
LOCAL_PACKAGE_NAME=$(LOCAL_PACKAGE_NAME))
endif
-endif
-ifeq (stlport_shared,$(LOCAL_NDK_STL_VARIANT))
-my_jni_shared_libraries += \
- $(HISTORICAL_NDK_VERSIONS_ROOT)/$(LOCAL_NDK_VERSION)/sources/cxx-stl/stlport/libs/$(TARGET_$(my_2nd_arch_prefix)CPU_ABI)/libstlport_shared.so
-else ifeq (c++_shared,$(LOCAL_NDK_STL_VARIANT))
my_jni_shared_libraries += \
$(HISTORICAL_NDK_VERSIONS_ROOT)/$(LOCAL_NDK_VERSION)/sources/cxx-stl/llvm-libc++/libs/$(TARGET_$(my_2nd_arch_prefix)CPU_ABI)/libc++_shared.so
endif
@@ -108,15 +103,19 @@
endif # outer my_prebuilt_jni_libs
# Verify that all included libraries are built against the NDK
+include $(BUILD_SYSTEM)/allowed_ndk_types.mk
ifneq ($(strip $(LOCAL_JNI_SHARED_LIBRARIES)),)
ifneq ($(LOCAL_SDK_VERSION),)
my_link_type := app:sdk
-my_warn_types := native:platform
-my_allowed_types := native:ndk
+my_warn_types := native:platform $(my_warn_ndk_types)
+my_allowed_types := $(my_allowed_ndk_types)
+ ifneq (,$(filter true,$(LOCAL_VENDOR_MODULE) $(LOCAL_ODM_MODULE) $(LOCAL_PROPRIETARY_MODULE)))
+ my_allowed_types += native:vendor native:vndk
+ endif
else
my_link_type := app:platform
-my_warn_types :=
-my_allowed_types := native:ndk native:platform native:vendor
+my_warn_types := $(my_warn_ndk_types)
+my_allowed_types := $(my_allowed_ndk_types) native:platform native:vendor native:vndk native:vndk_private
endif
my_link_deps := $(addprefix SHARED_LIBRARIES:,$(LOCAL_JNI_SHARED_LIBRARIES))
diff --git a/core/instrumentation_test_config_template.xml b/core/instrumentation_test_config_template.xml
new file mode 100644
index 0000000..18ea676
--- /dev/null
+++ b/core/instrumentation_test_config_template.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<!-- This test config file is auto-generated. -->
+<configuration description="Runs {LABEL}.">
+ <option name="test-suite-tag" value="apct" />
+ <option name="test-suite-tag" value="apct-instrumentation" />
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="{MODULE}.apk" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.{TEST_TYPE}" >
+ <option name="package" value="{PACKAGE}" />
+ <option name="runner" value="{RUNNER}" />
+ </test>
+</configuration>
diff --git a/core/jack-default.args b/core/jack-default.args
deleted file mode 100644
index 433bc53..0000000
--- a/core/jack-default.args
+++ /dev/null
@@ -1,9 +0,0 @@
--D sched.runner=multi-threaded
--D sched.runner.thread.kind=fixed
--D sched.runner.thread.fixed.count=4
---sanity-checks off
--D jack.reporter.level.file=error=--,warning=-
---verbose error
--D jack.jayce.cache=false
--D jack.lambda.grouping-scope=package
--D jack.lambda.simplify-stateless=true
diff --git a/core/jacoco.mk b/core/jacoco.mk
index a04d25e..6406df4 100644
--- a/core/jacoco.mk
+++ b/core/jacoco.mk
@@ -19,44 +19,20 @@
# (at the time of authorship, it is included by java.mk and
# java_host_library.mk)
-my_include_filter :=
-my_exclude_filter :=
+# determine Jacoco include/exclude filters even when coverage is not enabled
+# to get syntax checking on LOCAL_JACK_COVERAGE_(INCLUDE|EXCLUDE)_FILTER
+# copy filters from Jack but also skip some known java packages
+my_include_filter := $(strip $(LOCAL_JACK_COVERAGE_INCLUDE_FILTER))
+my_exclude_filter := $(strip $(DEFAULT_JACOCO_EXCLUDE_FILTER),$(LOCAL_JACK_COVERAGE_EXCLUDE_FILTER))
+
+my_include_args := $(call jacoco-class-filter-to-file-args, $(my_include_filter))
+my_exclude_args := $(call jacoco-class-filter-to-file-args, $(my_exclude_filter))
+
+# single-quote each arg of the include args so the '*' gets evaluated by zip
+# don't quote the exclude args they need to be evaluated by bash for rm -rf
+my_include_args := $(foreach arg,$(my_include_args),'$(arg)')
ifeq ($(LOCAL_EMMA_INSTRUMENT),true)
- ifeq ($(ANDROID_COMPILE_WITH_JACK),false)
- # determine Jacoco include/exclude filters
- DEFAULT_JACOCO_EXCLUDE_FILTER := org/junit/*,org/jacoco/*,org/mockito/*
- # copy filters from Jack but also skip some known java packages
- my_include_filter := $(strip $(LOCAL_JACK_COVERAGE_INCLUDE_FILTER))
- my_exclude_filter := $(strip $(DEFAULT_JACOCO_EXCLUDE_FILTER),$(LOCAL_JACK_COVERAGE_EXCLUDE_FILTER))
-
- # replace '.' with '/' and ',' with ' ', and quote each arg
- ifneq ($(strip $(my_include_filter)),)
- my_include_args := $(strip $(my_include_filter))
-
- my_include_args := $(subst .,/,$(my_include_args))
- my_include_args := '$(subst $(comma),' ',$(my_include_args))'
- else
- my_include_args :=
- endif
-
- # replace '.' with '/' and ',' with ' ', and quote each arg
- ifneq ($(strip $(my_exclude_filter)),)
- my_exclude_args := $(my_exclude_filter)
-
- my_exclude_args := $(subst .,/,$(my_exclude_args))
- my_exclude_args := $(subst $(comma)$(comma),$(comma),$(my_exclude_args))
- my_exclude_args := '$(subst $(comma),' ', $(my_exclude_args))'
- else
- my_exclude_args :=
- endif
- endif # ANDROID_COMPILE_WITH_JACK==false
-endif # LOCAL_EMMA_INSTRUMENT == true
-
-# determine whether to run the instrumenter based on whether there is any work
-# for it to do
-ifneq ($(my_include_filter),)
-
my_files := $(intermediates.COMMON)/jacoco
# make a task that unzips the classes that we want to instrument from the
@@ -74,7 +50,8 @@
unzip -q $(PRIVATE_FULL_CLASSES_PRE_JACOCO_JAR) \
-d $(PRIVATE_UNZIPPED_PATH) \
$(PRIVATE_INCLUDE_ARGS)
- rm -rf $(PRIVATE_EXCLUDE_ARGS)
+ (cd $(PRIVATE_UNZIPPED_PATH) && rm -rf $(PRIVATE_EXCLUDE_ARGS))
+ (cd $(PRIVATE_UNZIPPED_PATH) && find -not -name "*.class" -type f | xargs --no-run-if-empty rm)
touch $(PRIVATE_UNZIPPED_TIMESTAMP_PATH)
# Unfortunately in the previous task above,
# 'rm -rf $(PRIVATE_EXCLUDE_ARGS)' needs to be a separate
@@ -107,8 +84,8 @@
mkdir -p $(PRIVATE_INSTRUMENTED_PATH)
java -jar $(JACOCO_CLI_JAR) \
instrument \
- -quiet \
- -dest '$(PRIVATE_INSTRUMENTED_PATH)' \
+ --quiet \
+ --dest '$(PRIVATE_INSTRUMENTED_PATH)' \
$(PRIVATE_UNZIPPED_PATH)
touch $(PRIVATE_INSTRUMENTED_TIMESTAMP_PATH)
@@ -120,12 +97,13 @@
$(LOCAL_FULL_CLASSES_JACOCO_JAR): PRIVATE_TEMP_JAR_PATH := $(my_temp_jar_path)
$(LOCAL_FULL_CLASSES_JACOCO_JAR): PRIVATE_INSTRUMENTED_PATH := $(my_instrumented_path)
$(LOCAL_FULL_CLASSES_JACOCO_JAR): PRIVATE_FULL_CLASSES_PRE_JACOCO_JAR := $(LOCAL_FULL_CLASSES_PRE_JACOCO_JAR)
+$(LOCAL_FULL_CLASSES_JACOCO_JAR): $(JAR_ARGS)
$(LOCAL_FULL_CLASSES_JACOCO_JAR): $(my_instrumented_timestamp_path) $(LOCAL_FULL_CLASSES_PRE_JACOCO_JAR)
rm -f $@ $(PRIVATE_TEMP_JAR_PATH)
# copy the pre-jacoco jar (containing files excluded from instrumentation)
cp $(PRIVATE_FULL_CLASSES_PRE_JACOCO_JAR) $(PRIVATE_TEMP_JAR_PATH)
# copy instrumented files back into the resultant jar
- $(JAR) -uf $(PRIVATE_TEMP_JAR_PATH) -C $(PRIVATE_INSTRUMENTED_PATH) .
+ $(JAR) -uf $(PRIVATE_TEMP_JAR_PATH) $(call jar-args-sorted-files-in-directory,$(PRIVATE_INSTRUMENTED_PATH))
mv $(PRIVATE_TEMP_JAR_PATH) $@
# this is used to trigger $(my_classes_to_report_on_path) to build
@@ -133,8 +111,8 @@
# dependency.
$(LOCAL_FULL_CLASSES_JACOCO_JAR): $(my_classes_to_report_on_path)
-else # my_include_filter == ''
+else # LOCAL_EMMA_INSTRUMENT != true
LOCAL_FULL_CLASSES_JACOCO_JAR := $(LOCAL_FULL_CLASSES_PRE_JACOCO_JAR)
-endif # my_include_filter != ''
+endif # LOCAL_EMMA_INSTRUMENT == true
LOCAL_INTERMEDIATE_TARGETS += $(LOCAL_FULL_CLASSES_JACOCO_JAR)
diff --git a/core/java.mk b/core/java.mk
index 3601292..9147849 100644
--- a/core/java.mk
+++ b/core/java.mk
@@ -18,47 +18,6 @@
LOCAL_NO_STANDARD_LIBRARIES:=$(strip $(LOCAL_NO_STANDARD_LIBRARIES))
LOCAL_SDK_VERSION:=$(strip $(LOCAL_SDK_VERSION))
-ifneq ($(LOCAL_SDK_VERSION),)
- ifeq ($(LOCAL_NO_STANDARD_LIBRARIES),true)
- $(error $(LOCAL_PATH): Must not define both LOCAL_NO_STANDARD_LIBRARIES and LOCAL_SDK_VERSION)
- else
- ifeq ($(strip $(filter $(LOCAL_SDK_VERSION),$(TARGET_AVAILABLE_SDK_VERSIONS))),)
- $(error $(LOCAL_PATH): Invalid LOCAL_SDK_VERSION '$(LOCAL_SDK_VERSION)' \
- Choices are: $(TARGET_AVAILABLE_SDK_VERSIONS))
- else
- ifeq ($(LOCAL_SDK_VERSION)$(TARGET_BUILD_APPS),current)
- # Use android_stubs_current if LOCAL_SDK_VERSION is current and no TARGET_BUILD_APPS.
- LOCAL_JAVA_LIBRARIES := android_stubs_current $(LOCAL_JAVA_LIBRARIES)
- else ifeq ($(LOCAL_SDK_VERSION)$(TARGET_BUILD_APPS),system_current)
- LOCAL_JAVA_LIBRARIES := android_system_stubs_current $(LOCAL_JAVA_LIBRARIES)
- else ifeq ($(LOCAL_SDK_VERSION)$(TARGET_BUILD_APPS),test_current)
- LOCAL_JAVA_LIBRARIES := android_test_stubs_current $(LOCAL_JAVA_LIBRARIES)
- else
- LOCAL_JAVA_LIBRARIES := sdk_v$(LOCAL_SDK_VERSION) $(LOCAL_JAVA_LIBRARIES)
- endif
-
- ifeq ($(LOCAL_SDK_VERSION),current)
- my_jack_min_sdk_version := $(PLATFORM_JACK_MIN_SDK_VERSION)
- else ifeq ($(LOCAL_SDK_VERSION),system_current)
- my_jack_min_sdk_version := $(PLATFORM_JACK_MIN_SDK_VERSION)
- else ifeq ($(LOCAL_SDK_VERSION),test_current)
- my_jack_min_sdk_version := $(PLATFORM_JACK_MIN_SDK_VERSION)
- else
- my_jack_min_sdk_version := $(LOCAL_SDK_VERSION)
- endif
- endif
- endif
-else
- my_jack_min_sdk_version := $(PLATFORM_JACK_MIN_SDK_VERSION)
- ifneq ($(LOCAL_NO_STANDARD_LIBRARIES),true)
- LOCAL_JAVA_LIBRARIES := $(TARGET_DEFAULT_JAVA_LIBRARIES) $(LOCAL_JAVA_LIBRARIES)
- endif
-endif
-
-ifneq (,$(strip $(LOCAL_MIN_SDK_VERSION)))
- my_jack_min_sdk_version := $(LOCAL_MIN_SDK_VERSION)
-endif
-
proto_sources := $(filter %.proto,$(LOCAL_SRC_FILES))
ifneq ($(proto_sources),)
ifeq ($(LOCAL_PROTOC_OPTIMIZE_TYPE),micro)
@@ -100,27 +59,24 @@
intermediates := $(call local-intermediates-dir)
intermediates.COMMON := $(call local-intermediates-dir,COMMON)
-# Choose leaf name for the compiled jar file.
-ifeq ($(LOCAL_EMMA_INSTRUMENT),true)
-full_classes_compiled_jar_leaf := classes-no-debug-var.jar
-built_dex_intermediate_leaf := no-local
-else
-full_classes_compiled_jar_leaf := classes-full-debug.jar
-built_dex_intermediate_leaf := with-local
-endif
-
ifeq ($(LOCAL_PROGUARD_ENABLED),disabled)
LOCAL_PROGUARD_ENABLED :=
endif
-full_classes_compiled_jar := $(intermediates.COMMON)/$(full_classes_compiled_jar_leaf)
+full_classes_turbine_jar := $(intermediates.COMMON)/classes-turbine.jar
+full_classes_header_jarjar := $(intermediates.COMMON)/classes-header-jarjar.jar
+full_classes_header_jar := $(intermediates.COMMON)/classes-header.jar
+full_classes_compiled_jar := $(intermediates.COMMON)/classes-full-debug.jar
full_classes_processed_jar := $(intermediates.COMMON)/classes-processed.jar
full_classes_desugar_jar := $(intermediates.COMMON)/classes-desugar.jar
-jarjar_leaf := classes-jarjar.jar
-full_classes_jarjar_jar := $(intermediates.COMMON)/$(jarjar_leaf)
+full_classes_jarjar_jar := $(intermediates.COMMON)/classes-jarjar.jar
full_classes_proguard_jar := $(intermediates.COMMON)/classes-proguard.jar
-built_dex_intermediate := $(intermediates.COMMON)/$(built_dex_intermediate_leaf)/classes.dex
+full_classes_combined_jar := $(intermediates.COMMON)/classes-combined.jar
+built_dex_intermediate := $(intermediates.COMMON)/dex/classes.dex
+built_dex_hiddenapi := $(intermediates.COMMON)/dex-hiddenapi/classes.dex
full_classes_stubs_jar := $(intermediates.COMMON)/stubs.jar
+java_source_list_file := $(intermediates.COMMON)/java-source-list
+
ifeq ($(LOCAL_MODULE_CLASS)$(LOCAL_SRC_FILES)$(LOCAL_STATIC_JAVA_LIBRARIES)$(LOCAL_SOURCE_FILES_ALL_GENERATED),APPS)
# If this is an apk without any Java code (e.g. framework-res), we should skip compiling Java.
@@ -130,174 +86,22 @@
full_classes_jar := $(intermediates.COMMON)/classes.jar
built_dex := $(intermediates.COMMON)/classes.dex
endif
-# final Jack library, shrinked and obfuscated if it must be
-full_classes_jack := $(intermediates.COMMON)/classes.jack
-# intermediate Jack library without shrink and obfuscation
-noshrob_classes_jack := $(intermediates.COMMON)/classes.noshrob.jack
-jack_check_timestamp := $(intermediates.COMMON)/jack.check.timestamp
LOCAL_INTERMEDIATE_TARGETS += \
+ $(full_classes_turbine_jar) \
$(full_classes_compiled_jar) \
$(full_classes_desugar_jar) \
$(full_classes_jarjar_jar) \
$(full_classes_jar) \
+ $(full_classes_combined_jar) \
$(full_classes_proguard_jar) \
$(built_dex_intermediate) \
- $(full_classes_jack) \
- $(noshrob_classes_jack) \
- $(jack_check_timestamp) \
$(built_dex) \
- $(full_classes_stubs_jar)
-
+ $(full_classes_stubs_jar) \
+ $(java_source_list_file)
LOCAL_INTERMEDIATE_SOURCE_DIR := $(intermediates.COMMON)/src
-###############################################################
-## .rs files: RenderScript sources to .java files and .bc files
-## .fs files: Filterscript sources to .java files and .bc files
-###############################################################
-renderscript_sources := $(filter %.rs %.fs,$(LOCAL_SRC_FILES))
-# Because names of the java files from RenderScript are unknown until the
-# .rs file(s) are compiled, we have to depend on a timestamp file.
-RenderScript_file_stamp :=
-rs_generated_res_dir :=
-rs_compatibility_jni_libs :=
-ifneq ($(renderscript_sources),)
-renderscript_sources_fullpath := $(addprefix $(LOCAL_PATH)/, $(renderscript_sources))
-RenderScript_file_stamp := $(LOCAL_INTERMEDIATE_SOURCE_DIR)/RenderScript.stamp
-renderscript_intermediate.COMMON := $(intermediates.COMMON)/renderscript
-
-# Defaulting to an empty string uses the latest available platform SDK.
-renderscript_target_api :=
-
-ifneq (,$(LOCAL_RENDERSCRIPT_TARGET_API))
- renderscript_target_api := $(LOCAL_RENDERSCRIPT_TARGET_API)
-else
- ifneq (,$(LOCAL_SDK_VERSION))
- # Set target-api for LOCAL_SDK_VERSIONs other than current.
- ifneq (,$(filter-out current system_current test_current, $(LOCAL_SDK_VERSION)))
- renderscript_target_api := $(LOCAL_SDK_VERSION)
- endif
- endif # LOCAL_SDK_VERSION is set
-endif # LOCAL_RENDERSCRIPT_TARGET_API is set
-
-# For 64-bit, we always have to upgrade to at least 21 for compat build.
-ifneq ($(LOCAL_RENDERSCRIPT_COMPATIBILITY),)
- ifeq ($(TARGET_IS_64_BIT),true)
- ifneq ($(filter $(RSCOMPAT_32BIT_ONLY_API_LEVELS),$(renderscript_target_api)),)
- renderscript_target_api := 21
- endif
- endif
-endif
-
-ifeq ($(LOCAL_RENDERSCRIPT_CC),)
-LOCAL_RENDERSCRIPT_CC := $(LLVM_RS_CC)
-endif
-
-# Turn on all warnings and warnings as errors for RS compiles.
-# This can be disabled with LOCAL_RENDERSCRIPT_FLAGS := -Wno-error
-renderscript_flags := -Wall -Werror
-renderscript_flags += $(LOCAL_RENDERSCRIPT_FLAGS)
-
-# prepend the RenderScript system include path
-ifneq ($(filter-out current system_current test_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
-LOCAL_RENDERSCRIPT_INCLUDES := \
- $(HISTORICAL_SDK_VERSIONS_ROOT)/renderscript/clang-include \
- $(HISTORICAL_SDK_VERSIONS_ROOT)/renderscript/include \
- $(LOCAL_RENDERSCRIPT_INCLUDES)
-else
-LOCAL_RENDERSCRIPT_INCLUDES := \
- $(TOPDIR)external/clang/lib/Headers \
- $(TOPDIR)frameworks/rs/script_api/include \
- $(LOCAL_RENDERSCRIPT_INCLUDES)
-endif
-
-ifneq ($(LOCAL_RENDERSCRIPT_INCLUDES_OVERRIDE),)
-LOCAL_RENDERSCRIPT_INCLUDES := $(LOCAL_RENDERSCRIPT_INCLUDES_OVERRIDE)
-endif
-
-bc_files := $(patsubst %.fs,%.bc, $(patsubst %.rs,%.bc, $(notdir $(renderscript_sources))))
-bc_dep_files := $(addprefix $(renderscript_intermediate.COMMON)/,$(patsubst %.bc,%.d,$(bc_files)))
-
-$(RenderScript_file_stamp): PRIVATE_RS_INCLUDES := $(LOCAL_RENDERSCRIPT_INCLUDES)
-$(RenderScript_file_stamp): PRIVATE_RS_CC := $(LOCAL_RENDERSCRIPT_CC)
-$(RenderScript_file_stamp): PRIVATE_RS_FLAGS := $(renderscript_flags)
-$(RenderScript_file_stamp): PRIVATE_RS_SOURCE_FILES := $(renderscript_sources_fullpath)
-# By putting the generated java files into $(LOCAL_INTERMEDIATE_SOURCE_DIR), they will be
-# automatically found by the java compiling function transform-java-to-classes.jar.
-$(RenderScript_file_stamp): PRIVATE_RS_OUTPUT_DIR := $(renderscript_intermediate.COMMON)
-$(RenderScript_file_stamp): PRIVATE_RS_TARGET_API := $(renderscript_target_api)
-$(RenderScript_file_stamp): PRIVATE_DEP_FILES := $(bc_dep_files)
-$(RenderScript_file_stamp): $(renderscript_sources_fullpath) $(LOCAL_RENDERSCRIPT_CC)
- $(transform-renderscripts-to-java-and-bc)
-
-# include the dependency files (.d/.P) generated by llvm-rs-cc.
-$(call include-depfile,$(RenderScript_file_stamp).P,$(RenderScript_file_stamp))
-
-ifneq ($(LOCAL_RENDERSCRIPT_COMPATIBILITY),)
-
-
-ifeq ($(filter $(RSCOMPAT_32BIT_ONLY_API_LEVELS),$(renderscript_target_api)),)
-ifeq ($(TARGET_IS_64_BIT),true)
-renderscript_intermediate.bc_folder := $(renderscript_intermediate.COMMON)/res/raw/bc64/
-else
-renderscript_intermediate.bc_folder := $(renderscript_intermediate.COMMON)/res/raw/bc32/
-endif
-else
-renderscript_intermediate.bc_folder := $(renderscript_intermediate.COMMON)/res/raw/
-endif
-
-rs_generated_bc := $(addprefix \
- $(renderscript_intermediate.bc_folder), $(bc_files))
-
-renderscript_intermediate := $(intermediates)/renderscript
-
-# We don't need the .so files in bundled branches
-# Prevent these from showing up on the device
-# One exception is librsjni.so, which is needed for
-# both native path and compat path.
-rs_jni_lib := $(TARGET_OUT_INTERMEDIATE_LIBRARIES)/librsjni.so
-LOCAL_JNI_SHARED_LIBRARIES += librsjni
-
-ifneq (,$(TARGET_BUILD_APPS)$(FORCE_BUILD_RS_COMPAT))
-
-rs_compatibility_jni_libs := $(addprefix \
- $(renderscript_intermediate)/librs., \
- $(patsubst %.bc,%.so, $(bc_files)))
-
-$(rs_generated_bc) : $(RenderScript_file_stamp)
-
-rs_support_lib := $(TARGET_OUT_INTERMEDIATE_LIBRARIES)/libRSSupport.so
-LOCAL_JNI_SHARED_LIBRARIES += libRSSupport
-
-rs_support_io_lib :=
-# check if the target api level support USAGE_IO
-ifeq ($(filter $(RSCOMPAT_NO_USAGEIO_API_LEVELS),$(renderscript_target_api)),)
-rs_support_io_lib := $(TARGET_OUT_INTERMEDIATE_LIBRARIES)/libRSSupportIO.so
-LOCAL_JNI_SHARED_LIBRARIES += libRSSupportIO
-endif
-
-
-$(rs_compatibility_jni_libs): $(RenderScript_file_stamp) $(RS_PREBUILT_CLCORE) \
- $(rs_support_lib) $(rs_support_io_lib) $(rs_jni_lib) $(rs_compiler_rt)
-$(rs_compatibility_jni_libs): $(BCC_COMPAT)
-$(rs_compatibility_jni_libs): PRIVATE_CXX := $(CXX_WRAPPER) $(TARGET_CXX)
-$(rs_compatibility_jni_libs): $(renderscript_intermediate)/librs.%.so: \
- $(renderscript_intermediate.bc_folder)%.bc
- $(transform-bc-to-so)
-
-endif
-
-endif
-
-LOCAL_INTERMEDIATE_TARGETS += $(RenderScript_file_stamp)
-# Make sure the generated resource will be added to the apk.
-rs_generated_res_dir := $(renderscript_intermediate.COMMON)/res
-LOCAL_RESOURCE_DIR := $(rs_generated_res_dir) $(LOCAL_RESOURCE_DIR)
-endif
-
-
###########################################################
## AIDL: Compile .aidl files to .java
###########################################################
@@ -308,7 +112,7 @@
aidl_preprocess_import :=
ifdef LOCAL_SDK_VERSION
-ifneq ($(filter current system_current test_current, $(LOCAL_SDK_VERSION)$(TARGET_BUILD_APPS)),)
+ifneq ($(filter current system_current test_current core_current, $(LOCAL_SDK_VERSION)$(TARGET_BUILD_APPS)),)
# LOCAL_SDK_VERSION is current and no TARGET_BUILD_APPS
aidl_preprocess_import := $(TARGET_OUT_COMMON_INTERMEDIATES)/framework.aidl
else
@@ -320,7 +124,7 @@
endif # LOCAL_SDK_VERSION
$(foreach s,$(aidl_sources),\
- $(eval $(call define-aidl-java-rule,$(s),$(intermediates.COMMON),aidl_java_sources)))
+ $(eval $(call define-aidl-java-rule,$(s),$(intermediates.COMMON)/aidl,aidl_java_sources)))
$(foreach java,$(aidl_java_sources), \
$(call include-depfile,$(java:%.java=%.P),$(java)))
@@ -339,15 +143,7 @@
# command line.
ifndef LOCAL_CHECKED_MODULE
ifdef full_classes_jar
-ifdef LOCAL_JACK_ENABLED
-ifeq ($(LOCAL_JACK_ENABLED),javac_frontend)
LOCAL_CHECKED_MODULE := $(full_classes_compiled_jar)
-else
-LOCAL_CHECKED_MODULE := $(jack_check_timestamp)
-endif
-else
-LOCAL_CHECKED_MODULE := $(full_classes_compiled_jar)
-endif
endif
endif
@@ -360,11 +156,11 @@
###########################################################
ifneq ($(strip $(logtags_sources)),)
-logtags_java_sources := $(patsubst %.logtags,%.java,$(addprefix $(intermediates.COMMON)/src/, $(logtags_sources)))
+logtags_java_sources := $(patsubst %.logtags,%.java,$(addprefix $(intermediates.COMMON)/logtags/, $(logtags_sources)))
logtags_sources := $(addprefix $(LOCAL_PATH)/, $(logtags_sources))
$(logtags_java_sources): PRIVATE_MERGED_TAG := $(TARGET_OUT_COMMON_INTERMEDIATES)/all-event-log-tags.txt
-$(logtags_java_sources): $(intermediates.COMMON)/src/%.java: $(LOCAL_PATH)/%.logtags $(TARGET_OUT_COMMON_INTERMEDIATES)/all-event-log-tags.txt $(JAVATAGS) build/tools/event_log_tags.py
+$(logtags_java_sources): $(intermediates.COMMON)/logtags/%.java: $(LOCAL_PATH)/%.logtags $(TARGET_OUT_COMMON_INTERMEDIATES)/all-event-log-tags.txt $(JAVATAGS) build/make/tools/event_log_tags.py
$(transform-logtags-to-java)
else
@@ -374,12 +170,12 @@
##########################################
java_sources := $(addprefix $(LOCAL_PATH)/, $(filter %.java,$(LOCAL_SRC_FILES))) $(aidl_java_sources) $(logtags_java_sources) \
$(filter %.java,$(LOCAL_GENERATED_SOURCES))
-all_java_sources := $(java_sources) $(addprefix $(TARGET_OUT_COMMON_INTERMEDIATES)/, $(filter %.java,$(LOCAL_INTERMEDIATE_SOURCES)))
+java_intermediate_sources := $(addprefix $(TARGET_OUT_COMMON_INTERMEDIATES)/, $(filter %.java,$(LOCAL_INTERMEDIATE_SOURCES)))
+all_java_sources := $(java_sources) $(java_intermediate_sources)
include $(BUILD_SYSTEM)/java_common.mk
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_HAS_RS_SOURCES := $(if $(renderscript_sources),true)
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_RS_SOURCE_INTERMEDIATES_DIR := $(intermediates.COMMON)/renderscript
+include $(BUILD_SYSTEM)/sdk_check.mk
# Set the profile source so that the odex / profile code included from java.mk
# can find it.
@@ -402,13 +198,10 @@
# Make sure there's something to build.
ifdef full_classes_jar
ifndef need_compile_java
-$(error $(LOCAL_PATH): Target java module does not define any source or resource files)
+$(call pretty-error,Target java module does not define any source or resource files)
endif
endif
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_JACK_MIN_SDK_VERSION := $(my_jack_min_sdk_version)
-my_jack_min_sdk_version :=
-
# Since we're using intermediates.COMMON, make sure that it gets cleaned
# properly.
$(cleantarget): PRIVATE_CLEAN_FILES += $(intermediates.COMMON)
@@ -422,7 +215,7 @@
ALL_MODULES.$(LOCAL_MODULE).STUBS := $(full_classes_stubs_jar)
# The layers file allows you to enforce a layering between java packages.
-# Run build/tools/java-layers.py for more details.
+# Run build/make/tools/java-layers.py for more details.
layers_file := $(addprefix $(LOCAL_PATH)/, $(LOCAL_JAVA_LAYERS_FILE))
$(full_classes_compiled_jar): PRIVATE_JAVA_LAYERS_FILE := $(layers_file)
$(full_classes_compiled_jar): PRIVATE_WARNINGS_ENABLE := $(LOCAL_WARNINGS_ENABLE)
@@ -443,38 +236,98 @@
ifneq (,$(PRODUCT_MINIMIZE_JAVA_DEBUG_INFO))
ifneq (,$(filter userdebug user,$(TARGET_BUILD_VARIANT)))
LOCAL_JAVACFLAGS+= -g:source,lines
-LOCAL_JACK_FLAGS+= -D jack.dex.debug.vars=false -D jack.dex.debug.vars.synthetic=false
endif
endif
-$(full_classes_compiled_jar): PRIVATE_JAVACFLAGS := $(GLOBAL_JAVAC_DEBUG_FLAGS) $(LOCAL_JAVACFLAGS) $(annotation_processor_flags)
+# List of dependencies for anything that needs all java sources in place
+java_sources_deps := \
+ $(java_sources) \
+ $(java_resource_sources) \
+ $(proto_java_sources_file_stamp) \
+ $(LOCAL_SRCJARS) \
+ $(LOCAL_ADDITIONAL_DEPENDENCIES)
+
+$(java_source_list_file): $(java_sources_deps)
+ $(write-java-source-list)
+
+ifneq ($(TURBINE_ENABLED),false)
+
+$(full_classes_turbine_jar): PRIVATE_JAVACFLAGS := $(LOCAL_JAVACFLAGS) $(annotation_processor_flags)
+$(full_classes_turbine_jar): PRIVATE_SRCJARS := $(LOCAL_SRCJARS)
+$(full_classes_turbine_jar): PRIVATE_DONT_DELETE_JAR_META_INF := $(LOCAL_DONT_DELETE_JAR_META_INF)
+$(full_classes_turbine_jar): \
+ $(java_source_list_file) \
+ $(java_sources_deps) \
+ $(full_java_header_libs) \
+ $(full_java_bootclasspath_libs) \
+ $(full_java_system_modules_deps) \
+ $(NORMALIZE_PATH) \
+ $(JAR_ARGS) \
+ $(ZIPTIME) \
+ | $(TURBINE) \
+ $(MERGE_ZIPS)
+ $(transform-java-to-header.jar)
+
+.KATI_RESTAT: $(full_classes_turbine_jar)
+
+# Run jarjar before generate classes-header.jar if necessary.
+ifneq ($(strip $(LOCAL_JARJAR_RULES)),)
+$(full_classes_header_jarjar): PRIVATE_JARJAR_RULES := $(LOCAL_JARJAR_RULES)
+$(full_classes_header_jarjar): $(full_classes_turbine_jar) $(LOCAL_JARJAR_RULES) | $(JARJAR)
+ @echo Header JarJar: $@
+ $(hide) $(JAVA) -jar $(JARJAR) process $(PRIVATE_JARJAR_RULES) $< $@
+else
+full_classes_header_jarjar := $(full_classes_turbine_jar)
+endif
+
+$(eval $(call copy-one-file,$(full_classes_header_jarjar),$(full_classes_header_jar)))
+
+endif # TURBINE_ENABLED != false
+
+$(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)
$(full_classes_compiled_jar): PRIVATE_JAR_EXCLUDE_PACKAGES := $(LOCAL_JAR_EXCLUDE_PACKAGES)
$(full_classes_compiled_jar): PRIVATE_DONT_DELETE_JAR_META_INF := $(LOCAL_DONT_DELETE_JAR_META_INF)
+$(full_classes_compiled_jar): PRIVATE_JAVA_SOURCE_LIST := $(java_source_list_file)
+$(full_classes_compiled_jar): PRIVATE_ALL_JAVA_HEADER_LIBRARIES := $(full_java_header_libs)
+$(full_classes_compiled_jar): PRIVATE_SRCJARS := $(LOCAL_SRCJARS)
+$(full_classes_compiled_jar): PRIVATE_SRCJAR_LIST_FILE := $(intermediates.COMMON)/srcjar-list
+$(full_classes_compiled_jar): PRIVATE_SRCJAR_INTERMEDIATES_DIR := $(intermediates.COMMON)/srcjars
$(full_classes_compiled_jar): \
- $(java_sources) \
- $(java_resource_sources) \
- $(full_java_lib_deps) \
- $(jar_manifest_file) \
- $(layers_file) \
- $(RenderScript_file_stamp) \
- $(proto_java_sources_file_stamp) \
- $(annotation_processor_deps) \
- $(NORMALIZE_PATH) \
- $(LOCAL_ADDITIONAL_DEPENDENCIES) \
- | $(SOONG_JAVAC_WRAPPER)
- $(transform-java-to-classes.jar)
+ $(java_source_list_file) \
+ $(full_java_header_libs) \
+ $(java_sources_deps) \
+ $(full_java_bootclasspath_libs) \
+ $(full_java_system_modules_deps) \
+ $(layers_file) \
+ $(annotation_processor_deps) \
+ $(NORMALIZE_PATH) \
+ $(JAR_ARGS) \
+ $(ZIPSYNC) \
+ | $(SOONG_JAVAC_WRAPPER)
+ @echo "Target Java: $@
+ $(call compile-java,$(TARGET_JAVAC),$(PRIVATE_ALL_JAVA_HEADER_LIBRARIES))
javac-check : $(full_classes_compiled_jar)
javac-check-$(LOCAL_MODULE) : $(full_classes_compiled_jar)
+$(full_classes_combined_jar): PRIVATE_DONT_DELETE_JAR_META_INF := $(LOCAL_DONT_DELETE_JAR_META_INF)
+$(full_classes_combined_jar): $(full_classes_compiled_jar) \
+ $(jar_manifest_file) \
+ $(full_static_java_libs) | $(MERGE_ZIPS)
+ $(if $(PRIVATE_JAR_MANIFEST), $(hide) sed -e "s/%BUILD_NUMBER%/$(BUILD_NUMBER_FROM_FILE)/" \
+ $(PRIVATE_JAR_MANIFEST) > $(dir $@)/manifest.mf)
+ $(MERGE_ZIPS) -j --ignore-duplicates $(if $(PRIVATE_JAR_MANIFEST),-m $(dir $@)/manifest.mf) \
+ $(if $(PRIVATE_DONT_DELETE_JAR_META_INF),,-stripDir META-INF -zipToNotStrip $<) \
+ $@ $< $(call reverse-list,$(PRIVATE_STATIC_JAVA_LIBRARIES))
+
ifdef LOCAL_JAR_PROCESSOR
# LOCAL_JAR_PROCESSOR_ARGS must be evaluated here to set up the rule-local
# PRIVATE_JAR_PROCESSOR_ARGS variable, but $< and $@ are not available yet.
# Set ${in} and ${out} so they can be referenced by LOCAL_JAR_PROCESSOR_ARGS
# using deferred evaluation (LOCAL_JAR_PROCESSOR_ARGS = instead of :=).
-in := $(full_classes_compiled_jar)
+in := $(full_classes_combined_jar)
out := $(full_classes_processed_jar).tmp
my_jar_processor := $(HOST_OUT_JAVA_LIBRARIES)/$(LOCAL_JAR_PROCESSOR).jar
@@ -484,7 +337,7 @@
in :=
out :=
-$(full_classes_processed_jar): $(full_classes_compiled_jar) $(my_jar_processor)
+$(full_classes_processed_jar): $(full_classes_combined_jar) $(my_jar_processor)
@echo Processing $@ with $(PRIVATE_JAR_PROCESSOR)
$(hide) rm -f $@ $(PRIVATE_TMP_OUT)
$(hide) $(JAVA) -jar $(PRIVATE_JAR_PROCESSOR) $(PRIVATE_JAR_PROCESSOR_ARGS)
@@ -492,99 +345,109 @@
my_jar_processor :=
else
-full_classes_processed_jar := $(full_classes_compiled_jar)
-endif
-
-my_desugaring :=
-ifndef LOCAL_JACK_ENABLED
-ifndef LOCAL_IS_STATIC_JAVA_LIBRARY
-my_desugaring := true
-$(full_classes_desugar_jar): PRIVATE_DX_FLAGS := $(LOCAL_DX_FLAGS)
-$(full_classes_desugar_jar): $(full_classes_processed_jar) $(DESUGAR)
- $(desugar-classes-jar)
-endif
-endif
-
-ifndef my_desugaring
-full_classes_desugar_jar := $(full_classes_processed_jar)
+full_classes_processed_jar := $(full_classes_combined_jar)
endif
# Run jarjar if necessary
ifneq ($(strip $(LOCAL_JARJAR_RULES)),)
$(full_classes_jarjar_jar): PRIVATE_JARJAR_RULES := $(LOCAL_JARJAR_RULES)
-$(full_classes_jarjar_jar): $(full_classes_desugar_jar) $(LOCAL_JARJAR_RULES) | $(JARJAR)
+$(full_classes_jarjar_jar): $(full_classes_processed_jar) $(LOCAL_JARJAR_RULES) | $(JARJAR)
@echo JarJar: $@
$(hide) $(JAVA) -jar $(JARJAR) process $(PRIVATE_JARJAR_RULES) $< $@
else
-full_classes_jarjar_jar := $(full_classes_desugar_jar)
+full_classes_jarjar_jar := $(full_classes_processed_jar)
endif
-LOCAL_FULL_CLASSES_PRE_JACOCO_JAR := $(full_classes_jarjar_jar)
+$(eval $(call copy-one-file,$(full_classes_jarjar_jar),$(full_classes_jar)))
#######################################
+LOCAL_FULL_CLASSES_PRE_JACOCO_JAR := $(full_classes_jar)
+
include $(BUILD_SYSTEM)/jacoco.mk
#######################################
-full_classes_pre_proguard_jar := $(LOCAL_FULL_CLASSES_JACOCO_JAR)
+# Temporarily enable --multi-dex until proguard supports v53 class files
+# ( http://b/67673860 ) or we move away from proguard altogether.
+ifdef TARGET_OPENJDK9
+LOCAL_DX_FLAGS := $(filter-out --multi-dex,$(LOCAL_DX_FLAGS)) --multi-dex
+endif
+
+ifneq ($(USE_D8_DESUGAR),true)
+my_desugaring :=
+ifndef LOCAL_IS_STATIC_JAVA_LIBRARY
+my_desugaring := true
+$(full_classes_desugar_jar): PRIVATE_DX_FLAGS := $(LOCAL_DX_FLAGS)
+$(full_classes_desugar_jar): $(LOCAL_FULL_CLASSES_JACOCO_JAR) $(full_java_header_libs) $(DESUGAR)
+ $(desugar-classes-jar)
+endif
+else
+my_desugaring :=
+endif
+
+ifndef my_desugaring
+full_classes_desugar_jar := $(LOCAL_FULL_CLASSES_JACOCO_JAR)
+endif
+
+full_classes_pre_proguard_jar := $(full_classes_desugar_jar)
# Keep a copy of the jar just before proguard processing.
$(eval $(call copy-one-file,$(full_classes_pre_proguard_jar),$(intermediates.COMMON)/classes-pre-proguard.jar))
# Run proguard if necessary
ifdef LOCAL_PROGUARD_ENABLED
-ifneq ($(filter-out full custom nosystem obfuscation optimization shrinktests,$(LOCAL_PROGUARD_ENABLED)),)
+ifneq ($(filter-out full custom obfuscation optimization,$(LOCAL_PROGUARD_ENABLED)),)
$(warning while processing: $(LOCAL_MODULE))
$(error invalid value for LOCAL_PROGUARD_ENABLED: $(LOCAL_PROGUARD_ENABLED))
endif
proguard_dictionary := $(intermediates.COMMON)/proguard_dictionary
-jack_dictionary := $(intermediates.COMMON)/jack_dictionary
-# Hack: see b/20667396
-# When an app's LOCAL_SDK_VERSION is lower than the support library's LOCAL_SDK_VERSION,
-# we artifically raises the "SDK version" "linked" by ProGuard, to
+# When an app contains references to APIs that are not in the SDK specified by
+# its LOCAL_SDK_VERSION for example added by support library or by runtime
+# classes added by desugar, we artifically raise the "SDK version" "linked" by
+# ProGuard, to
# - suppress ProGuard warnings of referencing symbols unknown to the lower SDK version.
# - prevent ProGuard stripping subclass in the support library that extends class added in the higher SDK version.
-my_support_library_sdk_raise :=
-ifneq (,$(filter android-support-%,$(LOCAL_STATIC_JAVA_LIBRARIES)))
+# See b/20667396
+my_proguard_sdk_raise :=
ifdef LOCAL_SDK_VERSION
ifdef TARGET_BUILD_APPS
-ifeq (,$(filter current system_current test_current, $(LOCAL_SDK_VERSION)))
- my_support_library_sdk_raise := $(call java-lib-files, sdk_vcurrent)
+ifeq (,$(filter current system_current test_current core_current, $(LOCAL_SDK_VERSION)))
+ my_proguard_sdk_raise := $(call java-lib-header-files, sdk_vcurrent)
endif
else
# For platform build, we can't just raise to the "current" SDK,
# that would break apps that use APIs removed from the current SDK.
- my_support_library_sdk_raise := $(call java-lib-files,$(TARGET_DEFAULT_JAVA_LIBRARIES))
-endif
+ my_proguard_sdk_raise := $(call java-lib-header-files,$(TARGET_DEFAULT_BOOTCLASSPATH_LIBRARIES) $(TARGET_DEFAULT_JAVA_LIBRARIES))
endif
endif
-# jack already has the libraries in its classpath and doesn't support jars
-legacy_proguard_flags := $(addprefix -libraryjars ,$(my_support_library_sdk_raise) \
- $(filter-out $(my_support_library_sdk_raise),$(full_shared_java_libs)))
+ifeq ($(USE_R8),true)
+proguard_jars_prefix := -libraryjars
+else
+proguard_jars_prefix := -systemjars
+endif
+legacy_proguard_flags := $(addprefix $(proguard_jars_prefix) ,$(my_proguard_sdk_raise) \
+ $(filter-out $(my_proguard_sdk_raise), \
+ $(full_java_bootclasspath_libs) \
+ $(full_shared_java_header_libs)))
+
+legacy_proguard_lib_deps := $(my_proguard_sdk_raise) \
+ $(filter-out $(my_proguard_sdk_raise),$(full_shared_java_header_libs))
legacy_proguard_flags += -printmapping $(proguard_dictionary)
-jack_proguard_flags := -printmapping $(jack_dictionary)
common_proguard_flags := -forceprocessing
-common_proguard_flag_files :=
-ifeq ($(filter nosystem,$(LOCAL_PROGUARD_ENABLED)),)
-common_proguard_flag_files += $(BUILD_SYSTEM)/proguard.flags
-ifeq ($(LOCAL_EMMA_INSTRUMENT),true)
-ifdef LOCAL_JACK_ENABLED
-common_proguard_flag_files += $(BUILD_SYSTEM)/proguard.jacoco.flags
-else
-common_proguard_flags += -include $(BUILD_SYSTEM)/proguard.emma.flags
-endif # LOCAL_JACK_ENABLED
-endif
-# If this is a test package, add proguard keep flags for tests.
+common_proguard_flag_files := $(BUILD_SYSTEM)/proguard.flags
ifneq ($(LOCAL_INSTRUMENTATION_FOR)$(filter tests,$(LOCAL_MODULE_TAGS)),)
-common_proguard_flag_files += $(BUILD_SYSTEM)/proguard_tests.flags
-ifeq ($(filter shrinktests,$(LOCAL_PROGUARD_ENABLED)),)
common_proguard_flags += -dontshrink # don't shrink tests by default
-endif # shrinktests
endif # test package
+ifneq ($(LOCAL_PROGUARD_ENABLED),custom)
+ ifdef LOCAL_USE_AAPT2
+ common_proguard_flag_files += $(foreach l,$(LOCAL_STATIC_ANDROID_LIBRARIES),\
+ $(call intermediates-dir-for,JAVA_LIBRARIES,$(l),,COMMON)/export_proguard_flags)
+ endif
+endif
ifneq ($(common_proguard_flag_files),)
common_proguard_flags += $(addprefix -include , $(common_proguard_flag_files))
# This is included from $(BUILD_SYSTEM)/proguard.flags
@@ -604,8 +467,8 @@
ifeq ($(filter obfuscation,$(LOCAL_PROGUARD_ENABLED)),)
# If no obfuscation, link in the instrmented package's classes.jar as a library.
# link_instr_classes_jar is defined in base_rule.mk
-# jack already has this library in its classpath and doesn't support jars
legacy_proguard_flags += -libraryjars $(link_instr_classes_jar)
+legacy_proguard_lib_deps += $(link_instr_classes_jar)
else # obfuscation
# If obfuscation is enabled, the main app must be obfuscated too.
# We need to run obfuscation using the main app's dictionary,
@@ -616,10 +479,6 @@
-applymapping $(link_instr_intermediates_dir.COMMON)/proguard_dictionary \
-verbose \
$(legacy_proguard_flags)
-ifdef LOCAL_JACK_ENABLED
-jack_proguard_flags += -applymapping $(link_instr_intermediates_dir.COMMON)/jack_dictionary
-full_jack_deps += $(link_instr_intermediates_dir.COMMON)/jack_dictionary
-endif
# Sometimes (test + main app) uses different keep rules from the main app -
# apply the main app's dictionary anyway.
@@ -630,9 +489,11 @@
endif # no obfuscation
endif # LOCAL_INSTRUMENTATION_FOR
-endif # LOCAL_PROGUARD_ENABLED is not nosystem
proguard_flag_files := $(addprefix $(LOCAL_PATH)/, $(LOCAL_PROGUARD_FLAG_FILES))
+ifeq ($(USE_R8),true)
+proguard_flag_files += $(addprefix $(LOCAL_PATH)/, $(LOCAL_R8_FLAG_FILES))
+endif # USE_R8
LOCAL_PROGUARD_FLAGS += $(addprefix -include , $(proguard_flag_files))
ifdef LOCAL_TEST_MODULE_TO_PROGUARD_WITH
@@ -641,52 +502,66 @@
extra_input_jar :=
endif
-# If not using jack and building against the current SDK version then filter
-# out the junit, android.test and c.a.i.u.Predicate classes that are to be
-# removed from the Android API as part of b/30188076 but which are still
-# present in the Android API. This is to allow changes to be made to the
-# build to statically include those classes into the application without
-# simultaneously removing those classes from the API.
-proguard_injar_filters :=
-ifndef LOCAL_JACK_ENABLED
-ifdef LOCAL_SDK_VERSION
-ifeq (,$(filter-out current system_current test_current, $(LOCAL_SDK_VERSION)))
-proguard_injar_filters := (!junit/framework/**,!junit/runner/**,!junit/textui/**,!android/test/**,!com/android/internal/util/*)
-endif
+ifneq ($(filter obfuscation,$(LOCAL_PROGUARD_ENABLED)),)
+ifneq ($(USE_R8),true)
+ $(full_classes_proguard_jar): .KATI_IMPLICIT_OUTPUTS := $(proguard_dictionary)
+else
+ $(built_dex_intermediate): .KATI_IMPLICIT_OUTPUTS := $(proguard_dictionary)
endif
endif
-$(full_classes_proguard_jar): PRIVATE_PROGUARD_INJAR_FILTERS := $(proguard_injar_filters)
+# If R8 is not enabled run Proguard.
+ifneq ($(USE_R8),true)
+# Changes to these dependencies need to be replicated below when using R8
+# instead of Proguard + dx.
$(full_classes_proguard_jar): PRIVATE_EXTRA_INPUT_JAR := $(extra_input_jar)
$(full_classes_proguard_jar): PRIVATE_PROGUARD_FLAGS := $(legacy_proguard_flags) $(common_proguard_flags) $(LOCAL_PROGUARD_FLAGS)
-$(full_classes_proguard_jar) : $(full_classes_pre_proguard_jar) $(extra_input_jar) $(my_support_library_sdk_raise) $(common_proguard_flag_files) $(proguard_flag_files) | $(PROGUARD)
+$(full_classes_proguard_jar) : $(full_classes_pre_proguard_jar) $(extra_input_jar) $(my_proguard_sdk_raise) $(common_proguard_flag_files) $(proguard_flag_files) $(legacy_proguard_lib_deps) | $(PROGUARD)
$(call transform-jar-to-proguard)
+else # !USE_R8
+# Running R8 instead of Proguard, proguarded jar is actually the pre-Proguarded jar.
+full_classes_proguard_jar := $(full_classes_pre_proguard_jar)
+endif # !USE_R8
else # LOCAL_PROGUARD_ENABLED not defined
+proguard_flag_files :=
full_classes_proguard_jar := $(full_classes_pre_proguard_jar)
endif # LOCAL_PROGUARD_ENABLED defined
-$(eval $(call copy-one-file,$(full_classes_proguard_jar),$(full_classes_jar)))
-
-$(call define-jar-to-toc-rule, $(full_classes_jar))
-
ifneq ($(LOCAL_IS_STATIC_JAVA_LIBRARY),true)
-ifndef LOCAL_JACK_ENABLED
$(built_dex_intermediate): PRIVATE_DX_FLAGS := $(LOCAL_DX_FLAGS)
-# If you instrument class files that have local variable debug information in
-# them emma does not correctly maintain the local variable table.
-# This will cause an error when you try to convert the class files for Android.
-# The workaround here is to build different dex file here based on emma switch
-# then later copy into classes.dex. When emma is on, dx is run with --no-locals
-# option to remove local variable information
-ifeq ($(LOCAL_EMMA_INSTRUMENT),true)
-$(built_dex_intermediate): PRIVATE_DX_FLAGS += --no-locals
-endif
-$(built_dex_intermediate): $(full_classes_jar) $(DX)
- $(transform-classes.jar-to-dex)
-endif # LOCAL_JACK_ENABLED is disabled
-$(built_dex): $(built_dex_intermediate)
+my_r8 :=
+ifdef LOCAL_PROGUARD_ENABLED
+ifeq ($(USE_R8),true)
+# These are the dependencies for the proguarded jar when running
+# Proguard + dx. They are used for the generated dex when using R8, as
+# R8 does Proguard + dx
+my_r8 := true
+$(built_dex_intermediate): PRIVATE_EXTRA_INPUT_JAR := $(extra_input_jar)
+$(built_dex_intermediate): PRIVATE_PROGUARD_FLAGS := $(legacy_proguard_flags) $(common_proguard_flags) $(LOCAL_PROGUARD_FLAGS)
+$(built_dex_intermediate) : $(full_classes_proguard_jar) $(extra_input_jar) $(my_support_library_sdk_raise) $(common_proguard_flag_files) $(proguard_flag_files) $(legacy_proguard_lib_deps) $(R8_COMPAT_PROGUARD)
+ $(transform-jar-to-dex-r8)
+endif # USE_R8
+endif # LOCAL_PROGUARD_ENABLED
+
+ifndef my_r8
+$(built_dex_intermediate): $(full_classes_proguard_jar) $(DX) $(ZIP2ZIP)
+ifneq ($(USE_D8_DESUGAR),true)
+ $(transform-classes.jar-to-dex)
+else
+ $(transform-classes-d8.jar-to-dex)
+endif
+endif
+
+ifneq ($(filter $(LOCAL_MODULE),$(PRODUCT_BOOT_JARS)),) # is_boot_jar
+ $(eval $(call hiddenapi-copy-dex-files,$(built_dex_intermediate),$(built_dex_hiddenapi)))
+ built_dex_copy_from := $(built_dex_hiddenapi)
+else # !is_boot_jar
+ built_dex_copy_from := $(built_dex_intermediate)
+endif # is_boot_jar
+
+$(built_dex): $(built_dex_copy_from)
@echo Copying: $@
$(hide) mkdir -p $(dir $@)
$(hide) rm -f $(dir $@)/classes*.dex
@@ -722,135 +597,20 @@
endif # full_classes_jar is defined
-ifneq (,$(filter-out current system_current test_current, $(LOCAL_SDK_VERSION)))
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_DEFAULT_APP_TARGET_SDK := $(LOCAL_SDK_VERSION)
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_SDK_VERSION := $(LOCAL_SDK_VERSION)
+ifneq (,$(filter-out current system_current test_current core_current, $(LOCAL_SDK_VERSION)))
+ my_default_app_target_sdk := $(call get-numeric-sdk-version,$(LOCAL_SDK_VERSION))
+ my_sdk_version := $(call get-numeric-sdk-version,$(LOCAL_SDK_VERSION))
else
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_DEFAULT_APP_TARGET_SDK := $(DEFAULT_APP_TARGET_SDK)
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_SDK_VERSION := $(PLATFORM_SDK_VERSION)
+ my_default_app_target_sdk := $(DEFAULT_APP_TARGET_SDK)
+ my_sdk_version := $(PLATFORM_SDK_VERSION)
endif
-ifdef LOCAL_JACK_ENABLED
-$(LOCAL_INTERMEDIATE_TARGETS): \
- PRIVATE_JACK_INTERMEDIATES_DIR := $(intermediates.COMMON)/jack-rsc
-ifeq ($(LOCAL_JACK_ENABLED),incremental)
-$(LOCAL_INTERMEDIATE_TARGETS): \
- PRIVATE_JACK_INCREMENTAL_DIR := $(intermediates.COMMON)/jack-incremental
-$(noshrob_classes_jack): PRIVATE_JACK_INCREMENTAL_DIR := $(intermediates.COMMON)/jack-noshrob-incremental
-$(jack_check_timestamp): PRIVATE_JACK_INCREMENTAL_DIR := $(intermediates.COMMON)/jack-check-incremental
+ifdef LOCAL_MIN_SDK_VERSION
+ my_min_sdk_version := $(LOCAL_MIN_SDK_VERSION)
else
-$(LOCAL_INTERMEDIATE_TARGETS): \
- PRIVATE_JACK_INCREMENTAL_DIR :=
-$(noshrob_classes_jack): PRIVATE_JACK_INCREMENTAL_DIR :=
-$(jack_check_timestamp): PRIVATE_JACK_INCREMENTAL_DIR :=
+ my_min_sdk_version := $(call codename-or-sdk-to-sdk,$(my_default_app_target_sdk))
endif
-ifdef full_classes_jar
-ifdef LOCAL_PROGUARD_ENABLED
-
-ifndef LOCAL_JACK_PROGUARD_FLAGS
- LOCAL_JACK_PROGUARD_FLAGS := $(LOCAL_PROGUARD_FLAGS)
-endif
-LOCAL_JACK_PROGUARD_FLAGS += $(addprefix -include , $(proguard_flag_files))
-ifdef LOCAL_TEST_MODULE_TO_PROGUARD_WITH
- $(error $(LOCAL_MODULE): Build with jack when LOCAL_TEST_MODULE_TO_PROGUARD_WITH is defined is not yet implemented)
-endif
-
-# $(jack_dictionary) is just by-product of $(built_dex_intermediate).
-# The dummy command was added because, without it, make misses the fact the $(built_dex) also
-# change $(jack_dictionary).
-$(jack_dictionary): $(full_classes_jack)
- $(hide) touch $@
-
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_JACK_PROGUARD_FLAGS := $(common_proguard_flags) $(jack_proguard_flags) $(LOCAL_JACK_PROGUARD_FLAGS)
-else # LOCAL_PROGUARD_ENABLED not defined
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_JACK_PROGUARD_FLAGS :=
-endif # LOCAL_PROGUARD_ENABLED defined
-
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_JACK_FLAGS := $(GLOBAL_JAVAC_DEBUG_FLAGS) $(LOCAL_JACK_FLAGS) $(annotation_processor_flags)
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_JACK_VERSION := $(LOCAL_JACK_VERSION)
-
-jack_all_deps := $(java_sources) $(java_resource_sources) $(full_jack_deps) \
- $(jar_manifest_file) $(layers_file) $(RenderScript_file_stamp) \
- $(common_proguard_flag_files) $(proguard_flag_files) \
- $(proto_java_sources_file_stamp) $(annotation_processor_deps) \
- $(LOCAL_ADDITIONAL_DEPENDENCIES) $(LOCAL_JARJAR_RULES) \
- $(NORMALIZE_PATH) $(JACK_DEFAULT_ARGS) $(JACK)
-
-$(jack_check_timestamp): $(jack_all_deps) | setup-jack-server
- @echo Checking build with Jack: $@
- $(jack-check-java)
-
-ifeq ($(LOCAL_IS_STATIC_JAVA_LIBRARY),true)
-$(full_classes_jack): PRIVATE_JACK_PLUGIN_PATH := $(LOCAL_JACK_PLUGIN_PATH)
-$(full_classes_jack): PRIVATE_JACK_PLUGIN := $(LOCAL_JACK_PLUGIN)
-$(full_classes_jack): $(jack_all_deps) $(LOCAL_JACK_PLUGIN_PATH) | setup-jack-server
- @echo Building with Jack: $@
- $(java-to-jack)
-
-# Update timestamps of .toc files for static java libraries so
-# dependents will be always rebuilt.
-$(built_dex).toc: $(full_classes_jack)
- touch $@
-
-else #LOCAL_IS_STATIC_JAVA_LIBRARY
-$(built_dex_intermediate): PRIVATE_CLASSES_JACK := $(full_classes_jack)
-
-ifeq ($(LOCAL_EMMA_INSTRUMENT),true)
-LOCAL_JACK_PLUGIN_PATH += $(HOST_OUT_JAVA_LIBRARIES)/jack-coverage-plugin.jar
-LOCAL_JACK_PLUGIN += com.android.jack.coverage.CodeCoverage
-$(built_dex_intermediate): PRIVATE_JACK_COVERAGE_OPTIONS := \
- -D jack.coverage=true \
- -D jack.coverage.metadata.file=$(intermediates.COMMON)/coverage.em \
- -D jack.coverage.jacoco.package=$(JACOCO_PACKAGE_NAME) \
- $(addprefix -D jack.coverage.jacoco.include=,$(LOCAL_JACK_COVERAGE_INCLUDE_FILTER)) \
- $(addprefix -D jack.coverage.jacoco.exclude=,$(LOCAL_JACK_COVERAGE_EXCLUDE_FILTER))
-else
-$(built_dex_intermediate): PRIVATE_JACK_COVERAGE_OPTIONS :=
-endif
-
-# Compiling with javac to jar, then converting jar to dex with jack
-ifeq ($(LOCAL_JACK_ENABLED),javac_frontend)
-
-# PRIVATE_EXTRA_JAR_ARGS and source files were already handled during javac
-$(built_dex_intermediate): PRIVATE_EXTRA_JAR_ARGS :=
-$(built_dex_intermediate): PRIVATE_JAVA_SOURCES :=
-$(built_dex_intermediate): PRIVATE_SOURCE_INTERMEDIATES_DIR :=
-$(built_dex_intermediate): PRIVATE_HAS_PROTO_SOURCES :=
-$(built_dex_intermediate): PRIVATE_HAS_RS_SOURCES :=
-
-# Incremental compilation is not supported when mixing javac and jack
-$(built_dex_intermediate): PRIVATE_JACK_INCREMENTAL_DIR :=
-
-# Pass output of javac to jack
-$(built_dex_intermediate): PRIVATE_JACK_IMPORT_JAR := $(full_classes_compiled_jar)
-$(built_dex_intermediate): $(full_classes_compiled_jar)
-else # LOCAL_JACK_ENABLED != javac_frontend
-$(built_dex_intermediate): PRIVATE_JACK_IMPORT_JAR :=
-endif # LOCAL_JACK_ENABLED != javac_frontend
-
-$(built_dex_intermediate): PRIVATE_JACK_PLUGIN_PATH := $(LOCAL_JACK_PLUGIN_PATH)
-$(built_dex_intermediate): PRIVATE_JACK_PLUGIN := $(LOCAL_JACK_PLUGIN)
-$(built_dex_intermediate): $(jack_all_deps) $(LOCAL_JACK_PLUGIN_PATH) | setup-jack-server
- @echo Building with Jack: $@
- $(jack-java-to-dex)
-
-# $(full_classes_jack) is just by-product of $(built_dex_intermediate).
-# The dummy command was added because, without it, make misses the fact the $(built_dex) also
-# change $(full_classes_jack).
-$(full_classes_jack): $(built_dex_intermediate)
- $(hide) touch $@
-
-$(call define-dex-to-toc-rule, $(intermediates.COMMON))
-
-endif #LOCAL_IS_STATIC_JAVA_LIBRARY
-
-$(noshrob_classes_jack): PRIVATE_JACK_PLUGIN_PATH := $(LOCAL_JACK_PLUGIN_PATH)
-$(noshrob_classes_jack): PRIVATE_JACK_PLUGIN := $(LOCAL_JACK_PLUGIN)
-$(noshrob_classes_jack): PRIVATE_JACK_INTERMEDIATES_DIR := $(intermediates.COMMON)/jack-noshrob-rsc
-$(noshrob_classes_jack): PRIVATE_JACK_PROGUARD_FLAGS :=
-$(noshrob_classes_jack): $(jack_all_deps) $(LOCAL_JACK_PLUGIN_PATH) | setup-jack-server
- @echo Building with Jack: $@
- $(java-to-jack)
-endif # full_classes_jar is defined
-endif # LOCAL_JACK_ENABLED
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_DEFAULT_APP_TARGET_SDK := $(my_default_app_target_sdk)
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_SDK_VERSION := $(my_sdk_version)
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_MIN_SDK_VERSION := $(my_min_sdk_version)
diff --git a/core/java_common.mk b/core/java_common.mk
index bf7f039..8f4611e 100644
--- a/core/java_common.mk
+++ b/core/java_common.mk
@@ -1,5 +1,11 @@
# Common to host and target Java modules.
+my_soong_problems :=
+
+ifneq ($(filter ../%,$(LOCAL_SRC_FILES)),)
+my_soong_problems += dotdot_srcs
+endif
+
###########################################################
## Java version
###########################################################
@@ -15,18 +21,47 @@
# Modules can override this logic by specifying
# LOCAL_JAVA_LANGUAGE_VERSION explicitly.
ifeq (,$(LOCAL_JAVA_LANGUAGE_VERSION))
- private_sdk_versions_without_any_java_18_support := 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
- ifneq (,$(filter $(LOCAL_SDK_VERSION), $(private_sdk_versions_without_any_java_18_support)))
+ ifneq (,$(filter $(LOCAL_SDK_VERSION), $(TARGET_SDK_VERSIONS_WITHOUT_JAVA_18_SUPPORT)))
LOCAL_JAVA_LANGUAGE_VERSION := 1.7
- else
+ 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))
+ # TODO(ccross): allow 1.9 for current and unbundled once we have SDK system modules
+ LOCAL_JAVA_LANGUAGE_VERSION := 1.8
+ else
+ # DEFAULT_JAVA_LANGUAGE_VERSION is 1.8, unless TARGET_OPENJDK9 in which case it is 1.9
+ LOCAL_JAVA_LANGUAGE_VERSION := $(DEFAULT_JAVA_LANGUAGE_VERSION)
endif
endif
LOCAL_JAVACFLAGS += -source $(LOCAL_JAVA_LANGUAGE_VERSION) -target $(LOCAL_JAVA_LANGUAGE_VERSION)
###########################################################
+
+# OpenJDK versions up to 8 shipped with bootstrap and tools jars
+# (rt.jar, jce.jar, tools.jar etc.). These are no longer part of
+# OpenJDK 9, but we still make them available for host tools that
+# are targeting older versions.
+USE_HOST_BOOTSTRAP_JARS := true
+ifeq (,$(filter $(LOCAL_JAVA_LANGUAGE_VERSION), 1.6 1.7 1.8))
+USE_HOST_BOOTSTRAP_JARS := false
+endif
+
+###########################################################
+
+# Drop HOST_JDK_TOOLS_JAR from classpath when targeting versions > 9 (which don't have it).
+# TODO: Remove HOST_JDK_TOOLS_JAR and all references to it once host
+# bootstrap jars are no longer supported (ie. when USE_HOST_BOOTSTRAP_JARS
+# is always false). http://b/38418220
+ifneq ($(USE_HOST_BOOTSTRAP_JARS),true)
+LOCAL_CLASSPATH := $(filter-out $(HOST_JDK_TOOLS_JAR),$(LOCAL_CLASSPATH))
+endif
+
+###########################################################
## .proto files: Compile proto files to .java
###########################################################
+ifeq ($(strip $(LOCAL_PROTOC_OPTIMIZE_TYPE)),)
+ LOCAL_PROTOC_OPTIMIZE_TYPE := lite
+endif
proto_sources := $(filter %.proto,$(LOCAL_SRC_FILES))
# Because names of the .java files compiled from .proto files are unknown until the
# .proto files are compiled, we use a timestamp file as depedency.
@@ -56,7 +91,7 @@
endif
endif
$(proto_java_sources_file_stamp): PRIVATE_PROTOC_FLAGS := $(LOCAL_PROTOC_FLAGS)
-$(proto_java_sources_file_stamp): PRIVATE_PROTO_JAVA_OUTPUT_PARAMS := $(LOCAL_PROTO_JAVA_OUTPUT_PARAMS)
+$(proto_java_sources_file_stamp): PRIVATE_PROTO_JAVA_OUTPUT_PARAMS := $(if $(filter lite,$(LOCAL_PROTOC_OPTIMIZE_TYPE)),lite$(if $(LOCAL_PROTO_JAVA_OUTPUT_PARAMS),:,),)$(LOCAL_PROTO_JAVA_OUTPUT_PARAMS)
$(proto_java_sources_file_stamp) : $(proto_sources_fullpath) $(PROTOC)
$(call transform-proto-to-java)
@@ -142,7 +177,7 @@
#####################################
## Warn if there is unrecognized file in LOCAL_SRC_FILES.
my_unknown_src_files := $(filter-out \
- %.java %.aidl %.proto %.logtags %.fs %.rs, \
+ %.java %.aidl %.proto %.logtags, \
$(LOCAL_SRC_FILES) $(LOCAL_INTERMEDIATE_SOURCES) $(LOCAL_GENERATED_SOURCES))
ifneq ($(my_unknown_src_files),)
$(warning $(LOCAL_MODULE_MAKEFILE): $(LOCAL_MODULE): Unused source files: $(my_unknown_src_files))
@@ -153,14 +188,14 @@
# LOCAL_SOURCE_FILES_ALL_GENERATED is set only if the module does not have static source files,
# but generated source files in its LOCAL_INTERMEDIATE_SOURCE_DIR.
# You have to set up the dependency in some other way.
-need_compile_java := $(strip $(all_java_sources)$(all_res_assets)$(java_resource_sources))$(LOCAL_STATIC_JAVA_LIBRARIES)$(filter true,$(LOCAL_SOURCE_FILES_ALL_GENERATED))
+need_compile_java := $(strip $(all_java_sources)$(LOCAL_SRCJARS)$(all_res_assets)$(java_resource_sources))$(LOCAL_STATIC_JAVA_LIBRARIES)$(filter true,$(LOCAL_SOURCE_FILES_ALL_GENERATED))
ifdef need_compile_java
annotation_processor_flags :=
annotation_processor_deps :=
ifdef LOCAL_ANNOTATION_PROCESSORS
- annotation_processor_jars := $(call java-lib-deps,$(LOCAL_ANNOTATION_PROCESSORS),true)
+ annotation_processor_jars := $(call java-lib-files,$(LOCAL_ANNOTATION_PROCESSORS),true)
annotation_processor_flags += -processorpath $(call normalize-path-list,$(annotation_processor_jars))
annotation_processor_deps += $(annotation_processor_jars)
@@ -170,12 +205,11 @@
annotation_processor_jars :=
endif
-full_static_java_libs := \
- $(foreach lib,$(LOCAL_STATIC_JAVA_LIBRARIES), \
- $(call intermediates-dir-for, \
- JAVA_LIBRARIES,$(lib),$(LOCAL_IS_HOST_MODULE),COMMON)/classes.jar)
+full_static_java_libs := $(call java-lib-files,$(LOCAL_STATIC_JAVA_LIBRARIES),$(LOCAL_IS_HOST_MODULE))
+full_static_java_header_libs := $(call java-lib-header-files,$(LOCAL_STATIC_JAVA_LIBRARIES),$(LOCAL_IS_HOST_MODULE))
$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_STATIC_JAVA_LIBRARIES := $(full_static_java_libs)
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_STATIC_JAVA_HEADER_LIBRARIES := $(full_static_java_header_libs)
$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_RESOURCE_DIR := $(LOCAL_RESOURCE_DIR)
$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_ASSET_DIR := $(LOCAL_ASSET_DIR)
@@ -187,90 +221,157 @@
$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_PROTO_SOURCE_INTERMEDIATES_DIR := $(intermediates.COMMON)/proto
$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_HAS_RS_SOURCES :=
$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_JAVA_SOURCES := $(all_java_sources)
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_JAVA_SOURCE_LIST := $(java_source_list_file)
$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_RMTYPEDEFS := $(LOCAL_RMTYPEDEFS)
-# full_java_libs: The list of files that should be used as the classpath.
-# Using this list as a dependency list WILL NOT WORK.
-# full_java_lib_deps: Should be specified as a prerequisite of this module
-# to guarantee that the files in full_java_libs will
-# be up-to-date.
+full_java_bootclasspath_libs :=
+empty_bootclasspath :=
+my_system_modules :=
+
ifndef LOCAL_IS_HOST_MODULE
-ifeq ($(LOCAL_SDK_VERSION),)
-ifeq ($(LOCAL_NO_STANDARD_LIBRARIES),true)
-# No bootclasspath. But we still need "" to prevent javac from using default host bootclasspath.
-my_bootclasspath := ""
-else # LOCAL_NO_STANDARD_LIBRARIES
-my_bootclasspath := $(call java-lib-files,core-oj):$(call java-lib-files,core-libart)
-endif # LOCAL_NO_STANDARD_LIBRARIES
-else
-ifeq ($(LOCAL_SDK_VERSION)$(TARGET_BUILD_APPS),current)
-# LOCAL_SDK_VERSION is current and no TARGET_BUILD_APPS.
-my_bootclasspath := $(call java-lib-files,android_stubs_current)
-else ifeq ($(LOCAL_SDK_VERSION)$(TARGET_BUILD_APPS),system_current)
-my_bootclasspath := $(call java-lib-files,android_system_stubs_current)
-else ifeq ($(LOCAL_SDK_VERSION)$(TARGET_BUILD_APPS),test_current)
-my_bootclasspath := $(call java-lib-files,android_test_stubs_current)
-else
-my_bootclasspath := $(call java-lib-files,sdk_v$(LOCAL_SDK_VERSION))
-endif # current, system_current, or test_current
-endif # LOCAL_SDK_VERSION
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_BOOTCLASSPATH := -bootclasspath $(my_bootclasspath)
+ ifeq ($(LOCAL_SDK_VERSION),)
+ ifeq ($(LOCAL_NO_STANDARD_LIBRARIES),true)
+ # No bootclasspath. But we still need "" to prevent javac from using default host bootclasspath.
+ empty_bootclasspath := ""
+ # 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)
+ 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)
+ endif # LOCAL_NO_STANDARD_LIBRARIES
+ else
+ ifeq ($(LOCAL_NO_STANDARD_LIBRARIES),true)
+ $(call pretty-error,Must not define both LOCAL_NO_STANDARD_LIBRARIES and LOCAL_SDK_VERSION)
+ endif
+ ifeq ($(strip $(filter $(LOCAL_SDK_VERSION),$(TARGET_AVAILABLE_SDK_VERSIONS))),)
+ $(call pretty-error,Invalid LOCAL_SDK_VERSION '$(LOCAL_SDK_VERSION)' \
+ Choices are: $(TARGET_AVAILABLE_SDK_VERSIONS))
+ endif
+ ifeq ($(LOCAL_SDK_VERSION)$(TARGET_BUILD_APPS),current)
+ # LOCAL_SDK_VERSION is current and no TARGET_BUILD_APPS.
+ full_java_bootclasspath_libs := $(call java-lib-header-files,android_stubs_current)
+ else ifeq ($(LOCAL_SDK_VERSION)$(TARGET_BUILD_APPS),system_current)
+ full_java_bootclasspath_libs := $(call java-lib-header-files,android_system_stubs_current)
+ else ifeq ($(LOCAL_SDK_VERSION)$(TARGET_BUILD_APPS),test_current)
+ full_java_bootclasspath_libs := $(call java-lib-header-files,android_test_stubs_current)
+ else ifeq ($(LOCAL_SDK_VERSION)$(TARGET_BUILD_APPS),core_current)
+ full_java_bootclasspath_libs := $(call java-lib-header-files,core.current.stubs)
+ else
+ # core_<ver> is subset of <ver>. Instead of defining a prebuilt lib for core_<ver>,
+ # use the stub for <ver> when building for apps.
+ _version := $(patsubst core_%,%,$(LOCAL_SDK_VERSION))
+ full_java_bootclasspath_libs := $(call java-lib-header-files,sdk_v$(_version))
+ _version :=
+ endif # current, system_current, system_${VER}, test_current or core_current
+ endif # LOCAL_SDK_VERSION
-# In order to compile lambda code javac requires various invokedynamic-
-# related classes to be present. This change adds stubs needed for
-# javac to compile lambdas.
-my_additional_javac_libs :=
-ifndef TARGET_BUILD_APPS
-# TODO: support to build lamdbas using javac in unbundled build.
-# We may need to check in a prebuilt core-lambda-stubs to prebuilts/sdk.
-ifneq ($(LOCAL_NO_STANDARD_LIBRARIES),true)
-my_additional_javac_libs := core-lambda-stubs
-endif
-endif
+ ifneq ($(LOCAL_NO_STANDARD_LIBRARIES),true)
+ ifneq ($(LOCAL_MODULE),jacocoagent)
+ 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.
+ full_java_bootclasspath_libs += $(call java-lib-header-files,jacocoagent)
+ endif # EMMA_INSTRUMENT_STATIC
+ endif # EMMA_INSTRUMENT
+ endif # LOCAL_MODULE == jacocoagent
+ endif # LOCAL_NO_STANDARD_LIBRARIES
-full_shared_java_libs := $(call java-lib-files,$(LOCAL_JAVA_LIBRARIES) $(my_additional_javac_libs),$(LOCAL_IS_HOST_MODULE))
-full_java_lib_deps := $(call java-lib-deps,$(LOCAL_JAVA_LIBRARIES) $(my_additional_javac_libs),$(LOCAL_IS_HOST_MODULE))
-full_java_lib_deps := $(addsuffix .toc, $(full_java_lib_deps))
+ # In order to compile lambda code javac requires various invokedynamic-
+ # 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
+ 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)
+ endif
+ endif
+
+ full_shared_java_libs := $(call java-lib-files,$(LOCAL_JAVA_LIBRARIES),$(LOCAL_IS_HOST_MODULE))
+ full_shared_java_header_libs := $(call java-lib-header-files,$(LOCAL_JAVA_LIBRARIES),$(LOCAL_IS_HOST_MODULE))
else # LOCAL_IS_HOST_MODULE
-ifeq ($(USE_CORE_LIB_BOOTCLASSPATH),true)
-ifeq ($(LOCAL_NO_STANDARD_LIBRARIES),true)
-my_bootclasspath := ""
-else
-my_bootclasspath := $(call normalize-path-list,$(call java-lib-files,core-oj-hostdex core-libart-hostdex,true))
-endif
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_BOOTCLASSPATH := -bootclasspath $(my_bootclasspath)
+ ifeq ($(USE_CORE_LIB_BOOTCLASSPATH),true)
+ 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)
+ endif
-full_shared_java_libs := $(call java-lib-files,$(LOCAL_JAVA_LIBRARIES),true)
-full_java_lib_deps := $(full_shared_java_libs)
-else # !USE_CORE_LIB_BOOTCLASSPATH
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_BOOTCLASSPATH :=
-
-full_shared_java_libs := $(addprefix $(HOST_OUT_JAVA_LIBRARIES)/,\
- $(addsuffix $(COMMON_JAVA_PACKAGE_SUFFIX),$(LOCAL_JAVA_LIBRARIES)))
-full_java_lib_deps := $(full_shared_java_libs)
-endif # USE_CORE_LIB_BOOTCLASSPATH
+ my_system_modules := $(DEFAULT_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
+ # Give host-side tools a version of OpenJDK's standard libraries
+ # close to what they're targeting. As of Dec 2017, AOSP is only
+ # bundling OpenJDK 8 and 9, so nothing < 8 is available.
+ #
+ # When building with OpenJDK 8, the following should have no
+ # effect since those jars would be available by default.
+ #
+ # When building with OpenJDK 9 but targeting a version < 1.8,
+ # putting them on the bootclasspath means that:
+ # a) code can't (accidentally) refer to OpenJDK 9 specific APIs
+ # b) references to existing APIs are not reinterpreted in an
+ # OpenJDK 9-specific way, eg. calls to subclasses of
+ # java.nio.Buffer as in http://b/70862583
+ ifeq ($(USE_HOST_BOOTSTRAP_JARS),true)
+ full_java_bootclasspath_libs += $(ANDROID_JAVA8_HOME)/jre/lib/jce.jar
+ full_java_bootclasspath_libs += $(ANDROID_JAVA8_HOME)/jre/lib/rt.jar
+ endif
+ full_shared_java_libs := $(addprefix $(HOST_OUT_JAVA_LIBRARIES)/,\
+ $(addsuffix $(COMMON_JAVA_PACKAGE_SUFFIX),$(LOCAL_JAVA_LIBRARIES)))
+ full_shared_java_header_libs := $(full_shared_java_libs)
+ endif # USE_CORE_LIB_BOOTCLASSPATH
endif # !LOCAL_IS_HOST_MODULE
-full_java_libs := $(full_shared_java_libs) $(full_static_java_libs) $(LOCAL_CLASSPATH)
-full_java_lib_deps := $(full_java_lib_deps) $(full_static_java_libs) $(LOCAL_CLASSPATH)
+ifdef empty_bootclasspath
+ ifdef full_java_bootclasspath_libs
+ $(call pretty-error,internal error: empty_bootclasspath and full_java_bootclasspath_libs should not both be set)
+ endif
+endif
+
+full_java_system_modules_deps :=
+my_system_modules_dir :=
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_USE_SYSTEM_MODULES :=
+ifeq ($(LOCAL_JAVA_LANGUAGE_VERSION),1.9)
+ $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_USE_SYSTEM_MODULES := true
+ ifdef my_system_modules
+ ifneq ($(my_system_modules),none)
+ ifndef SOONG_SYSTEM_MODULES_$(my_system_modules)
+ $(call pretty-error, Invalid system modules $(my_system_modules))
+ endif
+ full_java_system_modules_deps := $(SOONG_SYSTEM_MODULES_$(my_system_modules))
+ my_system_modules_dir := $(patsubst %/lib/modules,%,$(SOONG_SYSTEM_MODULES_$(my_system_modules)))
+ endif
+ endif
+endif
+
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_BOOTCLASSPATH := $(full_java_bootclasspath_libs)
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_EMPTY_BOOTCLASSPATH := $(empty_bootclasspath)
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_SYSTEM_MODULES := $(my_system_modules)
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_SYSTEM_MODULES_DIR := $(my_system_modules_dir)
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_SYSTEM_MODULES_LIBS := $(call java-lib-files,$(SOONG_SYSTEM_MODULES_LIBS_$(my_system_modules)))
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_PATCH_MODULE := $(LOCAL_PATCH_MODULE)
ifndef LOCAL_IS_HOST_MODULE
# This is set by packages that are linking to other packages that export
# shared libraries, allowing them to make use of the code in the linked apk.
apk_libraries := $(sort $(LOCAL_APK_LIBRARIES) $(LOCAL_RES_LIBRARIES))
ifneq ($(apk_libraries),)
- link_apk_libraries := \
- $(foreach lib,$(apk_libraries), \
- $(call intermediates-dir-for, \
- APPS,$(lib),,COMMON)/classes-pre-proguard.jar)
+ link_apk_libraries := $(call app-lib-files,$(apk_libraries))
+ link_apk_header_libs := $(call app-lib-header-files,$(apk_libraries))
# link against the jar with full original names (before proguard processing).
full_shared_java_libs += $(link_apk_libraries)
- full_java_libs += $(link_apk_libraries)
- full_java_lib_deps += $(link_apk_libraries)
+ full_shared_java_header_libs += $(link_apk_header_libs)
endif
# This is set by packages that contain instrumentation, allowing them to
@@ -287,8 +388,13 @@
APPS,$(LOCAL_INSTRUMENTATION_FOR),,COMMON)
# link against the jar with full original names (before proguard processing).
link_instr_classes_jar := $(link_instr_intermediates_dir.COMMON)/classes-pre-proguard.jar
- full_java_libs += $(link_instr_classes_jar)
- full_java_lib_deps += $(link_instr_classes_jar)
+ ifneq ($(TURBINE_ENABLED),false)
+ link_instr_classes_header_jar := $(link_instr_intermediates_dir.COMMON)/classes-header.jar
+ else
+ link_instr_classes_header_jar := $(link_instr_intermediates_dir.COMMON)/classes.jar
+ endif
+ full_shared_java_libs += $(link_instr_classes_jar)
+ full_shared_java_header_libs += $(link_instr_classes_header_jar)
endif # LOCAL_INSTRUMENTATION_FOR
endif # LOCAL_IS_HOST_MODULE
@@ -305,100 +411,31 @@
endif
##########################################################
-ifndef LOCAL_IS_HOST_MODULE
-## AAPT Flags
-# aapt doesn't accept multiple --extra-packages flags.
-# We have to collapse them into a single --extra-packages flag here.
-LOCAL_AAPT_FLAGS := $(strip $(LOCAL_AAPT_FLAGS))
-ifdef LOCAL_AAPT_FLAGS
-ifeq ($(filter 0 1,$(words $(filter --extra-packages,$(LOCAL_AAPT_FLAGS)))),)
-aapt_flags := $(subst --extra-packages$(space),--extra-packages@,$(LOCAL_AAPT_FLAGS))
-aapt_flags_extra_packages := $(patsubst --extra-packages@%,%,$(filter --extra-packages@%,$(aapt_flags)))
-aapt_flags_extra_packages := $(sort $(subst :,$(space),$(aapt_flags_extra_packages)))
-LOCAL_AAPT_FLAGS := $(filter-out --extra-packages@%,$(aapt_flags)) \
- --extra-packages $(subst $(space),:,$(aapt_flags_extra_packages))
-aapt_flags_extra_packages :=
-aapt_flags :=
-endif
-endif
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_AAPT_FLAGS := $(LOCAL_AAPT_FLAGS) $(PRODUCT_AAPT_FLAGS)
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_TARGET_AAPT_CHARACTERISTICS := $(TARGET_AAPT_CHARACTERISTICS)
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_MANIFEST_PACKAGE_NAME := $(LOCAL_MANIFEST_PACKAGE_NAME)
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_MANIFEST_INSTRUMENTATION_FOR := $(LOCAL_MANIFEST_INSTRUMENTATION_FOR)
-
-ifdef aidl_sources
-ALL_MODULES.$(my_register_name).AIDL_FILES := $(aidl_sources)
-endif
-ifdef renderscript_sources
-ALL_MODULES.$(my_register_name).RS_FILES := $(renderscript_sources_fullpath)
-endif
-endif # !LOCAL_IS_HOST_MODULE
+full_java_libs := $(full_shared_java_libs) $(full_static_java_libs) $(LOCAL_CLASSPATH)
+full_java_header_libs := $(full_shared_java_header_libs) $(full_static_java_header_libs)
$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_ALL_JAVA_LIBRARIES := $(full_java_libs)
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_ALL_JAVA_HEADER_LIBRARIES := $(full_java_header_libs)
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_SHARED_JAVA_HEADER_LIBRARIES := $(full_shared_java_header_libs)
ALL_MODULES.$(my_register_name).INTERMEDIATE_SOURCE_DIR := \
$(ALL_MODULES.$(my_register_name).INTERMEDIATE_SOURCE_DIR) $(LOCAL_INTERMEDIATE_SOURCE_DIR)
-###########################################################
-# JACK
-###########################################################
-ifdef LOCAL_JACK_ENABLED
-ifdef need_compile_java
-LOCAL_JACK_FLAGS += -D jack.java.source.version=$(LOCAL_JAVA_LANGUAGE_VERSION)
-
-full_static_jack_libs := \
+##########################################################
+# Copy NOTICE files of transitive static dependencies
+# Don't do this in mm, since many of the targets won't exist.
+ifeq ($(ONE_SHOT_MAKEFILE),)
+installed_static_library_notice_file_targets := \
$(foreach lib,$(LOCAL_STATIC_JAVA_LIBRARIES), \
- $(call intermediates-dir-for, \
- JAVA_LIBRARIES,$(lib),$(LOCAL_IS_HOST_MODULE),COMMON)/classes.jack)
-
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_STATIC_JACK_LIBRARIES := $(full_static_jack_libs)
-
-full_shared_jack_libs := $(call jack-lib-files,$(LOCAL_JAVA_LIBRARIES),$(LOCAL_IS_HOST_MODULE))
-full_jack_deps := $(full_shared_jack_libs)
-
-ifndef LOCAL_IS_HOST_MODULE
-# Turn off .toc optimization for apps build as we cannot build dexdump.
-ifeq (,$(TARGET_BUILD_APPS))
-full_jack_deps := $(patsubst %.jack, %.dex.toc, $(full_jack_deps))
-endif
-endif # !LOCAL_IS_HOST_MODULE
-full_shared_jack_libs += $(LOCAL_JACK_CLASSPATH)
-full_jack_deps += $(full_static_jack_libs) $(LOCAL_JACK_CLASSPATH)
-
-ifndef LOCAL_IS_HOST_MODULE
-# This is set by packages that are linking to other packages that export
-# shared libraries, allowing them to make use of the code in the linked apk.
-ifneq ($(apk_libraries),)
- link_apk_jack_libraries := \
- $(foreach lib,$(apk_libraries), \
- $(call intermediates-dir-for, \
- APPS,$(lib),,COMMON)/classes.jack)
-
- # link against the jar with full original names (before proguard processing).
- full_shared_jack_libs += $(link_apk_jack_libraries)
- full_jack_deps += $(link_apk_jack_libraries)
+ NOTICE-$(if $(LOCAL_IS_HOST_MODULE),HOST,TARGET)-JAVA_LIBRARIES-$(lib))
+else
+installed_static_library_notice_file_targets :=
endif
-# This is set by packages that contain instrumentation, allowing them to
-# link against the package they are instrumenting. Currently only one such
-# package is allowed.
-ifdef LOCAL_INSTRUMENTATION_FOR
- # link against the jar with full original names (before proguard processing).
- link_instr_classes_jack := $(link_instr_intermediates_dir.COMMON)/classes.noshrob.jack
- full_shared_jack_libs += $(link_instr_classes_jack)
- full_jack_deps += $(link_instr_classes_jack)
-endif # LOCAL_INSTRUMENTATION_FOR
-endif # !LOCAL_IS_HOST_MODULE
-
-# Propagate local configuration options to this target.
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_JACK_SHARED_LIBRARIES:= $(full_shared_jack_libs)
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_JARJAR_RULES := $(LOCAL_JARJAR_RULES)
-
-endif # need_compile_java
-endif # LOCAL_JACK_ENABLED
-
+$(notice_target): | $(installed_static_library_notice_file_targets)
+$(LOCAL_INSTALLED_MODULE): | $(notice_target)
###########################################################
# Verify that all libraries are safe to use
@@ -406,22 +443,51 @@
ifndef LOCAL_IS_HOST_MODULE
ifeq ($(LOCAL_SDK_VERSION),system_current)
my_link_type := java:system
-my_warn_types := java:platform
-my_allowed_types := java:sdk java:system
+my_warn_types :=
+my_allowed_types := java:sdk java:system java:core
+else ifneq (,$(call has-system-sdk-version,$(LOCAL_SDK_VERSION)))
+my_link_type := java:system
+my_warn_types :=
+my_allowed_types := java:sdk java:system java:core
+else ifeq ($(LOCAL_SDK_VERSION),core_current)
+my_link_type := java:core
+my_warn_types :=
+my_allowed_types := java:core
else ifneq ($(LOCAL_SDK_VERSION),)
my_link_type := java:sdk
-my_warn_types := java:system java:platform
-my_allowed_types := java:sdk
+my_warn_types :=
+my_allowed_types := java:sdk java:core
else
my_link_type := java:platform
my_warn_types :=
-my_allowed_types := java:sdk java:system java:platform
+my_allowed_types := java:sdk java:system java:platform java:core
endif
-my_link_deps := $(addprefix JAVA_LIBRARIES:,$(LOCAL_STATIC_JAVA_LIBRARIES))
+ifdef LOCAL_AAPT2_ONLY
+my_link_type += aapt2_only
+endif
+ifdef LOCAL_USE_AAPT2
+my_allowed_types += aapt2_only
+endif
+
+my_link_deps := $(addprefix JAVA_LIBRARIES:,$(LOCAL_STATIC_JAVA_LIBRARIES) $(LOCAL_JAVA_LIBRARIES))
my_link_deps += $(addprefix APPS:,$(apk_libraries))
my_2nd_arch_prefix := $(LOCAL_2ND_ARCH_VAR_PREFIX)
my_common := COMMON
include $(BUILD_SYSTEM)/link_type.mk
endif # !LOCAL_IS_HOST_MODULE
+
+ifneq ($(LOCAL_MODULE_MAKEFILE),$(SOONG_ANDROID_MK))
+
+SOONG_CONV.$(LOCAL_MODULE).PROBLEMS := \
+ $(SOONG_CONV.$(LOCAL_MODULE).PROBLEMS) $(my_soong_problems)
+SOONG_CONV.$(LOCAL_MODULE).DEPS := \
+ $(SOONG_CONV.$(LOCAL_MODULE).DEPS) \
+ $(LOCAL_STATIC_JAVA_LIBRARIES) \
+ $(LOCAL_JAVA_LIBRARIES) \
+ $(LOCAL_JNI_SHARED_LIBRARIES)
+SOONG_CONV.$(LOCAL_MODULE).TYPE := java
+SOONG_CONV := $(SOONG_CONV) $(LOCAL_MODULE)
+
+endif
diff --git a/core/java_library.mk b/core/java_library.mk
index 84f4419..1b914f5 100644
--- a/core/java_library.mk
+++ b/core/java_library.mk
@@ -25,21 +25,8 @@
LOCAL_BUILT_MODULE_STEM := javalib.jar
-#################################
-include $(BUILD_SYSTEM)/configure_local_jack.mk
-#################################
-
-ifdef LOCAL_JACK_ENABLED
-ifdef LOCAL_IS_STATIC_JAVA_LIBRARY
-LOCAL_BUILT_MODULE_STEM := classes.jack
-endif
-endif
-
-# For non-static java libraries, other modules should depend on
-# out/target/common/obj/JAVA_LIBRARIES/.../javalib.jar (for jack)
-# or out/target/common/obj/JAVA_LIBRARIES/.../classes.jar (for javac).
-# For static java libraries, other modules should depend on
-# out/target/common/obj/JAVA_LIBRARIES/.../classes.jar
+# For java libraries, other modules should depend on
+# out/target/common/obj/JAVA_LIBRARIES/.../classes.jar.
# There are some dependencies outside the build system that assume static
# java libraries produce javalib.jar, so we will copy classes.jar there too.
intermediates.COMMON := $(call local-intermediates-dir,COMMON)
@@ -55,6 +42,8 @@
ifeq (true,$(LOCAL_EMMA_INSTRUMENT))
ifeq (true,$(EMMA_INSTRUMENT_STATIC))
LOCAL_STATIC_JAVA_LIBRARIES += jacocoagent
+# Exclude jacoco classes from proguard
+LOCAL_PROGUARD_FLAGS += -include $(BUILD_SYSTEM)/proguard.jacoco.flags
endif # LOCAL_EMMA_INSTRUMENT
endif # EMMA_INSTRUMENT_STATIC
else
@@ -68,31 +57,27 @@
ifeq ($(LOCAL_IS_STATIC_JAVA_LIBRARY),true)
# There are some dependencies outside the build system that assume classes.jar
# is available as javalib.jar so copy it there too.
-$(eval $(call copy-one-file,$(full_classes_jar),$(common_javalib.jar)))
+$(eval $(call copy-one-file,$(full_classes_proguard_jar),$(common_javalib.jar)))
-ifdef LOCAL_JACK_ENABLED
-$(eval $(call copy-one-file,$(full_classes_jack),$(LOCAL_BUILT_MODULE)))
-else
-$(eval $(call copy-one-file,$(full_classes_jar),$(LOCAL_BUILT_MODULE)))
-endif
+$(eval $(call copy-one-file,$(full_classes_proguard_jar),$(LOCAL_BUILT_MODULE)))
else # !LOCAL_IS_STATIC_JAVA_LIBRARY
$(common_javalib.jar): PRIVATE_DEX_FILE := $(built_dex)
$(common_javalib.jar): PRIVATE_SOURCE_ARCHIVE := $(full_classes_pre_proguard_jar)
$(common_javalib.jar): PRIVATE_DONT_DELETE_JAR_DIRS := $(LOCAL_DONT_DELETE_JAR_DIRS)
-$(common_javalib.jar) : $(built_dex) $(java_resource_sources) | $(ZIPTIME)
+$(common_javalib.jar) : $(built_dex) $(java_resource_sources) | $(ZIPTIME) $(ZIPALIGN)
@echo "target Jar: $(PRIVATE_MODULE) ($@)"
-ifdef LOCAL_JACK_ENABLED
- $(create-empty-package)
-else
- $(call initialize-package-file,$(PRIVATE_SOURCE_ARCHIVE),$@)
-endif
- $(add-dex-to-package)
-ifdef LOCAL_JACK_ENABLED
- $(add-carried-jack-resources)
-endif
- $(remove-timestamps-from-package)
+ $(call initialize-package-file,$(PRIVATE_SOURCE_ARCHIVE),$@.tmp)
+ $(call add-dex-to-package-arg,$@.tmp)
+ $(hide) $(ZIPTIME) $@.tmp
+ $(call commit-change-for-toc,$@)
+ifeq (true, $(LOCAL_UNCOMPRESS_DEX))
+ $(uncompress-dexs)
+ $(align-package)
+endif # LOCAL_UNCOMPRESS_DEX
+
+.KATI_RESTAT: $(common_javalib.jar)
ifdef LOCAL_DEX_PREOPT
ifneq ($(dexpreopt_boot_jar_module),) # boot jar
@@ -108,10 +93,7 @@
@echo "Dexpreopt Jar: $(PRIVATE_MODULE) ($@)"
$(call dexpreopt-one-file,$<,$@)
-$(eval $(call copy-one-file,$(common_javalib.jar),$(LOCAL_BUILT_MODULE)))
-ifneq (nostripping,$(LOCAL_DEX_PREOPT))
- $(call dexpreopt-remove-classes.dex,$@)
-endif
+$(eval $(call dexpreopt-copy-jar,$(common_javalib.jar),$(LOCAL_BUILT_MODULE),$(LOCAL_DEX_PREOPT)))
endif # ! boot jar
diff --git a/core/java_renderscript.mk b/core/java_renderscript.mk
new file mode 100644
index 0000000..191b3be
--- /dev/null
+++ b/core/java_renderscript.mk
@@ -0,0 +1,155 @@
+###############################################################
+## Renderscript support for java
+## Adds rules to convert .rs files to .java and .bc files
+###############################################################
+
+renderscript_sources := $(filter %.rs,$(LOCAL_SRC_FILES))
+LOCAL_SRC_FILES := $(filter-out %.rs,$(LOCAL_SRC_FILES))
+
+rs_generated_res_zip :=
+rs_generated_src_jar :=
+rs_compatibility_jni_libs :=
+ifneq ($(renderscript_sources),)
+renderscript_sources_fullpath := $(addprefix $(LOCAL_PATH)/, $(renderscript_sources))
+renderscript_intermediate.COMMON := $(intermediates.COMMON)/renderscript
+rs_generated_res_zip := $(renderscript_intermediate.COMMON)/res.zip
+rs_generated_src_jar := $(renderscript_intermediate.COMMON)/rs.srcjar
+
+LOCAL_SRCJARS += $(rs_generated_src_jar)
+
+# Defaulting to an empty string uses the latest available platform SDK.
+renderscript_target_api :=
+
+ifneq (,$(LOCAL_RENDERSCRIPT_TARGET_API))
+ renderscript_target_api := $(LOCAL_RENDERSCRIPT_TARGET_API)
+else
+ ifneq (,$(LOCAL_SDK_VERSION))
+ # Set target-api for LOCAL_SDK_VERSIONs other than current.
+ ifneq (,$(filter-out current system_current test_current core_current, $(LOCAL_SDK_VERSION)))
+ renderscript_target_api := $(call get-numeric-sdk-version,$(LOCAL_SDK_VERSION))
+ endif
+ endif # LOCAL_SDK_VERSION is set
+endif # LOCAL_RENDERSCRIPT_TARGET_API is set
+
+# For 64-bit, we always have to upgrade to at least 21 for compat build.
+ifneq ($(LOCAL_RENDERSCRIPT_COMPATIBILITY),)
+ ifeq ($(TARGET_IS_64_BIT),true)
+ ifneq ($(filter $(RSCOMPAT_32BIT_ONLY_API_LEVELS),$(renderscript_target_api)),)
+ renderscript_target_api := 21
+ endif
+ endif
+endif
+
+ifeq ($(LOCAL_RENDERSCRIPT_CC),)
+LOCAL_RENDERSCRIPT_CC := $(LLVM_RS_CC)
+endif
+
+# Turn on all warnings and warnings as errors for RS compiles.
+# This can be disabled with LOCAL_RENDERSCRIPT_FLAGS := -Wno-error
+renderscript_flags := -Wall -Werror
+renderscript_flags += $(LOCAL_RENDERSCRIPT_FLAGS)
+
+# prepend the RenderScript system include path
+ifneq ($(filter-out current system_current test_current core_current,$(LOCAL_SDK_VERSION))$(if $(TARGET_BUILD_APPS),$(filter current system_current test_current,$(LOCAL_SDK_VERSION))),)
+# if a numeric LOCAL_SDK_VERSION, or current LOCAL_SDK_VERSION with TARGET_BUILD_APPS
+LOCAL_RENDERSCRIPT_INCLUDES := \
+ $(HISTORICAL_SDK_VERSIONS_ROOT)/renderscript/clang-include \
+ $(HISTORICAL_SDK_VERSIONS_ROOT)/renderscript/include \
+ $(LOCAL_RENDERSCRIPT_INCLUDES)
+else
+LOCAL_RENDERSCRIPT_INCLUDES := \
+ $(TOPDIR)external/clang/lib/Headers \
+ $(TOPDIR)frameworks/rs/script_api/include \
+ $(LOCAL_RENDERSCRIPT_INCLUDES)
+endif
+
+ifneq ($(LOCAL_RENDERSCRIPT_INCLUDES_OVERRIDE),)
+LOCAL_RENDERSCRIPT_INCLUDES := $(LOCAL_RENDERSCRIPT_INCLUDES_OVERRIDE)
+endif
+
+bc_files := $(patsubst %.rs,%.bc, $(notdir $(renderscript_sources)))
+bc_dep_files := $(addprefix $(renderscript_intermediate.COMMON)/,$(patsubst %.bc,%.d,$(bc_files)))
+
+$(rs_generated_src_jar): PRIVATE_RS_INCLUDES := $(LOCAL_RENDERSCRIPT_INCLUDES)
+$(rs_generated_src_jar): PRIVATE_RS_CC := $(LOCAL_RENDERSCRIPT_CC)
+$(rs_generated_src_jar): PRIVATE_RS_FLAGS := $(renderscript_flags)
+$(rs_generated_src_jar): PRIVATE_RS_SOURCE_FILES := $(renderscript_sources_fullpath)
+$(rs_generated_src_jar): PRIVATE_RS_OUTPUT_DIR := $(renderscript_intermediate.COMMON)
+$(rs_generated_src_jar): PRIVATE_RS_TARGET_API := $(renderscript_target_api)
+$(rs_generated_src_jar): PRIVATE_DEP_FILES := $(bc_dep_files)
+$(rs_generated_src_jar): PRIVATE_RS_OUTPUT_RES_ZIP := $(rs_generated_res_zip)
+$(rs_generated_src_jar): .KATI_IMPLICIT_OUTPUTS := $(rs_generated_res_zip)
+$(rs_generated_src_jar): $(renderscript_sources_fullpath) $(LOCAL_RENDERSCRIPT_CC) $(SOONG_ZIP)
+ $(transform-renderscripts-to-java-and-bc)
+
+# include the dependency files (.d/.P) generated by llvm-rs-cc.
+$(call include-depfile,$(rs_generated_src_jar).P,$(rs_generated_src_jar))
+
+ifneq ($(LOCAL_RENDERSCRIPT_COMPATIBILITY),)
+
+
+ifeq ($(filter $(RSCOMPAT_32BIT_ONLY_API_LEVELS),$(renderscript_target_api)),)
+ifeq ($(TARGET_IS_64_BIT),true)
+renderscript_intermediate.bc_folder := $(renderscript_intermediate.COMMON)/res/raw/bc64/
+else
+renderscript_intermediate.bc_folder := $(renderscript_intermediate.COMMON)/res/raw/bc32/
+endif
+else
+renderscript_intermediate.bc_folder := $(renderscript_intermediate.COMMON)/res/raw/
+endif
+
+rs_generated_bc := $(addprefix \
+ $(renderscript_intermediate.bc_folder), $(bc_files))
+
+renderscript_intermediate := $(intermediates)/renderscript
+
+# We don't need the .so files in bundled branches
+# Prevent these from showing up on the device
+# One exception is librsjni.so, which is needed for
+# both native path and compat path.
+rs_jni_lib := $(TARGET_OUT_INTERMEDIATE_LIBRARIES)/librsjni.so
+LOCAL_JNI_SHARED_LIBRARIES += librsjni
+
+ifneq (,$(TARGET_BUILD_APPS)$(FORCE_BUILD_RS_COMPAT))
+
+rs_compatibility_jni_libs := $(addprefix \
+ $(renderscript_intermediate)/librs., \
+ $(patsubst %.bc,%.so, $(bc_files)))
+
+$(rs_generated_src_jar): .KATI_IMPLICIT_OUTPUTS += $(rs_generated_bc)
+
+rs_support_lib := $(TARGET_OUT_INTERMEDIATE_LIBRARIES)/libRSSupport.so
+LOCAL_JNI_SHARED_LIBRARIES += libRSSupport
+
+rs_support_io_lib :=
+# check if the target api level support USAGE_IO
+ifeq ($(filter $(RSCOMPAT_NO_USAGEIO_API_LEVELS),$(renderscript_target_api)),)
+rs_support_io_lib := $(TARGET_OUT_INTERMEDIATE_LIBRARIES)/libRSSupportIO.so
+LOCAL_JNI_SHARED_LIBRARIES += libRSSupportIO
+endif
+
+my_arch := $(TARGET_$(LOCAL_2ND_ARCH_VAR_PREFIX)ARCH)
+ifneq (,$(filter arm64 mips64 x86_64,$(my_arch)))
+ my_min_sdk_version := 21
+else
+ my_min_sdk_version := $(MIN_SUPPORTED_SDK_VERSION)
+endif
+
+$(rs_compatibility_jni_libs): $(RS_PREBUILT_CLCORE) \
+ $(rs_support_lib) $(rs_support_io_lib) $(rs_jni_lib) $(rs_compiler_rt)
+$(rs_compatibility_jni_libs): $(BCC_COMPAT)
+$(rs_compatibility_jni_libs): PRIVATE_CXX := $(CXX_WRAPPER) $(TARGET_CXX)
+$(rs_compatibility_jni_libs): PRIVATE_SDK_VERSION := $(my_min_sdk_version)
+$(rs_compatibility_jni_libs): $(renderscript_intermediate)/librs.%.so: \
+ $(renderscript_intermediate.bc_folder)%.bc \
+ $(SOONG_OUT_DIR)/ndk.timestamp
+ $(transform-bc-to-so)
+
+endif
+
+endif
+
+LOCAL_INTERMEDIATE_TARGETS += $(rs_generated_src_jar)
+# Make sure the generated resource will be added to the apk.
+LOCAL_RESOURCE_DIR := $(renderscript_intermediate.COMMON)/res $(LOCAL_RESOURCE_DIR)
+endif
diff --git a/core/jetifier.mk b/core/jetifier.mk
new file mode 100644
index 0000000..33a4624
--- /dev/null
+++ b/core/jetifier.mk
@@ -0,0 +1,34 @@
+#
+# Copyright (C) 2018 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# This file sets up the running of Jetifier
+
+# now add the rule to run jetifier
+ifeq ($(strip $(LOCAL_JETIFIER_ENABLED)),true)
+ my_jetifier_input_path := $(LOCAL_JETIFIER_INPUT_FILE)
+ my_files := $(intermediates.COMMON)/jetifier
+ my_jetifier_output_path := $(my_files)/jetified-$(notdir $(my_jetifier_input_path))
+
+$(my_jetifier_output_path) : $(my_jetifier_input_path) $(JETIFIER)
+ rm -rf $@
+ $(JETIFIER) -outputfile $@ -i $<
+
+ LOCAL_JETIFIER_OUTPUT_FILE := $(my_jetifier_output_path)
+ LOCAL_INTERMEDIATE_TARGETS += $(LOCAL_JETIFIER_OUTPUT_FILE)
+else
+ LOCAL_JETIFIER_OUTPUT_FILE := $(LOCAL_JETIFIER_INPUT_FILE)
+endif
+
diff --git a/core/local_systemsdk.mk b/core/local_systemsdk.mk
new file mode 100644
index 0000000..49085fd
--- /dev/null
+++ b/core/local_systemsdk.mk
@@ -0,0 +1,61 @@
+#
+# 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.
+#
+
+ifdef BOARD_SYSTEMSDK_VERSIONS
+ # Apps and jars in vendor or odm partition are forced to build against System SDK.
+ _is_vendor_app :=
+ ifneq (,$(filter true,$(LOCAL_VENDOR_MODULE) $(LOCAL_ODM_MODULE) $(LOCAL_PROPRIETARY_MODULE)))
+ # Note: no need to check LOCAL_MODULE_PATH* since LOCAL_[VENDOR|ODM|OEM]_MODULE is already
+ # set correctly before this is included.
+ _is_vendor_app := true
+ endif
+ ifneq (,$(filter JAVA_LIBRARIES APPS,$(LOCAL_MODULE_CLASS)))
+ ifndef LOCAL_SDK_VERSION
+ ifeq ($(_is_vendor_app),true)
+ ifeq (,$(findstring __auto_generated_rro,$(LOCAL_MODULE)))
+ # Runtime resource overlay for framework-res is exempted from building
+ # against System SDK.
+ # TODO(b/35859726): remove this exception
+ LOCAL_SDK_VERSION := system_current
+ endif
+ endif
+ endif
+ endif
+endif
+
+# Ensure that the selected System SDK version is one of the supported versions.
+# The range of support versions becomes narrower when BOARD_SYSTEMSDK_VERSIONS
+# is set, which is a subset of PLATFORM_SYSTEMSDK_VERSIONS.
+ifneq (,$(call has-system-sdk-version,$(LOCAL_SDK_VERSION)))
+ ifneq ($(_is_vendor_app),true)
+ # apps bundled in system partition can use all system sdk versions provided by the platform
+ _supported_systemsdk_versions := $(PLATFORM_SYSTEMSDK_VERSIONS)
+ else ifdef BOARD_SYSTEMSDK_VERSIONS
+ # When BOARD_SYSTEMSDK_VERSIONS is set, vendors apps are restricted to use those versions
+ # which is equal to or smaller than PLATFORM_SYSTEMSDK_VERSIONS
+ _supported_systemsdk_versions := $(BOARD_SYSTEMSDK_VERSIONS)
+ else
+ # If not, vendor apks are treated equally to system apps
+ _supported_systemsdk_versions := $(PLATFORM_SYSTEMSDK_VERSIONS)
+ endif
+ _system_sdk_version := $(call get-numeric-sdk-version,$(LOCAL_SDK_VERSION))
+ ifneq ($(_system_sdk_version),$(filter $(_system_sdk_version),$(_supported_systemsdk_versions)))
+ $(call pretty-error,Incompatible LOCAL_SDK_VERSION '$(LOCAL_SDK_VERSION)'. \
+ System SDK version '$(_system_sdk_version)' is not supported. Supported versions are: $(_supported_systemsdk_versions))
+ endif
+ _system_sdk_version :=
+ _supported_systemsdk_versions :=
+endif
diff --git a/core/local_vndk.mk b/core/local_vndk.mk
index 640aac7..3677d40 100644
--- a/core/local_vndk.mk
+++ b/core/local_vndk.mk
@@ -5,10 +5,8 @@
ifndef LOCAL_SDK_VERSION
ifneq (,$(filter true,$(LOCAL_VENDOR_MODULE) $(LOCAL_ODM_MODULE) $(LOCAL_OEM_MODULE) $(LOCAL_PROPRIETARY_MODULE)))
LOCAL_USE_VNDK:=true
- else
- ifneq (,$(filter $(TARGET_OUT_VENDOR)%,$(LOCAL_MODULE_PATH) $(LOCAL_MODULE_PATH_32) $(LOCAL_MODULE_PATH_64)))
- LOCAL_USE_VNDK:=true
- endif
+ # Note: no need to check LOCAL_MODULE_PATH* since LOCAL_[VENDOR|ODM|OEM]_MODULE is already
+ # set correctly before this is included.
endif
endif
endif
diff --git a/core/main.mk b/core/main.mk
index 1ea2160..1946edb 100644
--- a/core/main.mk
+++ b/core/main.mk
@@ -34,7 +34,7 @@
TOP := .
TOPDIR :=
-BUILD_SYSTEM := $(TOPDIR)build/core
+BUILD_SYSTEM := $(TOPDIR)build/make/core
# This is the default target. It must be the first declared target.
.PHONY: droid
@@ -52,6 +52,10 @@
dont_bother := true
endif
+.KATI_READONLY := SOONG_CONFIG_NAMESPACES
+.KATI_READONLY := $(foreach n,$(SOONG_CONFIG_NAMESPACES),SOONG_CONFIG_$(n))
+.KATI_READONLY := $(foreach n,$(SOONG_CONFIG_NAMESPACES),$(foreach k,$(SOONG_CONFIG_$(n)),SOONG_CONFIG_$(n)_$(k)))
+
include $(SOONG_MAKEVARS_MK)
include $(BUILD_SYSTEM)/clang/config.mk
@@ -60,16 +64,28 @@
# without changing the command line every time. Avoids rebuilds
# when using ninja.
$(shell mkdir -p $(OUT_DIR) && \
- echo -n $(BUILD_NUMBER) > $(OUT_DIR)/build_number.txt && \
- echo -n $(BUILD_DATETIME) > $(OUT_DIR)/build_date.txt)
-BUILD_NUMBER_FROM_FILE := $$(cat $(OUT_DIR)/build_number.txt)
-BUILD_DATETIME_FROM_FILE := $$(cat $(OUT_DIR)/build_date.txt)
+ echo -n $(BUILD_NUMBER) > $(OUT_DIR)/build_number.txt)
+BUILD_NUMBER_FILE := $(OUT_DIR)/build_number.txt
+
ifeq ($(HOST_OS),darwin)
DATE_FROM_FILE := date -r $(BUILD_DATETIME_FROM_FILE)
else
DATE_FROM_FILE := date -d @$(BUILD_DATETIME_FROM_FILE)
endif
+# Pick a reasonable string to use to identify files.
+ifeq ($(strip $(HAS_BUILD_NUMBER)),false)
+ # BUILD_NUMBER has a timestamp in it, which means that
+ # it will change every time. Pick a stable value.
+ FILE_NAME_TAG := eng.$(USER)
+else
+ FILE_NAME_TAG := $(file <$(BUILD_NUMBER_FILE))
+endif
+
+# Make an empty directory, which can be used to make empty jars
+EMPTY_DIRECTORY := $(OUT_DIR)/empty
+$(shell mkdir -p $(EMPTY_DIRECTORY) && rm -rf $(EMPTY_DIRECTORY)/*)
+
# CTS-specific config.
-include cts/build/config.mk
# VTS-specific config.
@@ -80,12 +96,16 @@
-include tools/tradefederation/build/suites/general-tests/config.mk
# STS-specific config.
-include test/sts/tools/sts-tradefed/build/config.mk
+# CTS-Instant-specific config
+-include test/suite_harness/tools/cts-instant-tradefed/build/config.mk
-# This allows us to force a clean build - included after the config.mk
-# environment setup is done, but before we generate any dependencies. This
-# file does the rm -rf inline so the deps which are all done below will
-# be generated correctly
-include $(BUILD_SYSTEM)/cleanbuild.mk
+# Clean rules
+.PHONY: clean-dex-files
+clean-dex-files:
+ $(hide) find $(OUT_DIR) -name "*.dex" | xargs rm -f
+ $(hide) for i in `find $(OUT_DIR) -name "*.jar" -o -name "*.apk"` ; do ((unzip -l $$i 2> /dev/null | \
+ grep -q "\.dex$$" && rm -f $$i) || continue ) ; done
+ @echo "All dex files and archives containing dex files have been removed."
# Include the google-specific config
-include vendor/google/build/config.mk
@@ -95,11 +115,21 @@
# (must be defined before including definitions.make)
INTERNAL_MODIFIER_TARGETS := all
-# EMMA_INSTRUMENT_STATIC merges the static emma library to each emma-enabled module.
+# EMMA_INSTRUMENT_STATIC merges the static jacoco library to each
+# jacoco-enabled module.
ifeq (true,$(EMMA_INSTRUMENT_STATIC))
EMMA_INSTRUMENT := true
endif
+ifeq (true,$(EMMA_INSTRUMENT))
+# Adding the jacoco library can cause the inclusion of
+# some typically banned classes
+# So if the user didn't specify SKIP_BOOT_JARS_CHECK, enable it here
+ifndef SKIP_BOOT_JARS_CHECK
+SKIP_BOOT_JARS_CHECK := true
+endif
+endif
+
#
# -----------------------------------------------------------------
# Validate ADDITIONAL_DEFAULT_PROPERTIES.
@@ -114,6 +144,8 @@
$(error ADDITIONAL_BUILD_PROPERTIES must not be set before here: $(ADDITIONAL_BUILD_PROPERTIES))
endif
+ADDITIONAL_BUILD_PROPERTIES :=
+
#
# -----------------------------------------------------------------
# Add the product-defined properties to the build properties.
@@ -169,39 +201,38 @@
# -----------------------------------------------------------------
# The pdk (Platform Development Kit) build
-include build/core/pdk_config.mk
+include build/make/core/pdk_config.mk
#
# -----------------------------------------------------------------
-# Jack version configuration
--include $(TOPDIR)prebuilts/sdk/tools/jack_versions.mk
--include $(TOPDIR)prebuilts/sdk/tools/jack_for_module.mk
-
-#
-# -----------------------------------------------------------------
-# Install and start Jack server
--include $(TOPDIR)prebuilts/sdk/tools/jack_server_setup.mk
-
-#
-# -----------------------------------------------------------------
-# Jacoco package name for Jack
--include $(TOPDIR)external/jacoco/config.mk
-
-#
-# -----------------------------------------------------------------
-# Enable dynamic linker developer warnings for userdebug, eng
-# and non-REL builds
+# Enable dynamic linker and hidden API developer warnings for
+# userdebug, eng and non-REL builds
ifneq ($(TARGET_BUILD_VARIANT),user)
- ADDITIONAL_BUILD_PROPERTIES += ro.bionic.ld.warning=1
+ ADDITIONAL_BUILD_PROPERTIES += ro.bionic.ld.warning=1 \
+ ro.art.hiddenapi.warning=1
else
# Enable it for user builds as long as they are not final.
ifneq ($(PLATFORM_VERSION_CODENAME),REL)
- ADDITIONAL_BUILD_PROPERTIES += ro.bionic.ld.warning=1
+ ADDITIONAL_BUILD_PROPERTIES += ro.bionic.ld.warning=1 \
+ ro.art.hiddenapi.warning=1
endif
endif
ADDITIONAL_BUILD_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 \
+ variables like PRODUCT_SEPOLICY_SPLIT should be used until that is \
+ possible.)
+
+# Sets ro.actionable_compatible_property.enabled to know on runtime whether the whitelist
+# 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
+
# -----------------------------------------------------------------
###
### In this section we set up the things that are different
@@ -418,16 +449,16 @@
# Include all of the makefiles in the system
#
-subdir_makefiles := $(SOONG_ANDROID_MK) $(call first-makefiles-under,$(TOP))
+subdir_makefiles := $(SOONG_ANDROID_MK) $(file <$(OUT_DIR)/.module_paths/Android.mk.list)
subdir_makefiles_total := $(words $(subdir_makefiles))
.KATI_READONLY := subdir_makefiles_total
$(foreach mk,$(subdir_makefiles),$(info [$(call inc_and_print,subdir_makefiles_inc)/$(subdir_makefiles_total)] including $(mk) ...)$(eval include $(mk)))
-ifdef PDK_FUSION_PLATFORM_ZIP
+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
+endif # PDK_FUSION_PLATFORM_ZIP || PDK_FUSION_PLATFORM_DIR
droid_targets : blueprint_tools
@@ -500,9 +531,10 @@
# 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 exectuable or shared library,
+# 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 select-bitness-of-required-modules
$(foreach m,$(ALL_MODULES),\
$(eval r := $(ALL_MODULES.$(m).REQUIRED))\
$(if $(r),\
@@ -518,6 +550,8 @@
$(eval ALL_MODULES.$(m).REQUIRED := $(strip $(r_r)))\
)\
)
+endef
+$(call select-bitness-of-required-modules)
r_r :=
define add-required-deps
@@ -532,24 +566,93 @@
$(1): $(2)
endef
+# Sets up dependencies such that whenever a host module is installed,
+# any other host modules listed in $(ALL_MODULES.$(m).REQUIRED) will also be installed
+define add-all-host-to-host-required-modules-deps
+$(foreach m,$(ALL_MODULES), \
+ $(eval r := $(ALL_MODULES.$(m).REQUIRED)) \
+ $(if $(r), \
+ $(eval r := $(call module-installed-files,$(r))) \
+ $(eval h_m := $(filter $(HOST_OUT)/%, $(ALL_MODULES.$(m).INSTALLED))) \
+ $(eval hc_m := $(filter $(HOST_CROSS_OUT)/%, $(ALL_MODULES.$(m).INSTALLED))) \
+ $(eval h_r := $(filter $(HOST_OUT)/%, $(r))) \
+ $(eval hc_r := $(filter $(HOST_CROSS_OUT)/%, $(r))) \
+ $(eval h_m := $(filter-out $(h_r), $(h_m))) \
+ $(eval hc_m := $(filter-out $(hc_r), $(hc_m))) \
+ $(if $(h_m), $(eval $(call add-required-deps, $(h_m),$(h_r)))) \
+ $(if $(hc_m), $(eval $(call add-required-deps, $(hc_m),$(hc_r)))) \
+ ) \
+)
+endef
+$(call add-all-host-to-host-required-modules-deps)
+
+# Sets up dependencies such that whenever a target module is installed,
+# any other target modules listed in $(ALL_MODULES.$(m).REQUIRED) will also be installed
+define add-all-target-to-target-required-modules-deps
$(foreach m,$(ALL_MODULES), \
$(eval r := $(ALL_MODULES.$(m).REQUIRED)) \
$(if $(r), \
$(eval r := $(call module-installed-files,$(r))) \
$(eval t_m := $(filter $(TARGET_OUT_ROOT)/%, $(ALL_MODULES.$(m).INSTALLED))) \
- $(eval h_m := $(filter $(HOST_OUT)/%, $(ALL_MODULES.$(m).INSTALLED))) \
- $(eval hc_m := $(filter $(HOST_CROSS_OUT)/%, $(ALL_MODULES.$(m).INSTALLED))) \
$(eval t_r := $(filter $(TARGET_OUT_ROOT)/%, $(r))) \
- $(eval h_r := $(filter $(HOST_OUT)/%, $(r))) \
- $(eval hc_r := $(filter $(HOST_CROSS_OUT)/%, $(r))) \
$(eval t_m := $(filter-out $(t_r), $(t_m))) \
- $(eval h_m := $(filter-out $(h_r), $(h_m))) \
- $(eval hc_m := $(filter-out $(hc_r), $(hc_m))) \
$(if $(t_m), $(eval $(call add-required-deps, $(t_m),$(t_r)))) \
- $(if $(h_m), $(eval $(call add-required-deps, $(h_m),$(h_r)))) \
- $(if $(hc_m), $(eval $(call add-required-deps, $(hc_m),$(hc_r)))) \
- ) \
- )
+ ) \
+)
+endef
+$(call add-all-target-to-target-required-modules-deps)
+
+# Sets up dependencies such that whenever a host module is installed,
+# any target modules listed in $(ALL_MODULES.$(m).TARGET_REQUIRED) will also be installed
+define add-all-host-to-target-required-modules-deps
+$(foreach m,$(ALL_MODULES), \
+ $(eval req_mods := $(ALL_MODULES.$(m).TARGET_REQUIRED))\
+ $(if $(req_mods), \
+ $(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)\
+ )\
+ $(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))) \
+ )\
+ )\
+)
+endef
+$(call add-all-host-to-target-required-modules-deps)
+
+# Sets up dependencies such that whenever a target module is installed,
+# any host modules listed in $(ALL_MODULES.$(m).HOST_REQUIRED) will also be installed
+define add-all-target-to-host-required-modules-deps
+$(foreach m,$(ALL_MODULES), \
+ $(eval req_mods := $(ALL_MODULES.$(m).HOST_REQUIRED))\
+ $(if $(req_mods), \
+ $(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)\
+ )\
+ $(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))) \
+ )\
+ )\
+)
+endef
+$(call add-all-target-to-host-required-modules-deps)
t_m :=
h_m :=
@@ -558,7 +661,7 @@
h_r :=
hc_r :=
-# Establish the dependecies on the shared libraries.
+# Establish the dependencies on the shared libraries.
# It also adds the shared library module names to ALL_MODULES.$(m).REQUIRED,
# so they can be expanded to product_MODULES later.
# $(1): TARGET_ or HOST_ or HOST_CROSS_.
@@ -794,6 +897,9 @@
# by the appropriate product definition file, which was included
# by product_config.mk.
product_MODULES := $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PACKAGES)
+ifdef BOARD_VNDK_VERSION
+ product_MODULES += vndk_package
+endif
# Filter out the overridden packages before doing expansion
product_MODULES := $(filter-out $(foreach p, $(product_MODULES), \
$(PACKAGES.$(p).OVERRIDES)), $(product_MODULES))
@@ -905,7 +1011,7 @@
$(warning $(ALL_MODULES.$(m).MAKEFILE): Module '$(m)' in PRODUCT_PACKAGES_TESTS has nothing to install!)))
endif
-# build/core/Makefile contains extra stuff that we don't want to pollute this
+# build/make/core/Makefile contains extra stuff that we don't want to pollute this
# top-level makefile with. It expects that ALL_DEFAULT_INSTALLED_MODULES
# contains everything that's built during the current make, but it also further
# extends ALL_DEFAULT_INSTALLED_MODULES.
@@ -983,6 +1089,9 @@
.PHONY: vendorimage
vendorimage: $(INSTALLED_VENDORIMAGE_TARGET)
+.PHONY: productimage
+productimage: $(INSTALLED_PRODUCTIMAGE_TARGET)
+
.PHONY: systemotherimage
systemotherimage: $(INSTALLED_SYSTEMOTHERIMAGE_TARGET)
@@ -1006,10 +1115,13 @@
$(INSTALLED_CACHEIMAGE_TARGET) \
$(INSTALLED_BPTIMAGE_TARGET) \
$(INSTALLED_VENDORIMAGE_TARGET) \
+ $(INSTALLED_PRODUCTIMAGE_TARGET) \
$(INSTALLED_SYSTEMOTHERIMAGE_TARGET) \
$(INSTALLED_FILES_FILE) \
$(INSTALLED_FILES_FILE_VENDOR) \
- $(INSTALLED_FILES_FILE_SYSTEMOTHER)
+ $(INSTALLED_FILES_FILE_PRODUCT) \
+ $(INSTALLED_FILES_FILE_SYSTEMOTHER) \
+ soong_docs
# dist_files only for putting your library into the dist directory with a full build.
.PHONY: dist_files
@@ -1037,13 +1149,8 @@
$(call dist-for-goals,apps_only, $(apps_only_dist_built_files))
ifeq ($(EMMA_INSTRUMENT),true)
- ifeq ($(ANDROID_COMPILE_WITH_JACK),false)
- $(JACOCO_REPORT_CLASSES_ALL) : $(apps_only_installed_files)
- $(call dist-for-goals,apps_only, $(JACOCO_REPORT_CLASSES_ALL))
- else
- $(EMMA_META_ZIP) : $(apps_only_installed_files)
- $(call dist-for-goals,apps_only, $(EMMA_META_ZIP))
- endif
+ $(JACOCO_REPORT_CLASSES_ALL) : $(apps_only_installed_files)
+ $(call dist-for-goals,apps_only, $(JACOCO_REPORT_CLASSES_ALL))
endif
$(PROGUARD_DICT_ZIP) : $(apps_only_installed_files)
@@ -1078,6 +1185,7 @@
$(COVERAGE_ZIP) \
$(INSTALLED_FILES_FILE) \
$(INSTALLED_FILES_FILE_VENDOR) \
+ $(INSTALLED_FILES_FILE_PRODUCT) \
$(INSTALLED_FILES_FILE_SYSTEMOTHER) \
$(INSTALLED_BUILD_PROP_TARGET) \
$(BUILT_TARGET_FILES_PACKAGE) \
@@ -1100,13 +1208,8 @@
endif
ifeq ($(EMMA_INSTRUMENT),true)
- ifeq ($(ANDROID_COMPILE_WITH_JACK),false)
- $(JACOCO_REPORT_CLASSES_ALL) : $(INSTALLED_SYSTEMIMAGE)
- $(call dist-for-goals, dist_files, $(JACOCO_REPORT_CLASSES_ALL))
- else
- $(EMMA_META_ZIP) : $(INSTALLED_SYSTEMIMAGE)
- $(call dist-for-goals, dist_files, $(EMMA_META_ZIP))
- endif
+ $(JACOCO_REPORT_CLASSES_ALL) : $(INSTALLED_SYSTEMIMAGE)
+ $(call dist-for-goals, dist_files, $(JACOCO_REPORT_CLASSES_ALL))
endif
# Building a full system-- the default is to build droidcore
@@ -1142,7 +1245,7 @@
target-native-tests : native-target-tests
tests : host-tests target-tests
-# Phony target to run all java compilations that use javac instead of jack.
+# Phony target to run all java compilations that use javac
.PHONY: javac-check
ifneq (,$(filter samplecode, $(MAKECMDGOALS)))
@@ -1164,6 +1267,9 @@
.PHONY: findbugs
findbugs: $(INTERNAL_FINDBUGS_HTML_TARGET) $(INTERNAL_FINDBUGS_XML_TARGET)
+.PHONY: findlsdumps
+findlsdumps: $(FIND_LSDUMPS_FILE)
+
#xxx scrape this from ALL_MODULE_NAME_TAGS
.PHONY: modules
modules:
diff --git a/core/math.mk b/core/math.mk
index 047d046..44e03ce 100644
--- a/core/math.mk
+++ b/core/math.mk
@@ -42,6 +42,11 @@
$(if $(call math_is_number,$(1)),,$(error Only positive integers <= 100 are supported (not $(1))))
endef
+# return a list containing integers ranging from [$(1),$(2)]
+define int_range_list
+$(call _math_check_valid,$(1))$(call _math_check_valid,$(2))$(wordlist $(1),$(2),$(__MATH_NUMBERS))
+endef
+
#$(call _math_check_valid,0)
#$(call _math_check_valid,1)
#$(call _math_check_valid,100)
@@ -67,6 +72,10 @@
$(if $(filter $(1),$(call math_max,$(1),$(2))),true)
endef
+define math_lt
+$(if $(call math_gt_or_eq,$(1),$(2)),,true)
+endef
+
#$(warning $(call math_gt_or_eq, 2, 1))
#$(warning $(call math_gt_or_eq, 1, 1))
#$(warning $(if $(call math_gt_or_eq, 1, 2),false,true))
@@ -75,3 +84,69 @@
define inc_and_print
$(strip $(eval $(1) := $($(1)) .)$(words $($(1))))
endef
+
+# Returns the words in $2 that are numbers and are less than $1
+define numbers_less_than
+$(strip \
+ $(foreach n,$2, \
+ $(if $(call math_is_number,$(n)), \
+ $(if $(call math_lt,$(n),$(1)), \
+ $(n)))))
+endef
+
+_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)))
+
+define _int_encode
+$(if $(filter $(words x $(_INT_LIMIT_WORDS)),$(words $(wordlist 1,$(1),x $(_INT_LIMIT_WORDS)))),\
+ $(call pretty-error,integer greater than $(words $(_INT_LIMIT_WORDS)) is not supported!),\
+ $(wordlist 1,$(1),$(_INT_LIMIT_WORDS)))
+endef
+
+# _int_max returns the maximum of the two arguments
+# input: two (x) lists; output: one (x) list
+# integer cannot be passed in directly. It has to be converted using _int_encode.
+define _int_max
+$(subst xx,x,$(join $(1),$(2)))
+endef
+
+# first argument is greater than second argument
+# output: non-empty if true
+# integer cannot be passed in directly. It has to be converted using _int_encode.
+define _int_greater-than
+$(filter-out $(words $(2)),$(words $(call _int_max,$(1),$(2))))
+endef
+
+# first argument equals to second argument
+# output: non-empty if true
+# integer cannot be passed in directly. It has to be converted using _int_encode.
+define _int_equal
+$(filter $(words $(1)),$(words $(2)))
+endef
+
+# first argument is greater than or equal to second argument
+# output: non-empty if true
+# integer cannot be passed in directly. It has to be converted using _int_encode.
+define _int_greater-or-equal
+$(call _int_greater-than,$(1),$(2))$(call _int_equal,$(1),$(2))
+endef
+
+define int_plus
+$(words $(call _int_encode,$(1)) $(call _int_encode,$(2)))
+endef
+
+define int_subtract
+$(if $(call _int_greater-or-equal,$(call _int_encode,$(1)),$(call _int_encode,$(2))),\
+ $(words $(filter-out xx,$(join $(call _int_encode,$(1)),$(call _int_encode,$(2))))),\
+ $(call pretty-error,$(1) subtract underflow $(2)))
+endef
+
+define int_multiply
+$(words $(foreach a,$(call _int_encode,$(1)),$(call _int_encode,$(2))))
+endef
+
+define int_divide
+$(if $(filter 0,$(2)),$(call pretty-error,division by zero is not allowed!),$(strip \
+ $(if $(call _int_greater-or-equal,$(call _int_encode,$(1)),$(call _int_encode,$(2))), \
+ $(call int_plus,$(call int_divide,$(call int_subtract,$(1),$(2)),$(2)),1),0)))
+endef
diff --git a/core/native_test_config_template.xml b/core/native_test_config_template.xml
new file mode 100644
index 0000000..a960529
--- /dev/null
+++ b/core/native_test_config_template.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<!-- This test config file is auto-generated. -->
+<configuration description="Runs {MODULE}.">
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+ <option name="cleanup" value="true" />
+ <option name="push" value="{MODULE}->/data/local/tmp/{MODULE}" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.GTest" >
+ <option name="native-test-device-path" value="/data/local/tmp" />
+ <option name="module-name" value="{MODULE}" />
+ </test>
+</configuration>
diff --git a/core/no_java_path/jar b/core/no_java_path/jar
deleted file mode 120000
index 8586397..0000000
--- a/core/no_java_path/jar
+++ /dev/null
@@ -1 +0,0 @@
-java
\ No newline at end of file
diff --git a/core/no_java_path/jarsigner b/core/no_java_path/jarsigner
deleted file mode 120000
index 8586397..0000000
--- a/core/no_java_path/jarsigner
+++ /dev/null
@@ -1 +0,0 @@
-java
\ No newline at end of file
diff --git a/core/no_java_path/java b/core/no_java_path/java
deleted file mode 100755
index f3422f3..0000000
--- a/core/no_java_path/java
+++ /dev/null
@@ -1,4 +0,0 @@
-#!/bin/bash
-
-echo "Error: JAVA_NOT_REQUIRED=true, $(basename $0) is unavailable." 1>&2
-exit 1
diff --git a/core/no_java_path/javac b/core/no_java_path/javac
deleted file mode 120000
index 8586397..0000000
--- a/core/no_java_path/javac
+++ /dev/null
@@ -1 +0,0 @@
-java
\ No newline at end of file
diff --git a/core/no_java_path/keytool b/core/no_java_path/keytool
deleted file mode 120000
index 8586397..0000000
--- a/core/no_java_path/keytool
+++ /dev/null
@@ -1 +0,0 @@
-java
\ No newline at end of file
diff --git a/core/notice_files.mk b/core/notice_files.mk
index f850fff..383d73c 100644
--- a/core/notice_files.mk
+++ b/core/notice_files.mk
@@ -57,7 +57,7 @@
# javalib.jar is the default name for the build module (and isn't meaningful)
# If that's what we have, substitute the module name instead. These files
# aren't included on the device, so this name is synthetic anyway.
- ifneq ($(filter javalib.jar classes.jack,$(module_leaf)),)
+ ifneq ($(filter javalib.jar,$(module_leaf)),)
module_leaf := $(LOCAL_MODULE).jar
endif
module_installed_filename := \
diff --git a/core/package_internal.mk b/core/package_internal.mk
index 5c4ad28..80d386d 100644
--- a/core/package_internal.mk
+++ b/core/package_internal.mk
@@ -60,10 +60,6 @@
intermediates := $(call local-intermediates-dir)
intermediates.COMMON := $(call local-intermediates-dir,COMMON)
-#################################
-include $(BUILD_SYSTEM)/configure_local_jack.mk
-#################################
-
# Package LOCAL_MODULE_TAGS default to optional
LOCAL_MODULE_TAGS := $(strip $(LOCAL_MODULE_TAGS))
ifeq ($(LOCAL_MODULE_TAGS),)
@@ -115,6 +111,8 @@
enforce_rro_enabled :=
else ifeq (true,$(LOCAL_ODM_MODULE))
enforce_rro_enabled :=
+ else ifeq (true,$(LOCAL_PRODUCT_MODULE))
+ enforce_rro_enabled :=
endif
else ifeq ($(filter $(TARGET_OUT)/%,$(LOCAL_MODULE_PATH)),)
enforce_rro_enabled :=
@@ -150,6 +148,10 @@
need_compile_asset := true
endif
+ifdef LOCAL_AAPT2_ONLY
+LOCAL_USE_AAPT2 := true
+endif
+
my_res_package :=
ifdef LOCAL_USE_AAPT2
# In aapt2 the last takes precedence.
@@ -259,13 +261,6 @@
endif # !custom
LOCAL_PROGUARD_FLAGS := $(addprefix -include ,$(proguard_options_file)) $(LOCAL_PROGUARD_FLAGS)
-ifdef LOCAL_JACK_ENABLED
-ifndef LOCAL_JACK_PROGUARD_FLAGS
- LOCAL_JACK_PROGUARD_FLAGS := $(LOCAL_PROGUARD_FLAGS)
-endif
-LOCAL_JACK_PROGUARD_FLAGS := $(addprefix -include ,$(proguard_options_file)) $(LOCAL_JACK_PROGUARD_FLAGS)
-endif # LOCAL_JACK_ENABLED
-
ifeq (true,$(EMMA_INSTRUMENT))
ifndef LOCAL_EMMA_INSTRUMENT
# No jacoco for test apks.
@@ -279,9 +274,11 @@
ifeq (true,$(LOCAL_EMMA_INSTRUMENT))
ifeq (true,$(EMMA_INSTRUMENT_STATIC))
-ifneq ($(LOCAL_SRC_FILES)$(LOCAL_STATIC_JAVA_LIBRARIES)$(LOCAL_SOURCE_FILES_ALL_GENERATED),)
+ifneq ($(LOCAL_SRC_FILES)$(LOCAL_SRCJARS)$(LOCAL_STATIC_JAVA_LIBRARIES)$(LOCAL_SOURCE_FILES_ALL_GENERATED),)
# Only add jacocoagent if the package contains some java code
LOCAL_STATIC_JAVA_LIBRARIES += jacocoagent
+# Exclude jacoco classes from proguard
+LOCAL_PROGUARD_FLAGS += -include $(BUILD_SYSTEM)/proguard.jacoco.flags
endif # Contains java code
else
ifdef LOCAL_SDK_VERSION
@@ -292,20 +289,8 @@
LOCAL_STATIC_JAVA_LIBRARIES += jacocoagent
# Exclude jacoco classes from proguard
LOCAL_PROGUARD_FLAGS += -include $(BUILD_SYSTEM)/proguard.jacoco.flags
-LOCAL_JACK_PROGUARD_FLAGS += -include $(BUILD_SYSTEM)/proguard.jacoco.flags
endif # Contains java code
-else # ! TARGET_BUILD_APPS
-ifdef LOCAL_JACK_ENABLED
-# If build against the SDK in full build, core.jar is not used
-# so coverage classes are not present.
-# Jack needs jacoco on the classpath but we do not want it to be in
-# the final apk. While it is a static library, we add it to the
-# LOCAL_JAVA_LIBRARIES which are only present on the classpath.
-# Note: we have nothing to do for proguard since jacoco will be
-# on the classpath only, thus not modified during the compilation.
-LOCAL_JAVA_LIBRARIES += jacocoagent
-endif # ! LOCAL_JACK_ENABLED
-endif # ! TARGET_BUILD_APPS
+endif # TARGET_BUILD_APPS
endif # LOCAL_SDK_VERSION
endif # EMMA_INSTRUMENT_STATIC
endif # LOCAL_EMMA_INSTRUMENT
@@ -316,7 +301,6 @@
data_binding_intermediates := $(intermediates.COMMON)/data-binding
LOCAL_JAVACFLAGS += -processorpath $(DATA_BINDING_COMPILER) -s $(data_binding_intermediates)/anno-src
-LOCAL_JACK_FLAGS += --processorpath $(DATA_BINDING_COMPILER)
LOCAL_STATIC_JAVA_LIBRARIES += databinding-baselibrary
LOCAL_STATIC_JAVA_AAR_LIBRARIES += databinding-library databinding-adapters
@@ -330,6 +314,9 @@
LOCAL_AAPT_FLAGS += --auto-add-overlay --extra-packages com.android.databinding.library
endif # LOCAL_DATA_BINDING
+# Process Support Library dependencies.
+include $(BUILD_SYSTEM)/support_libraries.mk
+
# If the module is a compressed module, we don't pre-opt it because its final
# installation location will be the data partition.
ifdef LOCAL_COMPRESSED_MODULE
@@ -338,12 +325,123 @@
include $(BUILD_SYSTEM)/android_manifest.mk
+resource_export_package :=
+
+include $(BUILD_SYSTEM)/java_renderscript.mk
+
+include $(BUILD_SYSTEM)/aapt_flags.mk
+
+ifeq ($(need_compile_res),true)
+
+###############################
+## APK splits
+built_apk_splits :=
+installed_apk_splits :=
+my_apk_split_configs :=
+
+ifdef LOCAL_PACKAGE_SPLITS
+ifdef LOCAL_COMPRESSED_MODULE
+$(error $(LOCAL_MODULE): LOCAL_COMPRESSED_MODULE is not currently supported for split installs)
+endif # LOCAL_COMPRESSED_MODULE
+
+my_apk_split_configs := $(LOCAL_PACKAGE_SPLITS)
+my_split_suffixes := $(subst $(comma),_,$(my_apk_split_configs))
+built_apk_splits := $(foreach s,$(my_split_suffixes),$(intermediates)/package_$(s).apk)
+endif
+
+$(R_file_stamp) $(my_res_package): PRIVATE_AAPT_FLAGS := $(LOCAL_AAPT_FLAGS)
+$(R_file_stamp) $(my_res_package): PRIVATE_TARGET_AAPT_CHARACTERISTICS := $(TARGET_AAPT_CHARACTERISTICS)
+$(R_file_stamp) $(my_res_package): PRIVATE_MANIFEST_PACKAGE_NAME := $(LOCAL_MANIFEST_PACKAGE_NAME)
+$(R_file_stamp) $(my_res_package): PRIVATE_MANIFEST_INSTRUMENTATION_FOR := $(LOCAL_MANIFEST_INSTRUMENTATION_FOR)
+
+###############################
+## AAPT/AAPT2
+
+ifdef LOCAL_USE_AAPT2
+ my_compiled_res_base_dir := $(intermediates.COMMON)/flat-res
+ ifneq (,$(renderscript_target_api))
+ ifneq ($(call math_gt_or_eq,$(renderscript_target_api),21),true)
+ my_generated_res_zips := $(rs_generated_res_zip)
+ endif # renderscript_target_api < 21
+ endif # renderscript_target_api is set
+ my_asset_dirs := $(LOCAL_ASSET_DIR)
+ my_full_asset_paths := $(all_assets)
+
+ # Add AAPT2 link specific flags.
+ $(my_res_package): PRIVATE_AAPT_FLAGS := $(LOCAL_AAPT_FLAGS)
+ ifndef LOCAL_AAPT_NAMESPACES
+ $(my_res_package): PRIVATE_AAPT_FLAGS += --no-static-lib-packages
+ endif
+
+ include $(BUILD_SYSTEM)/aapt2.mk
+else # LOCAL_USE_AAPT2
+
+ my_srcjar := $(intermediates.COMMON)/aapt.srcjar
+ LOCAL_SRCJARS += $(my_srcjar)
+ $(R_file_stamp): PRIVATE_SRCJAR := $(my_srcjar)
+ $(R_file_stamp): PRIVATE_JAVA_GEN_DIR := $(intermediates.COMMON)/aapt
+ $(R_file_stamp): .KATI_IMPLICIT_OUTPUTS := $(my_srcjar)
+ # Since we don't know where the real R.java file is going to end up,
+ # we need to use another file to stand in its place. We'll just
+ # copy the generated file to src/R.stamp, which means it will
+ # have the same contents and timestamp as the actual file.
+ #
+ # At the same time, this will copy the R.java file to a central
+ # 'R' directory to make it easier to add the files to an IDE.
+ #
+
+ $(R_file_stamp): PRIVATE_RESOURCE_PUBLICS_OUTPUT := \
+ $(intermediates.COMMON)/public_resources.xml
+ $(R_file_stamp): PRIVATE_PROGUARD_OPTIONS_FILE := $(proguard_options_file)
+ $(R_file_stamp): PRIVATE_RESOURCE_LIST := $(all_res_assets)
+ $(R_file_stamp): $(all_res_assets) $(full_android_manifest) $(rs_generated_res_zip) $(AAPT) $(SOONG_ZIP) | $(ACP)
+ @echo "target R.java/Manifest.java: $(PRIVATE_MODULE) ($@)"
+ @rm -rf $@ && mkdir -p $(dir $@)
+ $(create-resource-java-files)
+ $(call find-generated-R.java,$(PRIVATE_JAVA_GEN_DIR),$@)
+
+ $(proguard_options_file): $(R_file_stamp)
+
+ ifdef LOCAL_EXPORT_PACKAGE_RESOURCES
+ # Put this module's resources into a PRODUCT-agnositc package that
+ # other packages can use to build their own PRODUCT-agnostic R.java (etc.)
+ # files.
+ resource_export_package := $(intermediates.COMMON)/package-export.apk
+ $(R_file_stamp): $(resource_export_package)
+
+ # add-assets-to-package looks at PRODUCT_AAPT_CONFIG, but this target
+ # can't know anything about PRODUCT. Clear it out just for this target.
+ $(resource_export_package): PRIVATE_PRODUCT_AAPT_CONFIG :=
+ $(resource_export_package): PRIVATE_PRODUCT_AAPT_PREF_CONFIG :=
+ $(resource_export_package): PRIVATE_RESOURCE_LIST := $(all_res_assets)
+ $(resource_export_package): $(all_res_assets) $(full_android_manifest) $(rs_generated_res_zip) $(AAPT)
+ @echo "target Export Resources: $(PRIVATE_MODULE) ($@)"
+ $(create-empty-package)
+ $(add-assets-to-package)
+ endif
+
+endif # LOCAL_USE_AAPT2
+
+endif # need_compile_res
+
called_from_package_internal := true
#################################
include $(BUILD_SYSTEM)/java.mk
#################################
called_from_package_internal :=
+ifeq ($(need_compile_res),true)
+
+# Other modules should depend on the BUILT module if
+# they want to use this module's R.java file.
+$(LOCAL_BUILT_MODULE): $(R_file_stamp)
+
+# The R.java file must exist by the time the java source
+# list is generated
+$(java_source_list_file): $(R_file_stamp)
+
+endif # need_compile_res
+
LOCAL_SDK_RES_VERSION:=$(strip $(LOCAL_SDK_RES_VERSION))
ifeq ($(LOCAL_SDK_RES_VERSION),)
LOCAL_SDK_RES_VERSION:=$(LOCAL_SDK_VERSION)
@@ -375,152 +473,36 @@
$(hide) touch $@
# Make sure the data-binding process happens before javac and generation of R.java.
-$(R_file_stamp) $(full_classes_compiled_jar) : $(data_binding_stamp)
-# The dependency path when jack is enabled
-$(built_dex_intermediate) : $(data_binding_stamp)
+$(R_file_stamp): $(data_binding_stamp)
+$(java_source_list_file): $(data_binding_stamp)
+$(full_classes_compiled_jar): $(data_binding_stamp)
endif # LOCAL_DATA_BINDING
-ifeq ($(need_compile_res),true)
+framework_res_package_export :=
-###############################
-## APK splits
-built_apk_splits :=
-installed_apk_splits :=
-my_apk_split_configs :=
-
-ifdef LOCAL_PACKAGE_SPLITS
-ifdef LOCAL_COMPRESSED_MODULE
-$(error $(LOCAL_MODULE): LOCAL_COMPRESSED_MODULE is not currently supported for split installs)
-endif # LOCAL_COMPRESSED_MODULE
-
-my_apk_split_configs := $(LOCAL_PACKAGE_SPLITS)
-my_split_suffixes := $(subst $(comma),_,$(my_apk_split_configs))
-built_apk_splits := $(foreach s,$(my_split_suffixes),$(intermediates)/package_$(s).apk)
-installed_apk_splits := $(foreach s,$(my_split_suffixes),$(my_module_path)/$(LOCAL_MODULE)_$(s).apk)
-endif
-
-ifdef LOCAL_USE_AAPT2
-my_compiled_res_base_dir := $(intermediates)/flat-res
-renderscript_target_api :=
-ifneq (,$(LOCAL_RENDERSCRIPT_TARGET_API))
-renderscript_target_api := $(LOCAL_RENDERSCRIPT_TARGET_API)
-else
-ifneq (,$(LOCAL_SDK_VERSION))
-# Set target-api for LOCAL_SDK_VERSIONs other than current.
-ifneq (,$(filter-out current system_current test_current, $(LOCAL_SDK_VERSION)))
-renderscript_target_api := $(LOCAL_SDK_VERSION)
-endif
-endif # LOCAL_SDK_VERSION is set
-endif # LOCAL_RENDERSCRIPT_TARGET_API is set
-ifneq (,$(renderscript_target_api))
-ifneq ($(call math_gt_or_eq,$(renderscript_target_api),21),true)
-my_generated_res_dirs := $(rs_generated_res_dir)
-my_generated_res_dirs_deps := $(RenderScript_file_stamp)
-endif # renderscript_target_api < 21
-endif # renderscript_target_api is set
-my_asset_dirs := $(LOCAL_ASSET_DIR)
-my_full_asset_paths := $(all_assets)
-# Add AAPT2 link specific flags.
-$(my_res_package): PRIVATE_AAPT_FLAGS := $(LOCAL_AAPT_FLAGS) --no-static-lib-packages
-include $(BUILD_SYSTEM)/aapt2.mk
-else # LOCAL_USE_AAPT2
-
-# Since we don't know where the real R.java file is going to end up,
-# we need to use another file to stand in its place. We'll just
-# copy the generated file to src/R.stamp, which means it will
-# have the same contents and timestamp as the actual file.
-#
-# At the same time, this will copy the R.java file to a central
-# 'R' directory to make it easier to add the files to an IDE.
-#
-
-$(R_file_stamp): PRIVATE_RESOURCE_PUBLICS_OUTPUT := \
- $(intermediates.COMMON)/public_resources.xml
-$(R_file_stamp): PRIVATE_PROGUARD_OPTIONS_FILE := $(proguard_options_file)
-$(R_file_stamp): $(all_res_assets) $(full_android_manifest) $(RenderScript_file_stamp) $(AAPT) | $(ACP)
- @echo "target R.java/Manifest.java: $(PRIVATE_MODULE) ($@)"
- @rm -rf $@ && mkdir -p $(dir $@)
- $(create-resource-java-files)
- $(call find-generated-R.java)
-
-$(proguard_options_file): $(R_file_stamp)
-
-resource_export_package :=
-ifdef LOCAL_EXPORT_PACKAGE_RESOURCES
-# Put this module's resources into a PRODUCT-agnositc package that
-# other packages can use to build their own PRODUCT-agnostic R.java (etc.)
-# files.
-resource_export_package := $(intermediates.COMMON)/package-export.apk
-$(R_file_stamp): $(resource_export_package)
-
-# add-assets-to-package looks at PRODUCT_AAPT_CONFIG, but this target
-# can't know anything about PRODUCT. Clear it out just for this target.
-$(resource_export_package): PRIVATE_PRODUCT_AAPT_CONFIG :=
-$(resource_export_package): PRIVATE_PRODUCT_AAPT_PREF_CONFIG :=
-$(resource_export_package): $(all_res_assets) $(full_android_manifest) $(RenderScript_file_stamp) $(AAPT)
- @echo "target Export Resources: $(PRIVATE_MODULE) ($@)"
- $(create-empty-package)
- $(add-assets-to-package)
-endif
-
-endif # LOCAL_USE_AAPT2
-
-# Other modules should depend on the BUILT module if
-# they want to use this module's R.java file.
-$(LOCAL_BUILT_MODULE): $(R_file_stamp)
-
-ifdef LOCAL_JACK_ENABLED
-ifneq ($(built_dex_intermediate),)
-$(built_dex_intermediate): $(R_file_stamp)
-endif
-ifneq ($(noshrob_classes_jack),)
-$(noshrob_classes_jack): $(R_file_stamp)
-endif
-ifneq ($(full_classes_jack),)
-$(full_classes_jack): $(R_file_stamp)
-$(jack_check_timestamp): $(R_file_stamp)
-endif
-endif # LOCAL_JACK_ENABLED
-
-ifneq ($(full_classes_jar),)
-# If full_classes_jar is non-empty, we're building sources.
-# If we're building sources, the initial javac step (which
-# produces full_classes_compiled_jar) needs to ensure the
-# R.java and Manifest.java files have been generated first.
-$(full_classes_compiled_jar): $(R_file_stamp)
-endif
-
-endif # need_compile_res
-
-ifeq ($(LOCAL_NO_STANDARD_LIBRARIES),true)
-# We need to explicitly clear this var so that we don't
-# inherit the value from whomever caused us to be built.
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_AAPT_INCLUDES :=
-else
+ifneq ($(LOCAL_NO_STANDARD_LIBRARIES),true)
# Most packages should link against the resources defined by framework-res.
# Even if they don't have their own resources, they may use framework
# resources.
-ifneq ($(filter-out current system_current test_current,$(LOCAL_SDK_RES_VERSION))$(if $(TARGET_BUILD_APPS),$(filter current system_current test_current,$(LOCAL_SDK_RES_VERSION))),)
+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),$(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 := \
$(HISTORICAL_SDK_VERSIONS_ROOT)/$(LOCAL_SDK_RES_VERSION)/android.jar
-framework_res_package_export_deps := $(framework_res_package_export)
else # LOCAL_SDK_RES_VERSION
framework_res_package_export := \
$(call intermediates-dir-for,APPS,framework-res,,COMMON)/package-export.apk
-# We can't depend directly on the export.apk file; it won't get its
-# PRIVATE_ vars set up correctly if we do. Instead, depend on the
-# corresponding R.stamp file, which lists the export.apk as a dependency.
-framework_res_package_export_deps := \
- $(dir $(framework_res_package_export))src/R.stamp
endif # LOCAL_SDK_RES_VERSION
+endif # LOCAL_NO_STANDARD_LIBRARIES
+
all_library_res_package_exports := \
$(framework_res_package_export) \
$(foreach lib,$(LOCAL_RES_LIBRARIES),\
$(call intermediates-dir-for,APPS,$(lib),,COMMON)/package-export.apk)
all_library_res_package_export_deps := \
- $(framework_res_package_export_deps) \
+ $(framework_res_package_export) \
$(foreach lib,$(LOCAL_RES_LIBRARIES),\
$(call intermediates-dir-for,APPS,$(lib),,COMMON)/src/R.stamp)
$(resource_export_package) $(R_file_stamp) $(LOCAL_BUILT_MODULE): $(all_library_res_package_export_deps)
@@ -530,7 +512,14 @@
ifdef LOCAL_USE_AAPT2
$(my_res_package) : $(all_library_res_package_export_deps)
endif
-endif # LOCAL_NO_STANDARD_LIBRARIES
+
+# These four are set above for $(R_stamp_file) and $(my_res_package), but
+# $(LOCAL_BUILT_MODULE) is not set before java.mk, so they have to be set again
+# here.
+$(LOCAL_BUILT_MODULE): PRIVATE_AAPT_FLAGS := $(LOCAL_AAPT_FLAGS)
+$(LOCAL_BUILT_MODULE): PRIVATE_TARGET_AAPT_CHARACTERISTICS := $(TARGET_AAPT_CHARACTERISTICS)
+$(LOCAL_BUILT_MODULE): PRIVATE_MANIFEST_PACKAGE_NAME := $(LOCAL_MANIFEST_PACKAGE_NAME)
+$(LOCAL_BUILT_MODULE): PRIVATE_MANIFEST_INSTRUMENTATION_FOR := $(LOCAL_MANIFEST_INSTRUMENTATION_FOR)
ifneq ($(full_classes_jar),)
$(LOCAL_BUILT_MODULE): PRIVATE_DEX_FILE := $(built_dex)
@@ -598,14 +587,19 @@
$(my_res_package) $(LOCAL_BUILT_MODULE): PRIVATE_PRODUCT_AAPT_PREF_CONFIG := $(PRODUCT_AAPT_PREF_CONFIG)
endif
endif
+
$(LOCAL_BUILT_MODULE): PRIVATE_DONT_DELETE_JAR_DIRS := $(LOCAL_DONT_DELETE_JAR_DIRS)
+$(LOCAL_BUILT_MODULE): PRIVATE_RESOURCE_INTERMEDIATES_DIR := $(intermediates.COMMON)/resources
+$(LOCAL_BUILT_MODULE): PRIVATE_FULL_CLASSES_JAR := $(full_classes_jar)
$(LOCAL_BUILT_MODULE) : $(jni_shared_libraries)
+$(LOCAL_BUILT_MODULE) : $(JAR_ARGS)
ifdef LOCAL_USE_AAPT2
$(LOCAL_BUILT_MODULE): PRIVATE_RES_PACKAGE := $(my_res_package)
$(LOCAL_BUILT_MODULE) : $(my_res_package) $(AAPT2) | $(ACP)
else
-$(LOCAL_BUILT_MODULE) : $(all_res_assets) $(full_android_manifest) $(AAPT)
-endif
+$(LOCAL_BUILT_MODULE): PRIVATE_RESOURCE_LIST := $(all_res_assets)
+$(LOCAL_BUILT_MODULE) : $(all_res_assets) $(full_android_manifest) $(AAPT) $(ZIPALIGN)
+endif # LOCAL_USE_AAPT2
ifdef LOCAL_COMPRESSED_MODULE
$(LOCAL_BUILT_MODULE) : $(MINIGZIP)
endif
@@ -613,13 +607,9 @@
ifdef LOCAL_USE_AAPT2
$(call copy-file-to-new-target)
else # ! LOCAL_USE_AAPT2
-ifdef LOCAL_JACK_ENABLED
- $(create-empty-package)
-else
$(if $(PRIVATE_SOURCE_ARCHIVE),\
$(call initialize-package-file,$(PRIVATE_SOURCE_ARCHIVE),$@),\
$(create-empty-package))
-endif
$(add-assets-to-package)
endif # LOCAL_USE_AAPT2
ifneq ($(jni_shared_libraries),)
@@ -630,9 +620,13 @@
$(if $(PRIVATE_EXTRA_JAR_ARGS),$(call add-java-resources-to,$@))
else # full_classes_jar
$(add-dex-to-package)
+ifdef LOCAL_USE_AAPT2
+ $(call add-jar-resources-to-package,$@,$(PRIVATE_FULL_CLASSES_JAR),$(PRIVATE_RESOURCE_INTERMEDIATES_DIR))
+endif
endif # full_classes_jar
-ifdef LOCAL_JACK_ENABLED
- $(add-carried-jack-resources)
+ifeq (true, $(LOCAL_UNCOMPRESS_DEX))
+ @# No need to align, sign-package below will do it.
+ $(uncompress-dexs)
endif
ifdef LOCAL_DEX_PREOPT
ifneq ($(BUILD_PLATFORM_ZIP),)
@@ -642,7 +636,7 @@
ifneq (nostripping,$(LOCAL_DEX_PREOPT))
$(call dexpreopt-remove-classes.dex,$@)
endif
-endif
+endif # LOCAL_DEX_PREOPT
$(sign-package)
ifdef LOCAL_COMPRESSED_MODULE
$(compress-package)
@@ -666,6 +660,10 @@
$(built_odex) : $(dir $(LOCAL_BUILT_MODULE))% : $(built_dex)
$(hide) mkdir -p $(dir $@) && rm -f $@
$(add-dex-to-package)
+ifeq (true, $(LOCAL_UNCOMPRESS_DEX))
+ $(uncompress-dexs)
+ $(align-package)
+endif
$(hide) mv $@ $@.input
$(call dexpreopt-one-file,$@.input,$@)
$(hide) rm $@.input
@@ -689,6 +687,7 @@
$(sign-package)
# Rules to install the splits
+installed_apk_splits := $(foreach s,$(my_split_suffixes),$(my_module_path)/$(LOCAL_MODULE)_$(s).apk)
$(installed_apk_splits) : $(my_module_path)/$(LOCAL_MODULE)_%.apk : $(intermediates)/package_%.apk
@echo "Install: $@"
$(copy-file-to-new-target)
diff --git a/core/pdk_config.mk b/core/pdk_config.mk
index e12be29..57afa3f 100644
--- a/core/pdk_config.mk
+++ b/core/pdk_config.mk
@@ -7,12 +7,14 @@
host/common/obj/JAVA_LIBRARIES/hosttestlib_intermediates
PDK_PLATFORM_JAVA_ZIP_CONTENTS :=
-ifneq (,$(filter platform-java, $(MAKECMDGOALS))$(PDK_FUSION_PLATFORM_ZIP))
+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.hidl.base-V1.0-java_intermediates \
+ target/common/obj/JAVA_LIBRARIES/android.hidl.manager-V1.0-java_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 \
@@ -24,6 +26,7 @@
target/common/obj/JAVA_LIBRARIES/legacy-android-test_intermediates \
target/common/obj/JAVA_LIBRARIES/ext_intermediates \
target/common/obj/JAVA_LIBRARIES/framework_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 \
@@ -40,39 +43,60 @@
$(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.jack $(lib_dir)/classes.jar $(lib_dir)/classes.jar.toc \
+ $(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),)
-ifneq ($(wildcard external/proguard),)
-TARGET_BUILD_JAVA_SUPPORT_LEVEL := sdk
-else # no proguard
-TARGET_BUILD_JAVA_SUPPORT_LEVEL :=
-endif
-# platform supprot is set after checking platform.zip
+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_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))
-
-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
+ _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 $@) <- $<"
@@ -81,9 +105,17 @@
$(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,
@@ -101,74 +133,57 @@
$(hide) cp -fpPR $< $@
ifeq (true,$(TARGET_BUILD_PDK_JAVA_PLATFORM))
+ PDK_FUSION_OUT_DIR := $(OUT_DIR)
-PDK_FUSION_OUT_DIR := $(OUT_DIR)
-ifeq (debug,$(TARGET_BUILD_TYPE))
-PDK_FUSION_OUT_DIR := $(DEBUG_OUT_DIR)
-endif
+ 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
-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))
-# 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)))
-
-# pull .jack and .dex files
-$(foreach lib_dir,$(PDK_PLATFORM_JAVA_ZIP_JAVA_TARGET_LIB_DIR),\
- $(eval $(call JAVA_dependency_template,$(lib_dir)/classes.jar.toc,\
- $(lib_dir)/classes.jar $(lib_dir)/classes.jack)))
-$(foreach lib_dir,$(PDK_PLATFORM_JAVA_ZIP_JAVA_TARGET_LIB_DIR),\
- $(eval $(call JAVA_dependency_template,$(lib_dir)/classes.dex.toc,\
- $(lib_dir)/classes.jar $(lib_dir)/classes.jack $(lib_dir)/classes%.dex)))
+ # 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
+endif # TARGET_BUILD_PDK_JAVA_PLATFORM
ALL_PDK_FUSION_FILES := $(addprefix $(PRODUCT_OUT)/, $(_pdk_fusion_file_list))
-endif # PDK_FUSION_PLATFORM_ZIP
+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
-
+ $(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.
+ # files under $(PRODUCT_OUT)/symbols to help debugging.
+ # Source not included to PDK due to dependency issue, so provide symbols instead.
-# We may not be building all of them.
-# The platform.zip just silently ignores the nonexistent ones.
-PDK_SYMBOL_FILES_LIST := \
- system/bin/app_process32 \
- system/bin/app_process64
+ # We may not be building all of them.
+ # The platform.zip just silently ignores the nonexistent ones.
+ PDK_SYMBOL_FILES_LIST := \
+ system/bin/app_process32 \
+ system/bin/app_process64
-ifdef PDK_FUSION_PLATFORM_ZIP
-# 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
-endif # platform.zip build or PDK
+ 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
index 0c03f37..9aabd0f 100644
--- a/core/pdk_fusion_modules.mk
+++ b/core/pdk_fusion_modules.mk
@@ -2,10 +2,16 @@
# 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)
diff --git a/core/prebuilt_internal.mk b/core/prebuilt_internal.mk
index 620c22c..0efda57 100644
--- a/core/prebuilt_internal.mk
+++ b/core/prebuilt_internal.mk
@@ -20,19 +20,19 @@
ifdef LOCAL_PREBUILT_MODULE_FILE
my_prebuilt_src_file := $(LOCAL_PREBUILT_MODULE_FILE)
+else ifdef LOCAL_SRC_FILES_$($(my_prefix)$(LOCAL_2ND_ARCH_VAR_PREFIX)ARCH)
+ my_prebuilt_src_file := $(LOCAL_PATH)/$(LOCAL_SRC_FILES_$($(my_prefix)$(LOCAL_2ND_ARCH_VAR_PREFIX)ARCH))
+ LOCAL_SRC_FILES_$($(my_prefix)$(LOCAL_2ND_ARCH_VAR_PREFIX)ARCH) :=
+else ifdef LOCAL_SRC_FILES_$(my_32_64_bit_suffix)
+ my_prebuilt_src_file := $(LOCAL_PATH)/$(LOCAL_SRC_FILES_$(my_32_64_bit_suffix))
+ LOCAL_SRC_FILES_$(my_32_64_bit_suffix) :=
+else ifdef LOCAL_SRC_FILES
+ my_prebuilt_src_file := $(LOCAL_PATH)/$(LOCAL_SRC_FILES)
+ LOCAL_SRC_FILES :=
+else ifdef LOCAL_REPLACE_PREBUILT_APK_INSTALLED
+ # This is handled specially below
else
- ifdef LOCAL_SRC_FILES_$($(my_prefix)$(LOCAL_2ND_ARCH_VAR_PREFIX)ARCH)
- my_prebuilt_src_file := $(LOCAL_PATH)/$(LOCAL_SRC_FILES_$($(my_prefix)$(LOCAL_2ND_ARCH_VAR_PREFIX)ARCH))
- LOCAL_SRC_FILES_$($(my_prefix)$(LOCAL_2ND_ARCH_VAR_PREFIX)ARCH) :=
- else
- ifdef LOCAL_SRC_FILES_$(my_32_64_bit_suffix)
- my_prebuilt_src_file := $(LOCAL_PATH)/$(LOCAL_SRC_FILES_$(my_32_64_bit_suffix))
- LOCAL_SRC_FILES_$(my_32_64_bit_suffix) :=
- else
- my_prebuilt_src_file := $(LOCAL_PATH)/$(LOCAL_SRC_FILES)
- LOCAL_SRC_FILES :=
- endif
- endif
+ $(call pretty-error,No source files specified)
endif
LOCAL_CHECKED_MODULE := $(my_prebuilt_src_file)
@@ -173,10 +173,21 @@
endif
export_cflags :=
+include $(BUILD_SYSTEM)/allowed_ndk_types.mk
+
ifdef LOCAL_SDK_VERSION
-my_link_type := native:ndk
+my_link_type := native:ndk:$(my_ndk_stl_family):$(my_ndk_stl_link_type)
else ifdef LOCAL_USE_VNDK
-my_link_type := native:vendor
+ _name := $(patsubst %.vendor,%,$(LOCAL_MODULE))
+ ifneq ($(filter $(_name),$(VNDK_CORE_LIBRARIES) $(VNDK_SAMEPROCESS_LIBRARIES) $(LLNDK_LIBRARIES)),)
+ ifeq ($(filter $(_name),$(VNDK_PRIVATE_LIBRARIES)),)
+ my_link_type := native:vndk
+ else
+ my_link_type := native:vndk_private
+ endif
+ else
+ my_link_type := native:vendor
+ endif
else
my_link_type := native:platform
endif
@@ -228,7 +239,7 @@
else
my_coverage_path := $(TARGET_OUT_COVERAGE)/$(patsubst $(PRODUCT_OUT)/%,%,$(my_module_path))
endif
- my_coverage_path := $(my_coverage_path)/$(basename $(my_installed_module_stem)).gcnodir
+ my_coverage_path := $(my_coverage_path)/$(patsubst %.so,%,$(my_installed_module_stem)).gcnodir
$(eval $(call copy-one-file,$(LOCAL_PREBUILT_COVERAGE_ARCHIVE),$(my_coverage_path)))
$(LOCAL_BUILT_MODULE): $(my_coverage_path)
endif
@@ -379,6 +390,9 @@
$(built_module) : $(my_prebuilt_src_file) | $(ZIPALIGN) $(SIGNAPK_JAR)
$(transform-prebuilt-to-target)
$(uncompress-shared-libs)
+ifeq (true, $(LOCAL_UNCOMPRESS_DEX))
+ $(uncompress-dexs)
+endif # LOCAL_UNCOMPRESS_DEX
ifdef LOCAL_DEX_PREOPT
ifneq ($(BUILD_PLATFORM_ZIP),)
@# Keep a copy of apk with classes.dex unstripped
@@ -403,11 +417,19 @@
endif # ! LOCAL_REPLACE_PREBUILT_APK_INSTALLED
###############################
-## Rule to build the odex file
+## Rule to build the odex file.
+# In case we don't strip the built module, use it, as dexpreopt
+# can do optimizations based on whether the built module only
+# contains uncompressed dex code.
ifdef LOCAL_DEX_PREOPT
+ifeq (nostripping,$(LOCAL_DEX_PREOPT))
+$(built_odex) : $(built_module)
+ $(call dexpreopt-one-file,$<,$@)
+else
$(built_odex) : $(my_prebuilt_src_file)
$(call dexpreopt-one-file,$<,$@)
endif
+endif
###############################
## Install split apks.
@@ -470,11 +492,7 @@
@echo "Dexpreopt Jar: $(PRIVATE_MODULE) ($@)"
$(call dexpreopt-one-file,$<,$@)
-$(built_module) : $(my_prebuilt_src_file)
- $(call copy-file-to-target)
-ifneq (nostripping,$(LOCAL_DEX_PREOPT))
- $(call dexpreopt-remove-classes.dex,$@)
-endif
+$(eval $(call dexpreopt-copy-jar,$(my_prebuilt_src_file),$(built_module),$(LOCAL_DEX_PREOPT)))
endif # boot jar
else # ! LOCAL_DEX_PREOPT
$(built_module) : $(my_prebuilt_src_file)
@@ -500,6 +518,7 @@
# for host java libraries deps should be in the common dir, so we make a copy in
# the common dir.
common_classes_jar := $(intermediates.COMMON)/classes.jar
+common_header_jar := $(intermediates.COMMON)/classes-header.jar
$(common_classes_jar): PRIVATE_MODULE := $(LOCAL_MODULE)
$(common_classes_jar): PRIVATE_PREFIX := $(my_prefix)
@@ -507,10 +526,16 @@
$(common_classes_jar) : $(my_src_jar)
$(transform-prebuilt-to-target)
+ifneq ($(TURBINE_ENABLED),false)
+$(common_header_jar) : $(my_src_jar)
+ $(transform-prebuilt-to-target)
+endif
+
else # !LOCAL_IS_HOST_MODULE
# for target java libraries, the LOCAL_BUILT_MODULE is in a product-specific dir,
# while the deps should be in the common dir, so we make a copy in the common dir.
common_classes_jar := $(intermediates.COMMON)/classes.jar
+common_header_jar := $(intermediates.COMMON)/classes-header.jar
common_classes_pre_proguard_jar := $(intermediates.COMMON)/classes-pre-proguard.jar
common_javalib_jar := $(intermediates.COMMON)/javalib.jar
@@ -519,6 +544,10 @@
ifeq ($(LOCAL_SDK_VERSION),system_current)
my_link_type := java:system
+else ifneq (,$(call has-system-sdk-version,$(LOCAL_SDK_VERSION)))
+my_link_type := java:system
+else ifeq ($(LOCAL_SDK_VERSION),core_current)
+my_link_type := java:core
else ifneq ($(LOCAL_SDK_VERSION),)
my_link_type := java:sdk
else
@@ -542,47 +571,70 @@
my_src_aar := $(filter %.aar, $(my_prebuilt_src_file))
ifneq ($(my_src_aar),)
# This is .aar file, archive of classes.jar and Android resources.
-my_src_jar := $(intermediates.COMMON)/aar/classes.jar
+# run Jetifier if needed
+LOCAL_JETIFIER_INPUT_FILE := $(my_src_aar)
+include $(BUILD_SYSTEM)/jetifier.mk
+my_src_aar := $(LOCAL_JETIFIER_OUTPUT_FILE)
+
+my_src_jar := $(intermediates.COMMON)/aar/classes.jar
+my_src_proguard_options := $(intermediates.COMMON)/aar/proguard.txt
+
+$(my_src_jar) : .KATI_IMPLICIT_OUTPUTS := $(my_src_proguard_options)
$(my_src_jar) : $(my_src_aar)
$(hide) rm -rf $(dir $@) && mkdir -p $(dir $@) $(dir $@)/res
$(hide) unzip -qo -d $(dir $@) $<
# Make sure the extracted classes.jar has a new timestamp.
$(hide) touch $@
+ # Make sure the proguard file exists and has a new timestamp.
+ $(hide) touch $(dir $@)/proguard.txt
+else
+
+# run Jetifier if needed
+LOCAL_JETIFIER_INPUT_FILE := $(my_src_jar)
+include $(BUILD_SYSTEM)/jetifier.mk
+my_src_jar := $(LOCAL_JETIFIER_OUTPUT_FILE)
endif
$(common_classes_jar) : $(my_src_jar)
$(transform-prebuilt-to-target)
+ifneq ($(TURBINE_ENABLED),false)
+$(common_header_jar) : $(my_src_jar)
+ $(transform-prebuilt-to-target)
+endif
+
$(common_classes_pre_proguard_jar) : $(my_src_jar)
$(transform-prebuilt-to-target)
$(common_javalib_jar) : $(common_classes_jar)
$(transform-prebuilt-to-target)
-$(call define-jar-to-toc-rule, $(common_classes_jar))
+ifdef LOCAL_AAPT2_ONLY
+LOCAL_USE_AAPT2 := true
+endif
ifdef LOCAL_USE_AAPT2
ifneq ($(my_src_aar),)
+
+$(intermediates.COMMON)/export_proguard_flags : $(my_src_proguard_options)
+ $(transform-prebuilt-to-target)
+
LOCAL_SDK_RES_VERSION:=$(strip $(LOCAL_SDK_RES_VERSION))
ifeq ($(LOCAL_SDK_RES_VERSION),)
LOCAL_SDK_RES_VERSION:=$(LOCAL_SDK_VERSION)
endif
framework_res_package_export :=
-framework_res_package_export_deps :=
# 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))),)
framework_res_package_export := \
$(HISTORICAL_SDK_VERSIONS_ROOT)/$(LOCAL_SDK_RES_VERSION)/android.jar
-framework_res_package_export_deps := $(framework_res_package_export)
else
framework_res_package_export := \
$(call intermediates-dir-for,APPS,framework-res,,COMMON)/package-export.apk
-framework_res_package_export_deps := \
- $(dir $(framework_res_package_export))src/R.stamp
endif
endif
@@ -590,7 +642,7 @@
# We needed only very few PRIVATE variables and aapt2.mk input variables. Reset the unnecessary ones.
$(my_res_package): PRIVATE_AAPT2_CFLAGS :=
-$(my_res_package): PRIVATE_AAPT_FLAGS := --static-lib --no-static-lib-packages
+$(my_res_package): PRIVATE_AAPT_FLAGS := --static-lib --no-static-lib-packages --auto-add-overlay
$(my_res_package): PRIVATE_ANDROID_MANIFEST := $(intermediates.COMMON)/aar/AndroidManifest.xml
$(my_res_package): PRIVATE_AAPT_INCLUDES := $(framework_res_package_export)
$(my_res_package): PRIVATE_SOURCE_INTERMEDIATES_DIR :=
@@ -600,7 +652,7 @@
$(my_res_package): PRIVATE_PRODUCT_AAPT_CONFIG :=
$(my_res_package): PRIVATE_PRODUCT_AAPT_PREF_CONFIG :=
$(my_res_package): PRIVATE_TARGET_AAPT_CHARACTERISTICS :=
-$(my_res_package) : $(framework_res_package_export_deps)
+$(my_res_package) : $(framework_res_package_export)
full_android_manifest :=
my_res_resources :=
@@ -622,25 +674,6 @@
endif # ! prebuilt_module_is_dex_javalib
endif # LOCAL_IS_HOST_MODULE is not set
-ifneq ($(prebuilt_module_is_dex_javalib),true)
-
-ifdef LOCAL_JACK_ENABLED
-# We may be building classes.jack from a host jar for host dalvik Java library.
-$(intermediates.COMMON)/classes.jack : PRIVATE_JACK_FLAGS:=$(LOCAL_JACK_FLAGS)
-$(intermediates.COMMON)/classes.jack : PRIVATE_JACK_MIN_SDK_VERSION := $(if $(strip $(LOCAL_MIN_SDK_VERSION)),$(LOCAL_MIN_SDK_VERSION),1)
-$(intermediates.COMMON)/classes.jack : PRIVATE_JACK_PLUGIN_PATH := $(LOCAL_JACK_PLUGIN_PATH)
-$(intermediates.COMMON)/classes.jack : PRIVATE_JACK_PLUGIN := $(LOCAL_JACK_PLUGIN)
-$(intermediates.COMMON)/classes.jack : $(LOCAL_JACK_PLUGIN_PATH) $(my_src_jar) \
- $(LOCAL_ADDITIONAL_DEPENDENCIES) $(JACK_DEFAULT_ARGS) $(JACK) \
- | setup-jack-server
- $(transform-jar-to-jack)
-
-# Update timestamps of .toc files for prebuilts so dependents will be
-# always rebuilt.
-$(intermediates.COMMON)/classes.dex.toc: $(intermediates.COMMON)/classes.jack
- touch $@
-endif # LOCAL_JACK_ENABLED
-endif # ! prebuilt_module_is_dex_javalib
endif # JAVA_LIBRARIES
$(built_module) : $(LOCAL_ADDITIONAL_DEPENDENCIES)
diff --git a/core/product-graph.mk b/core/product-graph.mk
index 36e9037..576d14d 100644
--- a/core/product-graph.mk
+++ b/core/product-graph.mk
@@ -34,7 +34,7 @@
endef
-this_makefile := build/core/product-graph.mk
+this_makefile := build/make/core/product-graph.mk
products_svg := $(OUT_DIR)/products.svg
products_pdf := $(OUT_DIR)/products.pdf
@@ -77,7 +77,7 @@
$(foreach d,$(PRODUCTS.$(strip $(p)).INHERITS_FROM), echo \"$(d)\" -\> \"$(p)\" >> $@.in;))
$(foreach p,$(PRIVATE_PRODUCTS),$(call emit-product-node-props,$(p),$@.in))
$(hide) echo '}' >> $@.in
- $(hide) ./build/tools/filter-product-graph.py $(PRIVATE_PRODUCTS_FILTER) < $@.in > $@
+ $(hide) build/make/tools/filter-product-graph.py $(PRIVATE_PRODUCTS_FILTER) < $@.in > $@
# Evaluates to the name of the product file
# $(1) product file
@@ -103,6 +103,8 @@
$(hide) echo 'PRODUCT_MANUFACTURER=$$(PRODUCTS.$(strip $(1)).PRODUCT_MANUFACTURER)' >> $$@
$(hide) echo 'PRODUCT_PROPERTY_OVERRIDES=$$(PRODUCTS.$(strip $(1)).PRODUCT_PROPERTY_OVERRIDES)' >> $$@
$(hide) echo 'PRODUCT_DEFAULT_PROPERTY_OVERRIDES=$$(PRODUCTS.$(strip $(1)).PRODUCT_DEFAULT_PROPERTY_OVERRIDES)' >> $$@
+ $(hide) echo 'PRODUCT_SYSTEM_DEFAULT_PROPERTIES=$$(PRODUCTS.$(strip $(1)).PRODUCT_SYSTEM_DEFAULT_PROPERTIES)' >> $$@
+ $(hide) echo 'PRODUCT_PRODUCT_PROPERTIES=$$(PRODUCTS.$(strip $(1)).PRODUCT_PRODUCT_PROPERTIES)' >> $$@
$(hide) echo 'PRODUCT_CHARACTERISTICS=$$(PRODUCTS.$(strip $(1)).PRODUCT_CHARACTERISTICS)' >> $$@
$(hide) echo 'PRODUCT_COPY_FILES=$$(PRODUCTS.$(strip $(1)).PRODUCT_COPY_FILES)' >> $$@
$(hide) echo 'PRODUCT_OTA_PUBLIC_KEYS=$$(PRODUCTS.$(strip $(1)).PRODUCT_OTA_PUBLIC_KEYS)' >> $$@
@@ -120,11 +122,11 @@
$(call product-debug-filename, $(p)): \
$(OUT_DIR)/products/$(strip $(1)).txt \
- build/tools/product_debug.py \
+ build/make/tools/product_debug.py \
$(this_makefile)
@echo Product debug html file: $$@
$(hide) mkdir -p $$(dir $$@)
- $(hide) cat $$< | build/tools/product_debug.py > $$@
+ $(hide) cat $$< | build/make/tools/product_debug.py > $$@
endef
product_debug_files:=
diff --git a/core/product.mk b/core/product.mk
index 4682dac..899b806 100644
--- a/core/product.mk
+++ b/core/product.mk
@@ -88,6 +88,7 @@
PRODUCT_BRAND \
PRODUCT_PROPERTY_OVERRIDES \
PRODUCT_DEFAULT_PROPERTY_OVERRIDES \
+ PRODUCT_PRODUCT_PROPERTIES \
PRODUCT_CHARACTERISTICS \
PRODUCT_COPY_FILES \
PRODUCT_OTA_PUBLIC_KEYS \
@@ -102,6 +103,7 @@
PRODUCT_SDK_ADDON_COPY_MODULES \
PRODUCT_SDK_ADDON_DOC_MODULES \
PRODUCT_SDK_ADDON_SYS_IMG_SOURCE_PROP \
+ PRODUCT_SOONG_NAMESPACES \
PRODUCT_DEFAULT_WIFI_CHANNELS \
PRODUCT_DEFAULT_DEV_CERTIFICATE \
PRODUCT_RESTRICT_VENDOR_FILES \
@@ -112,27 +114,35 @@
PRODUCT_SUPPORTS_VERITY \
PRODUCT_SUPPORTS_VERITY_FEC \
PRODUCT_OEM_PROPERTIES \
+ PRODUCT_SYSTEM_DEFAULT_PROPERTIES \
PRODUCT_SYSTEM_PROPERTY_BLACKLIST \
+ PRODUCT_VENDOR_PROPERTY_BLACKLIST \
PRODUCT_SYSTEM_SERVER_APPS \
PRODUCT_SYSTEM_SERVER_JARS \
PRODUCT_ALWAYS_PREOPT_EXTRACTED_APK \
PRODUCT_DEXPREOPT_SPEED_APPS \
+ PRODUCT_LOADED_BY_PRIVILEGED_MODULES \
PRODUCT_VBOOT_SIGNING_KEY \
PRODUCT_VBOOT_SIGNING_SUBKEY \
PRODUCT_VERITY_SIGNING_KEY \
PRODUCT_SYSTEM_VERITY_PARTITION \
PRODUCT_VENDOR_VERITY_PARTITION \
+ PRODUCT_PRODUCT_VERITY_PARTITION \
PRODUCT_SYSTEM_SERVER_DEBUG_INFO \
+ PRODUCT_OTHER_JAVA_DEBUG_INFO \
PRODUCT_DEX_PREOPT_MODULE_CONFIGS \
+ PRODUCT_DEX_PREOPT_DEFAULT_COMPILER_FILTER \
PRODUCT_DEX_PREOPT_DEFAULT_FLAGS \
PRODUCT_DEX_PREOPT_BOOT_FLAGS \
PRODUCT_DEX_PREOPT_PROFILE_DIR \
PRODUCT_DEX_PREOPT_BOOT_IMAGE_PROFILE_LOCATION \
+ PRODUCT_DEX_PREOPT_GENERATE_DM_FILES \
PRODUCT_USE_PROFILE_FOR_BOOT_IMAGE \
PRODUCT_SYSTEM_SERVER_COMPILER_FILTER \
PRODUCT_SANITIZER_MODULE_CONFIGS \
PRODUCT_SYSTEM_BASE_FS_PATH \
PRODUCT_VENDOR_BASE_FS_PATH \
+ PRODUCT_PRODUCT_BASE_FS_PATH \
PRODUCT_SHIPPING_API_LEVEL \
VENDOR_PRODUCT_RESTRICT_VENDOR_FILES \
VENDOR_EXCEPTION_MODULES \
@@ -143,8 +153,11 @@
PRODUCT_SYSTEM_HEADROOM \
PRODUCT_MINIMIZE_JAVA_DEBUG_INFO \
PRODUCT_INTEGER_OVERFLOW_EXCLUDE_PATHS \
-
-
+ PRODUCT_ADB_KEYS \
+ PRODUCT_CFI_INCLUDE_PATHS \
+ PRODUCT_CFI_EXCLUDE_PATHS \
+ PRODUCT_COMPATIBLE_PROPERTY_OVERRIDE \
+ PRODUCT_ACTIONABLE_COMPATIBLE_PROPERTY_DISABLE \
define dump-product
$(info ==== $(1) ====)\
@@ -298,14 +311,15 @@
BOARD_FLASH_BLOCK_SIZE \
BOARD_VENDORIMAGE_PARTITION_SIZE \
BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE \
+ BOARD_PRODUCTIMAGE_PARTITION_SIZE \
+ BOARD_PRODUCTIMAGE_FILE_SYSTEM_TYPE \
BOARD_INSTALLER_CMDLINE \
_product_stash_var_list += \
DEFAULT_SYSTEM_DEV_CERTIFICATE \
WITH_DEXPREOPT \
- WITH_DEXPREOPT_BOOT_IMG_AND_SYSTEM_SERVER_ONLY \
- WITH_DEXPREOPT_APP_IMAGE
+ WITH_DEXPREOPT_BOOT_IMG_AND_SYSTEM_SERVER_ONLY
#
# Mark the variables in _product_stash_var_list as readonly
diff --git a/core/product_config.mk b/core/product_config.mk
index f7ae834..9406812 100644
--- a/core/product_config.mk
+++ b/core/product_config.mk
@@ -88,7 +88,7 @@
# Provide "PRODUCT-<prodname>-<goal>" targets, which lets you build
# a particular configuration without needing to set up the environment.
#
-ifndef KATI
+ifeq ($(CALLED_FROM_SETUP),true)
product_goals := $(strip $(filter PRODUCT-%,$(MAKECMDGOALS)))
ifdef product_goals
# Scrape the product and build names out of the goal,
@@ -129,14 +129,14 @@
# position, in case it matters.
override MAKECMDGOALS := $(patsubst $(goal_name),$(default_goal_substitution),$(MAKECMDGOALS))
endif
-endif # !KATI
+endif # CALLED_FROM_SETUP
# else: Use the value set in the environment or buildspec.mk.
# ---------------------------------------------------------------
# Provide "APP-<appname>" targets, which lets you build
# an unbundled app.
#
-ifndef KATI
+ifeq ($(CALLED_FROM_SETUP),true)
unbundled_goals := $(strip $(filter APP-%,$(MAKECMDGOALS)))
ifdef unbundled_goals
ifneq ($(words $(unbundled_goals)),1)
@@ -151,6 +151,13 @@
endif # unbundled_goals
endif
+# Now that we've parsed APP-* and PRODUCT-*, mark these as readonly
+TARGET_BUILD_APPS ?=
+.KATI_READONLY := \
+ TARGET_PRODUCT \
+ TARGET_BUILD_VARIANT \
+ TARGET_BUILD_APPS
+
# Default to building dalvikvm on hosts that support it...
ifeq ($(HOST_OS),linux)
# ... or if the if the option is already set
@@ -259,6 +266,7 @@
PRODUCT_SYSTEM_SERVER_JARS := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SYSTEM_SERVER_JARS))
PRODUCT_SYSTEM_SERVER_APPS := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SYSTEM_SERVER_APPS))
PRODUCT_DEXPREOPT_SPEED_APPS := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEXPREOPT_SPEED_APPS))
+PRODUCT_LOADED_BY_PRIVILEGED_MODULES := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_LOADED_BY_PRIVILEGED_MODULES))
# All of the apps that we force preopt, this overrides WITH_DEXPREOPT.
PRODUCT_ALWAYS_PREOPT_EXTRACTED_APK := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_ALWAYS_PREOPT_EXTRACTED_APK))
@@ -295,15 +303,6 @@
PRODUCT_AAPT_CONFIG := \
$(subst $(space),$(comma),$(strip $(PRODUCT_AAPT_CONFIG)))
-# product-scoped aapt flags
-PRODUCT_AAPT_FLAGS :=
-PRODUCT_AAPT2_CFLAGS :=
-ifneq ($(filter en_XA ar_XB,$(PRODUCT_LOCALES)),)
- # Force generating resources for pseudo-locales.
- PRODUCT_AAPT2_CFLAGS += --pseudo-localize
- PRODUCT_AAPT_FLAGS += --pseudo-localize
-endif
-
PRODUCT_BRAND := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_BRAND))
PRODUCT_MODEL := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_MODEL))
@@ -339,7 +338,7 @@
# The file at the source path should be copied to the destination path
# when building this product. <destination path> is relative to
# $(PRODUCT_OUT), so it should look like, e.g., "system/etc/file.xml".
-# The rules for these copy steps are defined in build/core/Makefile.
+# The rules for these copy steps are defined in build/make/core/Makefile.
# The optional :<owner> is used to indicate the owner of a vendor file.
PRODUCT_COPY_FILES := \
$(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_COPY_FILES))
@@ -359,6 +358,20 @@
$(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEFAULT_PROPERTY_OVERRIDES))
.KATI_READONLY := 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 default.prop of system partition
+PRODUCT_SYSTEM_DEFAULT_PROPERTIES := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SYSTEM_DEFAULT_PROPERTIES))
+.KATI_READONLY := PRODUCT_SYSTEM_DEFAULT_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 product partition
+PRODUCT_PRODUCT_PROPERTIES := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PRODUCT_PROPERTIES))
+.KATI_READONLY := PRODUCT_PRODUCT_PROPERTIES
+
# Should we use the default resources or add any product specific overlays
PRODUCT_PACKAGE_OVERLAYS := \
$(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_PACKAGE_OVERLAYS))
@@ -379,8 +392,12 @@
PRODUCT_EXTRA_RECOVERY_KEYS := $(sort \
$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_EXTRA_RECOVERY_KEYS))
+PRODUCT_DEX_PREOPT_DEFAULT_COMPILER_FILTER := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEX_PREOPT_DEFAULT_COMPILER_FILTER))
PRODUCT_DEX_PREOPT_DEFAULT_FLAGS := \
$(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEX_PREOPT_DEFAULT_FLAGS))
+PRODUCT_DEX_PREOPT_GENERATE_DM_FILES := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEX_PREOPT_GENERATE_DM_FILES))
PRODUCT_DEX_PREOPT_BOOT_FLAGS := \
$(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEX_PREOPT_BOOT_FLAGS))
PRODUCT_DEX_PREOPT_PROFILE_DIR := \
@@ -396,6 +413,8 @@
$(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SYSTEM_SERVER_COMPILER_FILTER))
PRODUCT_SYSTEM_SERVER_DEBUG_INFO := \
$(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SYSTEM_SERVER_DEBUG_INFO))
+PRODUCT_OTHER_JAVA_DEBUG_INFO := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_OTHER_JAVA_DEBUG_INFO))
# Resolve and setup per-module dex-preopt configs.
PRODUCT_DEX_PREOPT_MODULE_CONFIGS := \
@@ -456,3 +475,33 @@
# Whether any paths are excluded from sanitization when SANITIZE_TARGET=integer_overflow
PRODUCT_INTEGER_OVERFLOW_EXCLUDE_PATHS := \
$(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_INTEGER_OVERFLOW_EXCLUDE_PATHS))
+
+# ADB keys for debuggable builds
+PRODUCT_ADB_KEYS :=
+ifneq ($(filter eng userdebug,$(TARGET_BUILD_VARIANT)),)
+ PRODUCT_ADB_KEYS := $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_ADB_KEYS))
+endif
+ifneq ($(filter-out 0 1,$(words $(PRODUCT_ADB_KEYS))),)
+ $(error Only one file may be in PRODUCT_ADB_KEYS: $(PRODUCT_ADB_KEYS))
+endif
+.KATI_READONLY := PRODUCT_ADB_KEYS
+
+# Whether any paths are excluded from sanitization when SANITIZE_TARGET=cfi
+PRODUCT_CFI_EXCLUDE_PATHS := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_CFI_EXCLUDE_PATHS))
+
+# Whether any paths should have CFI enabled for components
+PRODUCT_CFI_INCLUDE_PATHS := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_CFI_INCLUDE_PATHS))
+
+# which Soong namespaces to export to Make
+PRODUCT_SOONG_NAMESPACES := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SOONG_NAMESPACES))
+
+# A flag to override PRODUCT_COMPATIBLE_PROPERTY
+PRODUCT_COMPATIBLE_PROPERTY_OVERRIDE := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_COMPATIBLE_PROPERTY_OVERRIDE))
+
+# Whether the whitelist of actionable compatible properties should be disabled or not
+PRODUCT_ACTIONABLE_COMPATIBLE_PROPERTY_DISABLE := \
+ $(strip $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_ACTIONABLE_COMPATIBLE_PROPERTY_DISABLE))
diff --git a/core/proguard.emma.flags b/core/proguard.emma.flags
deleted file mode 100644
index bf94086..0000000
--- a/core/proguard.emma.flags
+++ /dev/null
@@ -1,4 +0,0 @@
-# Keep everything for the emma classes
--keep class com.vladium.** {
- *;
-}
diff --git a/core/proguard_tests.flags b/core/proguard_tests.flags
deleted file mode 100644
index 1f840bc..0000000
--- a/core/proguard_tests.flags
+++ /dev/null
@@ -1,26 +0,0 @@
-# Keep everything for tests
-# This flag has been moved to the makefiles and is set for tests by default.
-#-dontshrink
-
-# But we may want to obfuscate if the main app gets obfuscated.
-# This flag has been moved to the makefiles.
-#-dontobfuscate
-
-#-keep class * extends junit.framework.TestCase {
-# public void test*();
-#}
-
-#-keepclasseswithmembers class * {
-# public static void run();
-# public static junit.framework.Test suite();
-#}
-
-# some AllTests don't include run().
-#-keepclasseswithmembers class * {
-# public static junit.framework.Test suite();
-#}
-
-#-keep class * extends junit.framework.TestSuite
-#-keep class * extends android.app.Instrumentation
-#-keep class * extends android.test.TestSuiteProvider
-
diff --git a/target/board/generic_armv5/BoardConfig.mk b/core/project_definitions.mk
similarity index 70%
copy from target/board/generic_armv5/BoardConfig.mk
copy to core/project_definitions.mk
index 016937a..5728b67 100644
--- a/target/board/generic_armv5/BoardConfig.mk
+++ b/core/project_definitions.mk
@@ -1,5 +1,5 @@
#
-# Copyright (C) 2011 The Android Open Source Project
+# 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.
@@ -14,10 +14,11 @@
# limitations under the License.
#
-include build/target/board/generic/BoardConfig.mk
+#
+# Allow projects to define their own globally-available variables.
+#
-TARGET_ARCH_VARIANT := armv5te
-TARGET_CPU_ABI := armeabi
-TARGET_CPU_ABI2 :=
-
-WITH_DEXPREOPT := false
+#
+# Include definitions for prebuilt SDK, if present.
+#
+-include prebuilts/sdk/current/definitions.mk
diff --git a/core/root.mk b/core/root.mk
index 6c8f795..1ef9aca 100644
--- a/core/root.mk
+++ b/core/root.mk
@@ -1,3 +1,3 @@
### DO NOT EDIT THIS FILE ###
-include build/core/main.mk
+include build/make/core/main.mk
### DO NOT EDIT THIS FILE ###
diff --git a/core/sdk_check.mk b/core/sdk_check.mk
new file mode 100644
index 0000000..c09fc7c
--- /dev/null
+++ b/core/sdk_check.mk
@@ -0,0 +1,37 @@
+
+# Enforcement checks that LOCAL_SDK_VERSION and LOCAL_PRIVATE_PLATFORM_APIS are
+# set correctly.
+# Should be included by java targets that allow specifying LOCAL_SDK_VERSION.
+# The JAVA_SDK_ENFORCEMENT_WARNING and JAVA_SDK_ENFORCEMENT_ERROR variables may
+# be set to a particular module class to enable warnings and errors for that
+# subtype.
+
+whitelisted_modules := framework-res__auto_generated_rro
+
+
+ifeq (,$(JAVA_SDK_ENFORCEMENT_ERROR))
+ JAVA_SDK_ENFORCEMENT_ERROR := APPS
+endif
+
+ifeq ($(LOCAL_SDK_VERSION)$(LOCAL_PRIVATE_PLATFORM_APIS),)
+ ifeq (,$(filter $(LOCAL_MODULE),$(whitelisted_modules)))
+ ifneq ($(JAVA_SDK_ENFORCEMENT_WARNING)$(JAVA_SDK_ENFORCEMENT_ERROR),)
+ my_message := Must specify LOCAL_SDK_VERSION or LOCAL_PRIVATE_PLATFORM_APIS,
+ ifeq ($(LOCAL_MODULE_CLASS),$(JAVA_SDK_ENFORCEMENT_ERROR))
+ $(call pretty-error,$(my_message))
+ endif
+ ifeq ($(LOCAL_MODULE_CLASS),$(JAVA_SDK_ENFORCEMENT_WARNING))
+ $(call pretty-warning,$(my_message))
+ endif
+ my_message :=
+ endif
+ endif
+else ifneq ($(LOCAL_SDK_VERSION),)
+ ifneq ($(LOCAL_PRIVATE_PLATFORM_APIS),)
+ my_message := Specifies both LOCAL_SDK_VERSION ($(LOCAL_SDK_VERSION)) and
+ my_message += LOCAL_PRIVATE_PLATFORM_APIS ($(LOCAL_PRIVATE_PLATFORM_APIS))
+ my_message += but should specify only one
+ $(call pretty-error,$(my_message))
+ my_message :=
+ endif
+endif
diff --git a/core/setup_one_odex.mk b/core/setup_one_odex.mk
index f0ffe81..51df43e 100644
--- a/core/setup_one_odex.mk
+++ b/core/setup_one_odex.mk
@@ -25,9 +25,85 @@
my_dex_preopt_image_location := $($(my_2nd_arch_prefix)DEFAULT_DEX_PREOPT_BUILT_IMAGE_LOCATION)
endif
my_dex_preopt_image_filename := $(call get-image-file-path,$($(my_2nd_arch_prefix)DEX2OAT_TARGET_ARCH),$(my_dex_preopt_image_location))
+
+# If LOCAL_ENFORCE_USES_LIBRARIES is not set, default to true if either of LOCAL_USES_LIBRARIES or
+# LOCAL_OPTIONAL_USES_LIBRARIES are specified.
+ifeq (,$(LOCAL_ENFORCE_USES_LIBRARIES))
+# Will change the default to true unconditionally in the future.
+ifneq (,$(LOCAL_OPTIONAL_USES_LIBRARIES))
+LOCAL_ENFORCE_USES_LIBRARIES := true
+endif
+ifneq (,$(LOCAL_USES_LIBRARIES))
+LOCAL_ENFORCE_USES_LIBRARIES := true
+endif
+endif
+
+my_uses_libraries := $(LOCAL_USES_LIBRARIES)
+my_optional_uses_libraries := $(LOCAL_OPTIONAL_USES_LIBRARIES)
+my_missing_uses_libraries := $(INTERNAL_PLATFORM_MISSING_USES_LIBRARIES)
+
+# If we have either optional or required uses-libraries, set up the class loader context
+# accordingly.
+my_lib_names :=
+my_optional_lib_names :=
+my_filtered_optional_uses_libraries :=
+my_system_dependencies :=
+my_stored_preopt_class_loader_context_libs :=
+my_conditional_uses_libraries_host :=
+my_conditional_uses_libraries_target :=
+
+ifneq (true,$(LOCAL_ENFORCE_USES_LIBRARIES))
+ # Pass special class loader context to skip the classpath and collision check.
+ # This will get removed once LOCAL_USES_LIBRARIES is enforced.
+ # Right now LOCAL_USES_LIBRARIES is opt in, for the case where it's not specified we still default
+ # to the &.
+ my_dex_preopt_class_loader_context := \&
+else
+ # Compute the filtered optional uses libraries by removing ones that are not supposed to exist.
+ my_filtered_optional_uses_libraries := \
+ $(filter-out $(my_missing_uses_libraries), $(my_optional_uses_libraries))
+ my_filtered_uses_libraries := $(my_uses_libraries) $(my_filtered_optional_uses_libraries)
+
+ # These are the ones we are verifying in the make rule, use the unfiltered libraries.
+ my_lib_names := $(my_uses_libraries)
+ my_optional_lib_names := $(my_optional_uses_libraries)
+
+ # Calculate system build dependencies based on the filtered libraries.
+ my_intermediate_libs := $(foreach lib_name, $(my_lib_names) $(my_filtered_optional_uses_libraries), \
+ $(call intermediates-dir-for,JAVA_LIBRARIES,$(lib_name),,COMMON)/javalib.jar)
+ my_dex_preopt_system_dependencies := $(my_intermediate_libs)
+ my_dex_preopt_class_loader_context := $(call normalize-path-list,$(my_intermediate_libs))
+
+ # The class loader context checksums are filled in by dex2oat.
+ my_stored_preopt_class_loader_context_libs := $(call normalize-path-list, \
+ $(foreach lib_name,$(my_filtered_uses_libraries),/system/framework/$(lib_name).jar))
+
+ # Fix up org.apache.http.legacy.boot since it should be org.apache.http.legacy in the manifest.
+ my_lib_names := $(patsubst org.apache.http.legacy.boot,org.apache.http.legacy,$(my_lib_names))
+ my_optional_lib_names := $(patsubst org.apache.http.legacy.boot,org.apache.http.legacy,$(my_optional_lib_names))
+ ifeq (,$(filter org.apache.http.legacy,$(my_lib_names) $(my_optional_lib_names)))
+ my_conditional_uses_libraries_host := $(call intermediates-dir-for,JAVA_LIBRARIES,org.apache.http.legacy.boot,,COMMON)/javalib.jar
+ my_conditional_uses_libraries_target := /system/framework/org.apache.http.legacy.boot.jar
+ endif
+endif
+
+# Always depend on org.apache.http.legacy.boot since it may get used by dex2oat-one-file for apps
+# targetting <SDK 28(P).
+my_always_depend_libraries := $(call intermediates-dir-for,JAVA_LIBRARIES,org.apache.http.legacy.boot,,COMMON)/javalib.jar
+
+$(my_built_odex): $(AAPT)
+$(my_built_odex): $(my_always_depend_libraries)
+$(my_built_odex): $(my_dex_preopt_system_dependencies)
+$(my_built_odex): PRIVATE_ENFORCE_USES_LIBRARIES := $(LOCAL_ENFORCE_USES_LIBRARIES)
+$(my_built_odex): PRIVATE_CONDITIONAL_USES_LIBRARIES_HOST := $(my_conditional_uses_libraries_host)
+$(my_built_odex): PRIVATE_CONDITIONAL_USES_LIBRARIES_TARGET := $(my_conditional_uses_libraries_target)
+$(my_built_odex): PRIVATE_USES_LIBRARY_NAMES := $(my_lib_names)
+$(my_built_odex): PRIVATE_OPTIONAL_USES_LIBRARY_NAMES := $(my_optional_lib_names)
$(my_built_odex): PRIVATE_2ND_ARCH_VAR_PREFIX := $(my_2nd_arch_prefix)
$(my_built_odex): PRIVATE_DEX_LOCATION := $(patsubst $(PRODUCT_OUT)%,%,$(LOCAL_INSTALLED_MODULE))
$(my_built_odex): PRIVATE_DEX_PREOPT_IMAGE_LOCATION := $(my_dex_preopt_image_location)
+$(my_built_odex): PRIVATE_DEX2OAT_CLASS_LOADER_CONTEXT := $(my_dex_preopt_class_loader_context)
+$(my_built_odex): PRIVATE_DEX2OAT_STORED_CLASS_LOADER_CONTEXT_LIBS := $(my_stored_preopt_class_loader_context_libs)
$(my_built_odex) : $($(my_2nd_arch_prefix)DEXPREOPT_ONE_FILE_DEPENDENCY_BUILT_BOOT_PREOPT) \
$(DEXPREOPT_ONE_FILE_DEPENDENCY_TOOLS) \
$(my_dex_preopt_image_filename)
diff --git a/core/shared_library_internal.mk b/core/shared_library_internal.mk
index 687536b..ab887e0 100644
--- a/core/shared_library_internal.mk
+++ b/core/shared_library_internal.mk
@@ -20,7 +20,9 @@
$(error $(LOCAL_PATH): Cannot set module stem for a library)
endif
+ifdef target-shared-library-hook
$(call target-shared-library-hook)
+endif
skip_build_from_source :=
ifdef LOCAL_PREBUILT_MODULE_FILE
diff --git a/core/soong_app_prebuilt.mk b/core/soong_app_prebuilt.mk
new file mode 100644
index 0000000..ae0d196
--- /dev/null
+++ b/core/soong_app_prebuilt.mk
@@ -0,0 +1,104 @@
+# App prebuilt coming from Soong.
+# Extra inputs:
+# LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE
+
+ifneq ($(LOCAL_MODULE_MAKEFILE),$(SOONG_ANDROID_MK))
+ $(call pretty-error,soong_app_prebuilt.mk may only be used from Soong)
+endif
+
+LOCAL_MODULE_SUFFIX := .apk
+LOCAL_BUILT_MODULE_STEM := package.apk
+
+#######################################
+include $(BUILD_SYSTEM)/base_rules.mk
+#######################################
+
+full_classes_jar := $(intermediates.COMMON)/classes.jar
+full_classes_pre_proguard_jar := $(intermediates.COMMON)/classes-pre-proguard.jar
+full_classes_header_jar := $(intermediates.COMMON)/classes-header.jar
+
+$(eval $(call copy-one-file,$(LOCAL_SOONG_CLASSES_JAR),$(full_classes_jar)))
+$(eval $(call copy-one-file,$(LOCAL_SOONG_CLASSES_JAR),$(full_classes_pre_proguard_jar)))
+
+ifdef LOCAL_SOONG_JACOCO_REPORT_CLASSES_JAR
+ $(eval $(call copy-one-file,$(LOCAL_SOONG_JACOCO_REPORT_CLASSES_JAR),\
+ $(intermediates.COMMON)/jacoco-report-classes.jar))
+ $(call add-dependency,$(LOCAL_BUILT_MODULE),\
+ $(intermediates.COMMON)/jacoco-report-classes.jar)
+endif
+
+ifdef LOCAL_SOONG_PROGUARD_DICT
+ $(eval $(call copy-one-file,$(LOCAL_SOONG_PROGUARD_DICT),\
+ $(intermediates.COMMON)/proguard_dictionary))
+ $(call add-dependency,$(LOCAL_BUILT_MODULE),\
+ $(intermediates.COMMON)/proguard_dictionary)
+endif
+
+ifneq ($(TURBINE_ENABLED),false)
+ifdef LOCAL_SOONG_HEADER_JAR
+$(eval $(call copy-one-file,$(LOCAL_SOONG_HEADER_JAR),$(full_classes_header_jar)))
+else
+$(eval $(call copy-one-file,$(full_classes_jar),$(full_classes_header_jar)))
+endif
+endif # TURBINE_ENABLED != false
+
+
+$(eval $(call copy-one-file,$(LOCAL_PREBUILT_MODULE_FILE),$(LOCAL_BUILT_MODULE)))
+
+ifdef LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE
+resource_export_package := $(intermediates.COMMON)/package-export.apk
+resource_export_stamp := $(intermediates.COMMON)/src/R.stamp
+
+$(resource_export_package): PRIVATE_STAMP := $(resource_export_stamp)
+$(resource_export_package): .KATI_IMPLICIT_OUTPUTS := $(resource_export_stamp)
+$(resource_export_package): $(LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE)
+ @echo "Copy: $$@"
+ $(copy-file-to-target)
+ touch $(PRIVATE_STAMP)
+$(call add-dependency,$(LOCAL_BUILT_MODULE),$(resource_export_package))
+
+endif # LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE
+
+java-dex: $(LOCAL_SOONG_DEX_JAR)
+
+ifdef LOCAL_DEX_PREOPT
+# defines built_odex along with rule to install odex
+include $(BUILD_SYSTEM)/dex_preopt_odex_install.mk
+
+$(built_odex): $(LOCAL_SOONG_DEX_JAR)
+ $(call dexpreopt-one-file,$<,$@)
+endif
+
+PACKAGES := $(PACKAGES) $(LOCAL_MODULE)
+ifdef LOCAL_CERTIFICATE
+ PACKAGES.$(LOCAL_MODULE).CERTIFICATE := $(LOCAL_CERTIFICATE)
+ PACKAGES.$(LOCAL_MODULE).PRIVATE_KEY := $(patsubst %.x509.pem,%.pk8,$(LOCAL_CERTIFICATE))
+endif
+
+ifndef LOCAL_IS_HOST_MODULE
+ifeq ($(LOCAL_SDK_VERSION),system_current)
+my_link_type := java:system
+else ifneq ($(LOCAL_SDK_VERSION),)
+my_link_type := java:sdk
+else
+my_link_type := java:platform
+endif
+# warn/allowed types are both empty because Soong modules can't depend on
+# make-defined modules.
+my_warn_types :=
+my_allowed_types :=
+
+my_link_deps :=
+my_2nd_arch_prefix := $(LOCAL_2ND_ARCH_VAR_PREFIX)
+my_common := COMMON
+include $(BUILD_SYSTEM)/link_type.mk
+endif # !LOCAL_IS_HOST_MODULE
+
+ifdef LOCAL_SOONG_RRO_DIRS
+ $(call append_enforce_rro_sources, \
+ $(my_register_name), \
+ false, \
+ $(LOCAL_FULL_MANIFEST_FILE), \
+ $(LOCAL_EXPORT_PACKAGE_RESOURCES), \
+ $(LOCAL_SOONG_RRO_DIRS))
+endif
diff --git a/core/soong_config.mk b/core/soong_config.mk
index cdd2896..f8cb2fb 100644
--- a/core/soong_config.mk
+++ b/core/soong_config.mk
@@ -13,6 +13,7 @@
endif
endif
+ifeq ($(WRITE_SOONG_VARIABLES),true)
# Converts a list to a JSON list.
# $1: List separator.
# $2: List.
@@ -24,75 +25,151 @@
# Converts a comma-separated list to a JSON list.
csv_to_json_list = $(call _json_list,$(comma),$(1))
+# 1: Key name
+# 2: Value
+add_json_val = $(eval _contents := $$(_contents) "$$(strip $$(1))":$$(space)$$(strip $$(2))$$(comma)$$(newline))
+add_json_str = $(call add_json_val,$(1),"$(strip $(2))")
+add_json_list = $(call add_json_val,$(1),$(call json_list,$(patsubst %,%,$(2))))
+add_json_csv = $(call add_json_val,$(1),$(call csv_to_json_list,$(strip $(2))))
+add_json_bool = $(call add_json_val,$(1),$(if $(strip $(2)),true,false))
+
+invert_bool = $(if $(strip $(1)),,true)
+
# Create soong.variables with copies of makefile settings. Runs every build,
# but only updates soong.variables if it changes
-SOONG_VARIABLES_TMP := $(SOONG_VARIABLES).$$$$
-$(SOONG_VARIABLES): FORCE
- $(hide) mkdir -p $(dir $@)
- $(hide) (\
- echo '{'; \
- echo ' "Make_suffix": "-$(TARGET_PRODUCT)",'; \
- echo ''; \
- echo ' "Platform_sdk_version": $(PLATFORM_SDK_VERSION),'; \
- echo ' "Platform_version_all_codenames": $(call csv_to_json_list,$(PLATFORM_VERSION_ALL_CODENAMES)),'; \
- echo ' "Unbundled_build": $(if $(TARGET_BUILD_APPS),true,false),'; \
- echo ' "Brillo": $(if $(BRILLO),true,false),'; \
- echo ' "Malloc_not_svelte": $(if $(filter true,$(MALLOC_SVELTE)),false,true),'; \
- echo ' "Allow_missing_dependencies": $(if $(ALLOW_MISSING_DEPENDENCIES),true,false),'; \
- echo ' "SanitizeHost": $(call json_list,$(SANITIZE_HOST)),'; \
- echo ' "SanitizeDevice": $(call json_list,$(SANITIZE_TARGET)),'; \
- echo ' "SanitizeDeviceDiag": $(call json_list,$(SANITIZE_TARGET_DIAG)),'; \
- echo ' "SanitizeDeviceArch": $(call json_list,$(SANITIZE_TARGET_ARCH)),'; \
- echo ' "HostStaticBinaries": $(if $(strip $(BUILD_HOST_static)),true,false),'; \
- echo ' "Binder32bit": $(if $(BINDER32BIT),true,false),'; \
- echo ' "DevicePrefer32BitExecutables": $(if $(filter true,$(TARGET_PREFER_32_BIT_EXECUTABLES)),true,false),'; \
- echo ' "UseGoma": $(if $(filter-out false,$(USE_GOMA)),true,false),'; \
- echo ' "Debuggable": $(if $(filter userdebug eng,$(TARGET_BUILD_VARIANT)),true,false),'; \
- echo ' "Eng": $(if $(filter eng,$(TARGET_BUILD_VARIANT)),true,false),'; \
- echo ' "VendorPath": "$(TARGET_COPY_OUT_VENDOR)",'; \
- echo ''; \
- echo ' "ClangTidy": $(if $(filter 1 true,$(WITH_TIDY)),true,false),'; \
- echo ' "TidyChecks": "$(WITH_TIDY_CHECKS)",'; \
- echo ''; \
- echo ' "NativeCoverage": $(if $(filter true,$(NATIVE_COVERAGE)),true,false),'; \
- echo ' "CoveragePaths": $(call csv_to_json_list,$(COVERAGE_PATHS)),'; \
- echo ' "CoverageExcludePaths": $(call csv_to_json_list,$(COVERAGE_EXCLUDE_PATHS)),'; \
- echo ''; \
- echo ' "DeviceName": "$(TARGET_DEVICE)",'; \
- echo ' "DeviceArch": "$(TARGET_ARCH)",'; \
- echo ' "DeviceArchVariant": "$(TARGET_ARCH_VARIANT)",'; \
- echo ' "DeviceCpuVariant": "$(TARGET_CPU_VARIANT)",'; \
- echo ' "DeviceAbi": ["$(TARGET_CPU_ABI)", "$(TARGET_CPU_ABI2)"],'; \
- echo ' "DeviceUsesClang": $(if $(USE_CLANG_PLATFORM_BUILD),$(USE_CLANG_PLATFORM_BUILD),false),'; \
- echo ' "DeviceVndkVersion": "$(BOARD_VNDK_VERSION)",'; \
- echo ''; \
- echo ' "DeviceSecondaryArch": "$(TARGET_2ND_ARCH)",'; \
- echo ' "DeviceSecondaryArchVariant": "$(TARGET_2ND_ARCH_VARIANT)",'; \
- echo ' "DeviceSecondaryCpuVariant": "$(TARGET_2ND_CPU_VARIANT)",'; \
- echo ' "DeviceSecondaryAbi": ["$(TARGET_2ND_CPU_ABI)", "$(TARGET_2ND_CPU_ABI2)"],'; \
- echo ''; \
- echo ' "HostArch": "$(HOST_ARCH)",'; \
- echo ' "HostSecondaryArch": "$(HOST_2ND_ARCH)",'; \
- echo ''; \
- echo ' "CrossHost": "$(HOST_CROSS_OS)",'; \
- echo ' "CrossHostArch": "$(HOST_CROSS_ARCH)",'; \
- echo ' "CrossHostSecondaryArch": "$(HOST_CROSS_2ND_ARCH)",'; \
- echo ' "Safestack": $(if $(filter true,$(USE_SAFESTACK)),true,false),'; \
- echo ' "EnableCFI": $(if $(filter false,$(ENABLE_CFI)),false,true),'; \
- echo ' "IntegerOverflowExcludePaths": $(call json_list,$(INTEGER_OVERFLOW_EXCLUDE_PATHS) $(PRODUCT_INTEGER_OVERFLOW_EXCLUDE_PATHS)),'; \
- echo ' "Device_uses_hwc2": $(if $(filter true,$(TARGET_USES_HWC2)),true,false),'; \
- echo ' "Override_rs_driver": "$(OVERRIDE_RS_DRIVER)",'; \
- echo ' "Treble": $(if $(filter true,$(PRODUCT_FULL_TREBLE)),true,false),'; \
- echo ' "Pdk": $(if $(filter true,$(TARGET_BUILD_PDK)),true,false),'; \
- echo ''; \
- echo ' "ArtUseReadBarrier": $(if $(filter false,$(PRODUCT_ART_USE_READ_BARRIER)),false,true),'; \
- echo ''; \
- echo ' "BtConfigIncludeDir": "$(BOARD_BLUETOOTH_BDROID_BUILDCFG_INCLUDE_DIR)",'; \
- echo ''; \
- echo ' "DeviceKernelHeaders": $(call json_list,$(strip $(TARGET_PROJECT_SYSTEM_INCLUDES)))'; \
- echo '}') > $(SOONG_VARIABLES_TMP); \
- if ! cmp -s $(SOONG_VARIABLES_TMP) $(SOONG_VARIABLES); then \
- mv $(SOONG_VARIABLES_TMP) $(SOONG_VARIABLES); \
+$(shell mkdir -p $(dir $(SOONG_VARIABLES)))
+_contents := {$(newline)
+
+$(call add_json_str, Make_suffix, -$(TARGET_PRODUCT))
+
+$(call add_json_str, BuildId, $(BUILD_ID))
+$(call add_json_str, BuildNumberFromFile, $$$(BUILD_NUMBER_FROM_FILE))
+
+$(call add_json_str, Platform_version_name, $(PLATFORM_VERSION))
+$(call add_json_val, Platform_sdk_version, $(PLATFORM_SDK_VERSION))
+$(call add_json_str, Platform_sdk_codename, $(PLATFORM_VERSION_CODENAME))
+$(call add_json_bool, Platform_sdk_final, $(filter REL,$(PLATFORM_VERSION_CODENAME)))
+$(call add_json_csv, Platform_version_active_codenames, $(PLATFORM_VERSION_ALL_CODENAMES))
+$(call add_json_csv, Platform_version_future_codenames, $(PLATFORM_VERSION_FUTURE_CODENAMES))
+
+$(call add_json_bool, Allow_missing_dependencies, $(ALLOW_MISSING_DEPENDENCIES))
+$(call add_json_bool, Unbundled_build, $(TARGET_BUILD_APPS))
+$(call add_json_bool, Pdk, $(filter true,$(TARGET_BUILD_PDK)))
+
+$(call add_json_bool, Debuggable, $(filter userdebug eng,$(TARGET_BUILD_VARIANT)))
+$(call add_json_bool, Eng, $(filter eng,$(TARGET_BUILD_VARIANT)))
+
+$(call add_json_str, DeviceName, $(TARGET_DEVICE))
+$(call add_json_str, DeviceArch, $(TARGET_ARCH))
+$(call add_json_str, DeviceArchVariant, $(TARGET_ARCH_VARIANT))
+$(call add_json_str, DeviceCpuVariant, $(TARGET_CPU_VARIANT))
+$(call add_json_list, DeviceAbi, $(TARGET_CPU_ABI) $(TARGET_CPU_ABI2))
+
+$(call add_json_str, DeviceSecondaryArch, $(TARGET_2ND_ARCH))
+$(call add_json_str, DeviceSecondaryArchVariant, $(TARGET_2ND_ARCH_VARIANT))
+$(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_str, HostArch, $(HOST_ARCH))
+$(call add_json_str, HostSecondaryArch, $(HOST_2ND_ARCH))
+$(call add_json_bool, HostStaticBinaries, $(BUILD_HOST_static))
+
+$(call add_json_str, CrossHost, $(HOST_CROSS_OS))
+$(call add_json_str, CrossHostArch, $(HOST_CROSS_ARCH))
+$(call add_json_str, CrossHostSecondaryArch, $(HOST_CROSS_2ND_ARCH))
+
+$(call add_json_list, ResourceOverlays, $(PRODUCT_PACKAGE_OVERLAYS) $(DEVICE_PACKAGE_OVERLAYS))
+$(call add_json_list, EnforceRROTargets, $(PRODUCT_ENFORCE_RRO_TARGETS))
+$(call add_json_list, EnforceRROExcludedOverlays, $(PRODUCT_ENFORCE_RRO_EXCLUDED_OVERLAYS))
+
+$(call add_json_str, AAPTCharacteristics, $(TARGET_AAPT_CHARACTERISTICS))
+$(call add_json_list, AAPTConfig, $(PRODUCT_AAPT_CONFIG))
+$(call add_json_str, AAPTPreferredConfig, $(PRODUCT_AAPT_PREF_CONFIG))
+$(call add_json_list, AAPTPrebuiltDPI, $(PRODUCT_AAPT_PREBUILT_DPI))
+
+$(call add_json_str, DefaultAppCertificate, $(PRODUCT_DEFAULT_DEV_CERTIFICATE))
+
+$(call add_json_str, AppsDefaultVersionName, $(APPS_DEFAULT_VERSION_NAME))
+
+$(call add_json_list, SanitizeHost, $(SANITIZE_HOST))
+$(call add_json_list, SanitizeDevice, $(SANITIZE_TARGET))
+$(call add_json_list, SanitizeDeviceDiag, $(SANITIZE_TARGET_DIAG))
+$(call add_json_list, SanitizeDeviceArch, $(SANITIZE_TARGET_ARCH))
+
+$(call add_json_bool, Safestack, $(filter true,$(USE_SAFESTACK)))
+$(call add_json_bool, EnableCFI, $(call invert_bool,$(filter false,$(ENABLE_CFI))))
+$(call add_json_list, CFIExcludePaths, $(CFI_EXCLUDE_PATHS) $(PRODUCT_CFI_EXCLUDE_PATHS))
+$(call add_json_list, CFIIncludePaths, $(CFI_INCLUDE_PATHS) $(PRODUCT_CFI_INCLUDE_PATHS))
+$(call add_json_list, IntegerOverflowExcludePaths, $(INTEGER_OVERFLOW_EXCLUDE_PATHS) $(PRODUCT_INTEGER_OVERFLOW_EXCLUDE_PATHS))
+
+$(call add_json_bool, ClangTidy, $(filter 1 true,$(WITH_TIDY)))
+$(call add_json_str, TidyChecks, $(WITH_TIDY_CHECKS))
+
+$(call add_json_bool, NativeCoverage, $(filter true,$(NATIVE_COVERAGE)))
+$(call add_json_list, CoveragePaths, $(COVERAGE_PATHS))
+$(call add_json_list, CoverageExcludePaths, $(COVERAGE_EXCLUDE_PATHS))
+
+$(call add_json_bool, ArtUseReadBarrier, $(call invert_bool,$(filter false,$(PRODUCT_ART_USE_READ_BARRIER))))
+$(call add_json_bool, Binder32bit, $(BINDER32BIT))
+$(call add_json_bool, Brillo, $(BRILLO))
+$(call add_json_str, BtConfigIncludeDir, $(BOARD_BLUETOOTH_BDROID_BUILDCFG_INCLUDE_DIR))
+$(call add_json_bool, Device_uses_hwc2, $(filter true,$(TARGET_USES_HWC2)))
+$(call add_json_list, DeviceKernelHeaders, $(TARGET_PROJECT_SYSTEM_INCLUDES))
+$(call add_json_bool, DevicePrefer32BitExecutables, $(filter true,$(TARGET_PREFER_32_BIT_EXECUTABLES)))
+$(call add_json_str, DeviceVndkVersion, $(BOARD_VNDK_VERSION))
+$(call add_json_str, Platform_vndk_version, $(PLATFORM_VNDK_VERSION))
+$(call add_json_list, ExtraVndkVersions, $(PRODUCT_EXTRA_VNDK_VERSIONS))
+$(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_str, Override_rs_driver, $(OVERRIDE_RS_DRIVER))
+
+$(call add_json_bool, Treble_linker_namespaces, $(filter true,$(PRODUCT_TREBLE_LINKER_NAMESPACES)))
+$(call add_json_bool, Enforce_vintf_manifest, $(filter true,$(PRODUCT_ENFORCE_VINTF_MANIFEST)))
+
+$(call add_json_bool, Uml, $(filter true,$(TARGET_USER_MODE_LINUX)))
+$(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, ProductPath, $(TARGET_COPY_OUT_PRODUCT))
+$(call add_json_bool, MinimizeJavaDebugInfo, $(filter true,$(PRODUCT_MINIMIZE_JAVA_DEBUG_INFO)))
+
+$(call add_json_bool, UseGoma, $(filter-out false,$(USE_GOMA)))
+$(call add_json_bool, Arc, $(filter true,$(TARGET_ARC)))
+
+$(call add_json_str, DistDir, $(if $(dist_goal), $(DIST_DIR)))
+
+$(call add_json_list, NamespacesToExport, $(PRODUCT_SOONG_NAMESPACES))
+
+$(call add_json_list, PgoAdditionalProfileDirs, $(PGO_ADDITIONAL_PROFILE_DIRS))
+
+_contents := $(_contents) "VendorVars": {$(newline)
+$(foreach namespace,$(SOONG_CONFIG_NAMESPACES),\
+ $(eval _contents := $$(_contents) "$(namespace)": {$$(newline)) \
+ $(foreach key,$(SOONG_CONFIG_$(namespace)),\
+ $(eval _contents := $$(_contents) "$(key)": "$(SOONG_CONFIG_$(namespace)_$(key))",$$(newline)))\
+ $(eval _contents := $$(_contents)$(if $(strip $(SOONG_CONFIG_$(namespace))),__SV_END) },$$(newline)))
+_contents := $(_contents)$(if $(strip $(SOONG_CONFIG_NAMESPACES)),__SV_END) },$(newline)
+
+_contents := $(subst $(comma)$(newline)__SV_END,$(newline),$(_contents)__SV_END}$(newline))
+
+$(file >$(SOONG_VARIABLES).tmp,$(_contents))
+
+$(shell if ! cmp -s $(SOONG_VARIABLES).tmp $(SOONG_VARIABLES); then \
+ mv $(SOONG_VARIABLES).tmp $(SOONG_VARIABLES); \
else \
- rm $(SOONG_VARIABLES_TMP); \
- fi
+ rm $(SOONG_VARIABLES).tmp; \
+ fi)
+
+_json_list :=
+json_list :=
+csv_to_json_list :=
+add_json_val :=
+add_json_str :=
+add_json_list :=
+add_json_csv :=
+add_json_bool :=
+invert_bool :=
+_contents :=
+
+endif # CONFIGURE_SOONG
diff --git a/core/soong_java_prebuilt.mk b/core/soong_java_prebuilt.mk
new file mode 100644
index 0000000..13b5f71
--- /dev/null
+++ b/core/soong_java_prebuilt.mk
@@ -0,0 +1,145 @@
+# Java prebuilt coming from Soong.
+# Extra inputs:
+# LOCAL_SOONG_HEADER_JAR
+# LOCAL_SOONG_DEX_JAR
+# LOCAL_SOONG_JACOCO_REPORT_CLASSES_JAR
+
+ifneq ($(LOCAL_MODULE_MAKEFILE),$(SOONG_ANDROID_MK))
+ $(call pretty-error,soong_java_prebuilt.mk may only be used from Soong)
+endif
+
+LOCAL_MODULE_SUFFIX := .jar
+LOCAL_BUILT_MODULE_STEM := javalib.jar
+
+#######################################
+include $(BUILD_SYSTEM)/base_rules.mk
+#######################################
+
+full_classes_jar := $(intermediates.COMMON)/classes.jar
+full_classes_pre_proguard_jar := $(intermediates.COMMON)/classes-pre-proguard.jar
+full_classes_header_jar := $(intermediates.COMMON)/classes-header.jar
+common_javalib.jar := $(intermediates.COMMON)/javalib.jar
+
+$(eval $(call copy-one-file,$(LOCAL_PREBUILT_MODULE_FILE),$(full_classes_jar)))
+$(eval $(call copy-one-file,$(LOCAL_PREBUILT_MODULE_FILE),$(full_classes_pre_proguard_jar)))
+
+ifdef LOCAL_DROIDDOC_STUBS_JAR
+$(eval $(call copy-one-file,$(LOCAL_DROIDDOC_STUBS_JAR),$(OUT_DOCS)/$(LOCAL_MODULE)-stubs.srcjar))
+ALL_DOCS += $(OUT_DOCS)/$(LOCAL_MODULE)-stubs.srcjar
+endif
+
+ifdef LOCAL_DROIDDOC_DOC_ZIP
+$(eval $(call copy-one-file,$(LOCAL_DROIDDOC_DOC_ZIP),$(OUT_DOCS)/$(LOCAL_MODULE)-docs.zip))
+endif
+
+ifdef LOCAL_SOONG_JACOCO_REPORT_CLASSES_JAR
+ $(eval $(call copy-one-file,$(LOCAL_SOONG_JACOCO_REPORT_CLASSES_JAR),\
+ $(intermediates.COMMON)/jacoco-report-classes.jar))
+ $(call add-dependency,$(common_javalib.jar),\
+ $(intermediates.COMMON)/jacoco-report-classes.jar)
+endif
+
+ifdef LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE
+ my_res_package := $(intermediates.COMMON)/package-res.apk
+
+ $(my_res_package): $(LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE)
+ @echo "Copy: $@"
+ $(copy-file-to-target)
+
+ $(call add-dependency,$(LOCAL_BUILT_MODULE),$(my_res_package))
+
+ my_proguard_flags := $(intermediates.COMMON)/export_proguard_flags
+ $(my_proguard_flags): $(LOCAL_SOONG_EXPORT_PROGUARD_FLAGS)
+ @echo "Export proguard flags: $@"
+ rm -f $@
+ touch $@
+ for f in $+; do \
+ echo -e "\n# including $$f" >>$@; \
+ cat $$f >>$@; \
+ done
+
+ $(call add-dependency,$(LOCAL_BUILT_MODULE),$(my_proguard_flags))
+
+ my_static_library_extra_packages := $(intermediates.COMMON)/extra_packages
+ $(eval $(call copy-one-file,$(LOCAL_SOONG_STATIC_LIBRARY_EXTRA_PACKAGES),$(my_static_library_extra_packages)))
+ $(call add-dependency,$(LOCAL_BUILT_MODULE),$(my_static_library_extra_packages))
+endif # LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE
+
+ifneq ($(TURBINE_ENABLED),false)
+ifdef LOCAL_SOONG_HEADER_JAR
+$(eval $(call copy-one-file,$(LOCAL_SOONG_HEADER_JAR),$(full_classes_header_jar)))
+else
+$(eval $(call copy-one-file,$(full_classes_jar),$(full_classes_header_jar)))
+endif
+endif # TURBINE_ENABLED != false
+
+ifdef LOCAL_SOONG_DEX_JAR
+ ifndef LOCAL_IS_HOST_MODULE
+ ifneq ($(filter $(LOCAL_MODULE),$(PRODUCT_BOOT_JARS)),) # is_boot_jar
+ $(eval $(call hiddenapi-copy-soong-jar,$(LOCAL_SOONG_DEX_JAR),$(common_javalib.jar)))
+ else # !is_boot_jar
+ $(eval $(call copy-one-file,$(LOCAL_SOONG_DEX_JAR),$(common_javalib.jar)))
+ endif # is_boot_jar
+ $(eval $(call add-dependency,$(common_javalib.jar),$(full_classes_jar) $(full_classes_header_jar)))
+
+ dex_preopt_profile_src_file := $(common_javalib.jar)
+
+ # defines built_odex along with rule to install odex
+ include $(BUILD_SYSTEM)/dex_preopt_odex_install.mk
+
+ dex_preopt_profile_src_file :=
+
+ ifdef LOCAL_DEX_PREOPT
+ ifneq ($(dexpreopt_boot_jar_module),) # boot jar
+ # boot jar's rules are defined in dex_preopt.mk
+ dexpreopted_boot_jar := $(DEXPREOPT_BOOT_JAR_DIR_FULL_PATH)/$(dexpreopt_boot_jar_module)_nodex.jar
+ $(eval $(call copy-one-file,$(dexpreopted_boot_jar),$(LOCAL_BUILT_MODULE)))
+
+ # For libart boot jars, we don't have .odex files.
+ else # ! boot jar
+ $(built_odex): PRIVATE_MODULE := $(LOCAL_MODULE)
+ # Use pattern rule - we may have multiple built odex files.
+$(built_odex) : $(dir $(LOCAL_BUILT_MODULE))% : $(common_javalib.jar)
+ @echo "Dexpreopt Jar: $(PRIVATE_MODULE) ($@)"
+ $(call dexpreopt-one-file,$<,$@)
+
+ $(eval $(call dexpreopt-copy-jar,$(common_javalib.jar),$(LOCAL_BUILT_MODULE),$(LOCAL_DEX_PREOPT)))
+ endif # ! boot jar
+ else # LOCAL_DEX_PREOPT
+ $(eval $(call copy-one-file,$(common_javalib.jar),$(LOCAL_BUILT_MODULE)))
+ endif # LOCAL_DEX_PREOPT
+ else # LOCAL_IS_HOST_MODULE
+ $(eval $(call copy-one-file,$(LOCAL_SOONG_DEX_JAR),$(LOCAL_BUILT_MODULE)))
+ $(eval $(call add-dependency,$(LOCAL_BUILT_MODULE),$(full_classes_jar) $(full_classes_header_jar)))
+ endif
+
+ java-dex : $(LOCAL_BUILT_MODULE)
+else
+ $(eval $(call copy-one-file,$(full_classes_jar),$(LOCAL_BUILT_MODULE)))
+endif
+
+javac-check : $(full_classes_jar)
+javac-check-$(LOCAL_MODULE) : $(full_classes_jar)
+
+ifndef LOCAL_IS_HOST_MODULE
+ifeq ($(LOCAL_SDK_VERSION),system_current)
+my_link_type := java:system
+else ifneq (,$(call has-system-sdk-version,$(LOCAL_SDK_VERSION)))
+my_link_type := java:system
+else ifeq ($(LOCAL_SDK_VERSION),core_current)
+my_link_type := java:core
+else ifneq ($(LOCAL_SDK_VERSION),)
+my_link_type := java:sdk
+else
+my_link_type := java:platform
+endif
+# warn/allowed types are both empty because Soong modules can't depend on
+# make-defined modules.
+my_warn_types :=
+my_allowed_types :=
+
+my_link_deps :=
+my_2nd_arch_prefix := $(LOCAL_2ND_ARCH_VAR_PREFIX)
+my_common := COMMON
+include $(BUILD_SYSTEM)/link_type.mk
+endif # !LOCAL_IS_HOST_MODULE
diff --git a/core/static_java_library.mk b/core/static_java_library.mk
index 1373011..0429dd2 100644
--- a/core/static_java_library.mk
+++ b/core/static_java_library.mk
@@ -24,14 +24,17 @@
LOCAL_IS_STATIC_JAVA_LIBRARY := true
LOCAL_MODULE_CLASS := JAVA_LIBRARIES
-#################################
-include $(BUILD_SYSTEM)/configure_local_jack.mk
-#################################
-
intermediates.COMMON := $(call local-intermediates-dir,COMMON)
my_res_package :=
+ifdef LOCAL_AAPT2_ONLY
+LOCAL_USE_AAPT2 := true
+endif
+
+# Process Support Library dependencies.
+include $(BUILD_SYSTEM)/support_libraries.mk
+
# Hack to build static Java library with Android resource
# See bug 5714516
all_resources :=
@@ -76,13 +79,6 @@
LOCAL_PROGUARD_FLAGS := $(addprefix -include ,$(proguard_options_file)) $(LOCAL_PROGUARD_FLAGS)
-ifdef LOCAL_JACK_ENABLED
-ifndef LOCAL_JACK_PROGUARD_FLAGS
- LOCAL_JACK_PROGUARD_FLAGS := $(LOCAL_PROGUARD_FLAGS)
-endif
-LOCAL_JACK_PROGUARD_FLAGS := $(addprefix -include ,$(proguard_options_file)) $(LOCAL_JACK_PROGUARD_FLAGS)
-endif # LOCAL_JACK_ENABLED
-
R_file_stamp := $(intermediates.COMMON)/src/R.stamp
LOCAL_INTERMEDIATE_TARGETS += $(R_file_stamp)
@@ -95,11 +91,11 @@
LOCAL_INTERMEDIATE_TARGETS += $(my_res_package)
endif # LOCAL_USE_AAPT2
-endif # LOCAL_RESOURCE_DIR
+endif # need_compile_res
all_res_assets := $(all_resources)
-include $(BUILD_SYSTEM)/java_library.mk
+include $(BUILD_SYSTEM)/java_renderscript.mk
ifeq (true,$(need_compile_res))
include $(BUILD_SYSTEM)/android_manifest.mk
@@ -110,33 +106,58 @@
endif
framework_res_package_export :=
-framework_res_package_export_deps :=
# 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))),)
framework_res_package_export := \
$(HISTORICAL_SDK_VERSIONS_ROOT)/$(LOCAL_SDK_RES_VERSION)/android.jar
-framework_res_package_export_deps := $(framework_res_package_export)
else
framework_res_package_export := \
$(call intermediates-dir-for,APPS,framework-res,,COMMON)/package-export.apk
-framework_res_package_export_deps := \
- $(dir $(framework_res_package_export))src/R.stamp
endif
endif
+ifdef LOCAL_USE_AAPT2
+import_proguard_flag_files := $(strip $(foreach l,$(LOCAL_STATIC_ANDROID_LIBRARIES),\
+ $(call intermediates-dir-for,JAVA_LIBRARIES,$(l),,COMMON)/export_proguard_flags))
+$(intermediates.COMMON)/export_proguard_flags: $(import_proguard_flag_files) $(addprefix $(LOCAL_PATH)/,$(LOCAL_EXPORT_PROGUARD_FLAG_FILES))
+ @echo "Export proguard flags: $@"
+ rm -f $@
+ touch $@
+ for f in $+; do \
+ echo -e "\n# including $$f" >>$@; \
+ cat $$f >>$@; \
+ done
+import_proguard_flag_files :=
+endif
+
+include $(BUILD_SYSTEM)/aapt_flags.mk
+
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_AAPT_FLAGS := $(LOCAL_AAPT_FLAGS)
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_TARGET_AAPT_CHARACTERISTICS := $(TARGET_AAPT_CHARACTERISTICS)
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_MANIFEST_PACKAGE_NAME := $(LOCAL_MANIFEST_PACKAGE_NAME)
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_MANIFEST_INSTRUMENTATION_FOR := $(LOCAL_MANIFEST_INSTRUMENTATION_FOR)
+
# add --non-constant-id to prevent inlining constants.
# AAR needs text symbol file R.txt.
ifdef LOCAL_USE_AAPT2
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_AAPT_FLAGS := $(LOCAL_AAPT_FLAGS) --static-lib --no-static-lib-packages
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_AAPT_FLAGS := $(LOCAL_AAPT_FLAGS) --static-lib --output-text-symbols $(intermediates.COMMON)/R.txt
+ifndef LOCAL_AAPT_NAMESPACES
+ $(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_AAPT_FLAGS += --no-static-lib-packages
+endif
$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_PRODUCT_AAPT_CONFIG :=
$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_PRODUCT_AAPT_PREF_CONFIG :=
$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_TARGET_AAPT_CHARACTERISTICS :=
else
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_AAPT_FLAGS := $(LOCAL_AAPT_FLAGS) --non-constant-id --output-text-symbols $(LOCAL_INTERMEDIATE_SOURCE_DIR)
+$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_AAPT_FLAGS := $(LOCAL_AAPT_FLAGS) --non-constant-id --output-text-symbols $(intermediates.COMMON)
+
+my_srcjar := $(intermediates.COMMON)/aapt.srcjar
+LOCAL_SRCJARS += $(my_srcjar)
+$(R_file_stamp): PRIVATE_SRCJAR := $(my_srcjar)
+$(R_file_stamp): PRIVATE_JAVA_GEN_DIR := $(intermediates.COMMON)/aapt
+$(R_file_stamp): .KATI_IMPLICIT_OUTPUTS := $(my_srcjar)
endif
-$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_SOURCE_INTERMEDIATES_DIR := $(LOCAL_INTERMEDIATE_SOURCE_DIR)
$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_ANDROID_MANIFEST := $(full_android_manifest)
$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_RESOURCE_PUBLICS_OUTPUT := $(intermediates.COMMON)/public_resources.xml
$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_RESOURCE_DIR := $(LOCAL_RESOURCE_DIR)
@@ -148,41 +169,36 @@
$(LOCAL_INTERMEDIATE_TARGETS): PRIVATE_MANIFEST_INSTRUMENTATION_FOR :=
ifdef LOCAL_USE_AAPT2
-# One more level with name res so we can zip up the flat resources that can be linked by apps.
-my_compiled_res_base_dir := $(intermediates.COMMON)/flat-res/res
-renderscript_target_api :=
-ifneq (,$(LOCAL_RENDERSCRIPT_TARGET_API))
-renderscript_target_api := $(LOCAL_RENDERSCRIPT_TARGET_API)
+ # One more level with name res so we can zip up the flat resources that can be linked by apps.
+ my_compiled_res_base_dir := $(intermediates.COMMON)/flat-res/res
+ ifneq (,$(renderscript_target_api))
+ ifneq ($(call math_gt_or_eq,$(renderscript_target_api),21),true)
+ my_generated_res_zips := $(rs_generated_res_zip)
+ endif # renderscript_target_api < 21
+ endif # renderscript_target_api is set
+ include $(BUILD_SYSTEM)/aapt2.mk
+ $(my_res_package) : $(framework_res_package_export)
+ $(my_res_package): .KATI_IMPLICIT_OUTPUTS += $(intermediates.COMMON)/R.txt
else
-ifneq (,$(LOCAL_SDK_VERSION))
-# Set target-api for LOCAL_SDK_VERSIONs other than current.
-ifneq (,$(filter-out current system_current test_current, $(LOCAL_SDK_VERSION)))
-renderscript_target_api := $(LOCAL_SDK_VERSION)
-endif
-endif # LOCAL_SDK_VERSION is set
-endif # LOCAL_RENDERSCRIPT_TARGET_API is set
-ifneq (,$(renderscript_target_api))
-ifneq ($(call math_gt_or_eq,$(renderscript_target_api),21),true)
-my_generated_res_dirs := $(rs_generated_res_dir)
-my_generated_res_dirs_deps := $(RenderScript_file_stamp)
-endif # renderscript_target_api < 21
-endif # renderscript_target_api is set
-include $(BUILD_SYSTEM)/aapt2.mk
-$(my_res_package) : $(framework_res_package_export_deps)
-else
-$(R_file_stamp) : $(all_resources) $(full_android_manifest) $(AAPT) $(framework_res_package_export_deps)
+ $(R_file_stamp): .KATI_IMPLICIT_OUTPUTS += $(intermediates.COMMON)/R.txt
+ $(R_file_stamp): PRIVATE_RESOURCE_LIST := $(all_resources)
+ $(R_file_stamp) : $(all_resources) $(full_android_manifest) $(AAPT) $(SOONG_ZIP) \
+ $(framework_res_package_export) $(rs_generated_res_zip)
@echo "target R.java/Manifest.java: $(PRIVATE_MODULE) ($@)"
$(create-resource-java-files)
- $(hide) find $(PRIVATE_SOURCE_INTERMEDIATES_DIR) -name R.java | xargs cat > $@
+ $(hide) find $(PRIVATE_JAVA_GEN_DIR) -name R.java | xargs cat > $@
endif # LOCAL_USE_AAPT2
+endif # need_compile_res
+
+include $(BUILD_SYSTEM)/java_library.mk
+
+ifeq (true,$(need_compile_res))
+
$(LOCAL_BUILT_MODULE): $(R_file_stamp)
-ifdef LOCAL_JACK_ENABLED
-$(noshrob_classes_jack): $(R_file_stamp)
-$(full_classes_jack): $(R_file_stamp)
-$(jack_check_timestamp): $(R_file_stamp)
-endif # LOCAL_JACK_ENABLED
+$(java_source_list_file): $(R_file_stamp)
$(full_classes_compiled_jar): $(R_file_stamp)
+$(full_classes_turbine_jar): $(R_file_stamp)
# if we have custom proguarding done use the proguarded classes jar instead of the normal classes jar
@@ -198,8 +214,9 @@
$(built_aar): PRIVATE_ANDROID_MANIFEST := $(full_android_manifest)
$(built_aar): PRIVATE_CLASSES_JAR := $(aar_classes_jar)
$(built_aar): PRIVATE_RESOURCE_DIR := $(LOCAL_RESOURCE_DIR)
-$(built_aar): PRIVATE_R_TXT := $(LOCAL_INTERMEDIATE_SOURCE_DIR)/R.txt
-$(built_aar) : $(aar_classes_jar) $(full_android_manifest)
+$(built_aar): PRIVATE_R_TXT := $(intermediates.COMMON)/R.txt
+$(built_aar): $(JAR_ARGS)
+$(built_aar) : $(aar_classes_jar) $(full_android_manifest) $(intermediates.COMMON)/R.txt
@echo "target AAR: $(PRIVATE_MODULE) ($@)"
$(hide) rm -rf $(dir $@)aar && mkdir -p $(dir $@)aar/res
$(hide) cp $(PRIVATE_ANDROID_MANIFEST) $(dir $@)aar/AndroidManifest.xml
@@ -208,7 +225,7 @@
$(hide) $(foreach res,$(PRIVATE_RESOURCE_DIR),cp -Rfn $(res)/* $(dir $@)aar/res;)
$(hide) cp $(PRIVATE_R_TXT) $(dir $@)aar/R.txt
$(hide) $(JAR) -cMf $@ \
- -C $(dir $@)aar .
+ $(call jar-args-sorted-files-in-directory,$(dir $@)aar)
# Register the aar file.
ALL_MODULES.$(LOCAL_MODULE).AAR := $(built_aar)
diff --git a/core/support_libraries.mk b/core/support_libraries.mk
new file mode 100644
index 0000000..7538ce0
--- /dev/null
+++ b/core/support_libraries.mk
@@ -0,0 +1,53 @@
+#
+# 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.
+#
+
+###########################################################
+## Rules for resolving Support Library dependencies.
+##
+## The following variables may be modified:
+## - LOCAL_JAVA_LIBRARIES
+## - LOCAL_STATIC_JAVA_LIBRARIES
+## - LOCAL_SHARED_ANDROID_LIBRARIES
+## - LOCAL_STATIC_ANDROID_LIBRARIES
+###########################################################
+
+# Some projects don't work correctly yet. Allow them to skip resolution.
+ifndef LOCAL_DISABLE_RESOLVE_SUPPORT_LIBRARIES
+
+# Aggregate all requested Support Library modules.
+requested_support_libs := $(filter $(SUPPORT_LIBRARIES_JARS) $(SUPPORT_LIBRARIES_AARS), \
+ $(LOCAL_JAVA_LIBRARIES) $(LOCAL_STATIC_JAVA_LIBRARIES) \
+ $(LOCAL_SHARED_ANDROID_LIBRARIES) $(LOCAL_STATIC_ANDROID_LIBRARIES))
+
+# Filter the Support Library modules out of the library variables. We don't
+# trust developers to get these right, so they will be added back by the
+# build system based on the output of this file and the type of build.
+LOCAL_JAVA_LIBRARIES := $(filter-out $(requested_support_libs), \
+ $(LOCAL_JAVA_LIBRARIES))
+LOCAL_STATIC_JAVA_LIBRARIES := $(filter-out $(requested_support_libs), \
+ $(LOCAL_STATIC_JAVA_LIBRARIES))
+LOCAL_SHARED_ANDROID_LIBRARIES := $(filter-out $(requested_support_libs), \
+ $(LOCAL_SHARED_ANDROID_LIBRARIES))
+LOCAL_STATIC_ANDROID_LIBRARIES := $(filter-out $(requested_support_libs), \
+ $(LOCAL_STATIC_ANDROID_LIBRARIES))
+
+LOCAL_STATIC_ANDROID_LIBRARIES := $(strip $(LOCAL_STATIC_ANDROID_LIBRARIES) \
+ $(filter $(SUPPORT_LIBRARIES_AARS),$(requested_support_libs)))
+LOCAL_STATIC_JAVA_LIBRARIES := $(strip $(LOCAL_STATIC_JAVA_LIBRARIES) \
+ $(filter $(SUPPORT_LIBRARIES_JARS),$(requested_support_libs)))
+
+endif #LOCAL_DISABLE_RESOLVE_SUPPORT_LIBRARIES
+LOCAL_DISABLE_RESOLVE_SUPPORT_LIBRARIES :=
diff --git a/target/board/generic_armv5/BoardConfig.mk b/core/target_test_config.mk
similarity index 70%
rename from target/board/generic_armv5/BoardConfig.mk
rename to core/target_test_config.mk
index 016937a..61f5d2b 100644
--- a/target/board/generic_armv5/BoardConfig.mk
+++ b/core/target_test_config.mk
@@ -1,5 +1,5 @@
#
-# Copyright (C) 2011 The Android Open Source Project
+# 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.
@@ -14,10 +14,10 @@
# limitations under the License.
#
-include build/target/board/generic/BoardConfig.mk
+#
+# Common rules for building a TradeFed test XML file for target side tests.
+#
-TARGET_ARCH_VARIANT := armv5te
-TARGET_CPU_ABI := armeabi
-TARGET_CPU_ABI2 :=
+$(call record-module-type,TARGET_TEST_CONFIG)
-WITH_DEXPREOPT := false
+include $(BUILD_SYSTEM)/test_config_common.mk
diff --git a/core/target_test_internal.mk b/core/target_test_internal.mk
index 59a3a9e..b5c3a7c 100644
--- a/core/target_test_internal.mk
+++ b/core/target_test_internal.mk
@@ -8,15 +8,9 @@
ifndef LOCAL_SDK_VERSION
LOCAL_STATIC_LIBRARIES += libgtest_main libgtest
else
- ifneq (,$(filter c++_%,$(LOCAL_NDK_STL_VARIANT)))
- my_ndk_gtest_suffix := _c++
- else ifneq ($(filter stlport_,$(LOCAL_NDK_STL_VARIANT)),)
- my_ndk_gtest_suffix := _stlport
- else ifneq ($(filter gnustl_,$(LOCAL_NDK_STL_VARIANT)),)
- my_ndk_gtest_suffix := _gnustl
- else # system STL, use stlport
- my_ndk_gtest_suffix := _stlport
- endif
+ # TODO(danalbert): Remove the suffix from the module since we only need the
+ # one variant now.
+ my_ndk_gtest_suffix := _c++
LOCAL_STATIC_LIBRARIES += \
libgtest_main_ndk$(my_ndk_gtest_suffix) \
libgtest_ndk$(my_ndk_gtest_suffix)
diff --git a/core/tasks/apicheck.mk b/core/tasks/apicheck.mk
index 3975d20..f4aee3f 100644
--- a/core/tasks/apicheck.mk
+++ b/core/tasks/apicheck.mk
@@ -51,7 +51,7 @@
$(INTERNAL_PLATFORM_REMOVED_API_FILE), \
-hide 2 -hide 3 -hide 4 -hide 5 -hide 6 -hide 24 -hide 25 -hide 26 -hide 27 \
-error 7 -error 8 -error 9 -error 10 -error 11 -error 12 -error 13 -error 14 -error 15 \
- -error 16 -error 17 -error 18 , \
+ -error 16 -error 17 -error 18 -error 31, \
cat $(BUILD_SYSTEM)/apicheck_msg_last.txt, \
check-public-api, \
$(call doc-timestamp-for,api-stubs) \
@@ -97,7 +97,7 @@
$(INTERNAL_PLATFORM_SYSTEM_REMOVED_API_FILE), \
-hide 2 -hide 3 -hide 4 -hide 5 -hide 6 -hide 24 -hide 25 -hide 26 -hide 27 \
-error 7 -error 8 -error 9 -error 10 -error 11 -error 12 -error 13 -error 14 -error 15 \
- -error 16 -error 17 -error 18 , \
+ -error 16 -error 17 -error 18 -error 31, \
cat $(BUILD_SYSTEM)/apicheck_msg_last.txt, \
check-system-api, \
$(call doc-timestamp-for,system-api-stubs) \
diff --git a/target/board/generic_armv5/device.mk b/core/tasks/apidiff.mk
similarity index 78%
rename from target/board/generic_armv5/device.mk
rename to core/tasks/apidiff.mk
index 7c4aaf2..4eb59af 100644
--- a/target/board/generic_armv5/device.mk
+++ b/core/tasks/apidiff.mk
@@ -1,5 +1,4 @@
-#
-# Copyright (C) 2011 The Android Open Source Project
+# 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.
@@ -12,6 +11,11 @@
# 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.
#
-include build/target/board/generic/device.mk
+.PHONY: api-diff
+
+api-diff: offline-sdk-referenceonly-diff
diff --git a/core/tasks/boot_jars_package_check.mk b/core/tasks/boot_jars_package_check.mk
index 188c267..dc79e23 100644
--- a/core/tasks/boot_jars_package_check.mk
+++ b/core/tasks/boot_jars_package_check.mk
@@ -24,8 +24,8 @@
stamp := $(intermediates)/stamp
built_boot_jars := $(foreach j, $(PRODUCT_BOOT_JARS), \
$(call intermediates-dir-for, JAVA_LIBRARIES, $(j),,COMMON)/classes.jar)
-script := build/core/tasks/check_boot_jars/check_boot_jars.py
-whitelist_file := build/core/tasks/check_boot_jars/package_whitelist.txt
+script := build/make/core/tasks/check_boot_jars/check_boot_jars.py
+whitelist_file := build/make/core/tasks/check_boot_jars/package_whitelist.txt
$(stamp): PRIVATE_BOOT_JARS := $(built_boot_jars)
$(stamp): PRIVATE_SCRIPT := $(script)
diff --git a/core/tasks/check_boot_jars/package_whitelist.txt b/core/tasks/check_boot_jars/package_whitelist.txt
index 15b9990..b0becba 100644
--- a/core/tasks/check_boot_jars/package_whitelist.txt
+++ b/core/tasks/check_boot_jars/package_whitelist.txt
@@ -121,7 +121,7 @@
###################################################
-# legacy-test.jar
+# android.test.base.jar
junit\.extensions
junit\.framework
android\.test
@@ -237,3 +237,7 @@
# Packages in the google namespace across all bootclasspath jars.
com\.google\.android\..*
com\.google\.vr\.platform.*
+
+###################################################
+# Packages used for Android in Chrome OS
+org\.chromium\.arc
diff --git a/core/tasks/check_emu_boot.mk b/core/tasks/check_emu_boot.mk
new file mode 100644
index 0000000..4870677
--- /dev/null
+++ b/core/tasks/check_emu_boot.mk
@@ -0,0 +1,23 @@
+check_emu_boot0 := $(DIST_DIR)/$(TARGET_PRODUCT)-$(TARGET_BUILD_VARIANT)-emulator-boot-test-result.txt
+$(check_emu_boot0) : PRIVATE_PREFIX := $(TARGET_PRODUCT)-$(TARGET_BUILD_VARIANT)
+$(check_emu_boot0) : PRIVATE_EMULATOR_BOOT_TEST_SH := device/generic/goldfish/tools/emulator_boot_test.sh
+$(check_emu_boot0) : PRIVATE_BOOT_COMPLETE_STRING := "emulator: INFO: boot completed"
+$(check_emu_boot0) : PRIVATE_BOOT_FAIL_STRING := "emulator: ERROR: fail to boot after"
+$(check_emu_boot0) : PRIVATE_SUCCESS_FILE := $(DIST_DIR)/$(PRIVATE_PREFIX)-BOOT-SUCCESS.txt
+$(check_emu_boot0) : PRIVATE_FAIL_FILE := $(DIST_DIR)/$(PRIVATE_PREFIX)-BOOT-FAIL.txt
+$(check_emu_boot0) : $(INSTALLED_QEMU_SYSTEMIMAGE) $(INSTALLED_QEMU_VENDORIMAGE) \
+ $(if $(BOARD_USERDATAIMAGE_PARTITION_SIZE),$(PRODUCT_OUT)/userdata.img) \
+ $(PRODUCT_OUT)/ramdisk.img device/generic/goldfish/tools/emulator_boot_test.sh
+ @mkdir -p $(dir $(check_emu_boot0))
+ $(hide) rm -f $(check_emu_boot0)
+ $(hide) rm -f $(PRIVATE_SUCCESS_FILE)
+ $(hide) rm -f $(PRIVATE_FAIL_FILE)
+ (export ANDROID_PRODUCT_OUT=$$(cd $(PRODUCT_OUT);pwd);\
+ export ANDROID_BUILD_TOP=$$(pwd);\
+ $(PRIVATE_EMULATOR_BOOT_TEST_SH) > $(check_emu_boot0))
+ (if grep -q $(PRIVATE_BOOT_COMPLETE_STRING) $(check_emu_boot0);\
+ then echo boot_succeeded > $(PRIVATE_SUCCESS_FILE); fi)
+ (if grep -q $(PRIVATE_BOOT_FAIL_STRING) $(check_emu_boot0);\
+ then echo boot_failed > $(PRIVATE_FAIL_FILE); fi)
+.PHONY: check_emu_boot
+check_emu_boot: $(check_emu_boot0)
diff --git a/core/tasks/collect_gpl_sources.mk b/core/tasks/collect_gpl_sources.mk
index 30ba62b..70f0afe 100644
--- a/core/tasks/collect_gpl_sources.mk
+++ b/core/tasks/collect_gpl_sources.mk
@@ -12,20 +12,22 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-gpl_source_tgz := $(call intermediates-dir-for,PACKAGING,gpl_source,HOST,COMMON)/gpl_source.tgz
+ifdef dist_goal
+
+# The rule below doesn't have dependenices on the files that it copies,
+# so manually generate directly into the DIST_DIR directory that is always
+# wiped between dist builds.
+gpl_source_tgz := $(DIST_DIR)/gpl_source.tgz
# FORCE since we can't know whether any of the sources changed
$(gpl_source_tgz): PRIVATE_PATHS := $(sort $(patsubst %/, %, $(dir $(ALL_GPL_MODULE_LICENSE_FILES))))
-$(gpl_source_tgz) : $(ALL_GPL_MODULE_LICENSE_FILES) FORCE
+$(gpl_source_tgz) : $(ALL_GPL_MODULE_LICENSE_FILES)
@echo Package gpl sources: $@
- @rm -rf $(dir $@) && mkdir -p $(dir $@)
$(hide) tar cfz $@ --exclude ".git*" $(PRIVATE_PATHS)
-
-.PHONY: gpl_source_tgz
-gpl_source_tgz : $(gpl_source_tgz)
-
# Dist the tgz only if we are doing a full build
ifeq (,$(TARGET_BUILD_APPS))
-$(call dist-for-goals, droidcore, $(gpl_source_tgz))
+droidcore: $(gpl_source_tgz)
endif
+
+endif # dist_goal
diff --git a/core/tasks/cts.mk b/core/tasks/cts.mk
index fdd9591..33c3a83 100644
--- a/core/tasks/cts.mk
+++ b/core/tasks/cts.mk
@@ -14,8 +14,9 @@
test_suite_name := cts
test_suite_tradefed := cts-tradefed
-test_suite_dynamic_config := cts/tools/cts-tradefed/DynamicConfig.xml
-test_suite_readme := cts/tools/cts-tradefed/README
+# TODO: Fix the following two lines after harness is moved to its own repo
+test_suite_dynamic_config := test/suite_harness/tools/cts-tradefed/DynamicConfig.xml
+test_suite_readme := test/suite_harness/tools/cts-tradefed/README
include $(BUILD_SYSTEM)/tasks/tools/compatibility.mk
diff --git a/core/tasks/cts_instant.mk b/core/tasks/cts_instant.mk
new file mode 100644
index 0000000..18f1db3
--- /dev/null
+++ b/core/tasks/cts_instant.mk
@@ -0,0 +1,25 @@
+# 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.
+
+test_suite_name := cts_instant
+test_suite_tradefed := cts-instant-tradefed
+test_suite_dynamic_config := test/suite_harness/tools/cts-instant-tradefed/DynamicConfig.xml
+test_suite_readme := test/suite_harness/tools/cts-instant-tradefed/README
+
+include $(BUILD_SYSTEM)/tasks/tools/compatibility.mk
+
+.PHONY: cts_instant
+cts_instant: $(compatibility_zip)
+$(call dist-for-goals, cts_instant, $(compatibility_zip))
+
diff --git a/core/tasks/device-tests.mk b/core/tasks/device-tests.mk
index b1b936a..a2b626e 100644
--- a/core/tasks/device-tests.mk
+++ b/core/tasks/device-tests.mk
@@ -6,7 +6,7 @@
#
# http://www.apache.org/licenses/LICENSE-2.0
#
-# Unless required by applicable law or agrls eed to in writing, software
+# 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
@@ -16,14 +16,23 @@
.PHONY: device-tests
device-tests-zip := $(PRODUCT_OUT)/device-tests.zip
-$(device-tests-zip): $(COMPATIBILITY.device-tests.FILES) $(SOONG_ZIP)
- echo $(sort $(COMPATIBILITY.device-tests.FILES)) > $@.list
- sed -i -e 's/\s\+/\n/g' $@.list
+# Create an artifact to include a list of test config files in device-tests.
+device-tests-list-zip := $(PRODUCT_OUT)/device-tests_list.zip
+$(device-tests-zip) : .KATI_IMPLICIT_OUTPUTS := $(device-tests-list-zip)
+$(device-tests-zip) : PRIVATE_device_tests_list := $(PRODUCT_OUT)/device-tests_list
+
+$(device-tests-zip) : $(COMPATIBILITY.device-tests.FILES) $(SOONG_ZIP)
+ echo $(sort $(COMPATIBILITY.device-tests.FILES)) | tr " " "\n" > $@.list
grep $(HOST_OUT_TESTCASES) $@.list > $@-host.list || true
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
+ rm -f $(PRIVATE_device_tests_list)
+ $(hide) grep -e .*.config$$ $@-host.list | sed s%$(HOST_OUT)%host%g > $(PRIVATE_device_tests_list)
+ $(hide) grep -e .*.config$$ $@-target.list | sed s%$(PRODUCT_OUT)%target%g >> $(PRIVATE_device_tests_list)
+ $(hide) $(SOONG_ZIP) -d -o $(device-tests-list-zip) -C $(dir $@) -f $(PRIVATE_device_tests_list)
+ rm -f $@.list $@-host.list $@-target.list $(PRIVATE_device_tests_list)
device-tests: $(device-tests-zip)
-$(call dist-for-goals, device-tests, $(device-tests-zip))
+$(call dist-for-goals, device-tests, $(device-tests-zip) $(device-tests-list-zip))
tests: device-tests
diff --git a/core/tasks/general-tests.mk b/core/tasks/general-tests.mk
index 763dd51..c7f1dc9 100644
--- a/core/tasks/general-tests.mk
+++ b/core/tasks/general-tests.mk
@@ -6,7 +6,7 @@
#
# http://www.apache.org/licenses/LICENSE-2.0
#
-# Unless required by applicable law or agrls eed to in writing, software
+# 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
@@ -15,12 +15,21 @@
.PHONY: general-tests
general-tests-zip := $(PRODUCT_OUT)/general-tests.zip
-$(general-tests-zip): $(COMPATIBILITY.general-tests.FILES) $(SOONG_ZIP)
- echo $(sort $(COMPATIBILITY.general-tests.FILES)) > $@.list
- sed -i -e 's/\s\+/\n/g' $@.list
+# Create an artifact to include a list of test config files in general-tests.
+general-tests-list-zip := $(PRODUCT_OUT)/general-tests_list.zip
+$(general-tests-zip) : .KATI_IMPLICIT_OUTPUTS := $(general-tests-list-zip)
+$(general-tests-zip) : PRIVATE_general_tests_list := $(PRODUCT_OUT)/general-tests_list
+
+$(general-tests-zip) : $(COMPATIBILITY.general-tests.FILES) $(SOONG_ZIP)
+ echo $(sort $(COMPATIBILITY.general-tests.FILES)) | tr " " "\n" > $@.list
grep $(HOST_OUT_TESTCASES) $@.list > $@-host.list || true
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
+ rm -f $(PRIVATE_general_tests_list)
+ $(hide) grep -e .*.config$$ $@-host.list | sed s%$(HOST_OUT)%host%g > $(PRIVATE_general_tests_list)
+ $(hide) grep -e .*.config$$ $@-target.list | sed s%$(PRODUCT_OUT)%target%g >> $(PRIVATE_general_tests_list)
+ $(hide) $(SOONG_ZIP) -d -o $(general-tests-list-zip) -C $(dir $@) -f $(PRIVATE_general_tests_list)
+ rm -f $@.list $@-host.list $@-target.list $(PRIVATE_general_tests_list)
general-tests: $(general-tests-zip)
-$(call dist-for-goals, general-tests, $(general-tests-zip))
+$(call dist-for-goals, general-tests, $(general-tests-zip) $(general-tests-list-zip))
diff --git a/core/tasks/module-info.mk b/core/tasks/module-info.mk
index e9b2ac7..b45526f 100644
--- a/core/tasks/module-info.mk
+++ b/core/tasks/module-info.mk
@@ -11,6 +11,8 @@
'"path": [$(foreach w,$(sort $(ALL_MODULES.$(m).PATH)),"$(w)", )], ' \
'"tags": [$(foreach w,$(sort $(ALL_MODULES.$(m).TAGS)),"$(w)", )], ' \
'"installed": [$(foreach w,$(sort $(ALL_MODULES.$(m).INSTALLED)),"$(w)", )], ' \
+ '"compatibility_suites": [$(foreach w,$(sort $(ALL_MODULES.$(m).COMPATIBILITY_SUITES)),"$(w)", )], ' \
+ '"auto_test_config": [$(ALL_MODULES.$(m).auto_test_config)], ' \
'},\n' \
) | sed -e 's/, *\]/]/g' -e 's/, *\}/ }/g' -e '$$s/,$$//' >> $@
$(hide) echo '}' >> $@
diff --git a/core/tasks/oem_image.mk b/core/tasks/oem_image.mk
index 32d56a7..66eec22 100644
--- a/core/tasks/oem_image.mk
+++ b/core/tasks/oem_image.mk
@@ -35,7 +35,7 @@
@mkdir -p $(oemimage_intermediates) && rm -rf $(oemimage_intermediates)/oem_image_info.txt
$(call generate-userimage-prop-dictionary, $(oemimage_intermediates)/oem_image_info.txt, skip_fsck=true)
$(hide) PATH=$(foreach p,$(INTERNAL_USERIMAGES_BINARY_PATHS),$(p):)$$PATH \
- ./build/tools/releasetools/build_image.py \
+ build/make/tools/releasetools/build_image.py \
$(TARGET_OUT_OEM) $(oemimage_intermediates)/oem_image_info.txt $@ $(TARGET_OUT)
$(hide) $(call assert-max-image-size,$@,$(BOARD_OEMIMAGE_PARTITION_SIZE))
diff --git a/core/tasks/sdk-addon.mk b/core/tasks/sdk-addon.mk
index e26773c..bc11b49 100644
--- a/core/tasks/sdk-addon.mk
+++ b/core/tasks/sdk-addon.mk
@@ -65,9 +65,9 @@
files_to_copy += \
$(addon_dir_img):$(INSTALLED_QEMU_SYSTEMIMAGE):images/$(TARGET_CPU_ABI)/system.img \
$(addon_dir_img):$(INSTALLED_QEMU_VENDORIMAGE):images/$(TARGET_CPU_ABI)/vendor.img \
- $(addon_dir_img):$(BUILT_USERDATAIMAGE_TARGET):images/$(TARGET_CPU_ABI)/userdata.img \
$(addon_dir_img):$(BUILT_RAMDISK_TARGET):images/$(TARGET_CPU_ABI)/ramdisk.img \
$(addon_dir_img):$(PRODUCT_OUT)/system/build.prop:images/$(TARGET_CPU_ABI)/build.prop \
+ $(addon_dir_img):device/generic/goldfish/data/etc/userdata.img:images/$(TARGET_CPU_ABI)/userdata.img \
$(addon_dir_img):$(target_notice_file_txt):images/$(TARGET_CPU_ABI)/NOTICE.txt \
$(addon_dir_img):$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SDK_ADDON_SYS_IMG_SOURCE_PROP):images/source.properties
@@ -105,21 +105,21 @@
$(full_target): PRIVATE_STAGING_DIR := $(call append-path,$(staging),$(addon_dir_leaf))
-$(full_target): $(sdk_addon_deps) | $(ACP)
+$(full_target): $(sdk_addon_deps) | $(ACP) $(SOONG_ZIP)
@echo Packaging SDK Addon: $@
$(hide) mkdir -p $(PRIVATE_STAGING_DIR)/docs
$(hide) for d in $(PRIVATE_DOCS_DIRS); do \
$(ACP) -r $$d $(PRIVATE_STAGING_DIR)/docs ;\
done
$(hide) mkdir -p $(dir $@)
- $(hide) ( F=$$(pwd)/$@ ; cd $(PRIVATE_STAGING_DIR)/.. && zip -rqX $$F $(notdir $(PRIVATE_STAGING_DIR)) )
+ $(hide) $(SOONG_ZIP) -o $@ -C $(dir $(PRIVATE_STAGING_DIR)) -D $(PRIVATE_STAGING_DIR)
$(full_target_img): PRIVATE_STAGING_DIR := $(call append-path,$(staging),$(addon_dir_img))/images/$(TARGET_CPU_ABI)
-$(full_target_img): $(full_target) $(addon_img_source_prop) | $(ACP)
+$(full_target_img): $(full_target) $(addon_img_source_prop) | $(ACP) $(SOONG_ZIP)
@echo Packaging SDK Addon System-Image: $@
$(hide) mkdir -p $(dir $@)
$(ACP) -r $(PRODUCT_OUT)/data $(PRIVATE_STAGING_DIR)/data
- $(hide) ( F=$$(pwd)/$@ ; cd $(PRIVATE_STAGING_DIR)/.. && zip -rqX $$F $(notdir $(PRIVATE_STAGING_DIR)) )
+ $(hide) $(SOONG_ZIP) -o $@ -C $(dir $(PRIVATE_STAGING_DIR)) -D $(PRIVATE_STAGING_DIR)
.PHONY: sdk_addon
diff --git a/core/tasks/test_mapping.mk b/core/tasks/test_mapping.mk
new file mode 100644
index 0000000..36275b0
--- /dev/null
+++ b/core/tasks/test_mapping.mk
@@ -0,0 +1,34 @@
+# 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.
+
+# Create an artifact to include TEST_MAPPING files in source tree.
+
+.PHONY: test_mapping
+
+intermediates := $(call intermediates-dir-for,PACKAGING,test_mapping)
+test_mappings_zip := $(intermediates)/test_mappings.zip
+test_mapping_list := $(OUT_DIR)/.module_paths/TEST_MAPPING.list
+test_mappings := $(file <$(test_mapping_list))
+$(test_mappings_zip) : PRIVATE_test_mappings := $(subst $(newline),\n,$(test_mappings))
+
+$(test_mappings_zip) : $(test_mappings) $(SOONG_ZIP)
+ @echo "Building artifact to include TEST_MAPPING files."
+ rm -rf $@
+ echo -e "$(PRIVATE_test_mappings)" > $@.list
+ $(SOONG_ZIP) -o $@ -C . -l $@.list
+ rm -f $@.list
+
+test_mapping : $(test_mappings_zip)
+
+$(call dist-for-goals, dist_files test_mapping,$(test_mappings_zip))
diff --git a/core/tasks/tools/build_custom_image.mk b/core/tasks/tools/build_custom_image.mk
index 719279c..a1151e9 100644
--- a/core/tasks/tools/build_custom_image.mk
+++ b/core/tasks/tools/build_custom_image.mk
@@ -62,12 +62,16 @@
$(eval my_image_copy_files += $(src))\
$(eval my_copy_pairs += $(src):$(my_staging_dir)/$(word 2,$(pair))))
-ifndef CUSTOM_IMAGE_AVB_KEY_PATH
-# If key path isn't specified, use the default signing args.
-my_avb_signing_args := $(INTERNAL_AVB_SIGNING_ARGS)
-else
-my_avb_signing_args := \
- --algorithm $(CUSTOM_IMAGE_AVB_ALGORITHM) --key $(CUSTOM_IMAGE_AVB_KEY_PATH)
+ifdef CUSTOM_IMAGE_AVB_KEY_PATH
+ifndef CUSTOM_IMAGE_AVB_ALGORITHM
+ $(error CUSTOM_IMAGE_AVB_ALGORITHM is not defined)
+endif
+ifndef CUSTOM_IMAGE_AVB_ROLLBACK_INDEX
+ $(error CUSTOM_IMAGE_AVB_ROLLBACK_INDEX is not defined)
+endif
+# set rollback_index via footer args
+CUSTOM_IMAGE_AVB_ADD_HASH_FOOTER_ARGS += --rollback_index $(CUSTOM_IMAGE_AVB_ROLLBACK_INDEX)
+CUSTOM_IMAGE_AVB_ADD_HASHTREE_FOOTER_ARGS += --rollback_index $(CUSTOM_IMAGE_AVB_ROLLBACK_INDEX)
endif
$(my_built_custom_image): PRIVATE_INTERMEDIATES := $(intermediates)
@@ -84,7 +88,8 @@
$(my_built_custom_image): PRIVATE_VERITY_BLOCK_DEVICE := $(CUSTOM_IMAGE_VERITY_BLOCK_DEVICE)
$(my_built_custom_image): PRIVATE_DICT_FILE := $(CUSTOM_IMAGE_DICT_FILE)
$(my_built_custom_image): PRIVATE_AVB_AVBTOOL := $(AVBTOOL)
-$(my_built_custom_image): PRIVATE_AVB_SIGNING_ARGS := $(my_avb_signing_args)
+$(my_built_custom_image): PRIVATE_AVB_KEY_PATH := $(CUSTOM_IMAGE_AVB_KEY_PATH)
+$(my_built_custom_image): PRIVATE_AVB_ALGORITHM:= $(CUSTOM_IMAGE_AVB_ALGORITHM)
$(my_built_custom_image): PRIVATE_AVB_HASH_ENABLE := $(CUSTOM_IMAGE_AVB_HASH_ENABLE)
$(my_built_custom_image): PRIVATE_AVB_ADD_HASH_FOOTER_ARGS := $(CUSTOM_IMAGE_AVB_ADD_HASH_FOOTER_ARGS)
$(my_built_custom_image): PRIVATE_AVB_HASHTREE_ENABLE := $(CUSTOM_IMAGE_AVB_HASHTREE_ENABLE)
@@ -130,8 +135,11 @@
echo "verity_block_device=$(PRIVATE_VERITY_BLOCK_DEVICE)" >> $(PRIVATE_INTERMEDIATES)/image_info.txt)
$(if $(PRIVATE_SUPPORT_VERITY_FEC),\
$(hide) echo "verity_fec=$(PRIVATE_SUPPORT_VERITY_FEC)" >> $(PRIVATE_INTERMEDIATES)/image_info.txt)
+ $(if $(filter eng, $(TARGET_BUILD_VARIANT)),$(hide) echo "verity_disable=true" >> $(PRIVATE_INTERMEDIATES)/image_info.txt)
$(hide) echo "avb_avbtool=$(PRIVATE_AVB_AVBTOOL)" >> $(PRIVATE_INTERMEDIATES)/image_info.txt
- $(hide) echo "avb_signing_args=$(PRIVATE_AVB_SIGNING_ARGS)" >> $(PRIVATE_INTERMEDIATES)/image_info.txt
+ $(if $(PRIVATE_AVB_KEY_PATH),\
+ $(hide) echo "avb_key_path=$(PRIVATE_AVB_KEY_PATH)" >> $(PRIVATE_INTERMEDIATES)/image_info.txt;\
+ echo "avb_algorithm=$(PRIVATE_AVB_ALGORITHM)" >> $(PRIVATE_INTERMEDIATES)/image_info.txt)
$(if $(PRIVATE_AVB_HASH_ENABLE),\
$(hide) echo "avb_hash_enable=$(PRIVATE_AVB_HASH_ENABLE)" >> $(PRIVATE_INTERMEDIATES)/image_info.txt;\
echo "avb_add_hash_footer_args=$(PRIVATE_AVB_ADD_HASH_FOOTER_ARGS)" >> $(PRIVATE_INTERMEDIATES)/image_info.txt)
@@ -143,9 +151,9 @@
cat $(PRIVATE_DICT_FILE) >> $(PRIVATE_INTERMEDIATES)/image_info.txt)
# Generate the image.
$(if $(filter oem,$(PRIVATE_MOUNT_POINT)), \
- $(hide) echo "oem.buildnumber=$(BUILD_NUMBER)" >> $(PRIVATE_STAGING_DIR)/oem.prop)
+ $(hide) echo "oem.buildnumber=$(BUILD_NUMBER_FROM_FILE)" >> $(PRIVATE_STAGING_DIR)/oem.prop)
$(hide) PATH=$(foreach p,$(INTERNAL_USERIMAGES_BINARY_PATHS),$(p):)$$PATH \
- ./build/tools/releasetools/build_image.py \
+ build/make/tools/releasetools/build_image.py \
$(PRIVATE_STAGING_DIR) $(PRIVATE_INTERMEDIATES)/image_info.txt $@ $(TARGET_OUT)
my_installed_custom_image := $(PRODUCT_OUT)/$(notdir $(my_built_custom_image))
diff --git a/core/tasks/tools/compatibility.mk b/core/tasks/tools/compatibility.mk
index 0fc2045..3d1d783 100644
--- a/core/tasks/tools/compatibility.mk
+++ b/core/tasks/tools/compatibility.mk
@@ -21,6 +21,8 @@
# test_suite_readme: the path to a README file for this test suite
# test_suite_prebuilt_tools: the set of prebuilt tools to be included directly
# in the 'tools' subdirectory of the test suite.
+# test_suite_tools: the set of tools for this test suite
+#
# Output variables:
# compatibility_zip: the path to the output zip file.
@@ -28,6 +30,7 @@
test_artifacts := $(COMPATIBILITY.$(test_suite_name).FILES)
test_tools := $(HOST_OUT_JAVA_LIBRARIES)/hosttestlib.jar \
$(HOST_OUT_JAVA_LIBRARIES)/tradefed.jar \
+ $(HOST_OUT_JAVA_LIBRARIES)/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 \
@@ -38,6 +41,8 @@
$(HOST_OUT_EXECUTABLES)/$(test_suite_tradefed) \
$(test_suite_readme)
+test_tools += $(test_suite_tools)
+
compatibility_zip := $(out_dir).zip
$(compatibility_zip): PRIVATE_NAME := android-$(test_suite_name)
$(compatibility_zip): PRIVATE_OUT_DIR := $(out_dir)
@@ -59,3 +64,4 @@
test_suite_dynamic_config :=
test_suite_readme :=
test_suite_prebuilt_tools :=
+test_suite_tools :=
diff --git a/core/tasks/tools/package-modules.mk b/core/tasks/tools/package-modules.mk
index 629a9b2..4155a39 100644
--- a/core/tasks/tools/package-modules.mk
+++ b/core/tasks/tools/package-modules.mk
@@ -28,9 +28,10 @@
# Ignore unknown installed files on partial builds
my_missing_files :=
-ifneq ($(ALLOW_MISSING_DEPENDENCIES),true)
-my_missing_files = $(shell $(call echo-warning,$(my_makefile),$(my_package_name): Unknown installed file for module '$(1)'))
-endif
+# These warnings are too noisy, silence them for now.
+#ifneq ($(ALLOW_MISSING_DEPENDENCIES),true)
+#my_missing_files = $(shell $(call echo-warning,$(my_makefile),$(my_package_name): Unknown installed file for module '$(1)'))
+#endif
# Iterate over modules' built files and installed files;
# Calculate the dest files in the output zip file.
diff --git a/core/tasks/tradefed-tests-list.mk b/core/tasks/tradefed-tests-list.mk
new file mode 100644
index 0000000..bcbdfcf
--- /dev/null
+++ b/core/tasks/tradefed-tests-list.mk
@@ -0,0 +1,38 @@
+# 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.
+
+# List all TradeFed tests from COMPATIBILITY.tradefed_tests_dir
+.PHONY: tradefed-tests-list
+
+tradefed_tests :=
+$(foreach dir, $(COMPATIBILITY.tradefed_tests_dir), \
+ $(eval tradefed_tests += $(shell find $(dir) -type f -name "*.xml")))
+tradefed_tests_list_intermediates := $(call intermediates-dir-for,PACKAGING,tradefed_tests_list,HOST,COMMON)
+tradefed_tests_list_zip := $(tradefed_tests_list_intermediates)/tradefed-tests_list.zip
+all_tests :=
+$(foreach test, $(tradefed_tests), \
+ $(eval all_tests += $(word 2,$(subst /res/config/,$(space),$(test)))))
+$(tradefed_tests_list_zip) : PRIVATE_tradefed_tests := $(subst .xml,,$(subst $(space),\n,$(sort $(all_tests))))
+$(tradefed_tests_list_zip) : PRIVATE_tradefed_tests_list := $(tradefed_tests_list_intermediates)/tradefed-tests_list
+
+$(tradefed_tests_list_zip) : $(tradefed_tests) $(SOONG_ZIP)
+ @echo "Package: $@"
+ $(hide) rm -rf $(dir $@) && mkdir -p $(dir $@)
+ $(hide) echo -e "$(PRIVATE_tradefed_tests)" > $(PRIVATE_tradefed_tests_list)
+ $(hide) $(SOONG_ZIP) -d -o $@ -C $(dir $@) -f $(PRIVATE_tradefed_tests_list)
+
+tradefed-tests-list : $(tradefed_tests_list_zip)
+$(call dist-for-goals, tradefed-tests-list, $(tradefed_tests_list_zip))
+
+tests: tradefed-tests-list
diff --git a/core/tasks/vendor_module_check.mk b/core/tasks/vendor_module_check.mk
index ae967c6..6695994 100644
--- a/core/tasks/vendor_module_check.mk
+++ b/core/tasks/vendor_module_check.mk
@@ -44,6 +44,7 @@
ti \
trusted_logic \
verizon \
+ waves \
widevine
diff --git a/core/tasks/vndk.mk b/core/tasks/vndk.mk
new file mode 100644
index 0000000..b9133df
--- /dev/null
+++ b/core/tasks/vndk.mk
@@ -0,0 +1,264 @@
+# 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.
+
+current_makefile := $(lastword $(MAKEFILE_LIST))
+
+# BOARD_VNDK_VERSION must be set to 'current' in order to generate a VNDK snapshot.
+ifeq ($(BOARD_VNDK_VERSION),current)
+
+# PLATFORM_VNDK_VERSION must be set.
+ifneq (,$(PLATFORM_VNDK_VERSION))
+
+# BOARD_VNDK_RUNTIME_DISABLE must not be set to 'true'.
+ifneq ($(BOARD_VNDK_RUNTIME_DISABLE),true)
+
+# Returns arch-specific libclang_rt.ubsan* library name.
+# Because VNDK_CORE_LIBRARIES includes all arch variants for libclang_rt.ubsan*
+# libs, the arch-specific libs are selected separately.
+#
+# Args:
+# $(1): if not empty, evaluates for TARGET_2ND_ARCH
+define clang-ubsan-vndk-core
+$(strip \
+ $(eval prefix := $(if $(1),2ND_,)) \
+ $(addsuffix .vendor,$($(addprefix $(prefix),UBSAN_RUNTIME_LIBRARY))) \
+)
+endef
+
+# Returns list of file paths of the intermediate objs
+#
+# Args:
+# $(1): list of module and filename pairs (e.g., ld.config.txt:ld.config.27.txt ...)
+# $(2): target class (e.g., SHARED_LIBRARIES, STATIC_LIBRARIES, ETC)
+# $(3): if not empty, evaluates for TARGET_2ND_ARCH
+define paths-of-intermediates
+$(strip \
+ $(foreach pair,$(1), \
+ $(eval split_pair := $(subst :,$(space),$(pair))) \
+ $(eval module := $(word 1,$(split_pair))) \
+ $(eval filename := $(word 2,$(split_pair))) \
+ $(eval dir := $(call intermediates-dir-for,$(2),$(module),,,$(3))) \
+ $(call append-path,$(dir),$(filename)) \
+ ) \
+)
+endef
+
+# Returns paths of notice files under $(TARGET_OUT_NOTICE_FILES)
+#
+# Args:
+# $(1): list of lib names (e.g., libfoo.vendor)
+# $(2): vndk lib type, one of 'vndk' or 'vndk-sp'
+define paths-of-notice-files
+$(strip \
+ $(eval lib_dir := lib$(if $(TARGET_IS_64BIT),64,)) \
+ $(eval vndk_dir := $(2)-$(PLATFORM_VNDK_VERSION)) \
+ $(foreach lib,$(1), \
+ $(eval notice_file_name := $(patsubst %.vendor,%.so.txt,$(lib))) \
+ $(TARGET_OUT_NOTICE_FILES)/src/system/$(lib_dir)/$(vndk_dir)/$(notice_file_name) \
+ ) \
+)
+endef
+
+# If in the future libclang_rt.ubsan* is removed from the VNDK-core list,
+# need to update the related logic in this file.
+ifeq (,$(filter libclang_rt.ubsan%,$(VNDK_CORE_LIBRARIES)))
+ $(warning libclang_rt.ubsan* is no longer a VNDK-core library. Please update this file.)
+ vndk_core_libs := $(addsuffix .vendor,$(VNDK_CORE_LIBRARIES))
+else
+ vndk_core_libs := $(addsuffix .vendor,$(filter-out libclang_rt.ubsan%,$(VNDK_CORE_LIBRARIES)))
+
+ vndk_core_libs += $(call clang-ubsan-vndk-core)
+ ifdef TARGET_2ND_ARCH
+ vndk_core_libs += $(call clang-ubsan-vndk-core,true)
+ endif
+endif
+
+vndk_sp_libs := $(addsuffix .vendor,$(VNDK_SAMEPROCESS_LIBRARIES))
+vndk_private_libs := $(addsuffix .vendor,$(VNDK_PRIVATE_LIBRARIES))
+
+vndk_snapshot_libs := \
+ $(vndk_core_libs) \
+ $(vndk_sp_libs)
+
+vndk_prebuilt_txts := \
+ ld.config.txt \
+ vndksp.libraries.txt \
+ llndk.libraries.txt
+
+vndk_snapshot_top := $(call intermediates-dir-for,PACKAGING,vndk-snapshot)
+vndk_snapshot_out := $(vndk_snapshot_top)/vndk-snapshot
+vndk_snapshot_configs_out := $(vndk_snapshot_top)/configs
+
+#######################################
+# vndkcore.libraries.txt
+vndkcore.libraries.txt := $(vndk_snapshot_configs_out)/vndkcore.libraries.txt
+$(vndkcore.libraries.txt): $(vndk_core_libs)
+ @echo 'Generating: $@'
+ @rm -f $@
+ @mkdir -p $(dir $@)
+ $(hide) echo -n > $@
+ $(hide) $(foreach lib,$^,echo $(patsubst %.vendor,%,$(lib)).so >> $@;)
+
+
+#######################################
+# vndkprivate.libraries.txt
+vndkprivate.libraries.txt := $(vndk_snapshot_configs_out)/vndkprivate.libraries.txt
+$(vndkprivate.libraries.txt): $(vndk_private_libs)
+ @echo 'Generating: $@'
+ @rm -f $@
+ @mkdir -p $(dir $@)
+ $(hide) echo -n > $@
+ $(hide) $(foreach lib,$^,echo $(patsubst %.vendor,%,$(lib)).so >> $@;)
+
+
+#######################################
+# module_paths.txt
+module_paths.txt := $(vndk_snapshot_configs_out)/module_paths.txt
+$(module_paths.txt): $(vndk_snapshot_libs)
+ @echo 'Generating: $@'
+ @rm -f $@
+ @mkdir -p $(dir $@)
+ $(hide) echo -n > $@
+ $(hide) $(foreach lib,$^,echo $(patsubst %.vendor,%,$(lib)).so $(ALL_MODULES.$(lib).PATH) >> $@;)
+
+
+vndk_snapshot_configs := \
+ $(vndkcore.libraries.txt) \
+ $(vndkprivate.libraries.txt) \
+ $(module_paths.txt)
+
+#######################################
+# vndk_snapshot_zip
+vndk_snapshot_variant := $(vndk_snapshot_out)/$(TARGET_ARCH)
+binder :=
+ifneq ($(TARGET_USES_64_BIT_BINDER), true)
+ binder := binder32
+endif
+vndk_lib_dir := $(subst $(space),/,$(strip $(vndk_snapshot_variant) $(binder) arch-$(TARGET_ARCH)-$(TARGET_ARCH_VARIANT)))
+vndk_lib_dir_2nd := $(subst $(space),/,$(strip $(vndk_snapshot_variant) $(binder) arch-$(TARGET_2ND_ARCH)-$(TARGET_2ND_ARCH_VARIANT)))
+vndk_snapshot_zip := $(PRODUCT_OUT)/android-vndk-$(TARGET_PRODUCT).zip
+
+$(vndk_snapshot_zip): PRIVATE_VNDK_SNAPSHOT_OUT := $(vndk_snapshot_out)
+
+$(vndk_snapshot_zip): PRIVATE_VNDK_CORE_OUT := $(vndk_lib_dir)/shared/vndk-core
+$(vndk_snapshot_zip): PRIVATE_VNDK_CORE_INTERMEDIATES := \
+ $(call paths-of-intermediates,$(foreach lib,$(vndk_core_libs),$(lib):$(lib).so),SHARED_LIBRARIES)
+
+$(vndk_snapshot_zip): PRIVATE_VNDK_SP_OUT := $(vndk_lib_dir)/shared/vndk-sp
+$(vndk_snapshot_zip): PRIVATE_VNDK_SP_INTERMEDIATES := \
+ $(call paths-of-intermediates,$(foreach lib,$(vndk_sp_libs),$(lib):$(lib).so),SHARED_LIBRARIES)
+
+$(vndk_snapshot_zip): PRIVATE_CONFIGS_OUT := $(vndk_snapshot_variant)/configs
+$(vndk_snapshot_zip): PRIVATE_CONFIGS_INTERMEDIATES := \
+ $(call paths-of-intermediates,$(foreach txt,$(vndk_prebuilt_txts), \
+ $(txt):$(patsubst %.txt,%.$(PLATFORM_VNDK_VERSION).txt,$(txt))),ETC) \
+ $(vndk_snapshot_configs)
+
+$(vndk_snapshot_zip): PRIVATE_NOTICE_FILES_OUT := $(vndk_snapshot_variant)/NOTICE_FILES
+$(vndk_snapshot_zip): PRIVATE_NOTICE_FILES_INTERMEDIATES := \
+ $(call paths-of-notice-files,$(vndk_core_libs),vndk) \
+ $(call paths-of-notice-files,$(vndk_sp_libs),vndk-sp)
+
+ifdef TARGET_2ND_ARCH
+$(vndk_snapshot_zip): PRIVATE_VNDK_CORE_OUT_2ND := $(vndk_lib_dir_2nd)/shared/vndk-core
+$(vndk_snapshot_zip): PRIVATE_VNDK_CORE_INTERMEDIATES_2ND := \
+ $(call paths-of-intermediates,$(foreach lib,$(vndk_core_libs),$(lib):$(lib).so),SHARED_LIBRARIES,true)
+
+$(vndk_snapshot_zip): PRIVATE_VNDK_SP_OUT_2ND := $(vndk_lib_dir_2nd)/shared/vndk-sp
+$(vndk_snapshot_zip): PRIVATE_VNDK_SP_INTERMEDIATES_2ND := \
+ $(call paths-of-intermediates,$(foreach lib,$(vndk_sp_libs),$(lib):$(lib).so),SHARED_LIBRARIES,true)
+endif
+
+# Args
+# $(1): destination directory
+# $(2): list of files to copy
+$(vndk_snapshot_zip): private-copy-vndk-intermediates = \
+ $(if $(2),$(strip \
+ @mkdir -p $(1); \
+ $(foreach file,$(2), \
+ if [ -e $(file) ]; then \
+ cp -p $(file) $(call append-path,$(1),$(subst .vendor,,$(notdir $(file)))); \
+ fi; \
+ ) \
+ ))
+
+vndk_snapshot_dependencies := \
+ $(vndk_snapshot_libs) \
+ $(vndk_prebuilt_txts) \
+ $(vndk_snapshot_configs)
+
+$(vndk_snapshot_zip): $(vndk_snapshot_dependencies) $(SOONG_ZIP)
+ @echo 'Generating VNDK snapshot: $@'
+ @rm -f $@
+ @rm -rf $(PRIVATE_VNDK_SNAPSHOT_OUT)
+ @mkdir -p $(PRIVATE_VNDK_SNAPSHOT_OUT)
+ $(call private-copy-vndk-intermediates, \
+ $(PRIVATE_VNDK_CORE_OUT),$(PRIVATE_VNDK_CORE_INTERMEDIATES))
+ $(call private-copy-vndk-intermediates, \
+ $(PRIVATE_VNDK_SP_OUT),$(PRIVATE_VNDK_SP_INTERMEDIATES))
+ $(call private-copy-vndk-intermediates, \
+ $(PRIVATE_CONFIGS_OUT),$(PRIVATE_CONFIGS_INTERMEDIATES))
+ $(call private-copy-vndk-intermediates, \
+ $(PRIVATE_NOTICE_FILES_OUT),$(PRIVATE_NOTICE_FILES_INTERMEDIATES))
+ifdef TARGET_2ND_ARCH
+ $(call private-copy-vndk-intermediates, \
+ $(PRIVATE_VNDK_CORE_OUT_2ND),$(PRIVATE_VNDK_CORE_INTERMEDIATES_2ND))
+ $(call private-copy-vndk-intermediates, \
+ $(PRIVATE_VNDK_SP_OUT_2ND),$(PRIVATE_VNDK_SP_INTERMEDIATES_2ND))
+endif
+ $(hide) $(SOONG_ZIP) -o $@ -C $(PRIVATE_VNDK_SNAPSHOT_OUT) -D $(PRIVATE_VNDK_SNAPSHOT_OUT)
+
+.PHONY: vndk
+vndk: $(vndk_snapshot_zip)
+
+$(call dist-for-goals, vndk, $(vndk_snapshot_zip))
+
+# clear global vars
+clang-ubsan-vndk-core :=
+paths-of-intermediates :=
+paths-of-notice-files :=
+vndk_core_libs :=
+vndk_sp_libs :=
+vndk_snapshot_libs :=
+vndk_prebuilt_txts :=
+vndk_snapshot_configs :=
+vndk_snapshot_top :=
+vndk_snapshot_out :=
+vndk_snapshot_configs_out :=
+vndk_snapshot_variant :=
+binder :=
+vndk_lib_dir :=
+vndk_lib_dir_2nd :=
+vndk_snapshot_dependencies :=
+
+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
+
+else # BOARD_VNDK_VERSION is NOT set to 'current'
+error_msg := "CANNOT generate VNDK snapshot. BOARD_VNDK_VERSION must be set to 'current'."
+endif # BOARD_VNDK_VERSION
+
+ifneq (,$(error_msg))
+
+.PHONY: vndk
+vndk:
+ $(call echo-error,$(current_makefile),$(error_msg))
+ exit 1
+
+endif
diff --git a/core/test_config_common.mk b/core/test_config_common.mk
new file mode 100644
index 0000000..487f9f2
--- /dev/null
+++ b/core/test_config_common.mk
@@ -0,0 +1,56 @@
+#
+# 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/verify_uses_libraries.sh b/core/verify_uses_libraries.sh
new file mode 100755
index 0000000..8135be6
--- /dev/null
+++ b/core/verify_uses_libraries.sh
@@ -0,0 +1,45 @@
+#!/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.
+
+
+# Parse sdk, targetSdk, and uses librares in the APK, then cross reference against build specified ones.
+
+set -e
+local_apk=$1
+badging=$(aapt dump badging "${local_apk}")
+export sdk_version=$(echo "${badging}" | grep "sdkVersion" | sed -n "s/sdkVersion:'\(.*\)'/\1/p")
+# Export target_sdk_version to the caller.
+export target_sdk_version=$(echo "${badging}" | grep "targetSdkVersion" | sed -n "s/targetSdkVersion:'\(.*\)'/\1/p")
+uses_libraries=$(echo "${badging}" | grep "uses-library" | sed -n "s/uses-library:'\(.*\)'/\1/p")
+optional_uses_libraries=$(echo "${badging}" | grep "uses-library-not-required" | sed -n "s/uses-library-not-required:'\(.*\)'/\1/p")
+
+# Verify that the uses libraries match exactly.
+# Currently we validate the ordering of the libraries since it matters for resolution.
+single_line_libs=$(echo "${uses_libraries}" | tr '\n' ' ' | awk '{$1=$1}1')
+if [[ "${single_line_libs}" != "${uses_library_names}" ]]; then
+ echo "LOCAL_USES_LIBRARIES (${uses_library_names})" \
+ "do not match (${single_line_libs}) in manifest for ${local_apk}"
+ exit 1
+fi
+
+# Verify that the optional uses libraries match exactly.
+single_line_optional_libs=$(echo "${optional_uses_libraries}" | tr '\n' ' ' | awk '{$1=$1}1')
+if [[ "${single_line_optional_libs}" != "${optional_uses_library_names}" ]]; then
+ echo "LOCAL_OPTIONAL_USES_LIBRARIES (${optional_uses_library_names}) " \
+ "do not match (${single_line_optional_libs}) in manifest for ${local_apk}"
+ exit 1
+fi
+
diff --git a/core/version_defaults.mk b/core/version_defaults.mk
index 5193eb2..80e5007 100644
--- a/core/version_defaults.mk
+++ b/core/version_defaults.mk
@@ -24,8 +24,9 @@
# DEFAULT_APP_TARGET_SDK
# BUILD_ID
# BUILD_NUMBER
-# BUILD_DATETIME
# PLATFORM_SECURITY_PATCH
+# PLATFORM_VNDK_VERSION
+# PLATFORM_SYSTEMSDK_VERSIONS
#
# Look for an optional file containing overrides of the defaults,
@@ -38,9 +39,9 @@
include $(INTERNAL_BUILD_ID_MAKEFILE)
endif
-DEFAULT_PLATFORM_VERSION := OPM1
-MIN_PLATFORM_VERSION := OPM1
-MAX_PLATFORM_VERSION := OPM1
+DEFAULT_PLATFORM_VERSION := PPR1
+MIN_PLATFORM_VERSION := PPR1
+MAX_PLATFORM_VERSION := PPR1
ALLOWED_VERSIONS := $(call allowed-platform-versions,\
$(MIN_PLATFORM_VERSION),\
@@ -74,11 +75,11 @@
# please add that PLATFORM_VERSION as well as clean up obsolete PLATFORM_VERSION's
# in the following text file:
# cts/tests/tests/os/assets/platform_versions.txt
-PLATFORM_VERSION.OPM1 := 8.1.0
+PLATFORM_VERSION.PPR1 := 9
# 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.OPM1 := REL
+PLATFORM_VERSION_CODENAME.PPR1 := REL
ifndef PLATFORM_VERSION
PLATFORM_VERSION := $(PLATFORM_VERSION.$(TARGET_PLATFORM_VERSION))
@@ -105,16 +106,7 @@
# When you increment the PLATFORM_SDK_VERSION please ensure you also
# clear out the following text file of all older PLATFORM_VERSION's:
# cts/tests/tests/os/assets/platform_versions.txt
- PLATFORM_SDK_VERSION := 27
-endif
-
-ifndef PLATFORM_JACK_MIN_SDK_VERSION
- # This is definition of the min SDK version given to Jack for the current
- # platform. For released version it should be the same as
- # PLATFORM_SDK_VERSION. During development, this number may be incremented
- # before PLATFORM_SDK_VERSION if the platform starts to add new java
- # language supports.
- PLATFORM_JACK_MIN_SDK_VERSION := o-b1
+ PLATFORM_SDK_VERSION := 28
endif
ifndef PLATFORM_VERSION_CODENAME
@@ -124,14 +116,17 @@
PLATFORM_VERSION_CODENAME := $(TARGET_PLATFORM_VERSION)
endif
- # This is all of the development codenames that are active. Should be either
- # the same as PLATFORM_VERSION_CODENAME or a comma-separated list of additional
- # codenames after PLATFORM_VERSION_CODENAME.
+ # This is all of the *active* development codenames. There are future
+ # codenames not included in this list. This confusing name is needed because
+ # all_codenames has been baked into build.prop for ages.
+ #
+ # Should be either the same as PLATFORM_VERSION_CODENAME or a comma-separated
+ # list of additional codenames after PLATFORM_VERSION_CODENAME.
PLATFORM_VERSION_ALL_CODENAMES :=
- # Build a list of all possible code names. Avoid duplicates, and stop when we
+ # Build a list of all active code names. Avoid duplicates, and stop when we
# reach a codename that matches PLATFORM_VERSION_CODENAME (anything beyond
- # that is not included in our build.
+ # that is not included in our build).
_versions_in_target := \
$(call find_and_earlier,$(ALL_VERSIONS),$(TARGET_PLATFORM_VERSION))
$(foreach version,$(_versions_in_target),\
@@ -139,9 +134,23 @@
$(if $(filter $(_codename),$(PLATFORM_VERSION_ALL_CODENAMES)),,\
$(eval PLATFORM_VERSION_ALL_CODENAMES += $(_codename))))
+ # This is all of the inactive development codenames. Available to be targeted
+ # in this branch but in the future relative to our current target.
+ PLATFORM_VERSION_FUTURE_CODENAMES :=
+
+ # Build a list of all untargeted code names. Avoid duplicates.
+ _versions_not_in_target := \
+ $(filter-out $(PLATFORM_VERSION_ALL_CODENAMES),$(ALL_VERSIONS))
+ $(foreach version,$(_versions_not_in_target),\
+ $(eval _codename := $(PLATFORM_VERSION_CODENAME.$(version)))\
+ $(if $(filter $(_codename),$(PLATFORM_VERSION_FUTURE_CODENAMES)),,\
+ $(eval PLATFORM_VERSION_FUTURE_CODENAMES += $(_codename))))
+
# And convert from space separated to comma separated.
PLATFORM_VERSION_ALL_CODENAMES := \
$(subst $(space),$(comma),$(strip $(PLATFORM_VERSION_ALL_CODENAMES)))
+ PLATFORM_VERSION_FUTURE_CODENAMES := \
+ $(subst $(space),$(comma),$(strip $(PLATFORM_VERSION_FUTURE_CODENAMES)))
endif
@@ -175,6 +184,47 @@
endif
endif
+ifndef PLATFORM_VNDK_VERSION
+ # This is the definition of the VNDK version for the current VNDK libraries.
+ # The version is only available when PLATFORM_VERSION_CODENAME == REL.
+ # Otherwise, it will be set to a CODENAME version. The ABI is allowed to be
+ # changed only before the Android version is released. Once
+ # PLATFORM_VNDK_VERSION is set to actual version, the ABI for this version
+ # will be frozon and emit build errors if any ABI for the VNDK libs are
+ # changed.
+ # After that the snapshot of the VNDK with this version will be generated.
+ #
+ # The VNDK version follows PLATFORM_SDK_VERSION.
+ ifeq (REL,$(PLATFORM_VERSION_CODENAME))
+ PLATFORM_VNDK_VERSION := $(PLATFORM_SDK_VERSION)
+ else
+ PLATFORM_VNDK_VERSION := $(PLATFORM_VERSION_CODENAME)
+ endif
+endif
+
+ifndef PLATFORM_SYSTEMSDK_MIN_VERSION
+ # This is the oldest version of system SDK that the platform supports. Contrary
+ # to the public SDK where platform essentially supports all previous SDK versions,
+ # platform supports only a few number of recent system SDK versions as some of
+ # old system APIs are gradually deprecated, removed and then deleted.
+ PLATFORM_SYSTEMSDK_MIN_VERSION := 28
+endif
+
+# This is the list of system SDK versions that the current platform supports.
+PLATFORM_SYSTEMSDK_VERSIONS :=
+ifneq (,$(PLATFORM_SYSTEMSDK_MIN_VERSION))
+ $(if $(call math_is_number,$(PLATFORM_SYSTEMSDK_MIN_VERSION)),,\
+ $(error PLATFORM_SYSTEMSDK_MIN_VERSION must be a number, but was $(PLATFORM_SYSTEMSDK_MIN_VERSION)))
+ PLATFORM_SYSTEMSDK_VERSIONS := $(call int_range_list,$(PLATFORM_SYSTEMSDK_MIN_VERSION),$(PLATFORM_SDK_VERSION))
+endif
+# Platform always supports the current version
+ifeq (REL,$(PLATFORM_VERSION_CODENAME))
+ PLATFORM_SYSTEMSDK_VERSIONS += $(PLATFORM_SDK_VERSION)
+else
+ PLATFORM_SYSTEMSDK_VERSIONS += $(PLATFORM_VERSION_CODENAME)
+endif
+PLATFORM_SYSTEMSDK_VERSIONS := $(strip $(sort $(PLATFORM_SYSTEMSDK_VERSIONS)))
+
ifndef PLATFORM_SECURITY_PATCH
# Used to indicate the security patch that has been applied to the device.
# It must signify that the build includes all security patches issued up through the designated Android Public Security Bulletin.
@@ -184,6 +234,16 @@
PLATFORM_SECURITY_PATCH := 2019-05-05
endif
+ifndef PLATFORM_SECURITY_PATCH_TIMESTAMP
+ # Used to indicate the matching timestamp for the security patch string in PLATFORM_SECURITY_PATCH.
+ ifneq (,$(findstring Darwin,$(UNAME)))
+ PLATFORM_SECURITY_PATCH_TIMESTAMP := $(shell date -jf '%Y-%m-%d %T %Z' '$(PLATFORM_SECURITY_PATCH) 00:00:00 GMT' +%s)
+ else
+ PLATFORM_SECURITY_PATCH_TIMESTAMP := $(shell date -d 'TZ="GMT" $(PLATFORM_SECURITY_PATCH)' +%s)
+ endif
+endif
+.KATI_READONLY := PLATFORM_SECURITY_PATCH_TIMESTAMP
+
ifndef PLATFORM_BASE_OS
# Used to indicate the base os applied to the device.
# Can be an arbitrary string, but must be a single word.
@@ -207,12 +267,18 @@
BUILD_DATETIME := $(shell date +%s)
endif
-ifneq (,$(findstring Darwin,$(shell uname -sm)))
+ifneq (,$(findstring Darwin,$(UNAME)))
DATE := date -r $(BUILD_DATETIME)
else
DATE := date -d @$(BUILD_DATETIME)
endif
+# Everything should be using BUILD_DATETIME_FROM_FILE instead.
+# BUILD_DATETIME and DATE can be removed once BUILD_NUMBER moves
+# to soong_ui.
+BUILD_DATETIME :=
+
+HAS_BUILD_NUMBER := true
ifndef BUILD_NUMBER
# BUILD_NUMBER should be set to the source control value that
# represents the current state of the source code. E.g., a
@@ -224,4 +290,12 @@
# from this date/time" value. Make it start with a non-digit so that
# anyone trying to parse it as an integer will probably get "0".
BUILD_NUMBER := eng.$(shell echo $${USER:0:6}).$(shell $(DATE) +%Y%m%d.%H%M%S)
+ HAS_BUILD_NUMBER := false
+endif
+
+ifndef PLATFORM_MIN_SUPPORTED_TARGET_SDK_VERSION
+ # Used to set minimum supported target sdk version. Apps targeting sdk
+ # version lower than the set value will fail to install and run on android
+ # device.
+ PLATFORM_MIN_SUPPORTED_TARGET_SDK_VERSION := 17
endif
diff --git a/envsetup.sh b/envsetup.sh
index 4cbe3e7..cf61950 100644
--- a/envsetup.sh
+++ b/envsetup.sh
@@ -1,8 +1,14 @@
function hmm() {
cat <<EOF
+
+Run "m help" for help with the build system itself.
+
Invoke ". build/envsetup.sh" from your shell to add the following functions to your environment:
- lunch: lunch <product_name>-<build_variant>
-- tapas: tapas [<App1> <App2> ...] [arm|x86|mips|armv5|arm64|x86_64|mips64] [eng|userdebug|user]
+ 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]
- croot: Changes directory to the top of the tree.
- m: Makes from the top of the tree.
- mm: Builds all of the modules in the current directory, but not their dependencies.
@@ -45,20 +51,18 @@
cached_vars=`cat $T/build/envsetup.sh | tr '()' ' ' | awk '{for(i=1;i<=NF;i++) if($i~/get_build_var/) print $(i+1)}' | sort -u | tr '\n' ' '`
cached_abs_vars=`cat $T/build/envsetup.sh | tr '()' ' ' | awk '{for(i=1;i<=NF;i++) if($i~/get_abs_build_var/) print $(i+1)}' | sort -u | tr '\n' ' '`
# Call the build system to dump the "<val>=<value>" pairs as a shell script.
- build_dicts_script=`\cd $T; CALLED_FROM_SETUP=true BUILD_SYSTEM=build/core \
- command make --no-print-directory -f build/core/config.mk \
- dump-many-vars \
- DUMP_MANY_VARS="$cached_vars" \
- DUMP_MANY_ABS_VARS="$cached_abs_vars" \
- DUMP_VAR_PREFIX="var_cache_" \
- DUMP_ABS_VAR_PREFIX="abs_var_cache_"`
+ build_dicts_script=`\builtin cd $T; build/soong/soong_ui.bash --dumpvars-mode \
+ --vars="$cached_vars" \
+ --abs-vars="$cached_abs_vars" \
+ --var-prefix=var_cache_ \
+ --abs-var-prefix=abs_var_cache_`
local ret=$?
if [ $ret -ne 0 ]
then
unset build_dicts_script
return $ret
fi
- # Excute the script to store the "<val>=<value>" pairs as shell variables.
+ # Execute the script to store the "<val>=<value>" pairs as shell variables.
eval "$build_dicts_script"
ret=$?
unset build_dicts_script
@@ -99,8 +103,7 @@
echo "Couldn't locate the top of the tree. Try setting TOP." >&2
return
fi
- (\cd $T; CALLED_FROM_SETUP=true BUILD_SYSTEM=build/core \
- command make --no-print-directory -f build/core/config.mk dumpvar-abs-$1)
+ (\cd $T; build/soong/soong_ui.bash --dumpvar-mode --abs $1)
}
# Get the exact value of a build variable.
@@ -117,8 +120,7 @@
echo "Couldn't locate the top of the tree. Try setting TOP." >&2
return
fi
- (\cd $T; CALLED_FROM_SETUP=true BUILD_SYSTEM=build/core \
- command make --no-print-directory -f build/core/config.mk dumpvar-$1)
+ (\cd $T; build/soong/soong_ui.bash --dumpvar-mode $1)
}
# check to see if the supplied product is one we can build
@@ -235,7 +237,12 @@
;;
esac
- export ANDROID_BUILD_PATHS=$(get_build_var ANDROID_BUILD_PATHS):$ANDROID_TOOLCHAIN:$ANDROID_TOOLCHAIN_2ND_ARCH:$ANDROID_DEV_SCRIPTS:
+ ANDROID_BUILD_PATHS=$(get_build_var ANDROID_BUILD_PATHS):$ANDROID_TOOLCHAIN
+ if [ -n "$ANDROID_TOOLCHAIN_2ND_ARCH" ]; then
+ ANDROID_BUILD_PATHS=$ANDROID_BUILD_PATHS:$ANDROID_TOOLCHAIN_2ND_ARCH
+ fi
+ ANDROID_BUILD_PATHS=$ANDROID_BUILD_PATHS:$ANDROID_DEV_SCRIPTS:
+ export ANDROID_BUILD_PATHS
# If prebuilts/android-emulator/<system>/ exists, prepend it to our PATH
# to ensure that the corresponding 'emulator' binaries are used.
@@ -258,13 +265,11 @@
export PATH=$ANDROID_BUILD_PATHS$PATH
export PYTHONPATH=$T/development/python-packages:$PYTHONPATH
- unset ANDROID_JAVA_TOOLCHAIN
- unset ANDROID_PRE_BUILD_PATHS
- if [ -n "$JAVA_HOME" ]; then
- export ANDROID_JAVA_TOOLCHAIN=$JAVA_HOME/bin
- export ANDROID_PRE_BUILD_PATHS=$ANDROID_JAVA_TOOLCHAIN:
- export PATH=$ANDROID_PRE_BUILD_PATHS$PATH
- fi
+ export ANDROID_JAVA_HOME=$(get_abs_build_var ANDROID_JAVA_HOME)
+ export JAVA_HOME=$ANDROID_JAVA_HOME
+ export ANDROID_JAVA_TOOLCHAIN=$(get_abs_build_var ANDROID_JAVA_TOOLCHAIN)
+ export ANDROID_PRE_BUILD_PATHS=$ANDROID_JAVA_TOOLCHAIN:
+ export PATH=$ANDROID_PRE_BUILD_PATHS$PATH
unset ANDROID_PRODUCT_OUT
export ANDROID_PRODUCT_OUT=$(get_abs_build_var PRODUCT_OUT)
@@ -297,7 +302,6 @@
function set_stuff_for_environment()
{
settitle
- set_java_home
setpaths
set_sequence_number
@@ -314,7 +318,12 @@
function settitle()
{
- if [ "$STAY_OFF_MY_LAWN" = "" ]; then
+ # This used to be opt-out with STAY_OFF_MY_LAWN, but this breaks folks
+ # actually using PROMPT_COMMAND (https://issuetracker.google.com/38402256),
+ # and the attempt to set the title doesn't do anything for the default
+ # window manager in debian right now, so switch it to opt-in for anyone
+ # who actually wants this.
+ if [ "$ANDROID_BUILD_SET_WINDOW_TITLE" = "true" ]; then
local arch=$(gettargetarch)
local product=$TARGET_PRODUCT
local variant=$TARGET_BUILD_VARIANT
@@ -651,10 +660,16 @@
# Run tapas with one or more app names (from LOCAL_PACKAGE_NAME)
function tapas()
{
- local arch="$(echo $* | xargs -n 1 echo | \grep -E '^(arm|x86|mips|armv5|arm64|x86_64|mips64)$' | xargs)"
+ 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 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|armv5|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|mips|arm64|x86_64|mips64|ldpi|mdpi|tvdpi|hdpi|xhdpi|xxhdpi|xxxhdpi|alldpi)$' | xargs)"
+
+ if [ "$showHelp" != "" ]; then
+ $(gettop)/build/make/tapasHelp.sh
+ return
+ fi
if [ $(echo $arch | wc -w) -gt 1 ]; then
echo "tapas: Error: Multiple build archs supplied: $arch"
@@ -673,7 +688,6 @@
case $arch in
x86) product=aosp_x86;;
mips) product=aosp_mips;;
- armv5) product=generic_armv5;;
arm64) product=aosp_arm64;;
x86_64) product=aosp_x86_64;;
mips64) product=aosp_mips64;;
@@ -702,7 +716,7 @@
function gettop
{
- local TOPFILE=build/core/envsetup.mk
+ 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)
@@ -727,33 +741,11 @@
fi
}
-# Return driver for "make", if any (eg. static analyzer)
-function getdriver()
-{
- local T="$1"
- test "$WITH_STATIC_ANALYZER" = "0" && unset WITH_STATIC_ANALYZER
- if [ -n "$WITH_STATIC_ANALYZER" ]; then
- # Use scan-build to collect all static analyzer reports into directory
- # /tmp/scan-build-yyyy-mm-dd-hhmmss-*
- # The clang compiler passed by --use-analyzer here is not important.
- # build/core/binary.mk will set CLANG_CXX and CLANG before calling
- # c++-analyzer and ccc-analyzer.
- local CLANG_VERSION=$(get_build_var LLVM_PREBUILTS_VERSION)
- local BUILD_OS=$(get_build_var BUILD_OS)
- local CLANG_DIR="$T/prebuilts/clang/host/${BUILD_OS}-x86/${CLANG_VERSION}"
- echo "\
-${CLANG_DIR}/tools/scan-build/bin/scan-build \
---use-analyzer ${CLANG_DIR}/bin/clang \
---status-bugs"
- fi
-}
-
function m()
{
local T=$(gettop)
- local DRV=$(getdriver $T)
if [ "$T" ]; then
- _wrap_build $DRV $T/build/soong/soong_ui.bash --make-mode $@
+ _wrap_build $T/build/soong/soong_ui.bash --make-mode $@
else
echo "Couldn't locate the top of the tree. Try setting TOP."
return 1
@@ -762,7 +754,7 @@
function findmakefile()
{
- local TOPFILE=build/core/envsetup.mk
+ local TOPFILE=build/make/core/envsetup.mk
local HERE=$PWD
local T=
while [ \( ! \( -f $TOPFILE \) \) -a \( $PWD != "/" \) ]; do
@@ -780,11 +772,10 @@
function mm()
{
local T=$(gettop)
- local DRV=$(getdriver $T)
# If we're sitting in the root of the build tree, just do a
# normal build.
if [ -f build/soong/soong_ui.bash ]; then
- _wrap_build $DRV $T/build/soong/soong_ui.bash --make-mode $@
+ _wrap_build $T/build/soong/soong_ui.bash --make-mode $@
else
# Find the closest Android.mk file.
local M=$(findmakefile)
@@ -819,7 +810,7 @@
if [ "1" = "${WITH_TIDY_ONLY}" -o "true" = "${WITH_TIDY_ONLY}" ]; then
MODULES=tidy_only
fi
- ONE_SHOT_MAKEFILE=$M _wrap_build $DRV $T/build/soong/soong_ui.bash --make-mode $MODULES $ARGS
+ ONE_SHOT_MAKEFILE=$M _wrap_build $T/build/soong/soong_ui.bash --make-mode $MODULES $ARGS
fi
fi
}
@@ -827,7 +818,6 @@
function mmm()
{
local T=$(gettop)
- local DRV=$(getdriver $T)
if [ "$T" ]; then
local MAKEFILE=
local MODULES=
@@ -887,7 +877,7 @@
fi
# Convert "/" to "-".
MODULES_IN_PATHS=${MODULES_IN_PATHS//\//-}
- ONE_SHOT_MAKEFILE="$MAKEFILE" _wrap_build $DRV $T/build/soong/soong_ui.bash --make-mode $DASH_ARGS $MODULES $MODULES_IN_PATHS $ARGS
+ ONE_SHOT_MAKEFILE="$MAKEFILE" _wrap_build $T/build/soong/soong_ui.bash --make-mode $DASH_ARGS $MODULES $MODULES_IN_PATHS $ARGS
else
echo "Couldn't locate the top of the tree. Try setting TOP."
return 1
@@ -897,9 +887,8 @@
function mma()
{
local T=$(gettop)
- local DRV=$(getdriver $T)
if [ -f build/soong/soong_ui.bash ]; then
- _wrap_build $DRV $T/build/soong/soong_ui.bash --make-mode $@
+ _wrap_build $T/build/soong/soong_ui.bash --make-mode $@
else
if [ ! "$T" ]; then
echo "Couldn't locate the top of the tree. Try setting TOP."
@@ -911,14 +900,13 @@
local MODULES_IN_PATHS=MODULES-IN-$(dirname ${M})
# Convert "/" to "-".
MODULES_IN_PATHS=${MODULES_IN_PATHS//\//-}
- _wrap_build $DRV $T/build/soong/soong_ui.bash --make-mode $@ $MODULES_IN_PATHS
+ _wrap_build $T/build/soong/soong_ui.bash --make-mode $@ $MODULES_IN_PATHS
fi
}
function mmma()
{
local T=$(gettop)
- local DRV=$(getdriver $T)
if [ "$T" ]; then
local DASH_ARGS=$(echo "$@" | awk -v RS=" " -v ORS=" " '/^-.*$/')
local DIRS=$(echo "$@" | awk -v RS=" " -v ORS=" " '/^[^-].*$/')
@@ -949,7 +937,7 @@
done
# Convert "/" to "-".
MODULES_IN_PATHS=${MODULES_IN_PATHS//\//-}
- _wrap_build $DRV $T/build/soong/soong_ui.bash --make-mode $DASH_ARGS $ARGS $MODULES_IN_PATHS
+ _wrap_build $T/build/soong/soong_ui.bash --make-mode $DASH_ARGS $ARGS $MODULES_IN_PATHS
else
echo "Couldn't locate the top of the tree. Try setting TOP."
return 1
@@ -972,7 +960,7 @@
function cproj()
{
- local TOPFILE=build/core/envsetup.mk
+ local TOPFILE=build/make/core/envsetup.mk
local HERE=$PWD
local T=
while [ \( ! \( -f $TOPFILE \) \) -a \( $PWD != "/" \) ]; do
@@ -1540,46 +1528,6 @@
\cd $T/$pathname
}
-# Force JAVA_HOME to point to java 1.7/1.8 if it isn't already set.
-function set_java_home() {
- # Clear the existing JAVA_HOME value if we set it ourselves, so that
- # we can reset it later, depending on the version of java the build
- # system needs.
- #
- # If we don't do this, the JAVA_HOME value set by the first call to
- # build/envsetup.sh will persist forever.
- if [ -n "$ANDROID_SET_JAVA_HOME" ]; then
- export JAVA_HOME=""
- fi
-
- if [ ! "$JAVA_HOME" ]; then
- if [ -n "$LEGACY_USE_JAVA7" ]; then
- echo Warning: Support for JDK 7 will be dropped. Switch to JDK 8.
- case `uname -s` in
- Darwin)
- export JAVA_HOME=$(/usr/libexec/java_home -v 1.7)
- ;;
- *)
- export JAVA_HOME=/usr/lib/jvm/java-7-openjdk-amd64
- ;;
- esac
- else
- case `uname -s` in
- Darwin)
- export JAVA_HOME=$(/usr/libexec/java_home -v 1.8)
- ;;
- *)
- export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64
- ;;
- esac
- fi
-
- # Keep track of the fact that we set JAVA_HOME ourselves, so that
- # we can change it on the next envsetup.sh, if required.
- export ANDROID_SET_JAVA_HOME=true
- fi
-}
-
# Print colored exit condition
function pez {
"$@"
@@ -1597,6 +1545,13 @@
{
# If we're in the top of an Android tree, use soong_ui.bash instead of make
if [ -f build/soong/soong_ui.bash ]; then
+ # Always use the real make if -C is passed in
+ for arg in "$@"; do
+ if [[ $arg == -C* ]]; then
+ echo command make
+ return
+ fi
+ done
echo build/soong/soong_ui.bash --make-mode
else
echo command make
@@ -1643,7 +1598,7 @@
function make()
{
- _wrap_build $(get_make_command) "$@"
+ _wrap_build $(get_make_command "$@") "$@"
}
function provision()
@@ -1675,6 +1630,14 @@
"$ANDROID_PRODUCT_OUT/provision-device" "$@"
}
+function atest()
+{
+ # TODO (sbasi): Replace this to be a destination in the build out when & if
+ # atest is built by the build system. (This will be necessary if it ever
+ # depends on external pip projects).
+ "$(gettop)"/tools/tradefederation/core/atest/atest.py "$@"
+}
+
if [ "x$SHELL" != "x/bin/bash" ]; then
case `ps -o command -p $$` in
*bash*)
diff --git a/help.sh b/help.sh
new file mode 100755
index 0000000..c143542
--- /dev/null
+++ b/help.sh
@@ -0,0 +1,55 @@
+#!/bin/bash
+
+# locate some directories
+cd "$(dirname $0)"
+SCRIPT_DIR="${PWD}"
+cd ../..
+TOP="${PWD}"
+
+message='The basic Android build process is:
+
+cd '"${TOP}"'
+source build/envsetup.sh # Add "lunch" (and other utilities and variables)
+ # to the shell environment.
+lunch [<product>-<variant>] # Choose the device to target.
+m -j [<goals>] # Execute the configured build.
+
+Usage of "m" imitates usage of the program "make".
+See '"${SCRIPT_DIR}"'/Usage.txt for more info about build usage and concepts.
+
+Common goals are:
+
+ clean (aka clobber) equivalent to rm -rf out/
+ checkbuild Build every module defined in the source tree
+ droid Default target
+ nothing Do not build anything, just parse and validate the build structure
+
+ java Build all the java code in the source tree
+ native Build all the native code in the source tree
+
+ host Build all the host code (not to be run on a device) in the source tree
+ target Build all the target code (to be run on the device) in the source tree
+
+ (java|native)-(host|target)
+ (host|target)-(java|native)
+ Build the intersection of the two given arguments
+
+ snod Quickly rebuild the system image from built packages
+ Stands for "System, NO Dependencies"
+ vnod Quickly rebuild the vendor image from built packages
+ Stands for "Vendor, NO Dependencies"
+ pnod Quickly rebuild the product image from built packages
+ Stands for "Product, NO Dependencies"
+
+
+So, for example, you could run:
+
+cd '"${TOP}"'
+source build/envsetup.sh
+lunch aosp_arm-userdebug
+m -j java
+
+to build all of the java code for the userdebug variant of the aosp_arm device.
+'
+
+echo "$message"
diff --git a/navbar.md b/navbar.md
new file mode 100644
index 0000000..e218a78
--- /dev/null
+++ b/navbar.md
@@ -0,0 +1,4 @@
+* [Home](/README.md)
+* [Usage](/Usage.txt)
+* [Changes](/Changes.md)
+* [Outdated Reference](/core/build-system.html)
diff --git a/tapasHelp.sh b/tapasHelp.sh
new file mode 100755
index 0000000..38b3e34
--- /dev/null
+++ b/tapasHelp.sh
@@ -0,0 +1,23 @@
+#!/bin/bash
+
+# locate some directories
+cd "$(dirname $0)"
+SCRIPT_DIR="${PWD}"
+cd ../..
+TOP="${PWD}"
+
+message='usage: tapas [<App1> <App2> ...] [arm|x86|mips|arm64|x86_64|mips64] [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.
+Additionally, an app built with "tapas" will have its dex file inside its apk,
+which should cause it to be suitable for installing on any api-compatible
+device. In other words, "tapas" configures the build of unbundled apps.
+
+The names <App1> <App2> ... should match LOCAL_PACKAGE_NAME as defined in an
+Android.mk
+
+The usage of the other arguments matches that of the rest of the platform
+build system and can be found by running `m help`'
+
+echo "$message"
diff --git a/target/board/generic_armv5/BoardConfig.mk b/target/Android.mk
similarity index 63%
copy from target/board/generic_armv5/BoardConfig.mk
copy to target/Android.mk
index 016937a..9929b00 100644
--- a/target/board/generic_armv5/BoardConfig.mk
+++ b/target/Android.mk
@@ -1,5 +1,5 @@
#
-# Copyright (C) 2011 The Android Open Source Project
+# 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.
@@ -14,10 +14,10 @@
# limitations under the License.
#
-include build/target/board/generic/BoardConfig.mk
+LOCAL_PATH := $(call my-dir)
-TARGET_ARCH_VARIANT := armv5te
-TARGET_CPU_ABI := armeabi
-TARGET_CPU_ABI2 :=
-
-WITH_DEXPREOPT := false
+# Only if this Android.mk was included not by a symlink should it be used.
+# This facilitates the transition away from symlinks: b/64397960
+ifeq ($(LOCAL_PATH),build/make/target)
+include $(call first-makefiles-under,$(LOCAL_PATH))
+endif
diff --git a/target/board/Android.mk b/target/board/Android.mk
index 5504c52..7fe45eb 100644
--- a/target/board/Android.mk
+++ b/target/board/Android.mk
@@ -20,7 +20,7 @@
board_info_txt := $(wildcard $(TARGET_DEVICE_DIR)/board-info.txt)
endif
$(INSTALLED_ANDROID_INFO_TXT_TARGET): $(board_info_txt)
- $(hide) build/tools/check_radio_versions.py $< $(BOARD_INFO_CHECK)
+ $(hide) build/make/tools/check_radio_versions.py $< $(BOARD_INFO_CHECK)
$(call pretty,"Generated: ($@)")
ifdef board_info_txt
$(hide) grep -v '#' $< > $@
@@ -34,14 +34,17 @@
ifdef DEVICE_MANIFEST_FILE
# $(DEVICE_MANIFEST_FILE) can be a list of files
include $(CLEAR_VARS)
-LOCAL_MODULE := manifest.xml
+LOCAL_MODULE := device_manifest.xml
+LOCAL_MODULE_STEM := manifest.xml
LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR)
+LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR)/etc/vintf
GEN := $(local-generated-sources-dir)/manifest.xml
$(GEN): PRIVATE_DEVICE_MANIFEST_FILE := $(DEVICE_MANIFEST_FILE)
$(GEN): $(DEVICE_MANIFEST_FILE) $(HOST_OUT_EXECUTABLES)/assemble_vintf
BOARD_SEPOLICY_VERS=$(BOARD_SEPOLICY_VERS) \
+ PRODUCT_ENFORCE_VINTF_MANIFEST=$(PRODUCT_ENFORCE_VINTF_MANIFEST) \
+ PRODUCT_SHIPPING_API_LEVEL=$(PRODUCT_SHIPPING_API_LEVEL) \
$(HOST_OUT_EXECUTABLES)/assemble_vintf -o $@ \
-i $(call normalize-path-list,$(PRIVATE_DEVICE_MANIFEST_FILE))
@@ -49,106 +52,3 @@
include $(BUILD_PREBUILT)
BUILT_VENDOR_MANIFEST := $(LOCAL_BUILT_MODULE)
endif
-
-# Device Compatibility Matrix
-ifdef DEVICE_MATRIX_FILE
-include $(CLEAR_VARS)
-LOCAL_MODULE := compatibility_matrix.xml
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR)
-
-GEN := $(local-generated-sources-dir)/compatibility_matrix.xml
-$(GEN): $(DEVICE_MATRIX_FILE) $(HOST_OUT_EXECUTABLES)/assemble_vintf
- # TODO(b/37342627): put BOARD_VNDK_VERSION & BOARD_VNDK_LIBRARIES into device matrix.
- $(HOST_OUT_EXECUTABLES)/assemble_vintf -i $< -o $@
-
-LOCAL_PREBUILT_MODULE_FILE := $(GEN)
-include $(BUILD_PREBUILT)
-BUILT_VENDOR_MATRIX := $(LOCAL_BUILT_MODULE)
-endif
-
-# Framework Manifest
-include $(CLEAR_VARS)
-LOCAL_MODULE := system_manifest.xml
-LOCAL_MODULE_STEM := manifest.xml
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT)
-
-GEN := $(local-generated-sources-dir)/manifest.xml
-
-$(GEN): PRIVATE_FLAGS :=
-
-# TODO(b/37954458), (b/37321309) remove check of PRODUCT_FULL_TREBLE after
-# putting device compatibility matrices for non-treble devices.
-ifeq ($(PRODUCT_FULL_TREBLE),true)
-ifdef BUILT_VENDOR_MATRIX
-$(GEN): $(BUILT_VENDOR_MATRIX)
-$(GEN): PRIVATE_FLAGS += -c "$(BUILT_VENDOR_MATRIX)"
-endif
-endif
-
-$(GEN): $(FRAMEWORK_MANIFEST_FILE) $(HOST_OUT_EXECUTABLES)/assemble_vintf
- BOARD_SEPOLICY_VERS=$(BOARD_SEPOLICY_VERS) $(HOST_OUT_EXECUTABLES)/assemble_vintf -i $< -o $@ $(PRIVATE_FLAGS)
-
-LOCAL_PREBUILT_MODULE_FILE := $(GEN)
-include $(BUILD_PREBUILT)
-BUILT_SYSTEM_MANIFEST := $(LOCAL_BUILT_MODULE)
-
-# Framework Compatibility Matrix
-include $(CLEAR_VARS)
-LOCAL_MODULE := system_compatibility_matrix.xml
-LOCAL_MODULE_STEM := compatibility_matrix.xml
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT)
-
-GEN := $(local-generated-sources-dir)/compatibility_matrix.xml
-
-$(GEN): PRIVATE_FLAGS :=
-
-# TODO(b/37954458), (b/37321309) remove check of PRODUCT_FULL_TREBLE after
-# putting complete HAL manifests on non-treble devices.
-ifeq ($(PRODUCT_FULL_TREBLE),true)
-ifdef BUILT_VENDOR_MANIFEST
-$(GEN): $(BUILT_VENDOR_MANIFEST)
-$(GEN): PRIVATE_FLAGS += -c "$(BUILT_VENDOR_MANIFEST)"
-endif
-endif
-
-ifeq (true,$(BOARD_AVB_ENABLE))
-$(GEN): $(AVBTOOL)
-# INTERNAL_AVB_SYSTEM_SIGNING_ARGS consists of BOARD_AVB_SYSTEM_KEY_PATH and
-# BOARD_AVB_SYSTEM_ALGORITHM. We should add the dependency of key path, which
-# is a file, here.
-$(GEN): $(BOARD_AVB_SYSTEM_KEY_PATH)
-# Use deferred assignment (=) instead of immediate assignment (:=).
-# Otherwise, cannot get INTERNAL_AVB_SYSTEM_SIGNING_ARGS.
-FRAMEWORK_VBMETA_VERSION = $$("$(AVBTOOL)" add_hashtree_footer \
- --print_required_libavb_version \
- $(INTERNAL_AVB_SYSTEM_SIGNING_ARGS) \
- $(BOARD_AVB_SYSTEM_ADD_HASHTREE_FOOTER_ARGS))
-else
-FRAMEWORK_VBMETA_VERSION := 0.0
-endif
-
-# All kernel versions that the system image works with.
-KERNEL_VERSIONS := 3.18 4.4 4.9
-KERNEL_CONFIG_DATA := test/vts-testcase/kernel/config/data
-
-$(GEN): $(foreach version,$(KERNEL_VERSIONS),\
- $(wildcard $(KERNEL_CONFIG_DATA)/android-$(version)/android-base*.cfg))
-$(GEN): PRIVATE_FLAGS += $(foreach version,$(KERNEL_VERSIONS),\
- --kernel=$(version):$(call normalize-path-list,\
- $(wildcard $(KERNEL_CONFIG_DATA)/android-$(version)/android-base*.cfg)))
-
-KERNEL_VERSIONS :=
-KERNEL_CONFIG_DATA :=
-
-$(GEN): $(FRAMEWORK_COMPATIBILITY_MATRIX_FILE) $(HOST_OUT_EXECUTABLES)/assemble_vintf
- # TODO(b/37405869) (b/37715375) inject avb versions as well for devices that have avb enabled.
- POLICYVERS=$(POLICYVERS) \
- BOARD_SEPOLICY_VERS=$(BOARD_SEPOLICY_VERS) \
- FRAMEWORK_VBMETA_VERSION=$(FRAMEWORK_VBMETA_VERSION) \
- $(HOST_OUT_EXECUTABLES)/assemble_vintf -i $< -o $@ $(PRIVATE_FLAGS)
-LOCAL_PREBUILT_MODULE_FILE := $(GEN)
-include $(BUILD_PREBUILT)
-BUILT_SYSTEM_COMPATIBILITY_MATRIX := $(LOCAL_BUILT_MODULE)
diff --git a/target/board/generic/BoardConfig.mk b/target/board/generic/BoardConfig.mk
index 331f082..6c82846 100644
--- a/target/board/generic/BoardConfig.mk
+++ b/target/board/generic/BoardConfig.mk
@@ -8,36 +8,43 @@
TARGET_NO_KERNEL := true
TARGET_ARCH := arm
-# Note: we build the platform images for ARMv7-A _without_ NEON.
+# Note: Before Pi, we built the platform images for ARMv7-A _without_ NEON.
#
-# Technically, the emulator supports ARMv7-A _and_ NEON instructions, but
-# emulated NEON code paths typically ends up 2x slower than the normal C code
-# it is supposed to replace (unlike on real devices where it is 2x to 3x
-# faster).
+ifneq ($(TARGET_BUILD_APPS)$(filter cts sdk,$(MAKECMDGOALS)),)
+# DO NOT USE
#
-# What this means is that the platform image will not use NEON code paths
-# that are slower to emulate. On the other hand, it is possible to emulate
-# application code generated with the NDK that uses NEON in the emulator.
+# This architecture variant should NOT be used for 32 bit arm platform
+# builds. It is the lowest common denominator required to build
+# an unbundled application for all supported 32 platforms.
+# cts for 32 bit arm is built using aosp_arm64 product.
#
+# If you are building a 32 bit platform (and not an application),
+# you should set the following as 2nd arch variant:
+#
+# TARGET_ARCH_VARIANT := armv7-a-neon
+#
+# DO NOT USE
TARGET_ARCH_VARIANT := armv7-a
+# DO NOT USE
+else
+# Starting from Pi, System image of aosp_arm products is the new GSI
+# for real devices newly launched for Pi. These devices are usualy not
+# as performant as the mainstream 64-bit devices and the performance
+# provided by NEON is important for them to pass related CTS tests.
+TARGET_ARCH_VARIANT := armv7-a-neon
+endif
TARGET_CPU_VARIANT := generic
TARGET_CPU_ABI := armeabi-v7a
TARGET_CPU_ABI2 := armeabi
HAVE_HTC_AUDIO_DRIVER := true
BOARD_USES_GENERIC_AUDIO := true
+TARGET_BOOTLOADER_BOARD_NAME := goldfish_$(TARGET_ARCH)
+
+TARGET_USES_64_BIT_BINDER := true
# no hardware camera
USE_CAMERA_STUB := true
-# Enable dex-preoptimization to speed up the first boot sequence
-# of an SDK AVD. Note that this operation only works on Linux for now
-ifeq ($(HOST_OS),linux)
- ifeq ($(WITH_DEXPREOPT),)
- WITH_DEXPREOPT := true
- WITH_DEXPREOPT_BOOT_IMG_AND_SYSTEM_SERVER_ONLY := false
- endif
-endif
-
TARGET_USES_HWC2 := true
NUM_FRAMEBUFFER_SURFACE_BUFFERS := 3
@@ -50,18 +57,57 @@
USE_OPENGL_RENDERER := true
TARGET_USERIMAGES_USE_EXT4 := true
-BOARD_SYSTEMIMAGE_PARTITION_SIZE := 2147483648 # 2 GB
+# Partition size is default 1.5GB (1536MB) for 64 bits projects
+BOARD_SYSTEMIMAGE_PARTITION_SIZE := 1610612736
BOARD_USERDATAIMAGE_PARTITION_SIZE := 576716800
TARGET_COPY_OUT_VENDOR := vendor
# ~100 MB vendor image. Please adjust system image / vendor image sizes
# when finalizing them.
BOARD_VENDORIMAGE_PARTITION_SIZE := 100000000
BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE := ext4
-BOARD_CACHEIMAGE_PARTITION_SIZE := 69206016
-BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE := ext4
BOARD_FLASH_BLOCK_SIZE := 512
TARGET_USERIMAGES_SPARSE_EXT_DISABLED := true
DEVICE_MATRIX_FILE := device/generic/goldfish/compatibility_matrix.xml
-BOARD_SEPOLICY_DIRS += build/target/board/generic/sepolicy
+# Android generic system image always create metadata partition
+BOARD_USES_METADATA_PARTITION := true
+
+# Set this to create /cache mount point for non-A/B devices that mounts /cache.
+# The partition size doesn't matter, just to make build pass.
+BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE := ext4
+BOARD_CACHEIMAGE_PARTITION_SIZE := 16777216
+
+BOARD_SEPOLICY_DIRS += device/generic/goldfish/sepolicy/common
BOARD_PROPERTY_OVERRIDES_SPLIT_ENABLED := true
+
+# Android Verified Boot (AVB):
+# Builds a special vbmeta.img that disables AVB verification.
+# Otherwise, AVB will prevent the device from booting the generic system.img.
+# Also checks that BOARD_AVB_ENABLE is not set, to prevent adding verity
+# metadata into system.img.
+ifeq ($(BOARD_AVB_ENABLE),true)
+$(error BOARD_AVB_ENABLE cannot be set for GSI)
+endif
+BOARD_BUILD_DISABLED_VBMETAIMAGE := true
+
+ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT)))
+# GSI is always userdebug and needs a couple of properties taking precedence
+# over those set by the vendor.
+TARGET_SYSTEM_PROP := build/make/target/board/gsi_system.prop
+endif
+BOARD_VNDK_VERSION := current
+
+# 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"
+
+# Enable A/B update
+TARGET_NO_RECOVERY := true
+BOARD_BUILD_SYSTEM_ROOT_IMAGE := true
diff --git a/target/board/generic/device.mk b/target/board/generic/device.mk
index e18c165..273ac71 100644
--- a/target/board/generic/device.mk
+++ b/target/board/generic/device.mk
@@ -14,18 +14,19 @@
# limitations under the License.
#
-# This is a build configuration for the product aspects that
-# are specific to the emulator.
+# minimal configuration for audio policy.
+PRODUCT_COPY_FILES += \
+ frameworks/av/services/audiopolicy/config/audio_policy_configuration_generic.xml:system/etc/audio_policy_configuration.xml \
+ frameworks/av/services/audiopolicy/config/primary_audio_policy_configuration.xml:system/etc/primary_audio_policy_configuration.xml \
+ frameworks/av/services/audiopolicy/config/r_submix_audio_policy_configuration.xml:system/etc/r_submix_audio_policy_configuration.xml \
+ frameworks/av/services/audiopolicy/config/audio_policy_volumes.xml:system/etc/audio_policy_volumes.xml \
+ frameworks/av/services/audiopolicy/config/default_volume_tables.xml:system/etc/default_volume_tables.xml \
-PRODUCT_PROPERTY_OVERRIDES := \
- ro.ril.hsxpa=1 \
- ro.ril.gprsclass=10
-
-PRODUCT_COPY_FILES := \
- device/generic/goldfish/data/etc/apns-conf.xml:system/etc/apns-conf.xml \
- device/generic/goldfish/camera/media_profiles.xml:system/etc/media_profiles.xml \
- frameworks/av/media/libstagefright/data/media_codecs_google_audio.xml:system/etc/media_codecs_google_audio.xml \
- frameworks/av/media/libstagefright/data/media_codecs_google_telephony.xml:system/etc/media_codecs_google_telephony.xml \
- frameworks/av/media/libstagefright/data/media_codecs_google_video.xml:system/etc/media_codecs_google_video.xml \
- device/generic/goldfish/camera/media_codecs.xml:system/etc/media_codecs.xml \
- hardware/libhardware_legacy/audio/audio_policy.conf:system/etc/audio_policy.conf
+# 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/sepolicy/adbd.te b/target/board/generic/sepolicy/adbd.te
deleted file mode 100644
index 9546c1a..0000000
--- a/target/board/generic/sepolicy/adbd.te
+++ /dev/null
@@ -1 +0,0 @@
-set_prop(adbd, ctl_mdnsd_prop);
diff --git a/target/board/generic/sepolicy/audioserver.te b/target/board/generic/sepolicy/audioserver.te
deleted file mode 100644
index c3c4a3a..0000000
--- a/target/board/generic/sepolicy/audioserver.te
+++ /dev/null
@@ -1 +0,0 @@
-allow audioserver bootanim:binder call;
diff --git a/target/board/generic/sepolicy/bootanim.te b/target/board/generic/sepolicy/bootanim.te
deleted file mode 100644
index 4be1c8a..0000000
--- a/target/board/generic/sepolicy/bootanim.te
+++ /dev/null
@@ -1,5 +0,0 @@
-allow bootanim self:process execmem;
-allow bootanim ashmem_device:chr_file execute;
-#TODO: This can safely be ignored until b/62954877 is fixed
-dontaudit bootanim system_data_file:dir read;
-set_prop(bootanim, qemu_prop)
diff --git a/target/board/generic/sepolicy/cameraserver.te b/target/board/generic/sepolicy/cameraserver.te
deleted file mode 100644
index 6cf5d6a..0000000
--- a/target/board/generic/sepolicy/cameraserver.te
+++ /dev/null
@@ -1,2 +0,0 @@
-allow cameraserver system_file:dir { open read };
-allow cameraserver hal_allocator:fd use;
diff --git a/target/board/generic/sepolicy/device.te b/target/board/generic/sepolicy/device.te
deleted file mode 100644
index d129441..0000000
--- a/target/board/generic/sepolicy/device.te
+++ /dev/null
@@ -1 +0,0 @@
-type qemu_device, dev_type, mlstrustedobject;
diff --git a/target/board/generic/sepolicy/domain.te b/target/board/generic/sepolicy/domain.te
deleted file mode 100644
index 5d5e4ac..0000000
--- a/target/board/generic/sepolicy/domain.te
+++ /dev/null
@@ -1,6 +0,0 @@
-# For /sys/qemu_trace files in the emulator.
-allow domain sysfs_writable:dir search;
-allow domain sysfs_writable:file rw_file_perms;
-allow domain qemu_device:chr_file rw_file_perms;
-
-get_prop(domain, qemu_prop)
diff --git a/target/board/generic/sepolicy/file.te b/target/board/generic/sepolicy/file.te
deleted file mode 100644
index f4ae9e4..0000000
--- a/target/board/generic/sepolicy/file.te
+++ /dev/null
@@ -1 +0,0 @@
-type sysfs_writable, fs_type, sysfs_type, mlstrustedobject;
diff --git a/target/board/generic/sepolicy/file_contexts b/target/board/generic/sepolicy/file_contexts
deleted file mode 100644
index f550f4d..0000000
--- a/target/board/generic/sepolicy/file_contexts
+++ /dev/null
@@ -1,35 +0,0 @@
-# goldfish
-/dev/block/mtdblock0 u:object_r:system_block_device:s0
-/dev/block/mtdblock1 u:object_r:userdata_block_device:s0
-/dev/block/mtdblock2 u:object_r:cache_block_device:s0
-
-# ranchu
-/dev/block/vda u:object_r:system_block_device:s0
-/dev/block/vdb u:object_r:cache_block_device:s0
-/dev/block/vdc u:object_r:userdata_block_device:s0
-/dev/block/vdd u:object_r:metadata_block_device:s0
-/dev/block/vde u:object_r:system_block_device:s0
-
-/dev/goldfish_pipe u:object_r:qemu_device:s0
-/dev/goldfish_sync u:object_r:qemu_device:s0
-/dev/qemu_.* u:object_r:qemu_device:s0
-/dev/ttyGF[0-9]* u:object_r:serial_device:s0
-/dev/ttyS2 u:object_r:console_device:s0
-/sys/qemu_trace(/.*)? u:object_r:sysfs_writable:s0
-/vendor/bin/init\.ranchu-core\.sh u:object_r:goldfish_setup_exec:s0
-/vendor/bin/init\.ranchu-net\.sh u:object_r:goldfish_setup_exec:s0
-/vendor/bin/qemu-props u:object_r:qemu_props_exec:s0
-
-/vendor/bin/hw/android\.hardware\.drm@1\.0-service\.widevine u:object_r:hal_drm_widevine_exec:s0
-
-/vendor/lib(64)?/hw/gralloc\.ranchu\.so u:object_r:same_process_hal_file:s0
-/vendor/lib(64)?/libEGL_emulation\.so u:object_r:same_process_hal_file:s0
-/vendor/lib(64)?/libGLESv1_CM_emulation\.so u:object_r:same_process_hal_file:s0
-/vendor/lib(64)?/libGLESv2_emulation\.so u:object_r:same_process_hal_file:s0
-/vendor/lib(64)?/libEGL_swiftshader\.so u:object_r:same_process_hal_file:s0
-/vendor/lib(64)?/libGLESv1_CM_swiftshader\.so u:object_r:same_process_hal_file:s0
-/vendor/lib(64)?/libGLESv2_swiftshader\.so u:object_r:same_process_hal_file:s0
-/vendor/lib(64)?/libOpenglSystemCommon\.so u:object_r:same_process_hal_file:s0
-/vendor/lib(64)?/lib_renderControl_enc\.so u:object_r:same_process_hal_file:s0
-/vendor/lib(64)?/libGLESv1_enc\.so u:object_r:same_process_hal_file:s0
-/vendor/lib(64)?/libGLESv2_enc\.so u:object_r:same_process_hal_file:s0
diff --git a/target/board/generic/sepolicy/goldfish_setup.te b/target/board/generic/sepolicy/goldfish_setup.te
deleted file mode 100644
index bcd49bd..0000000
--- a/target/board/generic/sepolicy/goldfish_setup.te
+++ /dev/null
@@ -1,12 +0,0 @@
-# goldfish-setup service: runs init.goldfish.sh script
-type goldfish_setup, domain;
-type goldfish_setup_exec, vendor_file_type, exec_type, file_type;
-
-init_daemon_domain(goldfish_setup)
-
-allow goldfish_setup self:capability { net_admin net_raw };
-allow goldfish_setup self:udp_socket { create ioctl };
-allow goldfish_setup vendor_toolbox_exec:file execute_no_trans;
-allowxperm goldfish_setup self:udp_socket ioctl priv_sock_ioctls;
-wakelock_use(goldfish_setup);
-allow goldfish_setup vendor_shell_exec:file { rx_file_perms };
diff --git a/target/board/generic/sepolicy/hal_camera_default.te b/target/board/generic/sepolicy/hal_camera_default.te
deleted file mode 100644
index eb88c36..0000000
--- a/target/board/generic/sepolicy/hal_camera_default.te
+++ /dev/null
@@ -1,3 +0,0 @@
-vndbinder_use(hal_camera_default);
-allow hal_camera_default hal_graphics_mapper_hwservice:hwservice_manager find;
-hal_client_domain(hal_camera_default, hal_graphics_composer)
diff --git a/target/board/generic/sepolicy/hal_cas_default.te b/target/board/generic/sepolicy/hal_cas_default.te
deleted file mode 100644
index 3ed3bee..0000000
--- a/target/board/generic/sepolicy/hal_cas_default.te
+++ /dev/null
@@ -1 +0,0 @@
-vndbinder_use(hal_cas_default);
diff --git a/target/board/generic/sepolicy/hal_drm_default.te b/target/board/generic/sepolicy/hal_drm_default.te
deleted file mode 100644
index 5a07433..0000000
--- a/target/board/generic/sepolicy/hal_drm_default.te
+++ /dev/null
@@ -1,2 +0,0 @@
-vndbinder_use(hal_drm_default);
-hal_client_domain(hal_drm_default, hal_graphics_composer)
diff --git a/target/board/generic/sepolicy/hal_drm_widevine.te b/target/board/generic/sepolicy/hal_drm_widevine.te
deleted file mode 100644
index 42d462a..0000000
--- a/target/board/generic/sepolicy/hal_drm_widevine.te
+++ /dev/null
@@ -1,12 +0,0 @@
-# define SELinux domain
-type hal_drm_widevine, domain;
-hal_server_domain(hal_drm_widevine, hal_drm)
-
-type hal_drm_widevine_exec, exec_type, vendor_file_type, file_type;
-init_daemon_domain(hal_drm_widevine)
-
-allow hal_drm mediacodec:fd use;
-allow hal_drm { appdomain -isolated_app }:fd use;
-
-vndbinder_use(hal_drm_widevine);
-hal_client_domain(hal_drm_widevine, hal_graphics_composer);
diff --git a/target/board/generic/sepolicy/hal_gnss_default.te b/target/board/generic/sepolicy/hal_gnss_default.te
deleted file mode 100644
index 0dd3d03..0000000
--- a/target/board/generic/sepolicy/hal_gnss_default.te
+++ /dev/null
@@ -1,3 +0,0 @@
-#============= hal_gnss_default ==============
-allow hal_gnss_default vndbinder_device:chr_file { ioctl open read write };
-
diff --git a/target/board/generic/sepolicy/hal_graphics_composer_default.te b/target/board/generic/sepolicy/hal_graphics_composer_default.te
deleted file mode 100644
index 034bdef..0000000
--- a/target/board/generic/sepolicy/hal_graphics_composer_default.te
+++ /dev/null
@@ -1,3 +0,0 @@
-#============= hal_graphics_composer_default ==============
-allow hal_graphics_composer_default vndbinder_device:chr_file { ioctl open read write };
-
diff --git a/target/board/generic/sepolicy/init.te b/target/board/generic/sepolicy/init.te
deleted file mode 100644
index 84a4e8d..0000000
--- a/target/board/generic/sepolicy/init.te
+++ /dev/null
@@ -1,2 +0,0 @@
-allow init tmpfs:lnk_file create_file_perms;
-dontaudit init kernel:system module_request;
diff --git a/target/board/generic/sepolicy/logpersist.te b/target/board/generic/sepolicy/logpersist.te
deleted file mode 100644
index 3fc0250..0000000
--- a/target/board/generic/sepolicy/logpersist.te
+++ /dev/null
@@ -1,13 +0,0 @@
-# goldfish logcat service: runs logcat -Q in logpersist domain
-
-# See global logcat.te/logpersist.te, only set for eng & userdebug,
-# allow for all builds in a non-conflicting manner.
-
-domain_auto_trans(init, logcat_exec, logpersist)
-
-# Read from logd.
-unix_socket_connect(logpersist, logdr, logd)
-
-# Write to /dev/ttyS2 and /dev/ttyGF2.
-allow logpersist serial_device:chr_file { write open };
-get_prop(logpersist, qemu_cmdline)
diff --git a/target/board/generic/sepolicy/mediacodec.te b/target/board/generic/sepolicy/mediacodec.te
deleted file mode 100644
index acf4e59..0000000
--- a/target/board/generic/sepolicy/mediacodec.te
+++ /dev/null
@@ -1 +0,0 @@
-allow mediacodec system_file:dir { open read };
diff --git a/target/board/generic/sepolicy/netd.te b/target/board/generic/sepolicy/netd.te
deleted file mode 100644
index 09a28b9..0000000
--- a/target/board/generic/sepolicy/netd.te
+++ /dev/null
@@ -1,3 +0,0 @@
-dontaudit netd self:capability sys_module;
-#TODO: This can safely be ignored until b/62954877 is fixed
-dontaudit netd kernel:system module_request;
diff --git a/target/board/generic/sepolicy/priv_app.te b/target/board/generic/sepolicy/priv_app.te
deleted file mode 100644
index 3d16f32..0000000
--- a/target/board/generic/sepolicy/priv_app.te
+++ /dev/null
@@ -1,5 +0,0 @@
-#TODO: b/62908025
-dontaudit priv_app firstboot_prop:file { getattr open };
-dontaudit priv_app device:dir { open read };
-dontaudit priv_app proc_interrupts:file { getattr open read };
-dontaudit priv_app proc_modules:file { getattr open read };
diff --git a/target/board/generic/sepolicy/property.te b/target/board/generic/sepolicy/property.te
deleted file mode 100644
index a486702..0000000
--- a/target/board/generic/sepolicy/property.te
+++ /dev/null
@@ -1,4 +0,0 @@
-type qemu_prop, property_type;
-type qemu_cmdline, property_type;
-type radio_noril_prop, property_type;
-type opengles_prop, property_type;
diff --git a/target/board/generic/sepolicy/property_contexts b/target/board/generic/sepolicy/property_contexts
deleted file mode 100644
index c66a85f..0000000
--- a/target/board/generic/sepolicy/property_contexts
+++ /dev/null
@@ -1,6 +0,0 @@
-qemu. u:object_r:qemu_prop:s0
-qemu.cmdline u:object_r:qemu_cmdline:s0
-ro.emu. u:object_r:qemu_prop:s0
-ro.emulator. u:object_r:qemu_prop:s0
-ro.radio.noril u:object_r:radio_noril_prop:s0
-ro.opengles. u:object_r:opengles_prop:s0
diff --git a/target/board/generic/sepolicy/qemu_props.te b/target/board/generic/sepolicy/qemu_props.te
deleted file mode 100644
index 0f5ec8c..0000000
--- a/target/board/generic/sepolicy/qemu_props.te
+++ /dev/null
@@ -1,9 +0,0 @@
-# qemu-props service: Sets system properties on boot.
-type qemu_props, domain;
-type qemu_props_exec, vendor_file_type, exec_type, file_type;
-
-init_daemon_domain(qemu_props)
-
-set_prop(qemu_props, qemu_prop)
-set_prop(qemu_props, dalvik_prop)
-set_prop(qemu_props, qemu_cmdline)
diff --git a/target/board/generic/sepolicy/shell.te b/target/board/generic/sepolicy/shell.te
deleted file mode 100644
index b246d7e..0000000
--- a/target/board/generic/sepolicy/shell.te
+++ /dev/null
@@ -1 +0,0 @@
-allow shell serial_device:chr_file rw_file_perms;
diff --git a/target/board/generic/sepolicy/surfaceflinger.te b/target/board/generic/sepolicy/surfaceflinger.te
deleted file mode 100644
index e03d07e..0000000
--- a/target/board/generic/sepolicy/surfaceflinger.te
+++ /dev/null
@@ -1,4 +0,0 @@
-allow surfaceflinger self:process execmem;
-allow surfaceflinger ashmem_device:chr_file execute;
-
-set_prop(surfaceflinger, qemu_prop)
diff --git a/target/board/generic/sepolicy/system_server.te b/target/board/generic/sepolicy/system_server.te
deleted file mode 100644
index 9063095..0000000
--- a/target/board/generic/sepolicy/system_server.te
+++ /dev/null
@@ -1,2 +0,0 @@
-get_prop(system_server, opengles_prop)
-get_prop(system_server, radio_noril_prop)
diff --git a/target/board/generic/sepolicy/vold.te b/target/board/generic/sepolicy/vold.te
deleted file mode 100644
index 5f3bdd4..0000000
--- a/target/board/generic/sepolicy/vold.te
+++ /dev/null
@@ -1 +0,0 @@
-dontaudit vold kernel:system module_request;
diff --git a/target/board/generic/sepolicy/zygote.te b/target/board/generic/sepolicy/zygote.te
deleted file mode 100644
index e97d895..0000000
--- a/target/board/generic/sepolicy/zygote.te
+++ /dev/null
@@ -1,4 +0,0 @@
-set_prop(zygote, qemu_prop)
-# TODO (b/63631799) fix this access
-# Suppress denials to storage. Webview zygote should not be accessing.
-dontaudit webview_zygote mnt_expand_file:dir getattr;
diff --git a/target/board/generic_arm64/BoardConfig.mk b/target/board/generic_arm64/BoardConfig.mk
index 46c8865..56f15de 100644
--- a/target/board/generic_arm64/BoardConfig.mk
+++ b/target/board/generic_arm64/BoardConfig.mk
@@ -20,12 +20,13 @@
TARGET_ARCH_VARIANT := armv8-a
TARGET_CPU_VARIANT := generic
TARGET_CPU_ABI := arm64-v8a
+TARGET_BOOTLOADER_BOARD_NAME := goldfish_$(TARGET_ARCH)
TARGET_2ND_ARCH := arm
TARGET_2ND_CPU_ABI := armeabi-v7a
TARGET_2ND_CPU_ABI2 := armeabi
-ifneq ($(TARGET_BUILD_APPS)$(filter cts,$(MAKECMDGOALS)),)
+ifneq ($(TARGET_BUILD_APPS)$(filter cts sdk,$(MAKECMDGOALS)),)
# DO NOT USE
# DO NOT USE
#
@@ -35,11 +36,11 @@
# platforms.
#
# If you're building a 64 bit platform (and not an application) the
-# ARM-v8 specification allows you to assume NEON and all the features
-# available in a cortex-A15 CPU. You should be able to set :
+# ARM-v8 specification allows you to assume all the features available in an
+# armv7-a-neon CPU. You should set the following as 2nd arch/cpu variant:
#
-# TARGET_2ND_ARCH_VARIANT := armv7-a-neon
-# TARGET_2ND_CPU_VARIANT := cortex-a15
+# TARGET_2ND_ARCH_VARIANT := armv8-a
+# TARGET_2ND_CPU_VARIANT := generic
#
# DO NOT USE
# DO NOT USE
@@ -50,8 +51,8 @@
# DO NOT USE
# DO NOT USE
else
-TARGET_2ND_ARCH_VARIANT := armv7-a-neon
-TARGET_2ND_CPU_VARIANT := cortex-a15
+TARGET_2ND_ARCH_VARIANT := armv8-a
+TARGET_2ND_CPU_VARIANT := generic
endif
@@ -60,15 +61,6 @@
# no hardware camera
USE_CAMERA_STUB := true
-# Enable dex-preoptimization to speed up the first boot sequence
-# of an SDK AVD. Note that this operation only works on Linux for now
-ifeq ($(HOST_OS),linux)
- ifeq ($(WITH_DEXPREOPT),)
- WITH_DEXPREOPT := true
- WITH_DEXPREOPT_BOOT_IMG_AND_SYSTEM_SERVER_ONLY := false
- endif
-endif
-
TARGET_USES_HWC2 := true
NUM_FRAMEBUFFER_SURFACE_BUFFERS := 3
@@ -81,18 +73,67 @@
USE_OPENGL_RENDERER := true
TARGET_USERIMAGES_USE_EXT4 := true
-BOARD_SYSTEMIMAGE_PARTITION_SIZE := 2684354560 # 2.5 GB
+BOARD_SYSTEMIMAGE_PARTITION_SIZE := 2684354560 # 2.5 GB
BOARD_USERDATAIMAGE_PARTITION_SIZE := 576716800
TARGET_COPY_OUT_VENDOR := vendor
# ~100 MB vendor image. Please adjust system image / vendor image sizes
# when finalizing them.
BOARD_VENDORIMAGE_PARTITION_SIZE := 100000000
BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE := ext4
-BOARD_CACHEIMAGE_PARTITION_SIZE := 69206016
-BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE := ext4
BOARD_FLASH_BLOCK_SIZE := 512
TARGET_USERIMAGES_SPARSE_EXT_DISABLED := true
DEVICE_MATRIX_FILE := device/generic/goldfish/compatibility_matrix.xml
+# Android generic system image always create metadata partition
+BOARD_USES_METADATA_PARTITION := true
+
+# Set this to create /cache mount point for non-A/B devices that mounts /cache.
+# The partition size doesn't matter, just to make build pass.
+BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE := ext4
+BOARD_CACHEIMAGE_PARTITION_SIZE := 16777216
+
BOARD_PROPERTY_OVERRIDES_SPLIT_ENABLED := true
-BOARD_SEPOLICY_DIRS += build/target/board/generic/sepolicy
+BOARD_SEPOLICY_DIRS += device/generic/goldfish/sepolicy/common
+
+# Android Verified Boot (AVB):
+# Builds a special vbmeta.img that disables AVB verification.
+# Otherwise, AVB will prevent the device from booting the generic system.img.
+# Also checks that BOARD_AVB_ENABLE is not set, to prevent adding verity
+# metadata into system.img.
+ifeq ($(BOARD_AVB_ENABLE),true)
+$(error BOARD_AVB_ENABLE cannot be set for GSI)
+endif
+BOARD_BUILD_DISABLED_VBMETAIMAGE := true
+
+ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT)))
+# GSI is always userdebug and needs a couple of properties taking precedence
+# over those set by the vendor.
+TARGET_SYSTEM_PROP := build/make/target/board/gsi_system.prop
+endif
+BOARD_VNDK_VERSION := current
+
+# Emulator system image is going to be used as GSI and some vendor still hasn't
+# cleaned up all device specific directories under root!
+
+# TODO(jiyong) These might be SoC specific.
+BOARD_ROOT_EXTRA_FOLDERS += firmware firmware/radio persist
+BOARD_ROOT_EXTRA_SYMLINKS := /vendor/lib/dsp:/dsp
+
+# TODO(b/36764215): remove this setting when the generic system image
+# no longer has QCOM-specific directories under /.
+BOARD_SEPOLICY_DIRS += build/target/board/generic_arm64_ab/sepolicy
+
+# 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"
+
+# Enable A/B update
+TARGET_NO_RECOVERY := true
+BOARD_BUILD_SYSTEM_ROOT_IMAGE := true
diff --git a/target/board/generic_arm64/device.mk b/target/board/generic_arm64/device.mk
index ca287eb..8e26700 100644
--- a/target/board/generic_arm64/device.mk
+++ b/target/board/generic_arm64/device.mk
@@ -14,20 +14,22 @@
# limitations under the License.
#
-# This is a build configuration for the product aspects that
-# are specific to the emulator.
+# minimal configuration for audio policy.
+PRODUCT_COPY_FILES += \
+ frameworks/av/services/audiopolicy/config/audio_policy_configuration_generic.xml:system/etc/audio_policy_configuration.xml \
+ frameworks/av/services/audiopolicy/config/primary_audio_policy_configuration.xml:system/etc/primary_audio_policy_configuration.xml \
+ frameworks/av/services/audiopolicy/config/r_submix_audio_policy_configuration.xml:system/etc/r_submix_audio_policy_configuration.xml \
+ frameworks/av/services/audiopolicy/config/audio_policy_volumes.xml:system/etc/audio_policy_volumes.xml \
+ frameworks/av/services/audiopolicy/config/default_volume_tables.xml:system/etc/default_volume_tables.xml \
-PRODUCT_PROPERTY_OVERRIDES := \
- ro.ril.hsxpa=1 \
- ro.ril.gprsclass=10
-
-PRODUCT_COPY_FILES := \
- device/generic/goldfish/data/etc/apns-conf.xml:system/etc/apns-conf.xml \
- device/generic/goldfish/camera/media_profiles.xml:system/etc/media_profiles.xml \
- frameworks/av/media/libstagefright/data/media_codecs_google_audio.xml:system/etc/media_codecs_google_audio.xml \
- frameworks/av/media/libstagefright/data/media_codecs_google_telephony.xml:system/etc/media_codecs_google_telephony.xml \
- frameworks/av/media/libstagefright/data/media_codecs_google_video.xml:system/etc/media_codecs_google_video.xml \
- device/generic/goldfish/camera/media_codecs.xml:system/etc/media_codecs.xml
+# 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
# Adjust the Dalvik heap to be appropriate for a tablet.
$(call inherit-product-if-exists, frameworks/base/build/tablet-dalvik-heap.mk)
diff --git a/target/board/generic_arm64_a/BoardConfig.mk b/target/board/generic_arm64_a/BoardConfig.mk
index 8f4043f..34a8ac0 100644
--- a/target/board/generic_arm64_a/BoardConfig.mk
+++ b/target/board/generic_arm64_a/BoardConfig.mk
@@ -23,7 +23,7 @@
TARGET_CPU_VARIANT := generic
TARGET_2ND_ARCH := arm
-TARGET_2ND_ARCH_VARIANT := armv7-a-neon
+TARGET_2ND_ARCH_VARIANT := armv8-a
TARGET_2ND_CPU_ABI := armeabi-v7a
TARGET_2ND_CPU_ABI2 := armeabi
-TARGET_2ND_CPU_VARIANT := cortex-a15
+TARGET_2ND_CPU_VARIANT := generic
diff --git a/target/board/generic_arm64_ab/BoardConfig.mk b/target/board/generic_arm64_ab/BoardConfig.mk
index 6744289..fc6b582 100644
--- a/target/board/generic_arm64_ab/BoardConfig.mk
+++ b/target/board/generic_arm64_ab/BoardConfig.mk
@@ -23,10 +23,10 @@
TARGET_CPU_VARIANT := generic
TARGET_2ND_ARCH := arm
-TARGET_2ND_ARCH_VARIANT := armv7-a-neon
+TARGET_2ND_ARCH_VARIANT := armv8-a
TARGET_2ND_CPU_ABI := armeabi-v7a
TARGET_2ND_CPU_ABI2 := armeabi
-TARGET_2ND_CPU_VARIANT := cortex-a15
+TARGET_2ND_CPU_VARIANT := generic
# Enable A/B update
TARGET_NO_RECOVERY := true
@@ -36,6 +36,11 @@
BOARD_ROOT_EXTRA_FOLDERS += firmware firmware/radio persist
BOARD_ROOT_EXTRA_SYMLINKS := /vendor/lib/dsp:/dsp
+# Set this to create /cache mount point for non-A/B devices that mounts /cache.
+# The partition size doesn't matter, just to make build pass.
+BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE := ext4
+BOARD_CACHEIMAGE_PARTITION_SIZE := 16777216
+
# TODO(b/36764215): remove this setting when the generic system image
# no longer has QCOM-specific directories under /.
BOARD_SEPOLICY_DIRS += build/target/board/generic_arm64_ab/sepolicy
diff --git a/target/board/generic_arm64_ab/sepolicy/OWNERS b/target/board/generic_arm64_ab/sepolicy/OWNERS
new file mode 100644
index 0000000..3828988
--- /dev/null
+++ b/target/board/generic_arm64_ab/sepolicy/OWNERS
@@ -0,0 +1,4 @@
+jeffv@google.com
+dcashman@google.com
+jbires@google.com
+sspatil@google.com
diff --git a/target/board/generic_arm_a/BoardConfig.mk b/target/board/generic_arm_a/BoardConfig.mk
index d930749..f0e1a39 100644
--- a/target/board/generic_arm_a/BoardConfig.mk
+++ b/target/board/generic_arm_a/BoardConfig.mk
@@ -17,7 +17,7 @@
include build/make/target/board/treble_common_32.mk
# Overwrite the setting in treble_common_32.mk for non-A/B arm GSI
-BOARD_SYSTEMIMAGE_PARTITION_SIZE := 805306368 # 768MB
+BOARD_SYSTEMIMAGE_PARTITION_SIZE := 943718400 # 900MB
TARGET_ARCH := arm
TARGET_ARCH_VARIANT := armv7-a-neon
diff --git a/target/board/generic_arm_ab/BoardConfig.mk b/target/board/generic_arm_ab/BoardConfig.mk
index 011bcdf..7c04cd5 100644
--- a/target/board/generic_arm_ab/BoardConfig.mk
+++ b/target/board/generic_arm_ab/BoardConfig.mk
@@ -17,7 +17,7 @@
include build/make/target/board/treble_common_32.mk
# Overwrite the setting in treble_common_32.mk for non-A/B arm GSI
-BOARD_SYSTEMIMAGE_PARTITION_SIZE := 805306368 # 768MB
+BOARD_SYSTEMIMAGE_PARTITION_SIZE := 943718400 # 900MB
TARGET_ARCH := arm
TARGET_ARCH_VARIANT := armv7-a-neon
@@ -28,3 +28,16 @@
# Enable A/B update
TARGET_NO_RECOVERY := true
BOARD_BUILD_SYSTEM_ROOT_IMAGE := true
+
+# TODO(jiyong) These might be SoC specific.
+BOARD_ROOT_EXTRA_FOLDERS += firmware firmware/radio persist
+BOARD_ROOT_EXTRA_SYMLINKS := /vendor/lib/dsp:/dsp
+
+# Set this to create /cache mount point for non-A/B devices that mounts /cache.
+# The partition size doesn't matter, just to make build pass.
+BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE := ext4
+BOARD_CACHEIMAGE_PARTITION_SIZE := 16777216
+
+# TODO(b/36764215): remove this setting when the generic system image
+# no longer has QCOM-specific directories under /.
+BOARD_SEPOLICY_DIRS += build/target/board/generic_arm64_ab/sepolicy
diff --git a/target/board/generic_armv5/AndroidBoard.mk b/target/board/generic_armv5/AndroidBoard.mk
deleted file mode 100644
index 7daff27..0000000
--- a/target/board/generic_armv5/AndroidBoard.mk
+++ /dev/null
@@ -1,17 +0,0 @@
-#
-# Copyright (C) 2011 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/target/board/generic/AndroidBoard.mk
diff --git a/target/board/generic_armv5/README.txt b/target/board/generic_armv5/README.txt
deleted file mode 100644
index 25d590a..0000000
--- a/target/board/generic_armv5/README.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-The "generic_armv5" product defines a non-hardware-specific target
-without a kernel or bootloader.
-
-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_armv5/system.prop b/target/board/generic_armv5/system.prop
deleted file mode 100644
index 137a0f9..0000000
--- a/target/board/generic_armv5/system.prop
+++ /dev/null
@@ -1,6 +0,0 @@
-#
-# system.prop for generic sdk
-#
-
-rild.libpath=/system/lib/libreference-ril.so
-rild.libargs=-d /dev/ttyS0
diff --git a/target/board/generic_mips/BoardConfig.mk b/target/board/generic_mips/BoardConfig.mk
index fb66d21..523408b 100644
--- a/target/board/generic_mips/BoardConfig.mk
+++ b/target/board/generic_mips/BoardConfig.mk
@@ -65,10 +65,12 @@
# when finalizing them.
BOARD_VENDORIMAGE_PARTITION_SIZE := 100000000
BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE := ext4
-BOARD_CACHEIMAGE_PARTITION_SIZE := 69206016
-BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE := ext4
BOARD_FLASH_BLOCK_SIZE := 512
TARGET_USERIMAGES_SPARSE_EXT_DISABLED := true
DEVICE_MATRIX_FILE := device/generic/goldfish/compatibility_matrix.xml
BOARD_SEPOLICY_DIRS += build/target/board/generic/sepolicy
+
+# Enable A/B update
+TARGET_NO_RECOVERY := true
+BOARD_BUILD_SYSTEM_ROOT_IMAGE := true
diff --git a/target/board/generic_mips64/BoardConfig.mk b/target/board/generic_mips64/BoardConfig.mk
index 67bb51f..2052d7b 100644
--- a/target/board/generic_mips64/BoardConfig.mk
+++ b/target/board/generic_mips64/BoardConfig.mk
@@ -80,8 +80,6 @@
# when finalizing them.
BOARD_VENDORIMAGE_PARTITION_SIZE := 100000000
BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE := ext4
-BOARD_CACHEIMAGE_PARTITION_SIZE := 69206016
-BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE := ext4
BOARD_FLASH_BLOCK_SIZE := 512
TARGET_USERIMAGES_SPARSE_EXT_DISABLED := true
DEVICE_MATRIX_FILE := device/generic/goldfish/compatibility_matrix.xml
@@ -89,3 +87,7 @@
BOARD_SEPOLICY_DIRS += build/target/board/generic/sepolicy
DEX_PREOPT_DEFAULT := nostripping
+
+# Enable A/B update
+TARGET_NO_RECOVERY := true
+BOARD_BUILD_SYSTEM_ROOT_IMAGE := true
diff --git a/target/board/generic_x86/BoardConfig.mk b/target/board/generic_x86/BoardConfig.mk
index 000a9a3..684dfc7 100644
--- a/target/board/generic_x86/BoardConfig.mk
+++ b/target/board/generic_x86/BoardConfig.mk
@@ -10,6 +10,11 @@
TARGET_ARCH := x86
TARGET_ARCH_VARIANT := x86
TARGET_PRELINK_MODULE := false
+TARGET_BOOTLOADER_BOARD_NAME := goldfish_$(TARGET_ARCH)
+
+#emulator now uses 64bit kernel to run 32bit x86 image
+#
+TARGET_USES_64_BIT_BINDER := true
# The IA emulator (qemu) uses the Goldfish devices
HAVE_HTC_AUDIO_DRIVER := true
@@ -41,19 +46,58 @@
TARGET_USERIMAGES_USE_EXT4 := true
BOARD_SYSTEMIMAGE_PARTITION_SIZE := 2684354560
-BOARD_USERDATAIMAGE_PARTITION_SIZE := 576716800
+# Resize to 4G to accomodate ASAN and CTS
+BOARD_USERDATAIMAGE_PARTITION_SIZE := 4294967296
TARGET_COPY_OUT_VENDOR := vendor
BOARD_PROPERTY_OVERRIDES_SPLIT_ENABLED := true
# ~100 MB vendor image. Please adjust system image / vendor image sizes
# when finalizing them.
BOARD_VENDORIMAGE_PARTITION_SIZE := 100000000
BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE := ext4
-BOARD_CACHEIMAGE_PARTITION_SIZE := 69206016
-BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE := ext4
BOARD_FLASH_BLOCK_SIZE := 512
TARGET_USERIMAGES_SPARSE_EXT_DISABLED := true
DEVICE_MATRIX_FILE := device/generic/goldfish/compatibility_matrix.xml
+# Android generic system image always create metadata partition
+BOARD_USES_METADATA_PARTITION := true
+
+# Set this to create /cache mount point for non-A/B devices that mounts /cache.
+# The partition size doesn't matter, just to make build pass.
+BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE := ext4
+BOARD_CACHEIMAGE_PARTITION_SIZE := 16777216
+
BOARD_SEPOLICY_DIRS += \
- build/target/board/generic/sepolicy \
- build/target/board/generic_x86/sepolicy
+ device/generic/goldfish/sepolicy/common \
+ device/generic/goldfish/sepolicy/x86
+
+# Android Verified Boot (AVB):
+# Builds a special vbmeta.img that disables AVB verification.
+# Otherwise, AVB will prevent the device from booting the generic system.img.
+# Also checks that BOARD_AVB_ENABLE is not set, to prevent adding verity
+# metadata into system.img.
+ifeq ($(BOARD_AVB_ENABLE),true)
+$(error BOARD_AVB_ENABLE cannot be set for GSI)
+endif
+BOARD_BUILD_DISABLED_VBMETAIMAGE := true
+
+ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT)))
+# GSI is always userdebug and needs a couple of properties taking precedence
+# over those set by the vendor.
+TARGET_SYSTEM_PROP := build/make/target/board/gsi_system.prop
+endif
+BOARD_VNDK_VERSION := current
+
+# Enable A/B update
+TARGET_NO_RECOVERY := true
+BOARD_BUILD_SYSTEM_ROOT_IMAGE := true
+
+# 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/generic_x86/device.mk b/target/board/generic_x86/device.mk
index 24c39a5..273ac71 100644
--- a/target/board/generic_x86/device.mk
+++ b/target/board/generic_x86/device.mk
@@ -14,21 +14,19 @@
# limitations under the License.
#
-# This is a build configuration for the product aspects that
-# are specific to the emulator.
+# minimal configuration for audio policy.
+PRODUCT_COPY_FILES += \
+ frameworks/av/services/audiopolicy/config/audio_policy_configuration_generic.xml:system/etc/audio_policy_configuration.xml \
+ frameworks/av/services/audiopolicy/config/primary_audio_policy_configuration.xml:system/etc/primary_audio_policy_configuration.xml \
+ frameworks/av/services/audiopolicy/config/r_submix_audio_policy_configuration.xml:system/etc/r_submix_audio_policy_configuration.xml \
+ frameworks/av/services/audiopolicy/config/audio_policy_volumes.xml:system/etc/audio_policy_volumes.xml \
+ frameworks/av/services/audiopolicy/config/default_volume_tables.xml:system/etc/default_volume_tables.xml \
-PRODUCT_PROPERTY_OVERRIDES := \
- ro.ril.hsxpa=1 \
- ro.ril.gprsclass=10
-
-PRODUCT_COPY_FILES := \
- device/generic/goldfish/data/etc/apns-conf.xml:system/etc/apns-conf.xml \
- device/generic/goldfish/camera/media_profiles.xml:system/etc/media_profiles.xml \
- frameworks/av/media/libstagefright/data/media_codecs_google_audio.xml:system/etc/media_codecs_google_audio.xml \
- frameworks/av/media/libstagefright/data/media_codecs_google_telephony.xml:system/etc/media_codecs_google_telephony.xml \
- frameworks/av/media/libstagefright/data/media_codecs_google_video.xml:system/etc/media_codecs_google_video.xml \
- device/generic/goldfish/camera/media_codecs.xml:system/etc/media_codecs.xml
-
-PRODUCT_PACKAGES := \
- audio.primary.goldfish \
- vibrator.goldfish
+# 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_x86/sepolicy/domain.te b/target/board/generic_x86/sepolicy/domain.te
deleted file mode 100644
index 0bc8d87..0000000
--- a/target/board/generic_x86/sepolicy/domain.te
+++ /dev/null
@@ -1 +0,0 @@
-allow domain cpuctl_device:dir search;
diff --git a/target/board/generic_x86/sepolicy/healthd.te b/target/board/generic_x86/sepolicy/healthd.te
deleted file mode 100644
index 95fa807..0000000
--- a/target/board/generic_x86/sepolicy/healthd.te
+++ /dev/null
@@ -1 +0,0 @@
-allow healthd self:capability sys_nice;
diff --git a/target/board/generic_x86/sepolicy/init.te b/target/board/generic_x86/sepolicy/init.te
deleted file mode 100644
index 3aa81d1..0000000
--- a/target/board/generic_x86/sepolicy/init.te
+++ /dev/null
@@ -1 +0,0 @@
-allow init tmpfs:lnk_file create_file_perms;
diff --git a/target/board/generic_x86/sepolicy/installd.te b/target/board/generic_x86/sepolicy/installd.te
deleted file mode 100644
index 7a558b1..0000000
--- a/target/board/generic_x86/sepolicy/installd.te
+++ /dev/null
@@ -1 +0,0 @@
-allow installd self:process execmem;
diff --git a/target/board/generic_x86/sepolicy/zygote.te b/target/board/generic_x86/sepolicy/zygote.te
deleted file mode 100644
index 93993a4..0000000
--- a/target/board/generic_x86/sepolicy/zygote.te
+++ /dev/null
@@ -1,2 +0,0 @@
-allow zygote self:process execmem;
-allow zygote self:capability sys_nice;
diff --git a/target/board/generic_x86_64/BoardConfig.mk b/target/board/generic_x86_64/BoardConfig.mk
index 883dd2e..5bcb9ad 100755
--- a/target/board/generic_x86_64/BoardConfig.mk
+++ b/target/board/generic_x86_64/BoardConfig.mk
@@ -10,6 +10,7 @@
TARGET_ARCH := x86_64
TARGET_ARCH_VARIANT := x86_64
TARGET_PRELINK_MODULE := false
+TARGET_BOOTLOADER_BOARD_NAME := goldfish_$(TARGET_ARCH)
TARGET_2ND_CPU_ABI := x86
TARGET_2ND_ARCH := x86
@@ -50,13 +51,51 @@
# when finalizing them.
BOARD_VENDORIMAGE_PARTITION_SIZE := 100000000
BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE := ext4
-BOARD_CACHEIMAGE_PARTITION_SIZE := 69206016
-BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE := ext4
BOARD_FLASH_BLOCK_SIZE := 512
TARGET_USERIMAGES_SPARSE_EXT_DISABLED := true
BOARD_PROPERTY_OVERRIDES_SPLIT_ENABLED := true
DEVICE_MATRIX_FILE := device/generic/goldfish/compatibility_matrix.xml
+# Android generic system image always create metadata partition
+BOARD_USES_METADATA_PARTITION := true
+
+# Set this to create /cache mount point for non-A/B devices that mounts /cache.
+# The partition size doesn't matter, just to make build pass.
+BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE := ext4
+BOARD_CACHEIMAGE_PARTITION_SIZE := 16777216
+
BOARD_SEPOLICY_DIRS += \
- build/target/board/generic/sepolicy \
- build/target/board/generic_x86/sepolicy
+ device/generic/goldfish/sepolicy/common \
+ device/generic/goldfish/sepolicy/x86
+
+# Android Verified Boot (AVB):
+# Builds a special vbmeta.img that disables AVB verification.
+# Otherwise, AVB will prevent the device from booting the generic system.img.
+# Also checks that BOARD_AVB_ENABLE is not set, to prevent adding verity
+# metadata into system.img.
+ifeq ($(BOARD_AVB_ENABLE),true)
+$(error BOARD_AVB_ENABLE cannot be set for GSI)
+endif
+BOARD_BUILD_DISABLED_VBMETAIMAGE := true
+
+ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT)))
+# GSI is always userdebug and needs a couple of properties taking precedence
+# over those set by the vendor.
+TARGET_SYSTEM_PROP := build/make/target/board/gsi_system.prop
+endif
+BOARD_VNDK_VERSION := current
+
+# 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"
+
+# Enable A/B update
+TARGET_NO_RECOVERY := true
+BOARD_BUILD_SYSTEM_ROOT_IMAGE := true
diff --git a/target/board/generic_x86_64/device.mk b/target/board/generic_x86_64/device.mk
index 24c39a5..273ac71 100755
--- a/target/board/generic_x86_64/device.mk
+++ b/target/board/generic_x86_64/device.mk
@@ -14,21 +14,19 @@
# limitations under the License.
#
-# This is a build configuration for the product aspects that
-# are specific to the emulator.
+# minimal configuration for audio policy.
+PRODUCT_COPY_FILES += \
+ frameworks/av/services/audiopolicy/config/audio_policy_configuration_generic.xml:system/etc/audio_policy_configuration.xml \
+ frameworks/av/services/audiopolicy/config/primary_audio_policy_configuration.xml:system/etc/primary_audio_policy_configuration.xml \
+ frameworks/av/services/audiopolicy/config/r_submix_audio_policy_configuration.xml:system/etc/r_submix_audio_policy_configuration.xml \
+ frameworks/av/services/audiopolicy/config/audio_policy_volumes.xml:system/etc/audio_policy_volumes.xml \
+ frameworks/av/services/audiopolicy/config/default_volume_tables.xml:system/etc/default_volume_tables.xml \
-PRODUCT_PROPERTY_OVERRIDES := \
- ro.ril.hsxpa=1 \
- ro.ril.gprsclass=10
-
-PRODUCT_COPY_FILES := \
- device/generic/goldfish/data/etc/apns-conf.xml:system/etc/apns-conf.xml \
- device/generic/goldfish/camera/media_profiles.xml:system/etc/media_profiles.xml \
- frameworks/av/media/libstagefright/data/media_codecs_google_audio.xml:system/etc/media_codecs_google_audio.xml \
- frameworks/av/media/libstagefright/data/media_codecs_google_telephony.xml:system/etc/media_codecs_google_telephony.xml \
- frameworks/av/media/libstagefright/data/media_codecs_google_video.xml:system/etc/media_codecs_google_video.xml \
- device/generic/goldfish/camera/media_codecs.xml:system/etc/media_codecs.xml
-
-PRODUCT_PACKAGES := \
- audio.primary.goldfish \
- vibrator.goldfish
+# 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_x86_64_ab/BoardConfig.mk b/target/board/generic_x86_64_ab/BoardConfig.mk
index e49863a..a098dfe 100644
--- a/target/board/generic_x86_64_ab/BoardConfig.mk
+++ b/target/board/generic_x86_64_ab/BoardConfig.mk
@@ -24,6 +24,11 @@
TARGET_2ND_ARCH := x86
TARGET_2ND_ARCH_VARIANT := x86_64
+# Set this to create /cache mount point for non-A/B devices that mounts /cache.
+# The partition size doesn't matter, just to make build pass.
+BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE := ext4
+BOARD_CACHEIMAGE_PARTITION_SIZE := 16777216
+
# Enable A/B update
TARGET_NO_RECOVERY := true
BOARD_BUILD_SYSTEM_ROOT_IMAGE := true
diff --git a/target/board/generic_x86_ab/BoardConfig.mk b/target/board/generic_x86_ab/BoardConfig.mk
index 6e51102..db4dacd 100644
--- a/target/board/generic_x86_ab/BoardConfig.mk
+++ b/target/board/generic_x86_ab/BoardConfig.mk
@@ -20,6 +20,11 @@
TARGET_ARCH := x86
TARGET_ARCH_VARIANT := x86
+# Set this to create /cache mount point for non-A/B devices that mounts /cache.
+# The partition size doesn't matter, just to make build pass.
+BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE := ext4
+BOARD_CACHEIMAGE_PARTITION_SIZE := 16777216
+
# Enable A/B update
TARGET_NO_RECOVERY := true
BOARD_BUILD_SYSTEM_ROOT_IMAGE := true
diff --git a/target/board/generic_x86_arm/BoardConfig.mk b/target/board/generic_x86_arm/BoardConfig.mk
index 131c001..c66aacc 100644
--- a/target/board/generic_x86_arm/BoardConfig.mk
+++ b/target/board/generic_x86_arm/BoardConfig.mk
@@ -61,4 +61,4 @@
BOARD_FLASH_BLOCK_SIZE := 512
TARGET_USERIMAGES_SPARSE_EXT_DISABLED := true
-BOARD_SEPOLICY_DIRS += build/target/board/generic/sepolicy
+BOARD_SEPOLICY_DIRS += device/generic/goldfish/sepolicy/common
diff --git a/target/board/gsi_system.prop b/target/board/gsi_system.prop
new file mode 100644
index 0000000..0c04a95
--- /dev/null
+++ b/target/board/gsi_system.prop
@@ -0,0 +1,8 @@
+# GSI always generate dex pre-opt in system image
+ro.cp_system_other_odex=0
+
+# GSI always disables adb authentication
+ro.adb.secure=0
+
+# TODO(b/78105955): disable privapp_permissions checking before the bug solved
+ro.control_privapp_permissions=disable
diff --git a/target/board/treble_common.mk b/target/board/treble_common.mk
index fd3363c..c4e68fe 100644
--- a/target/board/treble_common.mk
+++ b/target/board/treble_common.mk
@@ -19,7 +19,6 @@
# VNDK
BOARD_VNDK_VERSION := current
-BOARD_VNDK_RUNTIME_DISABLE := true
# Properties
TARGET_SYSTEM_PROP := build/make/target/board/treble_system.prop
@@ -40,28 +39,23 @@
# Generic AOSP image always requires separate vendor.img
TARGET_COPY_OUT_VENDOR := vendor
-# Enable dex pre-opt to speed up initial boot
-ifeq ($(HOST_OS),linux)
- ifeq ($(WITH_DEXPREOPT),)
- WITH_DEXPREOPT := true
- WITH_DEXPREOPT_PIC := true
- ifneq ($(TARGET_BUILD_VARIANT),user)
- # Retain classes.dex in APK's for non-user builds
- DEX_PREOPT_DEFAULT := nostripping
- endif
- endif
-endif
+# Android generic system image always create metadata partition
+BOARD_USES_METADATA_PARTITION := true
# Generic AOSP image does NOT support HWC1
TARGET_USES_HWC2 := true
# Set emulator framebuffer display device buffer count to 3
NUM_FRAMEBUFFER_SURFACE_BUFFERS := 3
-# TODO(b/35790399): remove when b/35790399 is fixed.
-BOARD_NAND_SPARE_SIZE := 0
-BOARD_FLASH_BLOCK_SIZE := 512
+# Audio
+USE_XML_AUDIO_POLICY_CONF := 1
-# b/64700195: add minimum support for odm.img
-# Currently odm.img can only be built by `make custom_images`.
-# Adding /odm mount point under root directory.
-BOARD_ROOT_EXTRA_FOLDERS += odm
+# Android Verified Boot (AVB):
+# Builds a special vbmeta.img that disables AVB verification.
+# Otherwise, AVB will prevent the device from booting the generic system.img.
+# Also checks that BOARD_AVB_ENABLE is not set, to prevent adding verity
+# metadata into system.img.
+ifeq ($(BOARD_AVB_ENABLE),true)
+$(error BOARD_AVB_ENABLE cannot be set for Treble GSI)
+endif
+BOARD_BUILD_DISABLED_VBMETAIMAGE := true
diff --git a/target/board/treble_system.prop b/target/board/treble_system.prop
index 4b54aaf..0c04a95 100644
--- a/target/board/treble_system.prop
+++ b/target/board/treble_system.prop
@@ -3,3 +3,6 @@
# GSI always disables adb authentication
ro.adb.secure=0
+
+# TODO(b/78105955): disable privapp_permissions checking before the bug solved
+ro.control_privapp_permissions=disable
diff --git a/target/product/AndroidProducts.mk b/target/product/AndroidProducts.mk
index 9e2adee..85330b3 100644
--- a/target/product/AndroidProducts.mk
+++ b/target/product/AndroidProducts.mk
@@ -36,7 +36,6 @@
PRODUCT_MAKEFILES := \
$(LOCAL_DIR)/aosp_arm.mk \
$(LOCAL_DIR)/full.mk \
- $(LOCAL_DIR)/generic_armv5.mk \
$(LOCAL_DIR)/aosp_x86.mk \
$(LOCAL_DIR)/full_x86.mk \
$(LOCAL_DIR)/aosp_mips.mk \
diff --git a/target/product/aosp_arm.mk b/target/product/aosp_arm.mk
index 9ed5284..b872f48 100644
--- a/target/product/aosp_arm.mk
+++ b/target/product/aosp_arm.mk
@@ -14,18 +14,15 @@
# limitations under the License.
#
-PRODUCT_PROPERTY_OVERRIDES += \
- rild.libpath=/vendor/lib/libreference-ril.so
+-include device/generic/goldfish/arm32-vendor.mk
-# Note: the following lines need to stay at the beginning so that it can
-# take priority and override the rules it inherit from other mk files
-# see copy file rules in core/Makefile
-PRODUCT_COPY_FILES += \
- development/sys-img/advancedFeatures.ini.arm:advancedFeatures.ini \
- prebuilts/qemu-kernel/arm/3.18/kernel-qemu2:kernel-ranchu \
- device/generic/goldfish/fstab.ranchu.arm:root/fstab.ranchu \
- device/generic/goldfish/fstab.ranchu.early.arm:root/fstab.ranchu.early
+# TODO(b/78308559): includes vr_hwc into GSI before vr_hwc move to vendor
+PRODUCT_PACKAGES += \
+ vr_hwc
include $(SRC_TARGET_DIR)/product/full.mk
+# Needed by Pi newly launched device to pass VtsTrebleSysProp on GSI
+PRODUCT_COMPATIBLE_PROPERTY_OVERRIDE := true
+
PRODUCT_NAME := aosp_arm
diff --git a/target/product/aosp_arm64.mk b/target/product/aosp_arm64.mk
index 18d613b..33defe1 100644
--- a/target/product/aosp_arm64.mk
+++ b/target/product/aosp_arm64.mk
@@ -14,28 +14,33 @@
# limitations under the License.
#
-PRODUCT_PROPERTY_OVERRIDES += \
- rild.libpath=/vendor/lib64/libreference-ril.so
-
# 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.
-# Note: the following lines need to stay at the beginning so that it can
-# take priority and override the rules it inherit from other mk files
-# see copy file rules in core/Makefile
-PRODUCT_COPY_FILES += \
- development/sys-img/advancedFeatures.ini.arm:advancedFeatures.ini \
- prebuilts/qemu-kernel/arm64/3.18/kernel-qemu2:kernel-ranchu \
- device/generic/goldfish/fstab.ranchu.arm:root/fstab.ranchu \
- device/generic/goldfish/fstab.ranchu.early.arm:root/fstab.ranchu.early
+-include device/generic/goldfish/arm64-vendor.mk
+# Copy different zygote settings for vendor.img to select by setting property
+# ro.zygote=zygote64_32 or ro.zygote=zygote32_64:
+# 1. 64-bit primary, 32-bit secondary OR
+# 2. 32-bit primary, 64-bit secondary
+# init.zygote64_32.rc is in the core_64_bit.mk below
+PRODUCT_COPY_FILES += \
+ system/core/rootdir/init.zygote32_64.rc:root/init.zygote32_64.rc
+
+# TODO(b/78308559): includes vr_hwc into GSI before vr_hwc move to vendor
+PRODUCT_PACKAGES += \
+ vr_hwc
+
+$(call inherit-product, $(SRC_TARGET_DIR)/product/emulator.mk)
$(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit.mk)
$(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_base_telephony.mk)
$(call inherit-product, $(SRC_TARGET_DIR)/board/generic_arm64/device.mk)
-include $(SRC_TARGET_DIR)/product/emulator.mk
+# Needed by Pi newly launched device to pass VtsTrebleSysProp on GSI
+PRODUCT_COMPATIBLE_PROPERTY_OVERRIDE := true
+
PRODUCT_NAME := aosp_arm64
PRODUCT_DEVICE := generic_arm64
PRODUCT_BRAND := Android
diff --git a/target/product/aosp_arm64_ab.mk b/target/product/aosp_arm64_ab.mk
index c96cb91..6ff1157 100644
--- a/target/product/aosp_arm64_ab.mk
+++ b/target/product/aosp_arm64_ab.mk
@@ -21,12 +21,6 @@
include build/make/target/product/treble_common_64.mk
-AB_OTA_UPDATER := true
-AB_OTA_PARTITIONS := system
-PRODUCT_PACKAGES += \
- update_engine \
- update_verifier
-
PRODUCT_NAME := aosp_arm64_ab
PRODUCT_DEVICE := generic_arm64_ab
PRODUCT_BRAND := Android
diff --git a/target/product/aosp_arm_ab.mk b/target/product/aosp_arm_ab.mk
index 98b2f99..9a4688e 100644
--- a/target/product/aosp_arm_ab.mk
+++ b/target/product/aosp_arm_ab.mk
@@ -21,12 +21,6 @@
include build/make/target/product/treble_common_32.mk
-AB_OTA_UPDATER := true
-AB_OTA_PARTITIONS := system
-PRODUCT_PACKAGES += \
- update_engine \
- update_verifier
-
PRODUCT_NAME := aosp_arm_ab
PRODUCT_DEVICE := generic_arm_ab
PRODUCT_BRAND := Android
diff --git a/target/product/aosp_mips.mk b/target/product/aosp_mips.mk
index a76b93a..5ee6185 100644
--- a/target/product/aosp_mips.mk
+++ b/target/product/aosp_mips.mk
@@ -1,5 +1,5 @@
#
-# Copyright 2013 The Android Open-Source Project
+# Copyright 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.
@@ -13,6 +13,19 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
+
+PRODUCT_PROPERTY_OVERRIDES += \
+ rild.libpath=/vendor/lib/libreference-ril.so
+
+# Note: the following lines need to stay at the beginning so that it can
+# take priority and override the rules it inherit from other mk files
+# see copy file rules in core/Makefile
+PRODUCT_COPY_FILES += \
+ development/sys-img/advancedFeatures.ini.arm:advancedFeatures.ini \
+ prebuilts/qemu-kernel/mips/3.18/kernel-qemu2:kernel-ranchu \
+ device/generic/goldfish/fstab.ranchu.mips:root/fstab.ranchu \
+ device/generic/goldfish/fstab.ranchu.early.arm:root/fstab.ranchu.early
+
include $(SRC_TARGET_DIR)/product/full_mips.mk
PRODUCT_NAME := aosp_mips
diff --git a/target/product/aosp_mips64.mk b/target/product/aosp_mips64.mk
index f606858..73d3731 100644
--- a/target/product/aosp_mips64.mk
+++ b/target/product/aosp_mips64.mk
@@ -1,5 +1,5 @@
#
-# Copyright 2013 The Android Open-Source Project
+# Copyright 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.
@@ -14,14 +14,22 @@
# limitations under the License.
#
+PRODUCT_PROPERTY_OVERRIDES += \
+ rild.libpath=/vendor/lib64/libreference-ril.so
+
# 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
-# mips64 build quite specifically for the emulator, and might not be
+# build quite specifically for the emulator, and might not be
# entirely appropriate to inherit from for on-device configurations.
-# This is for enabling ethernet support for ranchu.
-# Consider removing this after RIL support is provided in ranchu.
-PRODUCT_COPY_FILES += frameworks/native/data/etc/android.hardware.ethernet.xml:system/etc/permissions/android.hardware.ethernet.xml
+# Note: the following lines need to stay at the beginning so that it can
+# take priority and override the rules it inherit from other mk files
+# see copy file rules in core/Makefile
+PRODUCT_COPY_FILES += \
+ development/sys-img/advancedFeatures.ini.arm:advancedFeatures.ini \
+ prebuilts/qemu-kernel/mips64/3.18/kernel-qemu2:kernel-ranchu \
+ device/generic/goldfish/fstab.ranchu.mips:root/fstab.ranchu \
+ device/generic/goldfish/fstab.ranchu.early.arm:root/fstab.ranchu.early
$(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit.mk)
$(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_base_telephony.mk)
diff --git a/target/product/aosp_x86.mk b/target/product/aosp_x86.mk
index 03203ce..9ba9523 100644
--- a/target/product/aosp_x86.mk
+++ b/target/product/aosp_x86.mk
@@ -14,18 +14,15 @@
# limitations under the License.
#
-PRODUCT_PROPERTY_OVERRIDES += \
- rild.libpath=/vendor/lib/libreference-ril.so
+-include device/generic/goldfish/x86-vendor.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.
-PRODUCT_COPY_FILES += \
- development/sys-img/advancedFeatures.ini:advancedFeatures.ini \
- device/generic/goldfish/data/etc/encryptionkey.img:encryptionkey.img \
- prebuilts/qemu-kernel/x86/3.18/kernel-qemu2:kernel-ranchu
+# TODO(b/78308559): includes vr_hwc into GSI before vr_hwc move to vendor
+PRODUCT_PACKAGES += \
+ vr_hwc
include $(SRC_TARGET_DIR)/product/full_x86.mk
+# Needed by Pi newly launched device to pass VtsTrebleSysProp on GSI
+PRODUCT_COMPATIBLE_PROPERTY_OVERRIDE := true
+
PRODUCT_NAME := aosp_x86
diff --git a/target/product/aosp_x86_64.mk b/target/product/aosp_x86_64.mk
index 693bdaf..7afc782 100644
--- a/target/product/aosp_x86_64.mk
+++ b/target/product/aosp_x86_64.mk
@@ -14,24 +14,32 @@
# limitations under the License.
#
-PRODUCT_PROPERTY_OVERRIDES += \
- rild.libpath=/vendor/lib64/libreference-ril.so
-
# 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.
-PRODUCT_COPY_FILES += \
- development/sys-img/advancedFeatures.ini:advancedFeatures.ini \
- device/generic/goldfish/data/etc/encryptionkey.img:encryptionkey.img \
- prebuilts/qemu-kernel/x86_64/3.18/kernel-qemu2:kernel-ranchu
+-include device/generic/goldfish/x86_64-vendor.mk
+# Copy different zygote settings for vendor.img to select by setting property
+# ro.zygote=zygote64_32 or ro.zygote=zygote32_64:
+# 1. 64-bit primary, 32-bit secondary OR
+# 2. 32-bit primary, 64-bit secondary
+# init.zygote64_32.rc is in the core_64_bit.mk below
+PRODUCT_COPY_FILES += \
+ system/core/rootdir/init.zygote32_64.rc:root/init.zygote32_64.rc
+
+# TODO(b/78308559): includes vr_hwc into GSI before vr_hwc move to vendor
+PRODUCT_PACKAGES += \
+ vr_hwc
+
+$(call inherit-product, $(SRC_TARGET_DIR)/product/emulator.mk)
$(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit.mk)
$(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_base_telephony.mk)
$(call inherit-product, $(SRC_TARGET_DIR)/board/generic_x86_64/device.mk)
-include $(SRC_TARGET_DIR)/product/emulator.mk
+# Needed by Pi newly launched device to pass VtsTrebleSysProp on GSI
+PRODUCT_COMPATIBLE_PROPERTY_OVERRIDE := true
ifdef NET_ETH0_STARTONBOOT
PRODUCT_PROPERTY_OVERRIDES += net.eth0.startonboot=1
diff --git a/target/product/aosp_x86_64_ab.mk b/target/product/aosp_x86_64_ab.mk
index 4590dc5..3524dbc 100644
--- a/target/product/aosp_x86_64_ab.mk
+++ b/target/product/aosp_x86_64_ab.mk
@@ -21,12 +21,6 @@
include build/make/target/product/treble_common_64.mk
-AB_OTA_UPDATER := true
-AB_OTA_PARTITIONS := system
-PRODUCT_PACKAGES += \
- update_engine \
- update_verifier
-
PRODUCT_NAME := aosp_x86_64_ab
PRODUCT_DEVICE := generic_x86_64_ab
PRODUCT_BRAND := Android
diff --git a/target/product/aosp_x86_ab.mk b/target/product/aosp_x86_ab.mk
index 404a4da..e72b38d 100644
--- a/target/product/aosp_x86_ab.mk
+++ b/target/product/aosp_x86_ab.mk
@@ -21,12 +21,6 @@
include build/make/target/product/treble_common_32.mk
-AB_OTA_UPDATER := true
-AB_OTA_PARTITIONS := system
-PRODUCT_PACKAGES += \
- update_engine \
- update_verifier
-
PRODUCT_NAME := aosp_x86_ab
PRODUCT_DEVICE := generic_x86_ab
PRODUCT_BRAND := Android
diff --git a/target/product/base.mk b/target/product/base.mk
index 9e38623..bc3710c 100644
--- a/target/product/base.mk
+++ b/target/product/base.mk
@@ -23,6 +23,7 @@
appops \
am \
android.policy \
+ android.test.base \
android.test.mock \
android.test.runner \
app_process \
@@ -31,6 +32,7 @@
bit \
blkid \
bmgr \
+ bpfloader \
bugreport \
bugreportz \
cameraserver \
@@ -44,6 +46,7 @@
ime \
incidentd \
incident \
+ incident_helper \
incident_report \
input \
javax.obex \
@@ -60,6 +63,7 @@
libcamera2ndk \
libdl \
libdrmclearkeyplugin \
+ libdynproc \
libclearkeycasplugin \
libeffectproxy \
libeffects \
@@ -114,6 +118,7 @@
mtpd \
ndc \
netd \
+ perfetto \
ping \
ping6 \
platform.xml \
@@ -129,13 +134,28 @@
settings \
sgdisk \
sm \
+ statsd \
svc \
tc \
telecom \
+ traced \
+ traced_probes \
vdc \
vold \
wm
+# Add the compatibility library that is needed when org.apache.http.legacy
+# is removed from the bootclasspath.
+ifeq ($(REMOVE_OAHL_FROM_BCP),true)
+PRODUCT_PACKAGES += framework-oahl-backward-compatibility
+endif
+
+# Add the compatibility library that is needed when android.test.base
+# is removed from the bootclasspath.
+ifeq ($(REMOVE_ATB_FROM_BCP),true)
+PRODUCT_PACKAGES += framework-atb-backward-compatibility
+endif
+
# Essential HAL modules
PRODUCT_PACKAGES += \
android.hardware.cas@1.0-service \
@@ -147,8 +167,10 @@
# Packages included only for eng or userdebug builds, previously debug tagged
PRODUCT_PACKAGES_DEBUG := \
+ logpersist.start \
perfprofd \
- sqlite3
+ sqlite3 \
+ strace
PRODUCT_COPY_FILES := $(call add-to-product-copy-files-if-exists,\
frameworks/base/config/preloaded-classes:system/etc/preloaded-classes)
diff --git a/target/product/cfi-common.mk b/target/product/cfi-common.mk
new file mode 100644
index 0000000..7a53bc1
--- /dev/null
+++ b/target/product/cfi-common.mk
@@ -0,0 +1,39 @@
+#
+# Copyright (C) 2018 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# This is a set of common components to enable CFI for (across
+# compatible product configs)
+PRODUCT_CFI_INCLUDE_PATHS := \
+ device/google/cuttlefish_common/guest/libs/wpa_supplicant_8_lib \
+ device/google/wahoo/wifi_offload \
+ external/tinyxml2 \
+ external/wpa_supplicant_8 \
+ frameworks/av/camera \
+ frameworks/av/media \
+ frameworks/av/services \
+ frameworks/minikin \
+ hardware/broadcom/wlan/bcmdhd/wpa_supplicant_8_lib \
+ hardware/interfaces/nfc \
+ hardware/qcom/wlan/qcwcn/wpa_supplicant_8_lib \
+ harware/interfaces/keymaster \
+ system/bt \
+ system/chre \
+ system/core/libnetutils \
+ system/core/libziparchive \
+ system/gatekeeper \
+ system/keymaster \
+ system/nfc \
+ system/security \
diff --git a/target/product/core.mk b/target/product/core.mk
index a2b0f1c..c72bb2f 100644
--- a/target/product/core.mk
+++ b/target/product/core.mk
@@ -42,21 +42,24 @@
KeyChain \
Keyguard \
LatinIME \
- Launcher2 \
+ Launcher3QuickStep \
ManagedProvisioning \
MtpDocumentsProvider \
- PicoTts \
PacProcessor \
libpac \
PrintSpooler \
PrintRecommendationService \
ProxyHandler \
QuickSearchBox \
+ SecureElement \
Settings \
+ SettingsIntelligence \
SharedStorageBackup \
+ SimAppDialog \
StorageManager \
Telecom \
TeleService \
+ Traceur \
VpnDialogs \
vr \
MmsService
diff --git a/target/product/core_64_bit_only.mk b/target/product/core_64_bit_only.mk
new file mode 100644
index 0000000..72d30f5
--- /dev/null
+++ b/target/product/core_64_bit_only.mk
@@ -0,0 +1,30 @@
+#
+# 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.
+#
+
+# Inherit from this product for devices that support only 64-bit apps using:
+# $(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit_only.mk)
+# The inheritance for this must come before the inheritance chain that leads
+# to core_minimal.mk.
+
+# Copy the 64-bit zygote startup script
+PRODUCT_COPY_FILES += system/core/rootdir/init.zygote64.rc:root/init.zygote64.rc
+
+# 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
+
+TARGET_SUPPORTS_32_BIT_APPS := false
+TARGET_SUPPORTS_64_BIT_APPS := true
diff --git a/target/product/core_base.mk b/target/product/core_base.mk
index 151e8de..7dc0010 100644
--- a/target/product/core_base.mk
+++ b/target/product/core_base.mk
@@ -62,9 +62,4 @@
mdnsd \
requestsync \
-# Wifi modules
-PRODUCT_PACKAGES += \
- wifi-service \
- wificond \
-
$(call inherit-product, $(SRC_TARGET_DIR)/product/core_minimal.mk)
diff --git a/target/product/core_minimal.mk b/target/product/core_minimal.mk
index ab65f5b..85646c1 100644
--- a/target/product/core_minimal.mk
+++ b/target/product/core_minimal.mk
@@ -33,6 +33,7 @@
HTMLViewer \
MediaProvider \
PackageInstaller \
+ SecureElement \
SettingsProvider \
Shell \
StatementService \
@@ -60,7 +61,6 @@
iptables \
gatekeeperd \
keystore \
- keystore.default \
ld.config.txt \
ld.mc \
libaaudio \
@@ -77,7 +77,7 @@
libwebviewchromium_plat_support \
libwilhelm \
logd \
- make_ext4fs \
+ mke2fs \
e2fsck \
resize2fs \
tune2fs \
@@ -86,6 +86,7 @@
telephony-common \
uiautomator \
uncrypt \
+ vndk_snapshot_package \
voip-common \
webview \
webview_zygote \
@@ -110,16 +111,26 @@
# The order of PRODUCT_BOOT_JARS matters.
PRODUCT_BOOT_JARS := \
$(TARGET_CORE_JARS) \
- legacy-test \
ext \
framework \
telephony-common \
voip-common \
ims-common \
- org.apache.http.legacy.boot \
android.hidl.base-V1.0-java \
android.hidl.manager-V1.0-java
+ifeq ($(REMOVE_OAHL_FROM_BCP),true)
+PRODUCT_BOOT_JARS += framework-oahl-backward-compatibility
+else
+PRODUCT_BOOT_JARS += org.apache.http.legacy.boot
+endif
+
+ifeq ($(REMOVE_ATB_FROM_BCP),true)
+PRODUCT_BOOT_JARS += framework-atb-backward-compatibility
+else
+PRODUCT_BOOT_JARS += android.test.base
+endif
+
# The order of PRODUCT_SYSTEM_SERVER_JARS matters.
PRODUCT_SYSTEM_SERVER_JARS := \
services \
@@ -135,7 +146,7 @@
# Adoptable external storage supports both ext4 and f2fs
PRODUCT_PACKAGES += \
e2fsck \
- make_ext4fs \
+ mke2fs \
fsck.f2fs \
make_f2fs \
@@ -157,9 +168,17 @@
# On userdebug builds, collect more tombstones by default.
ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT)))
-PRODUCT_DEFAULT_PROPERTY_OVERRIDES += \
+PRODUCT_SYSTEM_DEFAULT_PROPERTIES += \
tombstoned.max_tombstone_count=50
endif
+PRODUCT_DEFAULT_PROPERTY_OVERRIDES += \
+ ro.logd.size.stats=64K \
+ log.tag.stats_log=I
+
$(call inherit-product, $(SRC_TARGET_DIR)/product/runtime_libart.mk)
$(call inherit-product, $(SRC_TARGET_DIR)/product/base.mk)
+
+# Enable CFI for security-sensitive components
+$(call inherit-product, $(SRC_TARGET_DIR)/product/cfi-common.mk)
+$(call inherit-product-if-exists, vendor/google/products/cfi-vendor.mk)
diff --git a/target/product/core_tiny.mk b/target/product/core_tiny.mk
index e473413..4ef7b48 100644
--- a/target/product/core_tiny.mk
+++ b/target/product/core_tiny.mk
@@ -41,6 +41,7 @@
DefaultContainerService \
ExtShared \
ExtServices \
+ SecureElement \
SettingsProvider \
Shell \
WallpaperBackup \
@@ -59,7 +60,7 @@
iptables \
gatekeeperd \
keystore \
- keystore.default \
+ ld.config.txt \
ld.mc \
libaaudio \
libOpenMAXAL \
@@ -71,11 +72,10 @@
libwilhelm \
libdrmframework_jni \
libdrmframework \
- make_ext4fs \
+ mke2fs \
e2fsck \
resize2fs \
tune2fs \
- nullwebview \
screencap \
sensorservice \
uiautomator \
@@ -96,17 +96,26 @@
# The order matters
PRODUCT_BOOT_JARS := \
$(TARGET_CORE_JARS) \
- legacy-test \
ext \
framework \
telephony-common \
voip-common \
ims-common \
- nullwebview \
- org.apache.http.legacy.boot \
android.hidl.base-V1.0-java \
android.hidl.manager-V1.0-java
+ifeq ($(REMOVE_OAHL_FROM_BCP),true)
+PRODUCT_BOOT_JARS += framework-oahl-backward-compatibility
+else
+PRODUCT_BOOT_JARS += org.apache.http.legacy.boot
+endif
+
+ifeq ($(REMOVE_ATB_FROM_BCP),true)
+PRODUCT_BOOT_JARS += framework-atb-backward-compatibility
+else
+PRODUCT_BOOT_JARS += android.test.base
+endif
+
# The order of PRODUCT_SYSTEM_SERVER_JARS matters.
PRODUCT_SYSTEM_SERVER_JARS := \
services \
diff --git a/target/product/embedded.mk b/target/product/embedded.mk
index 7efa686..69cf102 100644
--- a/target/product/embedded.mk
+++ b/target/product/embedded.mk
@@ -20,10 +20,13 @@
PRODUCT_PACKAGES += \
adb \
adbd \
- android.hardware.configstore@1.0-service \
+ usbd \
+ android.hardware.configstore@1.1-service \
android.hidl.allocator@1.0-service \
android.hidl.memory@1.0-impl \
+ android.hidl.memory@1.0-impl.vendor \
atrace \
+ blank_screen \
bootanimation \
bootstat \
charger \
@@ -48,6 +51,7 @@
libbinder \
libc \
libc_malloc_debug \
+ libc_malloc_hooks \
libcutils \
libdl \
libgui \
@@ -68,7 +72,6 @@
linker \
lmkd \
logcat \
- logwrapper \
lshal \
recovery \
service \
@@ -81,25 +84,18 @@
tzdatacheck \
vndservice \
vndservicemanager \
- compatibility_matrix.xml \
- manifest.xml \
- system_manifest.xml \
- system_compatibility_matrix.xml \
-# SELinux packages
+# VINTF data
PRODUCT_PACKAGES += \
- nonplat_mac_permissions.xml \
- nonplat_property_contexts \
- nonplat_seapp_contexts \
- nonplat_service_contexts \
- nonplat_hwservice_contexts \
- plat_mac_permissions.xml \
- plat_property_contexts \
- plat_seapp_contexts \
- plat_service_contexts \
- plat_hwservice_contexts \
+ device_compatibility_matrix.xml \
+ device_manifest.xml \
+ framework_manifest.xml \
+ framework_compatibility_matrix.xml \
+
+# SELinux packages are added as dependencies of the selinux_policy
+# phony package.
+PRODUCT_PACKAGES += \
selinux_policy \
- vndservice_contexts
# AID Generation for
# <pwd.h> and <grp.h>
@@ -109,9 +105,14 @@
fs_config_files \
fs_config_dirs
+# If there are product-specific adb keys defined, install them on debuggable
+# builds.
+PRODUCT_PACKAGES_DEBUG += \
+ adb_keys
+
# Ensure that this property is always defined so that bionic_systrace.cpp
# can rely on it being initially set by init.
-PRODUCT_DEFAULT_PROPERTY_OVERRIDES += \
+PRODUCT_SYSTEM_DEFAULT_PROPERTIES += \
debug.atrace.tags.enableflags=0
PRODUCT_COPY_FILES += \
diff --git a/target/product/empty-preloaded-classes b/target/product/empty-preloaded-classes
new file mode 100644
index 0000000..c2ff1e9
--- /dev/null
+++ b/target/product/empty-preloaded-classes
@@ -0,0 +1 @@
+# Empty preloaded-classes file for automated testing.
diff --git a/target/product/empty-profile b/target/product/empty-profile
new file mode 100644
index 0000000..c2ff1e9
--- /dev/null
+++ b/target/product/empty-profile
@@ -0,0 +1 @@
+# Empty preloaded-classes file for automated testing.
diff --git a/target/product/emulator.mk b/target/product/emulator.mk
index 0e1e581..f6e1011 100644
--- a/target/product/emulator.mk
+++ b/target/product/emulator.mk
@@ -18,136 +18,49 @@
# emulator-related modules to PRODUCT_PACKAGES.
#
-# Host modules
-PRODUCT_PACKAGES += \
-
-
# Device modules
PRODUCT_PACKAGES += \
- egl.cfg \
- gralloc.goldfish \
- gralloc.ranchu \
- libGLESv1_CM_emulation \
- lib_renderControl_enc \
- libEGL_emulation \
libGLES_android \
- libGLESv2_enc \
- libOpenglSystemCommon \
- libGLESv2_emulation \
- libGLESv1_enc \
- qemu-props \
- camera.goldfish \
- camera.goldfish.jpeg \
- camera.ranchu \
- camera.ranchu.jpeg \
- keystore.goldfish \
- keystore.ranchu \
- gatekeeper.ranchu \
- lights.goldfish \
- gps.goldfish \
- gps.ranchu \
- fingerprint.goldfish \
- sensors.goldfish \
- audio.primary.goldfish \
- audio.primary.goldfish_legacy \
- android.hardware.audio@2.0-service \
- vibrator.goldfish \
- power.goldfish \
- power.ranchu \
- fingerprint.ranchu \
- android.hardware.biometrics.fingerprint@2.1-service \
- sensors.ranchu \
- android.hardware.graphics.composer@2.1-impl \
- android.hardware.graphics.composer@2.1-service \
- android.hardware.graphics.allocator@2.0-service \
- android.hardware.graphics.allocator@2.0-impl \
- android.hardware.graphics.mapper@2.0-impl \
- hwcomposer.goldfish \
- hwcomposer.ranchu \
- sh_vendor \
vintf \
- toybox_vendor \
- CarrierConfig
-
-PRODUCT_PACKAGES += \
- android.hardware.audio@2.0-impl \
- android.hardware.audio.effect@2.0-impl \
- android.hardware.broadcastradio@1.0-impl \
- android.hardware.soundtrigger@2.0-impl
-
-PRODUCT_PACKAGES += \
- android.hardware.keymaster@3.0-impl \
- android.hardware.keymaster@3.0-service
-
-PRODUCT_PACKAGES += \
- android.hardware.gnss@1.0-service \
- android.hardware.gnss@1.0-impl
-
-PRODUCT_PACKAGES += \
- android.hardware.sensors@1.0-impl \
- android.hardware.sensors@1.0-service
-
-PRODUCT_PACKAGES += \
- android.hardware.drm@1.0-service \
- android.hardware.drm@1.0-impl
-
-PRODUCT_PACKAGES += \
- android.hardware.power@1.0-service \
- android.hardware.power@1.0-impl
-
-PRODUCT_PACKAGES += \
- camera.device@1.0-impl \
- android.hardware.camera.provider@2.4-service \
- android.hardware.camera.provider@2.4-impl \
-
-PRODUCT_PACKAGES += \
- android.hardware.gatekeeper@1.0-impl \
- android.hardware.gatekeeper@1.0-service
+ CarrierConfig \
# need this for gles libraries to load properly
# after moving to /vendor/lib/
PRODUCT_PACKAGES += \
- android.hardware.renderscript@1.0.vndk-sp\
- android.hardware.graphics.allocator@2.0.vndk-sp\
- android.hardware.graphics.mapper@2.0.vndk-sp\
- android.hardware.graphics.common@1.0.vndk-sp\
- libhwbinder.vndk-sp\
- libbase.vndk-sp\
- libcutils.vndk-sp\
- libhardware.vndk-sp\
- libhidlbase.vndk-sp\
- libhidltransport.vndk-sp\
- libutils.vndk-sp\
- libc++.vndk-sp\
- libRS_internal.vndk-sp\
- libRSDriver.vndk-sp\
- libRSCpuRef.vndk-sp\
- libbcinfo.vndk-sp\
- libblas.vndk-sp\
- libft2.vndk-sp\
- libpng.vndk-sp\
- libcompiler_rt.vndk-sp\
- libbacktrace.vndk-sp\
- libunwind.vndk-sp\
- liblzma.vndk-sp\
- libz.vndk-sp\
+ vndk-sp
+# WiFi: system side
+PRODUCT_PACKAGES += \
+ ip \
+ iw \
+ wificond \
-PRODUCT_COPY_FILES += \
- device/generic/goldfish/init.ranchu-core.sh:vendor/bin/init.ranchu-core.sh \
- device/generic/goldfish/init.ranchu-net.sh:vendor/bin/init.ranchu-net.sh \
- device/generic/goldfish/init.ranchu.rc:root/init.ranchu.rc \
- device/generic/goldfish/fstab.ranchu:root/fstab.ranchu \
- device/generic/goldfish/fstab.ranchu.early:root/fstab.ranchu.early \
- device/generic/goldfish/ueventd.ranchu.rc:root/ueventd.ranchu.rc \
- device/generic/goldfish/input/goldfish_rotary.idc:system/usr/idc/goldfish_rotary.idc \
- device/generic/goldfish/manifest.xml:$(TARGET_COPY_OUT_VENDOR)/manifest.xml \
- device/generic/goldfish/data/etc/permissions/privapp-permissions-goldfish.xml:system/etc/permissions/privapp-permissions-goldfish.xml \
- device/generic/goldfish/data/etc/config.ini:config.ini \
- frameworks/native/data/etc/android.hardware.usb.accessory.xml:system/etc/permissions/android.hardware.usb.accessory.xml
PRODUCT_PACKAGE_OVERLAYS := device/generic/goldfish/overlay
PRODUCT_CHARACTERISTICS := emulator
PRODUCT_FULL_TREBLE_OVERRIDE := true
+
+# goldfish vendor partition configurations
+$(call inherit-product-if-exists, device/generic/goldfish/vendor.mk)
+
+#watchdog tiggers reboot because location service is not
+#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 += \
+#config.disable_location=true
+
+# Enable Perfetto traced
+PRODUCT_SYSTEM_DEFAULT_PROPERTIES += \
+ persist.traced.enable=1
+
+# enable Google-specific location features,
+# like NetworkLocationProvider and LocationCollector
+PRODUCT_SYSTEM_DEFAULT_PROPERTIES += \
+ ro.com.google.locationfeatures=1
+
+# disable setupwizard
+PRODUCT_SYSTEM_DEFAULT_PROPERTIES += \
+ ro.setupwizard.mode=DISABLED
diff --git a/target/product/full.mk b/target/product/full.mk
index b66ae92..7c0578c 100644
--- a/target/product/full.mk
+++ b/target/product/full.mk
@@ -19,11 +19,10 @@
# build quite specifically for the emulator, and might not be
# entirely appropriate to inherit from for on-device configurations.
+$(call inherit-product, $(SRC_TARGET_DIR)/product/emulator.mk)
$(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_base_telephony.mk)
$(call inherit-product, $(SRC_TARGET_DIR)/board/generic/device.mk)
-include $(SRC_TARGET_DIR)/product/emulator.mk
-
# Overrides
PRODUCT_NAME := full
PRODUCT_DEVICE := generic
diff --git a/target/product/full_base.mk b/target/product/full_base.mk
index 65bdf0f..c390ffd 100644
--- a/target/product/full_base.mk
+++ b/target/product/full_base.mk
@@ -21,10 +21,6 @@
PRODUCT_PACKAGES := \
libfwdlockengine \
- OpenWnn \
- libWnnEngDic \
- libWnnJpnDic \
- libwnndict \
WAPPushManager
PRODUCT_PACKAGES += \
@@ -37,6 +33,20 @@
PhaseBeam \
PhotoTable
+# Bluetooth:
+# audio.a2dp.default is a system module. Generic system image includes
+# audio.a2dp.default to support A2DP if board has the capability.
+PRODUCT_PACKAGES += \
+ audio.a2dp.default
+
+# Net:
+# Vendors can use the platform-provided network configuration utilities (ip,
+# iptable, etc.) to configure the Linux networking stack, but these utilities
+# do not yet include a HIDL interface wrapper. This is a solution on
+# Android O.
+PRODUCT_PACKAGES += \
+ netutils-wrapper-1.0
+
# Additional settings used in all AOSP builds
PRODUCT_PROPERTY_OVERRIDES := \
ro.config.ringtone=Ring_Synth_04.ogg \
@@ -48,11 +58,11 @@
# Get some sounds
$(call inherit-product-if-exists, frameworks/base/data/sounds/AllAudio.mk)
-# Get the TTS language packs
-$(call inherit-product-if-exists, external/svox/pico/lang/all_pico_languages.mk)
-
# Get a list of languages.
-$(call inherit-product, $(SRC_TARGET_DIR)/product/locales_full.mk)
+$(call inherit-product, $(SRC_TARGET_DIR)/product/languages_full.mk)
# Get everything else from the parent package
$(call inherit-product, $(SRC_TARGET_DIR)/product/generic_no_telephony.mk)
+
+# Add adb keys to debuggable AOSP builds (if they exist)
+$(call inherit-product-if-exists, vendor/google/security/adb/vendor_key.mk)
diff --git a/target/product/full_base_telephony.mk b/target/product/full_base_telephony.mk
index 9a2c63a..af4097d 100644
--- a/target/product/full_base_telephony.mk
+++ b/target/product/full_base_telephony.mk
@@ -24,8 +24,8 @@
ro.com.android.dataroaming=true
PRODUCT_COPY_FILES := \
- device/generic/goldfish/data/etc/apns-conf.xml:system/etc/apns-conf.xml \
- frameworks/native/data/etc/handheld_core_hardware.xml:system/etc/permissions/handheld_core_hardware.xml
+ device/sample/etc/apns-full-conf.xml:system/etc/apns-conf.xml \
+ frameworks/native/data/etc/handheld_core_hardware.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/handheld_core_hardware.xml
$(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_base.mk)
$(call inherit-product, $(SRC_TARGET_DIR)/product/telephony.mk)
diff --git a/target/product/full_x86.mk b/target/product/full_x86.mk
index 4dff713..6ea2d05 100644
--- a/target/product/full_x86.mk
+++ b/target/product/full_x86.mk
@@ -23,11 +23,10 @@
# that isn't a wifi connection. This will instruct init.rc to enable the
# network connection so that you can use it with ADB
+$(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_x86/device.mk)
-include $(SRC_TARGET_DIR)/product/emulator.mk
-
ifdef NET_ETH0_STARTONBOOT
PRODUCT_PROPERTY_OVERRIDES += net.eth0.startonboot=1
endif
diff --git a/target/product/generic_armv5.mk b/target/product/generic_armv5.mk
deleted file mode 100644
index daa321a..0000000
--- a/target/product/generic_armv5.mk
+++ /dev/null
@@ -1,25 +0,0 @@
-#
-# Copyright (C) 2011 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-# This is a generic product that isn't specialized for a specific device.
-# It includes the base Android platform.
-
-$(call inherit-product, $(SRC_TARGET_DIR)/product/generic.mk)
-
-# Overrides
-PRODUCT_BRAND := generic_armv5
-PRODUCT_DEVICE := generic_armv5
-PRODUCT_NAME := generic_armv5
diff --git a/target/product/generic_no_telephony.mk b/target/product/generic_no_telephony.mk
index 190a889..6a84c35 100644
--- a/target/product/generic_no_telephony.mk
+++ b/target/product/generic_no_telephony.mk
@@ -29,6 +29,9 @@
Provision \
SystemUI \
SysuiDarkThemeOverlay \
+ DisplayCutoutEmulationDoubleOverlay \
+ DisplayCutoutEmulationCornerOverlay \
+ DisplayCutoutEmulationTallOverlay \
EasterEgg \
WallpaperCropper
diff --git a/target/product/go_defaults_common.mk b/target/product/go_defaults_common.mk
index ca58c1d..18907c1 100644
--- a/target/product/go_defaults_common.mk
+++ b/target/product/go_defaults_common.mk
@@ -20,7 +20,10 @@
PRODUCT_PROPERTY_OVERRIDES += \
ro.config.low_ram=true \
ro.lmk.critical_upgrade=true \
- ro.lmk.upgrade_pressure=40
+ ro.lmk.upgrade_pressure=40 \
+ ro.lmk.downgrade_pressure=60 \
+ ro.lmk.kill_heaviest_task=false \
+ ro.statsd.enable=false
# set threshold to filter unused apps
PRODUCT_PROPERTY_OVERRIDES += \
diff --git a/target/product/languages_full.mk b/target/product/languages_full.mk
index 846cd70..5f3795f 100644
--- a/target/product/languages_full.mk
+++ b/target/product/languages_full.mk
@@ -23,6 +23,7 @@
am_ET \
ar_EG \
ar_XB \
+ as_IN \
az_AZ \
be_BY \
bg_BG \
@@ -76,6 +77,7 @@
nb_NO \
ne_NP \
nl_NL \
+ or_IN \
pa_IN \
pl_PL \
pt_BR \
diff --git a/target/product/locales_full.mk b/target/product/locales_full.mk
deleted file mode 100644
index 3a90d2b..0000000
--- a/target/product/locales_full.mk
+++ /dev/null
@@ -1,3 +0,0 @@
-PRODUCT_LOCALES := en_US cs_CZ da_DK de_AT de_CH de_DE de_LI el_GR en_AU en_CA en_GB en_NZ en_SG eo_EU es_ES fr_CA fr_CH fr_BE fr_FR it_CH it_IT ja_JP ko_KR nb_NO nl_BE nl_NL pl_PL pt_PT ru_RU sv_SE tr_TR zh_CN zh_HK zh_TW am_ET hi_IN
-
-$(call inherit-product, build/target/product/languages_full.mk)
diff --git a/target/product/product_launched_with_k.mk b/target/product/product_launched_with_k.mk
new file mode 100644
index 0000000..87faa12
--- /dev/null
+++ b/target/product/product_launched_with_k.mk
@@ -0,0 +1,2 @@
+#PRODUCT_SHIPPING_API_LEVEL indicates the first api level, device has been commercially launched on.
+PRODUCT_SHIPPING_API_LEVEL := 19
diff --git a/target/product/product_launched_with_l.mk b/target/product/product_launched_with_l.mk
index 8127bc3..4e79749 100644
--- a/target/product/product_launched_with_l.mk
+++ b/target/product/product_launched_with_l.mk
@@ -1,3 +1,2 @@
-#PRODUCT_SHIPPING_API_LEVEL indicates the first api level, device has been commercially launced on.
+#PRODUCT_SHIPPING_API_LEVEL indicates the first api level, device has been commercially launched on.
PRODUCT_SHIPPING_API_LEVEL := 21
-
diff --git a/target/product/product_launched_with_l_mr1.mk b/target/product/product_launched_with_l_mr1.mk
index 7a5bd0f..2086832 100644
--- a/target/product/product_launched_with_l_mr1.mk
+++ b/target/product/product_launched_with_l_mr1.mk
@@ -1,2 +1,2 @@
-#PRODUCT_SHIPPING_API_LEVEL indicates the first api level, device has been commercially launced on.
+#PRODUCT_SHIPPING_API_LEVEL indicates the first api level, device has been commercially launched on.
PRODUCT_SHIPPING_API_LEVEL := 22
diff --git a/target/product/product_launched_with_m.mk b/target/product/product_launched_with_m.mk
index afd8647..1ba1014 100644
--- a/target/product/product_launched_with_m.mk
+++ b/target/product/product_launched_with_m.mk
@@ -1,2 +1,2 @@
-#PRODUCT_SHIPPING_API_LEVEL indicates the first api level, device has been commercially launced on.
+#PRODUCT_SHIPPING_API_LEVEL indicates the first api level, device has been commercially launched on.
PRODUCT_SHIPPING_API_LEVEL := 23
diff --git a/target/product/product_launched_with_n.mk b/target/product/product_launched_with_n.mk
index f7c5d79..cac29eb 100644
--- a/target/product/product_launched_with_n.mk
+++ b/target/product/product_launched_with_n.mk
@@ -1,2 +1,2 @@
-#PRODUCT_SHIPPING_API_LEVEL indicates the first api level, device has been commercially launced on.
+#PRODUCT_SHIPPING_API_LEVEL indicates the first api level, device has been commercially launched on.
PRODUCT_SHIPPING_API_LEVEL := 24
diff --git a/target/product/product_launched_with_n_mr1.mk b/target/product/product_launched_with_n_mr1.mk
index 65d4d3f..194a1aa 100644
--- a/target/product/product_launched_with_n_mr1.mk
+++ b/target/product/product_launched_with_n_mr1.mk
@@ -1,2 +1,2 @@
-#PRODUCT_SHIPPING_API_LEVEL indicates the first api level, device has been commercially launced on.
+#PRODUCT_SHIPPING_API_LEVEL indicates the first api level, device has been commercially launched on.
PRODUCT_SHIPPING_API_LEVEL := 25
diff --git a/target/product/product_launched_with_o.mk b/target/product/product_launched_with_o.mk
index 94d30c6..8e25a2b 100644
--- a/target/product/product_launched_with_o.mk
+++ b/target/product/product_launched_with_o.mk
@@ -1,2 +1,2 @@
-#PRODUCT_SHIPPING_API_LEVEL indicates the first api level, device has been commercially launced on.
+#PRODUCT_SHIPPING_API_LEVEL indicates the first api level, device has been commercially launched on.
PRODUCT_SHIPPING_API_LEVEL := 26
diff --git a/target/product/product_launched_with_o_mr1.mk b/target/product/product_launched_with_o_mr1.mk
index 25620aa..2f3d7e6 100644
--- a/target/product/product_launched_with_o_mr1.mk
+++ b/target/product/product_launched_with_o_mr1.mk
@@ -1,2 +1,2 @@
-#PRODUCT_SHIPPING_API_LEVEL indicates the first api level, device has been commercially launced on.
+#PRODUCT_SHIPPING_API_LEVEL indicates the first api level, device has been commercially launched on.
PRODUCT_SHIPPING_API_LEVEL := 27
diff --git a/target/product/product_launched_with_p.mk b/target/product/product_launched_with_p.mk
new file mode 100644
index 0000000..fe7591f
--- /dev/null
+++ b/target/product/product_launched_with_p.mk
@@ -0,0 +1,2 @@
+#PRODUCT_SHIPPING_API_LEVEL indicates the first api level, device has been commercially launched on.
+PRODUCT_SHIPPING_API_LEVEL := 28
\ No newline at end of file
diff --git a/target/product/profile_boot_common.mk b/target/product/profile_boot_common.mk
new file mode 100644
index 0000000..f243902
--- /dev/null
+++ b/target/product/profile_boot_common.mk
@@ -0,0 +1,45 @@
+#
+# Copyright 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.
+#
+
+# Use an empty profile to make non of the boot image be AOT compiled (for now).
+# Note that we could use a previous profile but we will miss the opportunity to
+# remove classes that are no longer in use.
+# Ideally we would just generate an empty boot.art but we don't have the build
+# support to separate the image from the compile code.
+PRODUCT_DEX_PREOPT_BOOT_IMAGE_PROFILE_LOCATION := build/target/product/empty-profile
+PRODUCT_DEX_PREOPT_BOOT_FLAGS := --count-hotness-in-compiled-code
+DEX_PREOPT_DEFAULT := nostripping
+
+# Disable uncompressing priv apps so that there is enough space to build the system partition.
+DONT_UNCOMPRESS_PRIV_APPS_DEXS := true
+
+# Use an empty preloaded-classes list.
+PRODUCT_COPY_FILES += \
+ build/target/product/empty-preloaded-classes:system/etc/preloaded-classes
+
+# Boot image property overrides.
+PRODUCT_PROPERTY_OVERRIDES += \
+ dalvik.vm.jitinitialsize=32m \
+ dalvik.vm.jitmaxsize=32m \
+ dalvik.vm.usejitprofiles=true \
+ dalvik.vm.hot-startup-method-samples=256 \
+ dalvik.vm.profilesystemserver=true \
+ dalvik.vm.profilebootimage=true
+
+# Use speed compiler filter since system server doesn't have JIT.
+PRODUCT_DEX_PREOPT_BOOT_FLAGS += --compiler-filter=speed
+
+PRODUCT_DIST_BOOT_AND_SYSTEM_JARS := true
diff --git a/target/product/runtime_libart.mk b/target/product/runtime_libart.mk
index 8aedee7..bda4524 100644
--- a/target/product/runtime_libart.mk
+++ b/target/product/runtime_libart.mk
@@ -27,7 +27,7 @@
# Additional mixins to the boot classpath.
PRODUCT_PACKAGES += \
- legacy-test \
+ android.test.base \
# Why are we pulling in ext, which is frameworks/base, depending on tagsoup and nist-sip?
PRODUCT_PACKAGES += \
@@ -56,32 +56,44 @@
PRODUCT_PACKAGES += \
cacerts \
-PRODUCT_DEFAULT_PROPERTY_OVERRIDES += \
+PRODUCT_PACKAGES += \
+ hiddenapi-package-whitelist.xml \
+
+PRODUCT_SYSTEM_DEFAULT_PROPERTIES += \
dalvik.vm.image-dex2oat-Xms=64m \
dalvik.vm.image-dex2oat-Xmx=64m \
dalvik.vm.dex2oat-Xms=64m \
dalvik.vm.dex2oat-Xmx=512m \
- ro.dalvik.vm.native.bridge=0 \
dalvik.vm.usejit=true \
dalvik.vm.usejitprofiles=true \
dalvik.vm.dexopt.secondary=true \
dalvik.vm.appimageformat=lz4
+PRODUCT_PROPERTY_OVERRIDES += \
+ 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_DEFAULT_PROPERTY_OVERRIDES += \
+ PRODUCT_SYSTEM_DEFAULT_PROPERTIES += \
pm.dexopt.first-boot=extract \
pm.dexopt.boot=extract
else
- PRODUCT_DEFAULT_PROPERTY_OVERRIDES += \
+ PRODUCT_SYSTEM_DEFAULT_PROPERTIES += \
pm.dexopt.first-boot=quicken \
pm.dexopt.boot=verify
endif
-PRODUCT_DEFAULT_PROPERTY_OVERRIDES += \
- pm.dexopt.install=quicken \
+# 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
+
+# Enable minidebuginfo generation unless overridden.
+PRODUCT_SYSTEM_DEFAULT_PROPERTIES += \
+ dalvik.vm.dex2oat-minidebuginfo=true
diff --git a/target/product/sdk_base.mk b/target/product/sdk_base.mk
index 6d4d59f..1e5ed19 100644
--- a/target/product/sdk_base.mk
+++ b/target/product/sdk_base.mk
@@ -17,38 +17,29 @@
PRODUCT_PROPERTY_OVERRIDES :=
PRODUCT_PACKAGES := \
- ApiDemos \
CellBroadcastReceiver \
CubeLiveWallpapers \
CustomLocale \
Development \
Dialer \
- EmulatorSmokeTests \
Gallery2 \
- GestureBuilder \
- Launcher3 \
+ Launcher3QuickStep \
Camera2 \
librs_jni \
- libwnndict \
- libWnnEngDic \
- libWnnJpnDic \
LiveWallpapersPicker \
Mms \
Music \
- OpenWnn \
Protips \
rild \
screenrecord \
SdkSetup \
- SmokeTest \
- SmokeTestApp \
SoftKeyboard \
sqlite3 \
SystemUI \
SysuiDarkThemeOverlay \
EasterEgg \
WallpaperPicker \
- WidgetPreview
+ WidgetPreview \
# Define the host tools and libs that are parts of the SDK.
-include sdk/build/product_sdk.mk
@@ -91,19 +82,20 @@
frameworks/base/data/sounds/effects/camera_click.ogg:system/media/audio/ui/camera_click.ogg \
frameworks/base/data/sounds/effects/VideoRecord.ogg:system/media/audio/ui/VideoRecord.ogg \
frameworks/base/data/sounds/effects/VideoStop.ogg:system/media/audio/ui/VideoStop.ogg \
- device/generic/goldfish/data/etc/handheld_core_hardware.xml:system/etc/permissions/handheld_core_hardware.xml \
- device/generic/goldfish/camera/media_profiles.xml:system/etc/media_profiles.xml \
- frameworks/av/media/libstagefright/data/media_codecs_google_audio.xml:system/etc/media_codecs_google_audio.xml \
- frameworks/av/media/libstagefright/data/media_codecs_google_telephony.xml:system/etc/media_codecs_google_telephony.xml \
- device/generic/goldfish/camera/media_codecs_google_video.xml:system/etc/media_codecs_google_video.xml \
- device/generic/goldfish/camera/media_codecs.xml:system/etc/media_codecs.xml \
- device/generic/goldfish/camera/media_codecs_performance.xml:system/etc/media_codecs_performance.xml \
- frameworks/native/data/etc/android.hardware.touchscreen.multitouch.jazzhand.xml:system/etc/permissions/android.hardware.touchscreen.multitouch.jazzhand.xml \
- frameworks/native/data/etc/android.hardware.camera.xml:system/etc/permissions/android.hardware.camera.xml \
- frameworks/native/data/etc/android.hardware.fingerprint.xml:system/etc/permissions/android.hardware.fingerprint.xml \
- frameworks/native/data/etc/android.software.autofill.xml:system/etc/permissions/android.software.autofill.xml \
- frameworks/av/media/libeffects/data/audio_effects.conf:system/etc/audio_effects.conf \
- device/generic/goldfish/audio_policy.conf:system/etc/audio_policy.conf
+ device/generic/goldfish/data/etc/handheld_core_hardware.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/handheld_core_hardware.xml \
+ device/generic/goldfish/camera/media_profiles.xml:$(TARGET_COPY_OUT_VENDOR)/etc/media_profiles_V1_0.xml \
+ frameworks/av/media/libstagefright/data/media_codecs_google_audio.xml:$(TARGET_COPY_OUT_VENDOR)/etc/media_codecs_google_audio.xml \
+ frameworks/av/media/libstagefright/data/media_codecs_google_telephony.xml:$(TARGET_COPY_OUT_VENDOR)/etc/media_codecs_google_telephony.xml \
+ device/generic/goldfish/camera/media_codecs_google_video.xml:$(TARGET_COPY_OUT_VENDOR)/etc/media_codecs_google_video.xml \
+ device/generic/goldfish/camera/media_codecs.xml:$(TARGET_COPY_OUT_VENDOR)/etc/media_codecs.xml \
+ device/generic/goldfish/camera/media_codecs_performance.xml:$(TARGET_COPY_OUT_VENDOR)/etc/media_codecs_performance.xml \
+ frameworks/native/data/etc/android.hardware.touchscreen.multitouch.jazzhand.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.touchscreen.multitouch.jazzhand.xml \
+ frameworks/native/data/etc/android.hardware.camera.autofocus.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.camera.autofocus.xml \
+ frameworks/native/data/etc/android.hardware.camera.full.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.camera.full.xml \
+ frameworks/native/data/etc/android.hardware.fingerprint.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.fingerprint.xml \
+ frameworks/native/data/etc/android.software.autofill.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.software.autofill.xml \
+ frameworks/av/media/libeffects/data/audio_effects.conf:$(TARGET_COPY_OUT_VENDOR)/etc/audio_effects.conf \
+ device/generic/goldfish/audio_policy.conf:$(TARGET_COPY_OUT_VENDOR)/etc/audio_policy.conf
include $(SRC_TARGET_DIR)/product/emulator.mk
@@ -119,14 +111,6 @@
$(call inherit-product-if-exists, frameworks/webview/chromium/chromium.mk)
$(call inherit-product, $(SRC_TARGET_DIR)/product/core.mk)
-# include available languages for TTS in the system image
--include external/svox/pico/lang/PicoLangDeDeInSystem.mk
--include external/svox/pico/lang/PicoLangEnGBInSystem.mk
--include external/svox/pico/lang/PicoLangEnUsInSystem.mk
--include external/svox/pico/lang/PicoLangEsEsInSystem.mk
--include external/svox/pico/lang/PicoLangFrFrInSystem.mk
--include external/svox/pico/lang/PicoLangItItInSystem.mk
-
# locale. en_US is both first and in alphabetical order to
# ensure this is the default locale.
PRODUCT_LOCALES := \
diff --git a/target/product/sdk_phone_arm64.mk b/target/product/sdk_phone_arm64.mk
index 2aa688b..c6b290f 100644
--- a/target/product/sdk_phone_arm64.mk
+++ b/target/product/sdk_phone_arm64.mk
@@ -14,32 +14,11 @@
# limitations under the License.
#
-PRODUCT_PROPERTY_OVERRIDES += \
- rild.libpath=/vendor/lib64/libreference-ril.so
+$(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_arm64.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.
-
-# Note: the following lines need to stay at the beginning so that it can
-# take priority and override the rules it inherit from other mk files
-# see copy file rules in core/Makefile
-PRODUCT_COPY_FILES += \
- development/sys-img/advancedFeatures.ini.arm:advancedFeatures.ini \
- prebuilts/qemu-kernel/arm64/3.18/kernel-qemu2:kernel-ranchu \
- device/generic/goldfish/fstab.ranchu.arm:root/fstab.ranchu \
- device/generic/goldfish/fstab.ranchu.early.arm:root/fstab.ranchu.early
-
-$(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit.mk)
-$(call inherit-product, $(SRC_TARGET_DIR)/product/sdk_base.mk)
-$(call inherit-product, $(SRC_TARGET_DIR)/board/generic_arm64/device.mk)
-
-# AOSP emulator images build the AOSP messaging app.
-# Google API images override with the Google API app.
-# See vendor/google/products/sdk_google_phone_*.mk
-PRODUCT_PACKAGES += \
- messaging
+# Define the host tools and libs that are parts of the SDK.
+$(call inherit-product, sdk/build/product_sdk.mk)
+$(call inherit-product, development/build/product_sdk.mk)
# Overrides
PRODUCT_BRAND := Android
diff --git a/target/product/sdk_phone_armv7.mk b/target/product/sdk_phone_armv7.mk
index e99f0f5..f2b51cf 100644
--- a/target/product/sdk_phone_armv7.mk
+++ b/target/product/sdk_phone_armv7.mk
@@ -14,25 +14,12 @@
# limitations under the License.
#
-PRODUCT_PROPERTY_OVERRIDES += \
- rild.libpath=/vendor/lib/libreference-ril.so
+$(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_arm.mk)
-# Note: the following lines need to stay at the beginning so that it can
-# take priority and override the rules it inherit from other mk files
-# see copy file rules in core/Makefile
-PRODUCT_COPY_FILES += \
- development/sys-img/advancedFeatures.ini.arm:advancedFeatures.ini \
- prebuilts/qemu-kernel/arm/3.18/kernel-qemu2:kernel-ranchu \
- device/generic/goldfish/fstab.ranchu.arm:root/fstab.ranchu \
- device/generic/goldfish/fstab.ranchu.early.arm:root/fstab.ranchu.early
+# Define the host tools and libs that are parts of the SDK.
+$(call inherit-product, sdk/build/product_sdk.mk)
+$(call inherit-product, development/build/product_sdk.mk)
-$(call inherit-product, $(SRC_TARGET_DIR)/product/sdk_base.mk)
-
-# AOSP emulator images build the AOSP messaging app.
-# Google API images override with the Google API app.
-# See vendor/google/products/sdk_google_phone_*.mk
-PRODUCT_PACKAGES += \
- messaging
# Overrides
PRODUCT_BRAND := Android
diff --git a/target/product/sdk_phone_x86.mk b/target/product/sdk_phone_x86.mk
index 1e82773..b34e5b6 100644
--- a/target/product/sdk_phone_x86.mk
+++ b/target/product/sdk_phone_x86.mk
@@ -14,25 +14,11 @@
# limitations under the License.
#
-PRODUCT_PROPERTY_OVERRIDES += \
- rild.libpath=/vendor/lib/libreference-ril.so
+$(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_x86.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.
-PRODUCT_COPY_FILES += \
- development/sys-img/advancedFeatures.ini:advancedFeatures.ini \
- device/generic/goldfish/data/etc/encryptionkey.img:encryptionkey.img \
- prebuilts/qemu-kernel/x86/3.18/kernel-qemu2:kernel-ranchu
-
-$(call inherit-product, $(SRC_TARGET_DIR)/product/sdk_base.mk)
-
-# AOSP emulator images build the AOSP messaging app.
-# Google API images override with the Google API app.
-# See vendor/google/products/sdk_google_phone_*.mk
-PRODUCT_PACKAGES += \
- messaging
+# Define the host tools and libs that are parts of the SDK.
+-include sdk/build/product_sdk.mk
+-include development/build/product_sdk.mk
# Overrides
PRODUCT_BRAND := Android
diff --git a/target/product/sdk_phone_x86_64.mk b/target/product/sdk_phone_x86_64.mk
index a18c4f8..37c078e 100644
--- a/target/product/sdk_phone_x86_64.mk
+++ b/target/product/sdk_phone_x86_64.mk
@@ -14,27 +14,11 @@
# limitations under the License.
#
-PRODUCT_PROPERTY_OVERRIDES += \
- rild.libpath=/vendor/lib64/libreference-ril.so
+$(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_x86_64.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.
-
-PRODUCT_COPY_FILES += \
- development/sys-img/advancedFeatures.ini:advancedFeatures.ini \
- device/generic/goldfish/data/etc/encryptionkey.img:encryptionkey.img \
- prebuilts/qemu-kernel/x86_64/3.18/kernel-qemu2:kernel-ranchu
-
-$(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit.mk)
-$(call inherit-product, $(SRC_TARGET_DIR)/product/sdk_base.mk)
-
-# AOSP emulator images build the AOSP messaging app.
-# Google API images override with the Google API app.
-# See vendor/google/products/sdk_google_phone_*.mk
-PRODUCT_PACKAGES += \
- messaging
+# Define the host tools and libs that are parts of the SDK.
+-include sdk/build/product_sdk.mk
+-include development/build/product_sdk.mk
# Overrides
PRODUCT_BRAND := Android
diff --git a/target/product/security/Android.mk b/target/product/security/Android.mk
index 5a40397..4142ea9 100644
--- a/target/product/security/Android.mk
+++ b/target/product/security/Android.mk
@@ -10,3 +10,16 @@
LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT)
include $(BUILD_PREBUILT)
+
+#######################################
+# adb key, if configured via PRODUCT_ADB_KEYS
+ifdef PRODUCT_ADB_KEYS
+ ifneq ($(filter eng userdebug,$(TARGET_BUILD_VARIANT)),)
+ include $(CLEAR_VARS)
+ LOCAL_MODULE := adb_keys
+ LOCAL_MODULE_CLASS := ETC
+ LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT)
+ LOCAL_PREBUILT_MODULE_FILE := $(PRODUCT_ADB_KEYS)
+ include $(BUILD_PREBUILT)
+ endif
+endif
diff --git a/target/product/security/README b/target/product/security/README
index 15f2e93..6a6e62d 100644
--- a/target/product/security/README
+++ b/target/product/security/README
@@ -34,5 +34,5 @@
$ java -jar out/host/linux-x86/framework/dumpkey.jar build/target/product/security/testkey.x509.pem
{64,0xc926ad21,{1795090719,2141396315,950055447,2581568430,4268923165,1920809988,546586521,3498997798,1776797858,3740060814,1805317999,1429410244,129622599,1422441418,1783893377,1222374759,2563319927,323993566,28517732,609753416,1826472888,215237850,4261642700,4049082591,3228462402,774857746,154822455,2497198897,2758199418,3019015328,2794777644,87251430,2534927978,120774784,571297800,3695899472,2479925187,3811625450,3401832990,2394869647,3267246207,950095497,555058928,414729973,1136544882,3044590084,465547824,4058146728,2731796054,1689838846,3890756939,1048029507,895090649,247140249,178744550,3547885223,3165179243,109881576,3944604415,1044303212,3772373029,2985150306,3737520932,3599964420},{3437017481,3784475129,2800224972,3086222688,251333580,2131931323,512774938,325948880,2657486437,2102694287,3820568226,792812816,1026422502,2053275343,2800889200,3113586810,165549746,4273519969,4065247892,1902789247,772932719,3941848426,3652744109,216871947,3164400649,1942378755,3996765851,1055777370,964047799,629391717,2232744317,3910558992,191868569,2758883837,3682816752,2997714732,2702529250,3570700455,3776873832,3924067546,3555689545,2758825434,1323144535,61311905,1997411085,376844204,213777604,4077323584,9135381,1625809335,2804742137,2952293945,1117190829,4237312782,1825108855,3013147971,1111251351,2568837572,1684324211,2520978805,367251975,810756730,2353784344,1175080310}}
-This is called by build/core/Makefile to incorporate the OTA signing keys
+This is called by build/make/core/Makefile to incorporate the OTA signing keys
into the recovery image.
diff --git a/target/product/treble_common.mk b/target/product/treble_common.mk
index 13b7769..6cf66af 100644
--- a/target/product/treble_common.mk
+++ b/target/product/treble_common.mk
@@ -31,15 +31,6 @@
PRODUCT_PACKAGES += \
messaging
-# All VNDK libraries (HAL interfaces, VNDK, VNDK-SP, LL-NDK)
-PRODUCT_PACKAGES += vndk_package
-
-# SP-NDK:
-PRODUCT_PACKAGES += \
- libvulkan \
-
-# Audio:
-USE_XML_AUDIO_POLICY_CONF := 1
# The following policy XML files are used as fallback for
# vendors/devices not using XML to configure audio policy.
PRODUCT_COPY_FILES += \
@@ -49,26 +40,29 @@
frameworks/av/services/audiopolicy/config/audio_policy_volumes.xml:system/etc/audio_policy_volumes.xml \
frameworks/av/services/audiopolicy/config/default_volume_tables.xml:system/etc/default_volume_tables.xml \
-# Bluetooth:
-# audio.a2dp.default is a system module. Generic system image includes
-# audio.a2dp.default to support A2DP if board has the capability.
-PRODUCT_PACKAGES += \
- audio.a2dp.default
+# Telephony:
+# Provide a default APN configuration
+PRODUCT_COPY_FILES += \
+ device/generic/goldfish/data/etc/apns-conf.xml:system/etc/apns-conf.xml
-# Net:
-# Vendors can use the platform-provided network configuration utilities (ip,
-# iptable, etc.) to configure the Linux networking stack, but these utilities
-# do not yet include a HIDL interface wrapper. This is a solution on
-# Android O.
-PRODUCT_PACKAGES += \
- netutils-wrapper-1.0
+# NFC:
+# Provide default libnfc-nci.conf file for devices that does not have one in
+# vendor/etc
+PRODUCT_COPY_FILES += \
+ device/generic/common/nfc/libnfc-nci.conf:system/etc/libnfc-nci.conf
-# Android Verified Boot (AVB):
-# Builds a special vbmeta.img that disables AVB verification.
-# Otherwise, AVB will prevent the device from booting the generic system.img.
-# Also checks that BOARD_AVB_ENABLE is not set, to prevent adding verity
-# metadata into system.img.
-ifeq ($(BOARD_AVB_ENABLE),true)
-$(error BOARD_AVB_ENABLE cannot be set for Treble GSI)
-endif
-BOARD_BUILD_DISABLED_VBMETAIMAGE := true
+# Support for the O-MR1 devices
+PRODUCT_COPY_FILES += \
+ build/make/target/product/vndk/init.gsi.rc:system/etc/init/init.gsi.rc \
+ build/make/target/product/vndk/init.vndk-27.rc:system/etc/init/gsi/init.vndk-27.rc
+
+# Name space configuration file for non-enforcing VNDK
+PRODUCT_PACKAGES += \
+ ld.config.vndk_lite.txt
+
+# Support addtional O-MR1 vendor interface
+PRODUCT_EXTRA_VNDK_VERSIONS := 27
+
+# TODO(b/78308559): includes vr_hwc into GSI before vr_hwc move to vendor
+PRODUCT_PACKAGES += \
+ vr_hwc
diff --git a/target/product/verity.mk b/target/product/verity.mk
index 0badb9f..d954159 100644
--- a/target/product/verity.mk
+++ b/target/product/verity.mk
@@ -14,20 +14,16 @@
# limitations under the License.
#
-# Provides dependencies necessary for verified boot (only for user and
-# userdebug builds)
+# Provides dependencies necessary for verified boot.
-user_variant := $(filter user userdebug,$(TARGET_BUILD_VARIANT))
-ifneq (,$(user_variant))
- PRODUCT_SUPPORTS_BOOT_SIGNER := true
- PRODUCT_SUPPORTS_VERITY := true
- PRODUCT_SUPPORTS_VERITY_FEC := true
+PRODUCT_SUPPORTS_BOOT_SIGNER := true
+PRODUCT_SUPPORTS_VERITY := true
+PRODUCT_SUPPORTS_VERITY_FEC := true
- # The dev key is used to sign boot and recovery images, and the verity
- # metadata table. Actual product deliverables will be re-signed by hand.
- # We expect this file to exist with the suffixes ".x509.pem" and ".pk8".
- PRODUCT_VERITY_SIGNING_KEY := build/target/product/security/verity
+# The dev key is used to sign boot and recovery images, and the verity
+# metadata table. Actual product deliverables will be re-signed by hand.
+# We expect this file to exist with the suffixes ".x509.pem" and ".pk8".
+PRODUCT_VERITY_SIGNING_KEY := build/target/product/security/verity
- PRODUCT_PACKAGES += \
- verity_key
-endif
+PRODUCT_PACKAGES += \
+ verity_key
diff --git a/target/product/vndk/28.txt b/target/product/vndk/28.txt
new file mode 100644
index 0000000..712e91c
--- /dev/null
+++ b/target/product/vndk/28.txt
@@ -0,0 +1,252 @@
+LLNDK: libEGL.so
+LLNDK: libGLESv1_CM.so
+LLNDK: libGLESv2.so
+LLNDK: libGLESv3.so
+LLNDK: libRS.so
+LLNDK: libandroid_net.so
+LLNDK: libc.so
+LLNDK: libdl.so
+LLNDK: libft2.so
+LLNDK: liblog.so
+LLNDK: libm.so
+LLNDK: libmediandk.so
+LLNDK: libnativewindow.so
+LLNDK: libneuralnetworks.so
+LLNDK: libsync.so
+LLNDK: libvndksupport.so
+LLNDK: libvulkan.so
+VNDK-SP: android.hardware.graphics.common@1.0.so
+VNDK-SP: android.hardware.graphics.common@1.1.so
+VNDK-SP: android.hardware.graphics.mapper@2.0.so
+VNDK-SP: android.hardware.graphics.mapper@2.1.so
+VNDK-SP: android.hardware.renderscript@1.0.so
+VNDK-SP: android.hidl.memory.token@1.0.so
+VNDK-SP: android.hidl.memory@1.0.so
+VNDK-SP: android.hidl.memory@1.0-impl.so
+VNDK-SP: libRSCpuRef.so
+VNDK-SP: libRSDriver.so
+VNDK-SP: libRS_internal.so
+VNDK-SP: libbacktrace.so
+VNDK-SP: libbase.so
+VNDK-SP: libbcinfo.so
+VNDK-SP: libblas.so
+VNDK-SP: libc++.so
+VNDK-SP: libcompiler_rt.so
+VNDK-SP: libcutils.so
+VNDK-SP: libhardware.so
+VNDK-SP: libhidlbase.so
+VNDK-SP: libhidlmemory.so
+VNDK-SP: libhidltransport.so
+VNDK-SP: libhwbinder.so
+VNDK-SP: libhwbinder_noltopgo.so
+VNDK-SP: libion.so
+VNDK-SP: liblzma.so
+VNDK-SP: libunwind.so
+VNDK-SP: libunwindstack.so
+VNDK-SP: libutils.so
+VNDK-SP: libutilscallstack.so
+VNDK-SP: libz.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.vr.composer@1.0.so
+VNDK-core: android.hardware.audio.common-util.so
+VNDK-core: android.hardware.audio.common@2.0.so
+VNDK-core: android.hardware.audio.common@2.0-util.so
+VNDK-core: android.hardware.audio.common@4.0.so
+VNDK-core: android.hardware.audio.common@4.0-util.so
+VNDK-core: android.hardware.audio.effect@2.0.so
+VNDK-core: android.hardware.audio.effect@4.0.so
+VNDK-core: android.hardware.audio@2.0.so
+VNDK-core: android.hardware.audio@4.0.so
+VNDK-core: android.hardware.authsecret@1.0.so
+VNDK-core: android.hardware.automotive.audiocontrol@1.0.so
+VNDK-core: android.hardware.automotive.evs@1.0.so
+VNDK-core: android.hardware.automotive.vehicle@2.0.so
+VNDK-core: android.hardware.biometrics.fingerprint@2.1.so
+VNDK-core: android.hardware.bluetooth.a2dp@1.0.so
+VNDK-core: android.hardware.bluetooth@1.0.so
+VNDK-core: android.hardware.boot@1.0.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.metadata@3.2.so
+VNDK-core: android.hardware.camera.metadata@3.3.so
+VNDK-core: android.hardware.camera.provider@2.4.so
+VNDK-core: android.hardware.cas.native@1.0.so
+VNDK-core: android.hardware.cas@1.0.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.drm@1.0.so
+VNDK-core: android.hardware.drm@1.1.so
+VNDK-core: android.hardware.dumpstate@1.0.so
+VNDK-core: android.hardware.gatekeeper@1.0.so
+VNDK-core: android.hardware.gnss@1.0.so
+VNDK-core: android.hardware.gnss@1.1.so
+VNDK-core: android.hardware.graphics.allocator@2.0.so
+VNDK-core: android.hardware.graphics.bufferqueue@1.0.so
+VNDK-core: android.hardware.graphics.composer@2.1.so
+VNDK-core: android.hardware.graphics.composer@2.2.so
+VNDK-core: android.hardware.health@1.0.so
+VNDK-core: android.hardware.health@2.0.so
+VNDK-core: android.hardware.ir@1.0.so
+VNDK-core: android.hardware.keymaster@3.0.so
+VNDK-core: android.hardware.keymaster@4.0.so
+VNDK-core: android.hardware.light@2.0.so
+VNDK-core: android.hardware.media.bufferpool@1.0.so
+VNDK-core: android.hardware.media.omx@1.0.so
+VNDK-core: android.hardware.media@1.0.so
+VNDK-core: android.hardware.memtrack@1.0.so
+VNDK-core: android.hardware.neuralnetworks@1.0.so
+VNDK-core: android.hardware.neuralnetworks@1.1.so
+VNDK-core: android.hardware.nfc@1.0.so
+VNDK-core: android.hardware.nfc@1.1.so
+VNDK-core: android.hardware.oemlock@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.radio.config@1.0.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.secure_element@1.0.so
+VNDK-core: android.hardware.sensors@1.0.so
+VNDK-core: android.hardware.soundtrigger@2.0.so
+VNDK-core: android.hardware.soundtrigger@2.0-core.so
+VNDK-core: android.hardware.soundtrigger@2.1.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.tv.cec@1.0.so
+VNDK-core: android.hardware.tv.input@1.0.so
+VNDK-core: android.hardware.usb.gadget@1.0.so
+VNDK-core: android.hardware.usb@1.0.so
+VNDK-core: android.hardware.usb@1.1.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.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.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@1.0.so
+VNDK-core: android.hardware.wifi@1.1.so
+VNDK-core: android.hardware.wifi@1.2.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.so
+VNDK-core: android.hidl.token@1.0-utils.so
+VNDK-core: android.system.net.netd@1.0.so
+VNDK-core: android.system.net.netd@1.1.so
+VNDK-core: android.system.wifi.keystore@1.0.so
+VNDK-core: libadf.so
+VNDK-core: libaudioroute.so
+VNDK-core: libaudioutils.so
+VNDK-core: libbinder.so
+VNDK-core: libcamera_metadata.so
+VNDK-core: libcap.so
+VNDK-core: libcn-cbor.so
+VNDK-core: libcrypto.so
+VNDK-core: libcrypto_utils.so
+VNDK-core: libcurl.so
+VNDK-core: libdiskconfig.so
+VNDK-core: libdumpstateutil.so
+VNDK-core: libevent.so
+VNDK-core: libexif.so
+VNDK-core: libexpat.so
+VNDK-core: libfmq.so
+VNDK-core: libgatekeeper.so
+VNDK-core: libgui.so
+VNDK-core: libhardware_legacy.so
+VNDK-core: libhidlallocatorutils.so
+VNDK-core: libhidlcache.so
+VNDK-core: libjpeg.so
+VNDK-core: libkeymaster_messages.so
+VNDK-core: libkeymaster_portable.so
+VNDK-core: libldacBT_abr.so
+VNDK-core: libldacBT_enc.so
+VNDK-core: liblz4.so
+VNDK-core: libmedia_helper.so
+VNDK-core: libmedia_omx.so
+VNDK-core: libmemtrack.so
+VNDK-core: libminijail.so
+VNDK-core: libmkbootimg_abi_check.so
+VNDK-core: libnetutils.so
+VNDK-core: libnl.so
+VNDK-core: libopus.so
+VNDK-core: libpagemap.so
+VNDK-core: libpcre2.so
+VNDK-core: libpiex.so
+VNDK-core: libpng.so
+VNDK-core: libpower.so
+VNDK-core: libprocinfo.so
+VNDK-core: libprotobuf-cpp-full.so
+VNDK-core: libprotobuf-cpp-lite.so
+VNDK-core: libpuresoftkeymasterdevice.so
+VNDK-core: libradio_metadata.so
+VNDK-core: libselinux.so
+VNDK-core: libsoftkeymasterdevice.so
+VNDK-core: libspeexresampler.so
+VNDK-core: libsqlite.so
+VNDK-core: libssl.so
+VNDK-core: libstagefright_amrnb_common.so
+VNDK-core: libstagefright_bufferqueue_helper.so
+VNDK-core: libstagefright_enc_common.so
+VNDK-core: libstagefright_flacdec.so
+VNDK-core: libstagefright_foundation.so
+VNDK-core: libstagefright_omx.so
+VNDK-core: libstagefright_omx_utils.so
+VNDK-core: libstagefright_soft_aacdec.so
+VNDK-core: libstagefright_soft_aacenc.so
+VNDK-core: libstagefright_soft_amrdec.so
+VNDK-core: libstagefright_soft_amrnbenc.so
+VNDK-core: libstagefright_soft_amrwbenc.so
+VNDK-core: libstagefright_soft_avcdec.so
+VNDK-core: libstagefright_soft_avcenc.so
+VNDK-core: libstagefright_soft_flacdec.so
+VNDK-core: libstagefright_soft_flacenc.so
+VNDK-core: libstagefright_soft_g711dec.so
+VNDK-core: libstagefright_soft_gsmdec.so
+VNDK-core: libstagefright_soft_hevcdec.so
+VNDK-core: libstagefright_soft_mp3dec.so
+VNDK-core: libstagefright_soft_mpeg2dec.so
+VNDK-core: libstagefright_soft_mpeg4dec.so
+VNDK-core: libstagefright_soft_mpeg4enc.so
+VNDK-core: libstagefright_soft_opusdec.so
+VNDK-core: libstagefright_soft_rawdec.so
+VNDK-core: libstagefright_soft_vorbisdec.so
+VNDK-core: libstagefright_soft_vpxdec.so
+VNDK-core: libstagefright_soft_vpxenc.so
+VNDK-core: libstagefright_xmlparser.so
+VNDK-core: libsuspend.so
+VNDK-core: libsysutils.so
+VNDK-core: libtinyalsa.so
+VNDK-core: libtinyxml2.so
+VNDK-core: libui.so
+VNDK-core: libusbhost.so
+VNDK-core: libvixl-arm.so
+VNDK-core: libvixl-arm64.so
+VNDK-core: libvorbisidec.so
+VNDK-core: libwifi-system-iface.so
+VNDK-core: libxml2.so
+VNDK-core: libyuv.so
+VNDK-core: libziparchive.so
+VNDK-private: libbacktrace.so
+VNDK-private: libblas.so
+VNDK-private: libcompiler_rt.so
+VNDK-private: libft2.so
+VNDK-private: libgui.so
+VNDK-private: libunwind.so
diff --git a/target/product/vndk/Android.mk b/target/product/vndk/Android.mk
index c8ed873..768cb80 100644
--- a/target/product/vndk/Android.mk
+++ b/target/product/vndk/Android.mk
@@ -1,7 +1,92 @@
+ifneq ($(BOARD_VNDK_VERSION),)
LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
+#####################################################################
+# Create the list of vndk libraries from the source code.
+INTERNAL_VNDK_LIB_LIST := $(call intermediates-dir-for,PACKAGING,vndk)/libs.txt
+$(INTERNAL_VNDK_LIB_LIST):
+ @echo "Generate: $@"
+ @mkdir -p $(dir $@)
+ $(hide) echo -n > $@
+ $(hide) $(foreach lib, $(filter-out libclang_rt.%,$(LLNDK_LIBRARIES)), \
+ echo LLNDK: $(lib).so >> $@;)
+ $(hide) $(foreach lib, $(VNDK_SAMEPROCESS_LIBRARIES), \
+ echo VNDK-SP: $(lib).so >> $@;)
+ $(hide) $(foreach lib, $(filter-out libclang_rt.%,$(VNDK_CORE_LIBRARIES)), \
+ echo VNDK-core: $(lib).so >> $@;)
+ $(hide) $(foreach lib, $(VNDK_PRIVATE_LIBRARIES), \
+ echo VNDK-private: $(lib).so >> $@;)
+#####################################################################
+# This is the up-to-date list of vndk libs.
+# TODO(b/62012285): the lib list should be stored somewhere under
+# /prebuilts/vndk
+ifeq (REL,$(PLATFORM_VERSION_CODENAME))
+LATEST_VNDK_LIB_LIST := $(LOCAL_PATH)/$(PLATFORM_VNDK_VERSION).txt
+ifeq ($(wildcard $(LATEST_VNDK_LIB_LIST)),)
+$(error $(LATEST_VNDK_LIB_LIST) file not found. Please copy "$(LOCAL_PATH)/current.txt" to "$(LATEST_VNDK_LIB_LIST)" and commit a CL for release branch)
+endif
+else
+LATEST_VNDK_LIB_LIST := $(LOCAL_PATH)/current.txt
+endif
+
+#####################################################################
+# Check the generate list against the latest list stored in the
+# source tree
+.PHONY: check-vndk-list
+
+# Check if vndk list is changed
+droidcore: check-vndk-list
+
+check-vndk-list-timestamp := $(call intermediates-dir-for,PACKAGING,vndk)/check-list-timestamp
+check-vndk-list: $(check-vndk-list-timestamp)
+
+_vndk_check_failure_message := " error: VNDK library list has been changed.\n"
+ifeq (REL,$(PLATFORM_VERSION_CODENAME))
+_vndk_check_failure_message += " Changing the VNDK library list is not allowed in API locked branches."
+else
+_vndk_check_failure_message += " Run update-vndk-list.sh to update $(LATEST_VNDK_LIB_LIST)"
+endif
+
+$(check-vndk-list-timestamp): $(INTERNAL_VNDK_LIB_LIST) $(LATEST_VNDK_LIB_LIST) $(HOST_OUT_EXECUTABLES)/update-vndk-list.sh
+ $(hide) ( diff --old-line-format="Removed %L" \
+ --new-line-format="Added %L" \
+ --unchanged-line-format="" \
+ $(LATEST_VNDK_LIB_LIST) $(INTERNAL_VNDK_LIB_LIST) \
+ || ( echo -e $(_vndk_check_failure_message); exit 1 ))
+ $(hide) mkdir -p $(dir $@)
+ $(hide) touch $@
+
+#####################################################################
+# Script to update the latest VNDK lib list
+include $(CLEAR_VARS)
+LOCAL_MODULE := update-vndk-list.sh
+LOCAL_MODULE_CLASS := EXECUTABLES
+LOCAL_MODULE_STEM := $(LOCAL_MODULE)
+LOCAL_IS_HOST_MODULE := true
+include $(BUILD_SYSTEM)/base_rules.mk
+$(LOCAL_BUILT_MODULE): PRIVATE_INTERNAL_VNDK_LIB_LIST := $(INTERNAL_VNDK_LIB_LIST)
+$(LOCAL_BUILT_MODULE): PRIVATE_LATEST_VNDK_LIB_LIST := $(LATEST_VNDK_LIB_LIST)
+$(LOCAL_BUILT_MODULE):
+ @echo "Generate: $@"
+ @mkdir -p $(dir $@)
+ @rm -f $@
+ $(hide) echo "#!/bin/bash" > $@
+ifeq (REL,$(PLATFORM_VERSION_CODENAME))
+ $(hide) echo "echo Updating VNDK library list is NOT allowed in API locked branches." >> $@; \
+ echo "exit 1" >> $@
+else
+ $(hide) echo "if [ -z \"\$${ANDROID_BUILD_TOP}\" ]; then" >> $@; \
+ echo " echo Run lunch or choosecombo first" >> $@; \
+ echo " exit 1" >> $@; \
+ echo "fi" >> $@; \
+ echo "cd \$${ANDROID_BUILD_TOP}" >> $@; \
+ echo "cp $(PRIVATE_INTERNAL_VNDK_LIB_LIST) $(PRIVATE_LATEST_VNDK_LIB_LIST)" >> $@; \
+ echo "echo $(PRIVATE_LATEST_VNDK_LIB_LIST) updated." >> $@
+endif
+ @chmod a+x $@
+
+include $(CLEAR_VARS)
LOCAL_MODULE := vndk_package
LOCAL_REQUIRED_MODULES := \
$(addsuffix .vendor,$(VNDK_CORE_LIBRARIES)) \
@@ -9,5 +94,12 @@
$(LLNDK_LIBRARIES) \
llndk.libraries.txt \
vndksp.libraries.txt
-
include $(BUILD_PHONY_PACKAGE)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := vndk_snapshot_package
+LOCAL_REQUIRED_MODULES := \
+ $(foreach vndk_ver,$(PRODUCT_EXTRA_VNDK_VERSIONS),vndk_v$(vndk_ver)_$(TARGET_ARCH))
+include $(BUILD_PHONY_PACKAGE)
+
+endif # BOARD_VNDK_VERSION is set
diff --git a/target/product/vndk/current.txt b/target/product/vndk/current.txt
new file mode 100644
index 0000000..712e91c
--- /dev/null
+++ b/target/product/vndk/current.txt
@@ -0,0 +1,252 @@
+LLNDK: libEGL.so
+LLNDK: libGLESv1_CM.so
+LLNDK: libGLESv2.so
+LLNDK: libGLESv3.so
+LLNDK: libRS.so
+LLNDK: libandroid_net.so
+LLNDK: libc.so
+LLNDK: libdl.so
+LLNDK: libft2.so
+LLNDK: liblog.so
+LLNDK: libm.so
+LLNDK: libmediandk.so
+LLNDK: libnativewindow.so
+LLNDK: libneuralnetworks.so
+LLNDK: libsync.so
+LLNDK: libvndksupport.so
+LLNDK: libvulkan.so
+VNDK-SP: android.hardware.graphics.common@1.0.so
+VNDK-SP: android.hardware.graphics.common@1.1.so
+VNDK-SP: android.hardware.graphics.mapper@2.0.so
+VNDK-SP: android.hardware.graphics.mapper@2.1.so
+VNDK-SP: android.hardware.renderscript@1.0.so
+VNDK-SP: android.hidl.memory.token@1.0.so
+VNDK-SP: android.hidl.memory@1.0.so
+VNDK-SP: android.hidl.memory@1.0-impl.so
+VNDK-SP: libRSCpuRef.so
+VNDK-SP: libRSDriver.so
+VNDK-SP: libRS_internal.so
+VNDK-SP: libbacktrace.so
+VNDK-SP: libbase.so
+VNDK-SP: libbcinfo.so
+VNDK-SP: libblas.so
+VNDK-SP: libc++.so
+VNDK-SP: libcompiler_rt.so
+VNDK-SP: libcutils.so
+VNDK-SP: libhardware.so
+VNDK-SP: libhidlbase.so
+VNDK-SP: libhidlmemory.so
+VNDK-SP: libhidltransport.so
+VNDK-SP: libhwbinder.so
+VNDK-SP: libhwbinder_noltopgo.so
+VNDK-SP: libion.so
+VNDK-SP: liblzma.so
+VNDK-SP: libunwind.so
+VNDK-SP: libunwindstack.so
+VNDK-SP: libutils.so
+VNDK-SP: libutilscallstack.so
+VNDK-SP: libz.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.vr.composer@1.0.so
+VNDK-core: android.hardware.audio.common-util.so
+VNDK-core: android.hardware.audio.common@2.0.so
+VNDK-core: android.hardware.audio.common@2.0-util.so
+VNDK-core: android.hardware.audio.common@4.0.so
+VNDK-core: android.hardware.audio.common@4.0-util.so
+VNDK-core: android.hardware.audio.effect@2.0.so
+VNDK-core: android.hardware.audio.effect@4.0.so
+VNDK-core: android.hardware.audio@2.0.so
+VNDK-core: android.hardware.audio@4.0.so
+VNDK-core: android.hardware.authsecret@1.0.so
+VNDK-core: android.hardware.automotive.audiocontrol@1.0.so
+VNDK-core: android.hardware.automotive.evs@1.0.so
+VNDK-core: android.hardware.automotive.vehicle@2.0.so
+VNDK-core: android.hardware.biometrics.fingerprint@2.1.so
+VNDK-core: android.hardware.bluetooth.a2dp@1.0.so
+VNDK-core: android.hardware.bluetooth@1.0.so
+VNDK-core: android.hardware.boot@1.0.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.metadata@3.2.so
+VNDK-core: android.hardware.camera.metadata@3.3.so
+VNDK-core: android.hardware.camera.provider@2.4.so
+VNDK-core: android.hardware.cas.native@1.0.so
+VNDK-core: android.hardware.cas@1.0.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.drm@1.0.so
+VNDK-core: android.hardware.drm@1.1.so
+VNDK-core: android.hardware.dumpstate@1.0.so
+VNDK-core: android.hardware.gatekeeper@1.0.so
+VNDK-core: android.hardware.gnss@1.0.so
+VNDK-core: android.hardware.gnss@1.1.so
+VNDK-core: android.hardware.graphics.allocator@2.0.so
+VNDK-core: android.hardware.graphics.bufferqueue@1.0.so
+VNDK-core: android.hardware.graphics.composer@2.1.so
+VNDK-core: android.hardware.graphics.composer@2.2.so
+VNDK-core: android.hardware.health@1.0.so
+VNDK-core: android.hardware.health@2.0.so
+VNDK-core: android.hardware.ir@1.0.so
+VNDK-core: android.hardware.keymaster@3.0.so
+VNDK-core: android.hardware.keymaster@4.0.so
+VNDK-core: android.hardware.light@2.0.so
+VNDK-core: android.hardware.media.bufferpool@1.0.so
+VNDK-core: android.hardware.media.omx@1.0.so
+VNDK-core: android.hardware.media@1.0.so
+VNDK-core: android.hardware.memtrack@1.0.so
+VNDK-core: android.hardware.neuralnetworks@1.0.so
+VNDK-core: android.hardware.neuralnetworks@1.1.so
+VNDK-core: android.hardware.nfc@1.0.so
+VNDK-core: android.hardware.nfc@1.1.so
+VNDK-core: android.hardware.oemlock@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.radio.config@1.0.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.secure_element@1.0.so
+VNDK-core: android.hardware.sensors@1.0.so
+VNDK-core: android.hardware.soundtrigger@2.0.so
+VNDK-core: android.hardware.soundtrigger@2.0-core.so
+VNDK-core: android.hardware.soundtrigger@2.1.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.tv.cec@1.0.so
+VNDK-core: android.hardware.tv.input@1.0.so
+VNDK-core: android.hardware.usb.gadget@1.0.so
+VNDK-core: android.hardware.usb@1.0.so
+VNDK-core: android.hardware.usb@1.1.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.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.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@1.0.so
+VNDK-core: android.hardware.wifi@1.1.so
+VNDK-core: android.hardware.wifi@1.2.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.so
+VNDK-core: android.hidl.token@1.0-utils.so
+VNDK-core: android.system.net.netd@1.0.so
+VNDK-core: android.system.net.netd@1.1.so
+VNDK-core: android.system.wifi.keystore@1.0.so
+VNDK-core: libadf.so
+VNDK-core: libaudioroute.so
+VNDK-core: libaudioutils.so
+VNDK-core: libbinder.so
+VNDK-core: libcamera_metadata.so
+VNDK-core: libcap.so
+VNDK-core: libcn-cbor.so
+VNDK-core: libcrypto.so
+VNDK-core: libcrypto_utils.so
+VNDK-core: libcurl.so
+VNDK-core: libdiskconfig.so
+VNDK-core: libdumpstateutil.so
+VNDK-core: libevent.so
+VNDK-core: libexif.so
+VNDK-core: libexpat.so
+VNDK-core: libfmq.so
+VNDK-core: libgatekeeper.so
+VNDK-core: libgui.so
+VNDK-core: libhardware_legacy.so
+VNDK-core: libhidlallocatorutils.so
+VNDK-core: libhidlcache.so
+VNDK-core: libjpeg.so
+VNDK-core: libkeymaster_messages.so
+VNDK-core: libkeymaster_portable.so
+VNDK-core: libldacBT_abr.so
+VNDK-core: libldacBT_enc.so
+VNDK-core: liblz4.so
+VNDK-core: libmedia_helper.so
+VNDK-core: libmedia_omx.so
+VNDK-core: libmemtrack.so
+VNDK-core: libminijail.so
+VNDK-core: libmkbootimg_abi_check.so
+VNDK-core: libnetutils.so
+VNDK-core: libnl.so
+VNDK-core: libopus.so
+VNDK-core: libpagemap.so
+VNDK-core: libpcre2.so
+VNDK-core: libpiex.so
+VNDK-core: libpng.so
+VNDK-core: libpower.so
+VNDK-core: libprocinfo.so
+VNDK-core: libprotobuf-cpp-full.so
+VNDK-core: libprotobuf-cpp-lite.so
+VNDK-core: libpuresoftkeymasterdevice.so
+VNDK-core: libradio_metadata.so
+VNDK-core: libselinux.so
+VNDK-core: libsoftkeymasterdevice.so
+VNDK-core: libspeexresampler.so
+VNDK-core: libsqlite.so
+VNDK-core: libssl.so
+VNDK-core: libstagefright_amrnb_common.so
+VNDK-core: libstagefright_bufferqueue_helper.so
+VNDK-core: libstagefright_enc_common.so
+VNDK-core: libstagefright_flacdec.so
+VNDK-core: libstagefright_foundation.so
+VNDK-core: libstagefright_omx.so
+VNDK-core: libstagefright_omx_utils.so
+VNDK-core: libstagefright_soft_aacdec.so
+VNDK-core: libstagefright_soft_aacenc.so
+VNDK-core: libstagefright_soft_amrdec.so
+VNDK-core: libstagefright_soft_amrnbenc.so
+VNDK-core: libstagefright_soft_amrwbenc.so
+VNDK-core: libstagefright_soft_avcdec.so
+VNDK-core: libstagefright_soft_avcenc.so
+VNDK-core: libstagefright_soft_flacdec.so
+VNDK-core: libstagefright_soft_flacenc.so
+VNDK-core: libstagefright_soft_g711dec.so
+VNDK-core: libstagefright_soft_gsmdec.so
+VNDK-core: libstagefright_soft_hevcdec.so
+VNDK-core: libstagefright_soft_mp3dec.so
+VNDK-core: libstagefright_soft_mpeg2dec.so
+VNDK-core: libstagefright_soft_mpeg4dec.so
+VNDK-core: libstagefright_soft_mpeg4enc.so
+VNDK-core: libstagefright_soft_opusdec.so
+VNDK-core: libstagefright_soft_rawdec.so
+VNDK-core: libstagefright_soft_vorbisdec.so
+VNDK-core: libstagefright_soft_vpxdec.so
+VNDK-core: libstagefright_soft_vpxenc.so
+VNDK-core: libstagefright_xmlparser.so
+VNDK-core: libsuspend.so
+VNDK-core: libsysutils.so
+VNDK-core: libtinyalsa.so
+VNDK-core: libtinyxml2.so
+VNDK-core: libui.so
+VNDK-core: libusbhost.so
+VNDK-core: libvixl-arm.so
+VNDK-core: libvixl-arm64.so
+VNDK-core: libvorbisidec.so
+VNDK-core: libwifi-system-iface.so
+VNDK-core: libxml2.so
+VNDK-core: libyuv.so
+VNDK-core: libziparchive.so
+VNDK-private: libbacktrace.so
+VNDK-private: libblas.so
+VNDK-private: libcompiler_rt.so
+VNDK-private: libft2.so
+VNDK-private: libgui.so
+VNDK-private: libunwind.so
diff --git a/target/product/vndk/init.gsi.rc b/target/product/vndk/init.gsi.rc
new file mode 100644
index 0000000..0150b1a
--- /dev/null
+++ b/target/product/vndk/init.gsi.rc
@@ -0,0 +1,2 @@
+# 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/vndk/init.vndk-27.rc b/target/product/vndk/init.vndk-27.rc
new file mode 100644
index 0000000..d464a2f
--- /dev/null
+++ b/target/product/vndk/init.vndk-27.rc
@@ -0,0 +1,3 @@
+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/tools/Android.mk b/tools/Android.mk
index 9073ac3..c05d681 100644
--- a/tools/Android.mk
+++ b/tools/Android.mk
@@ -16,4 +16,8 @@
LOCAL_PATH := $(call my-dir)
+# Only if this Android.mk was included not by a symlink should it be used.
+# This facilitates the transition away from symlinks: b/64397960
+ifeq ($(LOCAL_PATH),build/make/tools)
include $(call all-makefiles-under,$(LOCAL_PATH))
+endif
diff --git a/tools/acp/Android.bp b/tools/acp/Android.bp
index faf2034..64f5a10 100644
--- a/tools/acp/Android.bp
+++ b/tools/acp/Android.bp
@@ -5,6 +5,7 @@
cc_binary_host {
srcs: ["acp.c"],
+ cflags: ["-Wall", "-Werror"],
static_libs: ["libhost"],
name: "acp",
diff --git a/tools/acp/acp.c b/tools/acp/acp.c
index eb1de1f..d4a9fbc 100644
--- a/tools/acp/acp.c
+++ b/tools/acp/acp.c
@@ -41,10 +41,9 @@
int process(int argc, char* const argv[], unsigned int options)
{
int retVal = 0;
- int i, cc;
+ int i;
char* stripDest = NULL;
int stripDestLen;
- struct stat destStat;
bool destMustBeDir = false;
struct stat sb;
diff --git a/tools/adbs b/tools/adbs
deleted file mode 100755
index a8f06c0..0000000
--- a/tools/adbs
+++ /dev/null
@@ -1,45 +0,0 @@
-#!/usr/bin/env python
-
-# Copyright (C) 2009 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the 'License');
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an 'AS IS' BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-import os
-import os.path
-import re
-import string
-import sys
-
-sys.path.insert(0, os.path.dirname(__file__) + "/../../development/scripts")
-import stack_core
-import symbol
-
-if __name__ == '__main__':
- # pass the options to adb
- adb_cmd = "adb " + ' '.join(sys.argv[1:])
-
- # create tracer for line parsing
- tracer = stack_core.TraceConverter()
-
- # invoke the adb command and filter its output
- stream = os.popen(adb_cmd)
- while (True):
- line = stream.readline()
- if (line == ''):
- break
- if(tracer.ProcessLine(line) == False):
- print(line.strip())
- sys.stdout.flush()
-
- # adb itself aborts
- stream.close()
diff --git a/tools/apicheck/Android.mk b/tools/apicheck/Android.mk
index b547058..ab3493d 100644
--- a/tools/apicheck/Android.mk
+++ b/tools/apicheck/Android.mk
@@ -12,7 +12,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-ifneq ($(TARGET_BUILD_PDK),true)
LOCAL_PATH := $(call my-dir)
# the hat script
@@ -26,4 +25,3 @@
include $(BUILD_PREBUILT)
# Apicheck is now part of Doclava -- See external/doclava.
-endif
diff --git a/tools/apicheck/etc/apicheck b/tools/apicheck/etc/apicheck
index c710c46..e4ffb77 100644
--- a/tools/apicheck/etc/apicheck
+++ b/tools/apicheck/etc/apicheck
@@ -18,7 +18,7 @@
# and set up progdir to be the fully-qualified pathname of its directory.
#
# The classpath and other java options used in apicheck are specified in
-# build/core/tasks/apicheck.mk.
+# build/make/core/tasks/apicheck.mk.
prog="$0"
while [ -h "${prog}" ]; do
diff --git a/tools/atree/Android.bp b/tools/atree/Android.bp
new file mode 100644
index 0000000..5fbe042
--- /dev/null
+++ b/tools/atree/Android.bp
@@ -0,0 +1,14 @@
+// Copyright 2007 The Android Open Source Project
+//
+// Copies files into the directory structure described by a manifest
+
+cc_binary_host {
+ name: "atree",
+ srcs: [
+ "atree.cpp",
+ "files.cpp",
+ "fs.cpp",
+ ],
+ cflags: ["-Wall", "-Werror"],
+ static_libs: ["libhost"],
+}
diff --git a/tools/atree/Android.mk b/tools/atree/Android.mk
deleted file mode 100644
index f598db5..0000000
--- a/tools/atree/Android.mk
+++ /dev/null
@@ -1,19 +0,0 @@
-# Copyright 2007 The Android Open Source Project
-#
-# Copies files into the directory structure described by a manifest
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
- atree.cpp \
- files.cpp \
- fs.cpp
-
-LOCAL_STATIC_LIBRARIES := \
- libhost
-
-LOCAL_MODULE := atree
-
-include $(BUILD_HOST_EXECUTABLE)
-
diff --git a/tools/atree/files.cpp b/tools/atree/files.cpp
index d945f58..d5c8a97 100644
--- a/tools/atree/files.cpp
+++ b/tools/atree/files.cpp
@@ -425,8 +425,6 @@
const vector<string>& excludes,
vector<FileRecord>* more)
{
- int err;
-
string full = path_append(rec.sourceBase, rec.sourceName);
full = path_append(full, path);
diff --git a/tools/auto_gen_test_config.py b/tools/auto_gen_test_config.py
new file mode 100755
index 0000000..c7c5bdc
--- /dev/null
+++ b/tools/auto_gen_test_config.py
@@ -0,0 +1,89 @@
+#!/usr/bin/env python
+#
+# 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.
+
+"""A tool to generate TradeFed test config file.
+"""
+
+import os
+import shutil
+import sys
+from xml.dom.minidom import parse
+
+ATTRIBUTE_LABEL = 'android:label'
+ATTRIBUTE_RUNNER = 'android:name'
+ATTRIBUTE_PACKAGE = 'package'
+
+PLACEHOLDER_LABEL = '{LABEL}'
+PLACEHOLDER_MODULE = '{MODULE}'
+PLACEHOLDER_PACKAGE = '{PACKAGE}'
+PLACEHOLDER_RUNNER = '{RUNNER}'
+PLACEHOLDER_TEST_TYPE = '{TEST_TYPE}'
+
+
+def main(argv):
+ """Entry point of auto_gen_test_config.
+
+ Args:
+ argv: A list of arguments.
+ Returns:
+ 0 if no error, otherwise 1.
+ """
+ if len(argv) != 4:
+ sys.stderr.write(
+ 'Invalid arguements. The script requires 4 arguments for file paths: '
+ 'target_config android_manifest empty_config '
+ 'instrumentation_test_config_template.\n')
+ return 1
+ target_config = argv[0]
+ android_manifest = argv[1]
+ empty_config = argv[2]
+ instrumentation_test_config_template = argv[3]
+
+ manifest = parse(android_manifest)
+ instrumentation_elements = manifest.getElementsByTagName('instrumentation')
+ manifest_elements = manifest.getElementsByTagName('manifest')
+ if len(instrumentation_elements) != 1 or len(manifest_elements) != 1:
+ # Failed to locate instrumentation or manifest element in AndroidManifest.
+ # file. Empty test config file will be created.
+ shutil.copyfile(empty_config, target_config)
+ return 0
+
+ module = os.path.splitext(os.path.basename(target_config))[0]
+ instrumentation = instrumentation_elements[0]
+ manifest = manifest_elements[0]
+ if instrumentation.attributes.has_key(ATTRIBUTE_LABEL):
+ label = instrumentation.attributes[ATTRIBUTE_LABEL].value
+ else:
+ label = module
+ runner = instrumentation.attributes[ATTRIBUTE_RUNNER].value
+ package = manifest.attributes[ATTRIBUTE_PACKAGE].value
+ test_type = ('InstrumentationTest'
+ if runner.endswith('.InstrumentationTestRunner')
+ else 'AndroidJUnitTest')
+
+ with open(instrumentation_test_config_template) as template:
+ config = template.read()
+ config = config.replace(PLACEHOLDER_LABEL, label)
+ config = config.replace(PLACEHOLDER_MODULE, module)
+ config = config.replace(PLACEHOLDER_PACKAGE, package)
+ config = config.replace(PLACEHOLDER_TEST_TYPE, test_type)
+ config = config.replace(PLACEHOLDER_RUNNER, runner)
+ with open(target_config, 'w') as config_file:
+ config_file.write(config)
+ return 0
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv[1:]))
diff --git a/tools/auto_gen_test_config_test.py b/tools/auto_gen_test_config_test.py
new file mode 100644
index 0000000..e68c27f
--- /dev/null
+++ b/tools/auto_gen_test_config_test.py
@@ -0,0 +1,173 @@
+#!/usr/bin/env python
+#
+# Copyright 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.
+
+"""Unittests for auto_gen_test_config."""
+
+import os
+import shutil
+import tempfile
+import unittest
+
+import auto_gen_test_config
+
+TEST_MODULE = 'TestModule'
+
+MANIFEST_INVALID = """<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android">
+</manifest>
+"""
+
+MANIFEST_JUNIT_TEST = """<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.my.tests.x">
+ <instrumentation
+ android:name="android.support.test.runner.AndroidJUnitRunner"
+ android:targetPackage="com.android.my.tests" />
+</manifest>
+"""
+
+MANIFEST_INSTRUMENTATION_TEST = """<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.my.tests.x">
+ <instrumentation
+ android:name="android.test.InstrumentationTestRunner"
+ android:targetPackage="com.android.my.tests"
+ android:label="My Tests" />
+</manifest>
+"""
+
+EXPECTED_JUNIT_TEST_CONFIG = """<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<!-- This test config file is auto-generated. -->
+<configuration description="Runs TestModule.">
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="test-file-name" value="TestModule.apk" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="com.android.my.tests.x" />
+ <option name="runner" value="android.support.test.runner.AndroidJUnitRunner" />
+ </test>
+</configuration>
+"""
+
+EXPECTED_INSTRUMENTATION_TEST_CONFIG = """<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<!-- This test config file is auto-generated. -->
+<configuration description="Runs My Tests.">
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="test-file-name" value="TestModule.apk" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.InstrumentationTest" >
+ <option name="package" value="com.android.my.tests.x" />
+ <option name="runner" value="android.test.InstrumentationTestRunner" />
+ </test>
+</configuration>
+"""
+
+TOOLS_DIR = os.path.dirname(os.path.dirname(__file__))
+EMPTY_TEST_CONFIG = os.path.join(
+ TOOLS_DIR, '..', 'core', 'empty_test_config.xml')
+INSTRUMENTATION_TEST_CONFIG_TEMPLATE = os.path.join(
+ TOOLS_DIR, '..', 'core', 'instrumentation_test_config_template.xml')
+
+
+class AutoGenTestConfigUnittests(unittest.TestCase):
+ """Unittests for auto_gen_test_config."""
+
+ def setUp(self):
+ """Setup directory for test."""
+ self.test_dir = tempfile.mkdtemp()
+ self.config_file = os.path.join(self.test_dir, TEST_MODULE + '.config')
+ self.manifest_file = os.path.join(self.test_dir, 'AndroidManifest.xml')
+
+ def tearDown(self):
+ """Cleanup the test directory."""
+ shutil.rmtree(self.test_dir, ignore_errors=True)
+
+ def testInvalidManifest(self):
+ """An empty test config should be generated if AndroidManifest is invalid.
+ """
+ with open(self.manifest_file, 'w') as f:
+ f.write(MANIFEST_INVALID)
+
+ argv = [self.config_file,
+ self.manifest_file,
+ EMPTY_TEST_CONFIG,
+ INSTRUMENTATION_TEST_CONFIG_TEMPLATE]
+ auto_gen_test_config.main(argv)
+ with open(self.config_file) as config_file:
+ with open(EMPTY_TEST_CONFIG) as empty_config:
+ self.assertEqual(config_file.read(), empty_config.read())
+
+ def testCreateJUnitTestConfig(self):
+ """Test creating test config for AndroidJUnitTest.
+ """
+ with open(self.manifest_file, 'w') as f:
+ f.write(MANIFEST_JUNIT_TEST)
+
+ argv = [self.config_file,
+ self.manifest_file,
+ EMPTY_TEST_CONFIG,
+ INSTRUMENTATION_TEST_CONFIG_TEMPLATE]
+ auto_gen_test_config.main(argv)
+ with open(self.config_file) as config_file:
+ self.assertEqual(config_file.read(), EXPECTED_JUNIT_TEST_CONFIG)
+
+ def testCreateInstrumentationTestConfig(self):
+ """Test creating test config for InstrumentationTest.
+ """
+ with open(self.manifest_file, 'w') as f:
+ f.write(MANIFEST_INSTRUMENTATION_TEST)
+
+ argv = [self.config_file,
+ self.manifest_file,
+ EMPTY_TEST_CONFIG,
+ INSTRUMENTATION_TEST_CONFIG_TEMPLATE]
+ auto_gen_test_config.main(argv)
+ with open(self.config_file) as config_file:
+ self.assertEqual(
+ config_file.read(), EXPECTED_INSTRUMENTATION_TEST_CONFIG)
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tools/buildinfo.sh b/tools/buildinfo.sh
index d214aab..5a54462 100755
--- a/tools/buildinfo.sh
+++ b/tools/buildinfo.sh
@@ -13,6 +13,7 @@
echo "ro.build.version.release=$PLATFORM_VERSION"
echo "ro.build.version.security_patch=$PLATFORM_SECURITY_PATCH"
echo "ro.build.version.base_os=$PLATFORM_BASE_OS"
+echo "ro.build.version.min_supported_target_sdk=$PLATFORM_MIN_SUPPORTED_TARGET_SDK_VERSION"
echo "ro.build.date=`$DATE`"
echo "ro.build.date.utc=`$DATE +%s`"
echo "ro.build.type=$TARGET_BUILD_TYPE"
diff --git a/tools/check_builds.sh b/tools/check_builds.sh
index c255bf0..7e4ea7c 100644
--- a/tools/check_builds.sh
+++ b/tools/check_builds.sh
@@ -65,7 +65,7 @@
inputs="$inputs $TEST_BUILD_DIR/dist-$1/installed-files.txt"
shift
done
- build/tools/compare_fileslist.py $inputs > $TEST_BUILD_DIR/sizes.html
+ build/make/tools/compare_fileslist.py $inputs > $TEST_BUILD_DIR/sizes.html
}
function check_builds
@@ -87,6 +87,6 @@
fi
shift
done
- build/tools/compare_fileslist.py $inputs > $TEST_BUILD_DIR/sizes.html
+ build/make/tools/compare_fileslist.py $inputs > $TEST_BUILD_DIR/sizes.html
}
diff --git a/tools/checkowners.py b/tools/checkowners.py
index b874955..1190d30 100755
--- a/tools/checkowners.py
+++ b/tools/checkowners.py
@@ -34,8 +34,8 @@
+ urllib.quote(address))
echo('Checking email address: ' + address)
result = urllib2.urlopen(request).read()
- expected = '"email": "' + address + '"'
- checked_addresses[address] = (result.find(expected) >= 0)
+ checked_addresses[address] = (
+ result.find('"email":') >= 0 and result.find('"_account_id":') >= 0)
return checked_addresses[address]
diff --git a/tools/docker/.gitignore b/tools/docker/.gitignore
new file mode 100644
index 0000000..df0b367
--- /dev/null
+++ b/tools/docker/.gitignore
@@ -0,0 +1 @@
+gitconfig
diff --git a/tools/docker/Dockerfile b/tools/docker/Dockerfile
new file mode 100644
index 0000000..ec65aaf
--- /dev/null
+++ b/tools/docker/Dockerfile
@@ -0,0 +1,25 @@
+FROM ubuntu:14.04
+ARG userid
+ARG groupid
+ARG username
+
+RUN apt-get update && apt-get install -y git-core gnupg flex bison gperf build-essential zip curl zlib1g-dev gcc-multilib g++-multilib libc6-dev-i386 lib32ncurses5-dev x11proto-core-dev libx11-dev lib32z-dev ccache libgl1-mesa-dev libxml2-utils xsltproc unzip python openjdk-7-jdk
+
+RUN curl -o jdk8.tgz https://android.googlesource.com/platform/prebuilts/jdk/jdk8/+archive/master.tar.gz \
+ && tar -zxf jdk8.tgz linux-x86 \
+ && mv linux-x86 /usr/lib/jvm/java-8-openjdk-amd64 \
+ && rm -rf jdk8.tgz
+
+RUN curl -o /usr/local/bin/repo https://storage.googleapis.com/git-repo-downloads/repo \
+ && echo "e147f0392686c40cfd7d5e6f332c6ee74c4eab4d24e2694b3b0a0c037bf51dc5 /usr/local/bin/repo" | sha256sum --strict -c - \
+ && chmod a+x /usr/local/bin/repo
+
+RUN groupadd -g $groupid $username \
+ && useradd -m -u $userid -g $groupid $username \
+ && echo $username >/root/username \
+ && echo "export USER="$username >>/home/$username/.gitconfig
+COPY gitconfig /home/$username/.gitconfig
+RUN chown $userid:$groupid /home/$username/.gitconfig
+ENV HOME=/home/$username
+
+ENTRYPOINT chroot --userspec=$(cat /root/username):$(cat /root/username) / /bin/bash -i
diff --git a/tools/docker/README.md b/tools/docker/README.md
new file mode 100644
index 0000000..304fd18
--- /dev/null
+++ b/tools/docker/README.md
@@ -0,0 +1,18 @@
+The Dockerfile in this directory sets up an Ubuntu Trusty image ready to build
+a variety of Android branches (>= Lollipop). It's particulary useful to build
+older branches that required 14.04 if you've upgraded to something newer.
+
+First, build the image:
+```
+# Copy your host gitconfig, or create a stripped down version
+$ cp ~/.gitconfig gitconfig
+$ docker build --build-arg userid=$(id -u) --build-arg groupid=$(id -g) --build-arg username=$(id -un) -t android-build-trusty .
+```
+
+Then you can start up new instances with:
+```
+$ docker run -it --rm -v $ANDROID_BUILD_TOP:/src android-build-trusty
+> cd /src; source build/envsetup.sh
+> lunch aosp_arm-eng
+> m -j50
+```
diff --git a/tools/droiddoc/templates-sac/assets/GPL-LICENSE.txt b/tools/droiddoc/templates-sac/assets/GPL-LICENSE.txt
deleted file mode 100644
index 66a0f18..0000000
--- a/tools/droiddoc/templates-sac/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-sac/assets/LICENSE.txt b/tools/droiddoc/templates-sac/assets/LICENSE.txt
deleted file mode 100644
index e84328b..0000000
--- a/tools/droiddoc/templates-sac/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-sac/assets/android-developer-docs.css b/tools/droiddoc/templates-sac/assets/android-developer-docs.css
deleted file mode 100644
index cd610f7..0000000
--- a/tools/droiddoc/templates-sac/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-sac/assets/css/default.css b/tools/droiddoc/templates-sac/assets/css/default.css
deleted file mode 100644
index 4eafa25..0000000
--- a/tools/droiddoc/templates-sac/assets/css/default.css
+++ /dev/null
@@ -1,4662 +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: 20px; }
-
-#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;
-}
-
-.nowrap {
- white-space: nowrap;
-}
-
-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; }
- .layout-content-row:after {
- content: ".";
- display: block;
- height: 0;
- clear: both;
- visibility: hidden; }
- * 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: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 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; }
-
-.new,
-.new-child {
- font-size: .78em;
- font-weight: bold;
- color: #ff3d3d;
- vertical-align:top;
- white-space:nowrap;
-}
-
-/* content header */
-.content-header {
- height: 30px;
- margin:20px 0 25px;
- padding:0 0 10px;}
-.content-header.just-links {
- margin-bottom:0;
- padding-bottom:0;}
-
-.content-header h1 {
- color:#000;
- margin:0;
- border-bottom:0;
- padding:0;
-}
-
-.content-footer {
- border-top: 1px solid #ccc;
- margin-top: 10px;
- padding-top:10px;
- height: 30px;
-}
-
-.content-footer-sac {
- border-top: 1px solid #ccc;
-}
-.content-footer .col-9 {
- margin-left:0;
-}
-.content-footer .col-4 {
- margin-right:0;
-}
-.content-footer.wrap {
- width:940px;
-}
-
-.paging-links {
- position: relative; }
- .paging-links a {
- position: absolute; }
- .paging-links a,
- .training-nav-top a {
- font-size: 14px;
- line-height: 30px;
- color: #555555;
- text-decoration: none;
- text-transform: uppercase; }
- .paging-links .prev-page-link:before,
- .training-nav-top .prev-page-link:before {
- 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: 0px; }
- .next-page-link:after,
- .start-class-link:after,
- .start-course-link:after,
- .next-class-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; }
-
-
- .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;
- }
-
- /* 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;
- }
-
- .content-footer.next-class {
- display:block;
- border:0;
- margin-top:0;
- padding-top:0;
- }
-
- .content-footer.next-class a.next-class-link {
- display:block;
- float:right;
- text-transform:uppercase;
- }
-
-
-
- /* inner-doc tabs w/ title */
-
-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; } }
-
-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; }
-
-/* 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: 5px 0 20px;
- 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;
-}
-dt {
- font-weight:bold;
-}
-dd {
- margin:0 0 10px 30px;
- padding: 5px;
-}
-dd p,
-dd pre,
-dd ul,
-dd ol,
-dd dl {
- margin:10px 0 0;
-}
-li p,
-li pre,
-li ul,
-li ol,
-li dl {
- margin-top:5px;
- margin-bottom:5px;
-}
-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 {
- color: #258aaf;
- text-decoration: none;
-}
-a:focus, a:hover, a:active {
- color: #33B5E5;
- text-decoration: none;
-}
-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;
-}
-
-/* opcodes table */
-
-table.instruc td:first-child {
- width: 12%;
-}
-
-table.instruc td:first-child + td {
- width: 23%;
-}
-
-table.instruc td:first-child + td + td {
- width: 28%;
-}
-
-table.instruc td:first-child + td + td + td {
- width: 37%;
-}
-
-/* supplemental opcode format table */
-
-table.supplement td:first-child {
- width: 20%;
-}
-
-table.supplement td:first-child + td {
- width: 20%;
-}
-
-table.supplement td:first-child + td + td {
- width: 60%;
-}
-
-/* math details table */
-
-table.math td:first-child {
- width: 10%;
-}
-
-table.math td:first-child + td {
- width: 30%;
-}
-
-table.math td:first-child + td + td {
- width: 60%;
-}
-
-/* --------------------------------------------------------------------------
-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,
- a.totop {
- 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 {
- padding: 2.2em 0 0.2em 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;
-}
-.design a.selected {
- color: #33b5e5;
-}
-.develop a.selected {
- color: #F80;
-}
-.distribute a.selected {
- color: #9C0;
-}
-.source a.selected {
- color: #33b5e5;
-}
-.devices a.selected {
- color: #F80;
-}
-.security a.selected {
- color: #9C0;
-}
-.compatibility a.selected {
- color: #9933CC;
-}
-
-
-.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-bottom {
- padding:0 0 20px;
-}
-
-#tb-wrapper,
-#qv-wrapper {
- float:right;
- clear:right;
- margin:-27px 0 0 20px; /* negative top-margin to counter the content-header bottom margin */
- padding:0 0 20px;
-}
-
-#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 {
- padding:0 0 0 15px;
-}
-
-#tb .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;
-}
-
-.sidebox * {
- font-size:inherit;
-}
-
-#tb ol,
-#tb ul,
-#qv ul {
- margin:0 15px 10px 35px;
-}
-
-#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;
-}
-
-
-/* --------------------------------------------------------------------------
-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: #080; }
-.kwd { color: #008; }
-.com { color: #800; }
-.typ { color: #606; }
-.lit { color: #066; }
-.pun { color: #660; }
-.pln { color: #000; }
-.tag { color: #008; }
-.atn { color: #828; }
-.atv { color: #080; }
-.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;
- display: none;
-}
-#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, #devdoc-nav, #swapper,
-#nav-tree, #tree-list {
- overflow:hidden;
- margin-left:0;
-}
-
-#nav-tree, #swapper {
- display: none;
-}
-
-#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;
-}
-#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 */
- display: none;
-
-}
-#api-nav-title {
- padding:0 5px;
- white-space:nowrap;
- display: none;
-}
-
-#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 p {
- margin:10px 0 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;
-}
-
-/* --------------------------------------------------------------------------
-Butterbar
-*/
-#butterbar-wrapper {
- position:absolute;
- top:0;
- left:0;
- width:100%;
-}
-#butterbar {
- width:940px;
- margin:0 auto;
-}
-#butterbar-message {
- background-color:#f80;
- float:right;
- font-size:12px;
- font-weight:bold;
- padding:0 10px;
- border-radius: 0 0 5px 5px;
-}
-#butterbar-message a {color:#fff !important}
-#butterbar-message a: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 {
- list-style:none;
- margin-left:0;
-}
-#tb .nolist {
- margin-left:15px;
-}
-
-
-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: 0 0 4px 0;
- 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;
-}
-
-#devdoc-nav a.totop {
- display:block;
- top:0;
- width:inherit;
- background: transparent url(../images/styles/gototop.png) no-repeat scroll 50% 50%;
- text-indent:-9999em;
-}
-#devdoc-nav a.totop {
- position:fixed;
- display:none;
-}
-#devdoc-nav a.totop:hover {
- background-color:#33B5E5;
-}
-
-.content-footer a.totop {
- text-transform:uppercase;
- line-height:30px;
-}
-
-.expandable {
- height:34px;
- padding-left:20px;
- 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);
-}
-
-
-
-/* -----------------------------------------------
-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#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 #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#naMessage div { position:absolute; }
-
-div#naMessage strong {
- font-size:1.1em;
-}
-
-
-/* --------------------------------------------------------------------------
-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 5px;
- margin: 20px 0 10px;
- font-size:13px;
- border-bottom:solid 1px #ccc;
-}
-
-#jd-header h1 {
- margin:0;
- padding:0;
-}
-
-/* page-top-right container for reference pages (holds
-links to summary tables) */
-#api-info-block {
- font-size:13px;
- margin:20px 0 0;
- padding:0 10px 6px;
- font-weight:normal;
- float:right;
- text-align:right;
- color:#999;
- max-width:70%;
-}
-
-#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:13px;
- 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 */
-
-#search_autocomplete {
- font-weight:normal;
-}
-
-#search_filtered_wrapper {
- width: 193px;
- float: right;
-}
-#search_filtered_div {
- position:absolute;
- z-index:9999;
- min-width:171px; /* +padding and border makes this match input width */
- padding:5px;
- border: solid 1px #C5C5C5;
- background: white;
- top: 35px;
- -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);
-}
-
-ul#search_filtered {
- min-width:100%;
- margin:0;
- list-style: none;
- margin: 0;
- padding: 0;
-}
-
-#search_filtered .jd-selected {
- background-color: #33B5E5;
- cursor:pointer;
-}
-#search_filtered .jd-selected,
-#search_filtered .jd-selected a {
- color:#f7f7f7 !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;
-}
-
-#search_filtered li.header {
- color:#aaa;
- font-weight:bold;
- font-size: 0.81em;
- border: none;
- margin: 8px 0 2px;
- padding:1px 5px;
- line-height:1.5em;
-}
-
-#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;
-}
-
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-/*********** 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;
-}
-
-// Fudging this so SAC looks OK
-.develop #header .wrap {
- border-color: #CCC;
-}
-
-.distribute #header .wrap {
- border-color: #9C0;
-}
-
-.logo a {
- width:123px;
- float:left;
-}
-
-#header .logo {
- margin-top: -6px;
- margin-left: 0px;
- margin-bottom:0px;
- width: 160px;
- padding-right:10px;
-}
-
-#header .saclogo {
- margin-top: -3px;
- margin-left: 0px;
- margin-bottom: 0px;
- margin-right: 30px;
- width: 140px;
- padding-right:0px;
- border-right:1px solid #CCC;
-}
-
-.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:180px;
- margin-top:-30px;
- display:none;
- overflow:hidden;
-}
-
-#header-wrap.quicknav #quicknav {
-
-}
-
-#quicknav ul {
- margin:10px 0;
- padding:0;
-}
-
-#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:196px;
-
-}
-
-/* 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: -webkit-opacity;
- -moz-transition-duration: .25s;
- -moz-transition-timing-function:ease;
-
- -o-transition-property: -webkit-opacity;
- -o-transition-duration: .25s;
- -o-transition-timing-function:ease;
-
- -transition-property: -webkit-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;
-}
-
-
-
-
-a.download-sdk {
- float:right;
- margin:-10px 0;
- height:30px;
- padding-top:4px;
- padding-bottom:0px;
-}
-
-#nav-x {
- padding-top: 14px;
-}
-
-#nav-x .wrap {
- min-height:34px;
-}
-
-#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;
- overflow: hidden;
- 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: 300px;
- width: 940px;
- position: relative;
- overflow:hidden;
-}
-.slideshow-develop .frame {
- width: 940px;
- height: 300px;
-}
-.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;
-}
-.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;
-}
-
-
-
-/************ DISTRIBUTE HOMEPAGE ***************/
-
-.marquee {
- width: 760px;
-}
-.marquee .main-img {
- float: left;
- margin-top: 20px;
- width: 490px;
-}
-.marquee .copy {
- width: 270px;
- float: left;
- margin-top: 30px;
-}
-.distribute-features {
- margin: 0;
-}
-.distribute-features ul {
- margin: 0;
-}
-.distribute-features ul li {
- list-style: none;
- float: left;
- border-top: 1px solid #9C0;
- width: 220px;
- margin-right: 50px;
-}
-.distribute-features ul li.last {
- margin-right: 0px;
-}
-
-
-
-/************ DEVELOP TOPIC CONTAINERS ************/
-
-.landing-banner,
-.landing-docs {
- margin:20px 0 0;
-}
-.landing-banner div:first-child,
-.landing-docs div:first-child,
-.landing-docs .col-12 {
- margin-left:0;
- min-height:280px;
-}
-.landing-banner div:last-child,
-.landing-docs div:last-child,
-.landing-docs .col-12 {
- margin-right:0;
-}
-
-.landing-banner h1 {
- margin-top:0;
-}
-.landing-docs {
- clear:left;
- 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;
-}
-
-.feedback {
- float:right !important;
- margin: 0 0 0 10px;
- font-size: 14px;
-}
-
-
-/************* 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;
-}
-
-.annotation-message {
- display: block;
-}
-
-.dac-custom-search {
- background: #fff;
- margin: 0 -10px;
- padding: 20px 10px;
- z-index: 1;
-}
-
-.dac-custom-search .dac-fab, .dac-custom-search .dac-button-social {
- top: -48px;
-}
-
-.dac-custom-search-section-title {
- color: #505050;
-}
-
-.dac-custom-search-entry {
- margin-bottom: 36px;
- margin-top: 24px;
- margin-left: 0em;
-}
-
-.dac-custom-search-image {
- background-size: cover;
- height: 112px;
-}
-
-.dac-custom-search-title {
- color: #333;
- font-size: 14px;
- font-weight: 700;
- line-height: 0px;
- padding: 0;
- margin: 1em 0em 1em 0em;
-}
-
-.dac-custom-search-title a {
- color: inherit;
-}
-
-.dac-custom-search-section {
- color: #999;
- font-size: 16px;
- font-variant: small-caps;
- font-weight: 700;
- margin: -5px 0 0 0;
-}
-
-.dac-custom-search-snippet {
- color: #666;
- margin: 0em 0em .25em 0em;
-}
-
-.dac-custom-search-link {
- font-weight: 500;
- word-wrap: break-word;
- width: 100%;
-}
-
-.dac-custom-search-load-more {
- background: none;
- border: none;
- color: #333;
- cursor: pointer;
- display: block;
- font-size: 14px;
- font-weight: 700;
- margin: 75px auto;
- outline: none;
- padding: 10px;
-}
-
-.dac-custom-search-load-more:hover {
- opacity: 0.7;
-}
-
-.dac-custom-search-no-results {
- color: #999;
-}
-
diff --git a/tools/droiddoc/templates-sac/assets/css/fullscreen.css b/tools/droiddoc/templates-sac/assets/css/fullscreen.css
deleted file mode 100644
index 71cf65b..0000000
--- a/tools/droiddoc/templates-sac/assets/css/fullscreen.css
+++ /dev/null
@@ -1,200 +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%;
-}
-
-#nav-x .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 */
-}
-
-
-
-
-}
-
-.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-sac/assets/design/default.js b/tools/droiddoc/templates-sac/assets/design/default.js
deleted file mode 100644
index 3ba8486..0000000
--- a/tools/droiddoc/templates-sac/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-sac/assets/images/android-developers-logo.png b/tools/droiddoc/templates-sac/assets/images/android-developers-logo.png
deleted file mode 100644
index 30a8f62..0000000
--- a/tools/droiddoc/templates-sac/assets/images/android-developers-logo.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/android_wrench.png b/tools/droiddoc/templates-sac/assets/images/android_wrench.png
deleted file mode 100644
index 6390a2d..0000000
--- a/tools/droiddoc/templates-sac/assets/images/android_wrench.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/arrow-left-develop.png b/tools/droiddoc/templates-sac/assets/images/arrow-left-develop.png
deleted file mode 100644
index 5fdfaa3..0000000
--- a/tools/droiddoc/templates-sac/assets/images/arrow-left-develop.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/arrow-left.png b/tools/droiddoc/templates-sac/assets/images/arrow-left.png
deleted file mode 100644
index 43afec8..0000000
--- a/tools/droiddoc/templates-sac/assets/images/arrow-left.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/arrow-right-develop.png b/tools/droiddoc/templates-sac/assets/images/arrow-right-develop.png
deleted file mode 100644
index c86f1f3..0000000
--- a/tools/droiddoc/templates-sac/assets/images/arrow-right-develop.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/arrow-right.png b/tools/droiddoc/templates-sac/assets/images/arrow-right.png
deleted file mode 100644
index 6f7d6db..0000000
--- a/tools/droiddoc/templates-sac/assets/images/arrow-right.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/arrow_bluelink_down.png b/tools/droiddoc/templates-sac/assets/images/arrow_bluelink_down.png
deleted file mode 100755
index 58c248a..0000000
--- a/tools/droiddoc/templates-sac/assets/images/arrow_bluelink_down.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/arrow_bluelink_up.png b/tools/droiddoc/templates-sac/assets/images/arrow_bluelink_up.png
deleted file mode 100755
index 7d0f38e..0000000
--- a/tools/droiddoc/templates-sac/assets/images/arrow_bluelink_up.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/arrow_left_off.jpg b/tools/droiddoc/templates-sac/assets/images/arrow_left_off.jpg
deleted file mode 100755
index fd32a64..0000000
--- a/tools/droiddoc/templates-sac/assets/images/arrow_left_off.jpg
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/arrow_left_on.jpg b/tools/droiddoc/templates-sac/assets/images/arrow_left_on.jpg
deleted file mode 100755
index 143184b..0000000
--- a/tools/droiddoc/templates-sac/assets/images/arrow_left_on.jpg
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/arrow_right_off.jpg b/tools/droiddoc/templates-sac/assets/images/arrow_right_off.jpg
deleted file mode 100755
index 17d2efe..0000000
--- a/tools/droiddoc/templates-sac/assets/images/arrow_right_off.jpg
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/arrow_right_on.jpg b/tools/droiddoc/templates-sac/assets/images/arrow_right_on.jpg
deleted file mode 100755
index baa2af1..0000000
--- a/tools/droiddoc/templates-sac/assets/images/arrow_right_on.jpg
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/arrows-up-down.png b/tools/droiddoc/templates-sac/assets/images/arrows-up-down.png
deleted file mode 100644
index a2a91ed..0000000
--- a/tools/droiddoc/templates-sac/assets/images/arrows-up-down.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/bg_community_leftDiv.jpg b/tools/droiddoc/templates-sac/assets/images/bg_community_leftDiv.jpg
deleted file mode 100755
index a6d6f0e..0000000
--- a/tools/droiddoc/templates-sac/assets/images/bg_community_leftDiv.jpg
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/bg_fade.jpg b/tools/droiddoc/templates-sac/assets/images/bg_fade.jpg
deleted file mode 100755
index c6c70b6..0000000
--- a/tools/droiddoc/templates-sac/assets/images/bg_fade.jpg
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/bg_gradient.jpg b/tools/droiddoc/templates-sac/assets/images/bg_gradient.jpg
deleted file mode 100644
index 884f8f5..0000000
--- a/tools/droiddoc/templates-sac/assets/images/bg_gradient.jpg
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/bg_images_sprite.png b/tools/droiddoc/templates-sac/assets/images/bg_images_sprite.png
deleted file mode 100755
index 84437e7..0000000
--- a/tools/droiddoc/templates-sac/assets/images/bg_images_sprite.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/bg_logo.png b/tools/droiddoc/templates-sac/assets/images/bg_logo.png
deleted file mode 100755
index 7cf0cb9..0000000
--- a/tools/droiddoc/templates-sac/assets/images/bg_logo.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/blog-default.png b/tools/droiddoc/templates-sac/assets/images/blog-default.png
deleted file mode 100644
index f8ab6c3..0000000
--- a/tools/droiddoc/templates-sac/assets/images/blog-default.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/body-gradient-tab.png b/tools/droiddoc/templates-sac/assets/images/body-gradient-tab.png
deleted file mode 100644
index 5223ac3..0000000
--- a/tools/droiddoc/templates-sac/assets/images/body-gradient-tab.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/body-gradient.png b/tools/droiddoc/templates-sac/assets/images/body-gradient.png
deleted file mode 100755
index 9d59855..0000000
--- a/tools/droiddoc/templates-sac/assets/images/body-gradient.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/close.png b/tools/droiddoc/templates-sac/assets/images/close.png
deleted file mode 100644
index 6ae3391..0000000
--- a/tools/droiddoc/templates-sac/assets/images/close.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/dac_logo.png b/tools/droiddoc/templates-sac/assets/images/dac_logo.png
deleted file mode 100644
index 0f11044..0000000
--- a/tools/droiddoc/templates-sac/assets/images/dac_logo.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/developers-logo.png b/tools/droiddoc/templates-sac/assets/images/developers-logo.png
deleted file mode 100755
index 08122ee..0000000
--- a/tools/droiddoc/templates-sac/assets/images/developers-logo.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/fullscreen.png b/tools/droiddoc/templates-sac/assets/images/fullscreen.png
deleted file mode 100644
index 01f971c..0000000
--- a/tools/droiddoc/templates-sac/assets/images/fullscreen.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/grad-rule-qv.png b/tools/droiddoc/templates-sac/assets/images/grad-rule-qv.png
deleted file mode 100644
index bae2d18..0000000
--- a/tools/droiddoc/templates-sac/assets/images/grad-rule-qv.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/home/Android_Dev_Lab_l.png b/tools/droiddoc/templates-sac/assets/images/home/Android_Dev_Lab_l.png
deleted file mode 100644
index 3c04f24..0000000
--- a/tools/droiddoc/templates-sac/assets/images/home/Android_Dev_Lab_l.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/home/GDC2011.png b/tools/droiddoc/templates-sac/assets/images/home/GDC2011.png
deleted file mode 100644
index 82ce918..0000000
--- a/tools/droiddoc/templates-sac/assets/images/home/GDC2011.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/home/GTV_icon_large.png b/tools/droiddoc/templates-sac/assets/images/home/GTV_icon_large.png
deleted file mode 100644
index 72d54ad..0000000
--- a/tools/droiddoc/templates-sac/assets/images/home/GTV_icon_large.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/home/GTV_icon_small.png b/tools/droiddoc/templates-sac/assets/images/home/GTV_icon_small.png
deleted file mode 100644
index 3da1699..0000000
--- a/tools/droiddoc/templates-sac/assets/images/home/GTV_icon_small.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/home/IO-logo-2011.png b/tools/droiddoc/templates-sac/assets/images/home/IO-logo-2011.png
deleted file mode 100644
index 4a28447..0000000
--- a/tools/droiddoc/templates-sac/assets/images/home/IO-logo-2011.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/home/IO-logo.png b/tools/droiddoc/templates-sac/assets/images/home/IO-logo.png
deleted file mode 100644
index 65334c8..0000000
--- a/tools/droiddoc/templates-sac/assets/images/home/IO-logo.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/home/adc2_l.png b/tools/droiddoc/templates-sac/assets/images/home/adc2_l.png
deleted file mode 100644
index 0b101a4..0000000
--- a/tools/droiddoc/templates-sac/assets/images/home/adc2_l.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/home/adc2_s.png b/tools/droiddoc/templates-sac/assets/images/home/adc2_s.png
deleted file mode 100644
index 0d36bdb..0000000
--- a/tools/droiddoc/templates-sac/assets/images/home/adc2_s.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/home/android_adc.png b/tools/droiddoc/templates-sac/assets/images/home/android_adc.png
deleted file mode 100644
index 9fe7f8f..0000000
--- a/tools/droiddoc/templates-sac/assets/images/home/android_adc.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/home/bg_home_announcement.png b/tools/droiddoc/templates-sac/assets/images/home/bg_home_announcement.png
deleted file mode 100755
index 91485ff..0000000
--- a/tools/droiddoc/templates-sac/assets/images/home/bg_home_announcement.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/home/bg_home_bottom.jpg b/tools/droiddoc/templates-sac/assets/images/home/bg_home_bottom.jpg
deleted file mode 100755
index dacd401..0000000
--- a/tools/droiddoc/templates-sac/assets/images/home/bg_home_bottom.jpg
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/home/bg_home_carousel.png b/tools/droiddoc/templates-sac/assets/images/home/bg_home_carousel.png
deleted file mode 100755
index 5ce5e30..0000000
--- a/tools/droiddoc/templates-sac/assets/images/home/bg_home_carousel.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/home/bg_home_carousel_board.png b/tools/droiddoc/templates-sac/assets/images/home/bg_home_carousel_board.png
deleted file mode 100755
index c577e02..0000000
--- a/tools/droiddoc/templates-sac/assets/images/home/bg_home_carousel_board.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/home/bg_home_carousel_wheel.png b/tools/droiddoc/templates-sac/assets/images/home/bg_home_carousel_wheel.png
deleted file mode 100755
index aa224ad..0000000
--- a/tools/droiddoc/templates-sac/assets/images/home/bg_home_carousel_wheel.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/home/carousel_buttons_sprite.png b/tools/droiddoc/templates-sac/assets/images/home/carousel_buttons_sprite.png
deleted file mode 100755
index e98c942..0000000
--- a/tools/droiddoc/templates-sac/assets/images/home/carousel_buttons_sprite.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/home/devphone-large.png b/tools/droiddoc/templates-sac/assets/images/home/devphone-large.png
deleted file mode 100644
index 0db0f6c..0000000
--- a/tools/droiddoc/templates-sac/assets/images/home/devphone-large.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/home/devphone-small.png b/tools/droiddoc/templates-sac/assets/images/home/devphone-small.png
deleted file mode 100644
index e10bfa9..0000000
--- a/tools/droiddoc/templates-sac/assets/images/home/devphone-small.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/home/donut-android.png b/tools/droiddoc/templates-sac/assets/images/home/donut-android.png
deleted file mode 100755
index 6aba06b..0000000
--- a/tools/droiddoc/templates-sac/assets/images/home/donut-android.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/home/eclair-android.png b/tools/droiddoc/templates-sac/assets/images/home/eclair-android.png
deleted file mode 100644
index d476ce9..0000000
--- a/tools/droiddoc/templates-sac/assets/images/home/eclair-android.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/home/froyo-android.png b/tools/droiddoc/templates-sac/assets/images/home/froyo-android.png
deleted file mode 100644
index c63f7f0..0000000
--- a/tools/droiddoc/templates-sac/assets/images/home/froyo-android.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/home/gdc-logo.png b/tools/droiddoc/templates-sac/assets/images/home/gdc-logo.png
deleted file mode 100644
index 5fb53fb..0000000
--- a/tools/droiddoc/templates-sac/assets/images/home/gdc-logo.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/home/gingerdroid.png b/tools/droiddoc/templates-sac/assets/images/home/gingerdroid.png
deleted file mode 100644
index 8399d84..0000000
--- a/tools/droiddoc/templates-sac/assets/images/home/gingerdroid.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/home/google-plus-small.png b/tools/droiddoc/templates-sac/assets/images/home/google-plus-small.png
deleted file mode 100644
index 5bb7d7a..0000000
--- a/tools/droiddoc/templates-sac/assets/images/home/google-plus-small.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/home/google-plus.png b/tools/droiddoc/templates-sac/assets/images/home/google-plus.png
deleted file mode 100644
index 90871e1..0000000
--- a/tools/droiddoc/templates-sac/assets/images/home/google-plus.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/home/honeycomb-android.png b/tools/droiddoc/templates-sac/assets/images/home/honeycomb-android.png
deleted file mode 100644
index 6cc5031..0000000
--- a/tools/droiddoc/templates-sac/assets/images/home/honeycomb-android.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/home/icon-about.png b/tools/droiddoc/templates-sac/assets/images/home/icon-about.png
deleted file mode 100644
index 8339762..0000000
--- a/tools/droiddoc/templates-sac/assets/images/home/icon-about.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/home/icon-design.png b/tools/droiddoc/templates-sac/assets/images/home/icon-design.png
deleted file mode 100644
index 0d31cdf..0000000
--- a/tools/droiddoc/templates-sac/assets/images/home/icon-design.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/home/icon-develop.png b/tools/droiddoc/templates-sac/assets/images/home/icon-develop.png
deleted file mode 100644
index e02b20f..0000000
--- a/tools/droiddoc/templates-sac/assets/images/home/icon-develop.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/home/icon-distribute.png b/tools/droiddoc/templates-sac/assets/images/home/icon-distribute.png
deleted file mode 100644
index 4824072..0000000
--- a/tools/droiddoc/templates-sac/assets/images/home/icon-distribute.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/home/ics-android.png b/tools/droiddoc/templates-sac/assets/images/home/ics-android.png
deleted file mode 100644
index be62ca8..0000000
--- a/tools/droiddoc/templates-sac/assets/images/home/ics-android.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/home/io-large.png b/tools/droiddoc/templates-sac/assets/images/home/io-large.png
deleted file mode 100755
index 986053c..0000000
--- a/tools/droiddoc/templates-sac/assets/images/home/io-large.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/home/io-small.png b/tools/droiddoc/templates-sac/assets/images/home/io-small.png
deleted file mode 100755
index 3a22549..0000000
--- a/tools/droiddoc/templates-sac/assets/images/home/io-small.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/home/maps-large.png b/tools/droiddoc/templates-sac/assets/images/home/maps-large.png
deleted file mode 100644
index b26f65a..0000000
--- a/tools/droiddoc/templates-sac/assets/images/home/maps-large.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/home/maps-small.png b/tools/droiddoc/templates-sac/assets/images/home/maps-small.png
deleted file mode 100644
index cc5f1fa..0000000
--- a/tools/droiddoc/templates-sac/assets/images/home/maps-small.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/home/market-large.png b/tools/droiddoc/templates-sac/assets/images/home/market-large.png
deleted file mode 100644
index 069fee7..0000000
--- a/tools/droiddoc/templates-sac/assets/images/home/market-large.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/home/market-small.png b/tools/droiddoc/templates-sac/assets/images/home/market-small.png
deleted file mode 100644
index fa1201c..0000000
--- a/tools/droiddoc/templates-sac/assets/images/home/market-small.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/home/sdk-large.png b/tools/droiddoc/templates-sac/assets/images/home/sdk-large.png
deleted file mode 100644
index 315a1bf..0000000
--- a/tools/droiddoc/templates-sac/assets/images/home/sdk-large.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/home/sdk-small.png b/tools/droiddoc/templates-sac/assets/images/home/sdk-small.png
deleted file mode 100644
index 0f1670d..0000000
--- a/tools/droiddoc/templates-sac/assets/images/home/sdk-small.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/hr_gray_main.jpg b/tools/droiddoc/templates-sac/assets/images/hr_gray_main.jpg
deleted file mode 100755
index f7a0a2f..0000000
--- a/tools/droiddoc/templates-sac/assets/images/hr_gray_main.jpg
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/hr_gray_side.jpg b/tools/droiddoc/templates-sac/assets/images/hr_gray_side.jpg
deleted file mode 100755
index 6667476..0000000
--- a/tools/droiddoc/templates-sac/assets/images/hr_gray_side.jpg
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/icon_contribute.jpg b/tools/droiddoc/templates-sac/assets/images/icon_contribute.jpg
deleted file mode 100755
index 1aa12b6..0000000
--- a/tools/droiddoc/templates-sac/assets/images/icon_contribute.jpg
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/icon_design.png b/tools/droiddoc/templates-sac/assets/images/icon_design.png
deleted file mode 100644
index c12907c..0000000
--- a/tools/droiddoc/templates-sac/assets/images/icon_design.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/icon_download.jpg b/tools/droiddoc/templates-sac/assets/images/icon_download.jpg
deleted file mode 100755
index f8c1165..0000000
--- a/tools/droiddoc/templates-sac/assets/images/icon_download.jpg
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/icon_download2.jpg b/tools/droiddoc/templates-sac/assets/images/icon_download2.jpg
deleted file mode 100755
index c0af7a2..0000000
--- a/tools/droiddoc/templates-sac/assets/images/icon_download2.jpg
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/icon_guidelines_logo.png b/tools/droiddoc/templates-sac/assets/images/icon_guidelines_logo.png
deleted file mode 100644
index 9362c8f..0000000
--- a/tools/droiddoc/templates-sac/assets/images/icon_guidelines_logo.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/icon_market.jpg b/tools/droiddoc/templates-sac/assets/images/icon_market.jpg
deleted file mode 100644
index 0fbb197..0000000
--- a/tools/droiddoc/templates-sac/assets/images/icon_market.jpg
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/icon_more.png b/tools/droiddoc/templates-sac/assets/images/icon_more.png
deleted file mode 100644
index 6cd03a3..0000000
--- a/tools/droiddoc/templates-sac/assets/images/icon_more.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/icon_play.png b/tools/droiddoc/templates-sac/assets/images/icon_play.png
deleted file mode 100644
index 8bfdc7b..0000000
--- a/tools/droiddoc/templates-sac/assets/images/icon_play.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/icon_robot.jpg b/tools/droiddoc/templates-sac/assets/images/icon_robot.jpg
deleted file mode 100755
index ca0fd39..0000000
--- a/tools/droiddoc/templates-sac/assets/images/icon_robot.jpg
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/icon_search.png b/tools/droiddoc/templates-sac/assets/images/icon_search.png
deleted file mode 100644
index ee90a12..0000000
--- a/tools/droiddoc/templates-sac/assets/images/icon_search.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/icon_world.jpg b/tools/droiddoc/templates-sac/assets/images/icon_world.jpg
deleted file mode 100755
index 65b8fa6..0000000
--- a/tools/droiddoc/templates-sac/assets/images/icon_world.jpg
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/left_off.jpg b/tools/droiddoc/templates-sac/assets/images/left_off.jpg
deleted file mode 100755
index fd32a64..0000000
--- a/tools/droiddoc/templates-sac/assets/images/left_off.jpg
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/left_on.jpg b/tools/droiddoc/templates-sac/assets/images/left_on.jpg
deleted file mode 100755
index 143184b..0000000
--- a/tools/droiddoc/templates-sac/assets/images/left_on.jpg
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/locale.png b/tools/droiddoc/templates-sac/assets/images/locale.png
deleted file mode 100644
index de3aae7..0000000
--- a/tools/droiddoc/templates-sac/assets/images/locale.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/logo_breadcrumbz.jpg b/tools/droiddoc/templates-sac/assets/images/logo_breadcrumbz.jpg
deleted file mode 100755
index e743f86..0000000
--- a/tools/droiddoc/templates-sac/assets/images/logo_breadcrumbz.jpg
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/more_bottom.png b/tools/droiddoc/templates-sac/assets/images/more_bottom.png
deleted file mode 100644
index 632546a..0000000
--- a/tools/droiddoc/templates-sac/assets/images/more_bottom.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/more_check.png b/tools/droiddoc/templates-sac/assets/images/more_check.png
deleted file mode 100644
index f2fcbfc..0000000
--- a/tools/droiddoc/templates-sac/assets/images/more_check.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/more_mid.png b/tools/droiddoc/templates-sac/assets/images/more_mid.png
deleted file mode 100644
index 99bc999..0000000
--- a/tools/droiddoc/templates-sac/assets/images/more_mid.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/more_top.png b/tools/droiddoc/templates-sac/assets/images/more_top.png
deleted file mode 100644
index 8ead1d3..0000000
--- a/tools/droiddoc/templates-sac/assets/images/more_top.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/open_source.png b/tools/droiddoc/templates-sac/assets/images/open_source.png
deleted file mode 100755
index 12bb1fb..0000000
--- a/tools/droiddoc/templates-sac/assets/images/open_source.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/preliminary.png b/tools/droiddoc/templates-sac/assets/images/preliminary.png
deleted file mode 100644
index fe0da3d..0000000
--- a/tools/droiddoc/templates-sac/assets/images/preliminary.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/quicknav_arrow.png b/tools/droiddoc/templates-sac/assets/images/quicknav_arrow.png
deleted file mode 100644
index 697ac82..0000000
--- a/tools/droiddoc/templates-sac/assets/images/quicknav_arrow.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/quicknav_btn_bg.png b/tools/droiddoc/templates-sac/assets/images/quicknav_btn_bg.png
deleted file mode 100644
index b80c9a8..0000000
--- a/tools/droiddoc/templates-sac/assets/images/quicknav_btn_bg.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/resizable-e.gif b/tools/droiddoc/templates-sac/assets/images/resizable-e.gif
deleted file mode 100755
index f748097..0000000
--- a/tools/droiddoc/templates-sac/assets/images/resizable-e.gif
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/resizable-e2.gif b/tools/droiddoc/templates-sac/assets/images/resizable-e2.gif
deleted file mode 100755
index e45d0c5..0000000
--- a/tools/droiddoc/templates-sac/assets/images/resizable-e2.gif
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/resizable-eg.gif b/tools/droiddoc/templates-sac/assets/images/resizable-eg.gif
deleted file mode 100755
index 6196616..0000000
--- a/tools/droiddoc/templates-sac/assets/images/resizable-eg.gif
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/resizable-s.gif b/tools/droiddoc/templates-sac/assets/images/resizable-s.gif
deleted file mode 100755
index 7f6a4eb..0000000
--- a/tools/droiddoc/templates-sac/assets/images/resizable-s.gif
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/resizable-s2.gif b/tools/droiddoc/templates-sac/assets/images/resizable-s2.gif
deleted file mode 100755
index 99e869c..0000000
--- a/tools/droiddoc/templates-sac/assets/images/resizable-s2.gif
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/resizable-s2.png b/tools/droiddoc/templates-sac/assets/images/resizable-s2.png
deleted file mode 100644
index f3a6d2d..0000000
--- a/tools/droiddoc/templates-sac/assets/images/resizable-s2.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/resizable-sg.gif b/tools/droiddoc/templates-sac/assets/images/resizable-sg.gif
deleted file mode 100755
index b4bea10..0000000
--- a/tools/droiddoc/templates-sac/assets/images/resizable-sg.gif
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/resource-article.png b/tools/droiddoc/templates-sac/assets/images/resource-article.png
deleted file mode 100644
index 416493f..0000000
--- a/tools/droiddoc/templates-sac/assets/images/resource-article.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/resource-big-article.png b/tools/droiddoc/templates-sac/assets/images/resource-big-article.png
deleted file mode 100644
index 7273275..0000000
--- a/tools/droiddoc/templates-sac/assets/images/resource-big-article.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/resource-big-sample.png b/tools/droiddoc/templates-sac/assets/images/resource-big-sample.png
deleted file mode 100644
index 59b6b68..0000000
--- a/tools/droiddoc/templates-sac/assets/images/resource-big-sample.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/resource-big-tutorial.png b/tools/droiddoc/templates-sac/assets/images/resource-big-tutorial.png
deleted file mode 100644
index c32e89a..0000000
--- a/tools/droiddoc/templates-sac/assets/images/resource-big-tutorial.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/resource-big-video.png b/tools/droiddoc/templates-sac/assets/images/resource-big-video.png
deleted file mode 100644
index 59d46a0..0000000
--- a/tools/droiddoc/templates-sac/assets/images/resource-big-video.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/resource-sample.png b/tools/droiddoc/templates-sac/assets/images/resource-sample.png
deleted file mode 100644
index f7a411c..0000000
--- a/tools/droiddoc/templates-sac/assets/images/resource-sample.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/resource-tutorial.png b/tools/droiddoc/templates-sac/assets/images/resource-tutorial.png
deleted file mode 100644
index 10a14fe..0000000
--- a/tools/droiddoc/templates-sac/assets/images/resource-tutorial.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/resource-video.png b/tools/droiddoc/templates-sac/assets/images/resource-video.png
deleted file mode 100644
index 8fd5cae..0000000
--- a/tools/droiddoc/templates-sac/assets/images/resource-video.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/right_off.jpg b/tools/droiddoc/templates-sac/assets/images/right_off.jpg
deleted file mode 100755
index 17d2efe..0000000
--- a/tools/droiddoc/templates-sac/assets/images/right_off.jpg
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/right_on.jpg b/tools/droiddoc/templates-sac/assets/images/right_on.jpg
deleted file mode 100755
index baa2af1..0000000
--- a/tools/droiddoc/templates-sac/assets/images/right_on.jpg
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/sac_logo.png b/tools/droiddoc/templates-sac/assets/images/sac_logo.png
deleted file mode 100644
index 4ad113c..0000000
--- a/tools/droiddoc/templates-sac/assets/images/sac_logo.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/sac_logo@2x.png b/tools/droiddoc/templates-sac/assets/images/sac_logo@2x.png
deleted file mode 100644
index 4040f3f..0000000
--- a/tools/droiddoc/templates-sac/assets/images/sac_logo@2x.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/sidenav-rule.png b/tools/droiddoc/templates-sac/assets/images/sidenav-rule.png
deleted file mode 100644
index eab9920..0000000
--- a/tools/droiddoc/templates-sac/assets/images/sidenav-rule.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/slide_1.jpg b/tools/droiddoc/templates-sac/assets/images/slide_1.jpg
deleted file mode 100755
index 6d75be1..0000000
--- a/tools/droiddoc/templates-sac/assets/images/slide_1.jpg
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/slide_2.jpg b/tools/droiddoc/templates-sac/assets/images/slide_2.jpg
deleted file mode 100755
index aa994c2..0000000
--- a/tools/droiddoc/templates-sac/assets/images/slide_2.jpg
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/slide_3.jpg b/tools/droiddoc/templates-sac/assets/images/slide_3.jpg
deleted file mode 100755
index b04deb3..0000000
--- a/tools/droiddoc/templates-sac/assets/images/slide_3.jpg
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/slide_large_1.jpg b/tools/droiddoc/templates-sac/assets/images/slide_large_1.jpg
deleted file mode 100755
index a992e92..0000000
--- a/tools/droiddoc/templates-sac/assets/images/slide_large_1.jpg
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/slide_large_2.jpg b/tools/droiddoc/templates-sac/assets/images/slide_large_2.jpg
deleted file mode 100755
index 9af63f4..0000000
--- a/tools/droiddoc/templates-sac/assets/images/slide_large_2.jpg
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/slide_large_3.jpg b/tools/droiddoc/templates-sac/assets/images/slide_large_3.jpg
deleted file mode 100755
index fcf236c..0000000
--- a/tools/droiddoc/templates-sac/assets/images/slide_large_3.jpg
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/slide_off.jpg b/tools/droiddoc/templates-sac/assets/images/slide_off.jpg
deleted file mode 100755
index 5971227..0000000
--- a/tools/droiddoc/templates-sac/assets/images/slide_off.jpg
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/slide_on.jpg b/tools/droiddoc/templates-sac/assets/images/slide_on.jpg
deleted file mode 100755
index 7ca3577..0000000
--- a/tools/droiddoc/templates-sac/assets/images/slide_on.jpg
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/spacer.gif b/tools/droiddoc/templates-sac/assets/images/spacer.gif
deleted file mode 100755
index f96b355..0000000
--- a/tools/droiddoc/templates-sac/assets/images/spacer.gif
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/styles/callout.png b/tools/droiddoc/templates-sac/assets/images/styles/callout.png
deleted file mode 100644
index 5d49f34..0000000
--- a/tools/droiddoc/templates-sac/assets/images/styles/callout.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/styles/device_galaxynexus_blank_land_span13.png b/tools/droiddoc/templates-sac/assets/images/styles/device_galaxynexus_blank_land_span13.png
deleted file mode 100644
index bab6aca..0000000
--- a/tools/droiddoc/templates-sac/assets/images/styles/device_galaxynexus_blank_land_span13.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/styles/device_galaxynexus_blank_land_span8.png b/tools/droiddoc/templates-sac/assets/images/styles/device_galaxynexus_blank_land_span8.png
deleted file mode 100644
index cb180bf..0000000
--- a/tools/droiddoc/templates-sac/assets/images/styles/device_galaxynexus_blank_land_span8.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/styles/device_galaxynexus_blank_port_span5.png b/tools/droiddoc/templates-sac/assets/images/styles/device_galaxynexus_blank_port_span5.png
deleted file mode 100644
index bdccc2f..0000000
--- a/tools/droiddoc/templates-sac/assets/images/styles/device_galaxynexus_blank_port_span5.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/styles/device_galaxynexus_blank_port_span9.png b/tools/droiddoc/templates-sac/assets/images/styles/device_galaxynexus_blank_port_span9.png
deleted file mode 100644
index 5e0135b..0000000
--- a/tools/droiddoc/templates-sac/assets/images/styles/device_galaxynexus_blank_port_span9.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/styles/disclosure_down.png b/tools/droiddoc/templates-sac/assets/images/styles/disclosure_down.png
deleted file mode 100644
index 6a0a8ee..0000000
--- a/tools/droiddoc/templates-sac/assets/images/styles/disclosure_down.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/styles/disclosure_left.png b/tools/droiddoc/templates-sac/assets/images/styles/disclosure_left.png
deleted file mode 100644
index e887b2a..0000000
--- a/tools/droiddoc/templates-sac/assets/images/styles/disclosure_left.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/styles/disclosure_right.png b/tools/droiddoc/templates-sac/assets/images/styles/disclosure_right.png
deleted file mode 100644
index ced7fa4..0000000
--- a/tools/droiddoc/templates-sac/assets/images/styles/disclosure_right.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/styles/disclosure_up.png b/tools/droiddoc/templates-sac/assets/images/styles/disclosure_up.png
deleted file mode 100644
index ddd4ec9..0000000
--- a/tools/droiddoc/templates-sac/assets/images/styles/disclosure_up.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/styles/gototop.png b/tools/droiddoc/templates-sac/assets/images/styles/gototop.png
deleted file mode 100644
index 5f09a29..0000000
--- a/tools/droiddoc/templates-sac/assets/images/styles/gototop.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/styles/ico_action.png b/tools/droiddoc/templates-sac/assets/images/styles/ico_action.png
deleted file mode 100644
index 30e4cc7..0000000
--- a/tools/droiddoc/templates-sac/assets/images/styles/ico_action.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/styles/ico_good.png b/tools/droiddoc/templates-sac/assets/images/styles/ico_good.png
deleted file mode 100644
index afebe1c..0000000
--- a/tools/droiddoc/templates-sac/assets/images/styles/ico_good.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/styles/ico_movie_inline.png b/tools/droiddoc/templates-sac/assets/images/styles/ico_movie_inline.png
deleted file mode 100644
index 7cfb5c5..0000000
--- a/tools/droiddoc/templates-sac/assets/images/styles/ico_movie_inline.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/styles/ico_phone_tablet.png b/tools/droiddoc/templates-sac/assets/images/styles/ico_phone_tablet.png
deleted file mode 100644
index 003b876..0000000
--- a/tools/droiddoc/templates-sac/assets/images/styles/ico_phone_tablet.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/styles/ico_use.png b/tools/droiddoc/templates-sac/assets/images/styles/ico_use.png
deleted file mode 100644
index 9d868b3..0000000
--- a/tools/droiddoc/templates-sac/assets/images/styles/ico_use.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/styles/ico_web.png b/tools/droiddoc/templates-sac/assets/images/styles/ico_web.png
deleted file mode 100644
index 0848e3c..0000000
--- a/tools/droiddoc/templates-sac/assets/images/styles/ico_web.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/styles/ico_wrong.png b/tools/droiddoc/templates-sac/assets/images/styles/ico_wrong.png
deleted file mode 100644
index b7d04ce..0000000
--- a/tools/droiddoc/templates-sac/assets/images/styles/ico_wrong.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/styles/open_new_page.png b/tools/droiddoc/templates-sac/assets/images/styles/open_new_page.png
deleted file mode 100644
index 6197e3a..0000000
--- a/tools/droiddoc/templates-sac/assets/images/styles/open_new_page.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/triangle-closed-small.png b/tools/droiddoc/templates-sac/assets/images/triangle-closed-small.png
deleted file mode 100644
index 002364a..0000000
--- a/tools/droiddoc/templates-sac/assets/images/triangle-closed-small.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/triangle-closed.png b/tools/droiddoc/templates-sac/assets/images/triangle-closed.png
deleted file mode 100644
index 40a68d9..0000000
--- a/tools/droiddoc/templates-sac/assets/images/triangle-closed.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/triangle-opened-small.png b/tools/droiddoc/templates-sac/assets/images/triangle-opened-small.png
deleted file mode 100644
index e1eb784..0000000
--- a/tools/droiddoc/templates-sac/assets/images/triangle-opened-small.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/triangle-opened.png b/tools/droiddoc/templates-sac/assets/images/triangle-opened.png
deleted file mode 100644
index 789f5fa..0000000
--- a/tools/droiddoc/templates-sac/assets/images/triangle-opened.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/uiguidelines1.png b/tools/droiddoc/templates-sac/assets/images/uiguidelines1.png
deleted file mode 100644
index 5ce1611..0000000
--- a/tools/droiddoc/templates-sac/assets/images/uiguidelines1.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/images/video-droid.png b/tools/droiddoc/templates-sac/assets/images/video-droid.png
deleted file mode 100644
index 25163b6..0000000
--- a/tools/droiddoc/templates-sac/assets/images/video-droid.png
+++ /dev/null
Binary files differ
diff --git a/tools/droiddoc/templates-sac/assets/js/android_3p-bundle.js b/tools/droiddoc/templates-sac/assets/js/android_3p-bundle.js
deleted file mode 100644
index a67b5b0..0000000
--- a/tools/droiddoc/templates-sac/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-sac/assets/js/docs.js b/tools/droiddoc/templates-sac/assets/js/docs.js
deleted file mode 100644
index d0c12a8..0000000
--- a/tools/droiddoc/templates-sac/assets/js/docs.js
+++ /dev/null
@@ -1,2609 +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 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
-
-
-/****** ON LOAD SET UP STUFF *********/
-
-var navBarIsFixed = false;
-$(document).ready(function() {
-
- // 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});
- }
- }
- });
- }
- });
-
- // layout hosted on devsite is special
- if (devsite) {
- // move the lang selector into the overflow menu
- $("#moremenu .mid div.header:last").after($("#language").detach());
- }
-
- // 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 search's onkeyup handler here so we can show suggestions
- // even while search results are visible
- $("#search_autocomplete").keyup(function() {return search_changed(event, false, toRoot)});
-
- // 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); // see search_autocomplete.js
- hideResults(); // see search_autocomplete.js
- });
- $('.search').click(function() {
- if (!$('#search_autocomplete').is(":focus")) {
- $('#search_autocomplete').focus();
- }
- });
-
- // 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';
- }
- }
-
- 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");
-
- // highlight Develop tab
- } else if ($("body").hasClass("develop") || $("body").hasClass("google")) {
- $("#header li.develop a").addClass("selected");
-
- // In Develop docs, also highlight appropriate sub-tab
- var rootDir = pagePath.substring(1,pagePath.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");
- }
-
- // highlight Distribute tab
- } else if ($("body").hasClass("distribute")) {
- $("#header li.distribute a").addClass("selected");
- }
-
-
- // select current page in sidenav and header, and set up prev/next links if they exist
- var $selNavLink = $('#nav').find('a[href="' + pagePath + '"]');
- 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();
- });
-
- // 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')) {
- // 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 training = $(".next-class-link").length; // decides whether to provide "next class" link
- var isCrossingBoundary = false;
-
- if ($selListItem.hasClass('nav-section')) {
- // 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) {
- isCrossingBoundary = true;
- // no more topics in this section, jump to the first topic in the next section
- $nextLink = $selListItem.parents('li:eq(0)').next('li.nav-section').find('a:eq(0)');
- 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 (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; });
-
- $('.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");
- }
-
- 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");
- }
- }
-
- // If this is a training 'article', there should be no prev/next nav
- // ... if the grandparent is the "nav" ... and it has no child list items...
- if (training && $selListItem.parents('ul').eq(1).is('[id="nav"]') &&
- !$selListItem.find('li').length) {
- $('.next-page-link,.prev-page-link').attr('href','').addClass("disabled")
- .click(function() { return false; });
- }
-
- }
-//If auto-toc div is present, generate the automated TOC
-if ($("#auto-toc").is('*')) {
- var previous = $(this); //needs to be not null first time through loop
- var toc = "";
- $("#jd-content").find("h2, h3").not(':first-child').each(function(i) { // have to skip the first h2, which is "In this Document" with not:first-child
- var current = $(this);
- if(current.is("h3") && previous.is("h2")){ //need nested ols for h3s
- toc+="<ol>";
- }
- else if(current.is("h2") && previous.is("h3")){ //close up the nested ol
- toc+="</ol>";
- }
- toc+="<li><a href='#" + current[0].id + "'>" +
- current.html() + "</a></li>";
-
- previous = current; //keep track of previous element next time through loop
- });
- $("#auto-toc").append(toc); //append to the div
-}
-
- // Set up the course landing pages for Training with class names and descriptions
- if ($('body.trainingcourse').length) {
- var $classLinks = $selListItem.find('ul li a').not('#nav .nav-section .nav-section ul a');
- var $classDescriptions = $classLinks.attr('description');
-
- 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">' + $(this).attr('description') + '</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" 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" 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
- $('#nav li.nav-section .nav-section-header').click(function() {
- var section = $(this).closest('li.nav-section');
- if (section.hasClass('expanded')) {
- /* hide me */
- // if (section.hasClass('selected') || section.find('li').hasClass('selected')) {
- // /* but not if myself or my descendents are selected */
- // return;
- // }
- section.children('ul').slideUp(250, function() {
- section.closest('li').removeClass('expanded');
- resizeNav();
- });
- } else {
- /* show me */
- // first hide all other siblings
- var $others = $('li.nav-section.expanded', $(this).closest('ul'));
- $others.removeClass('expanded').children('ul').slideUp(250);
-
- // now expand me
- section.closest('li').addClass('expanded');
- section.children('ul').slideDown(250, function() {
- resizeNav();
- });
- }
- });
-
- $(".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 (navBarIsFixed) {
- if ((stylesheet.attr("disabled") == "disabled") || stylesheet.length == 0) {
- updateSideNavPosition();
- } else {
- updateSidenavFullscreenWidth();
- }
- }
- resizeNav();
- });
-
-
- // Set up fixed navbar
- var prevScrollLeft = 0; // used to compare current position to previous position of horiz scroll
- $(window).scroll(function(event) {
- if ($('#side-nav').length == 0) return;
- if (event.target.nodeName == "DIV") {
- // Dump scroll event if the target is a DIV, because that means the event is coming
- // from a scrollable div and so there's no need to make adjustments to our layout
- return;
- }
- var scrollTop = $(window).scrollTop();
- var headerHeight = $('#header').outerHeight();
- var subheaderHeight = $('#nav-x').outerHeight();
- var searchResultHeight = $('#searchResults').is(":visible") ?
- $('#searchResults').outerHeight() : 0;
- var totalHeaderHeight = headerHeight + subheaderHeight + searchResultHeight;
- // we set the navbar fixed when the scroll position is beyond the height of the site header...
- var navBarShouldBeFixed = scrollTop > totalHeaderHeight;
- // ... except if the document content is shorter than the sidenav height.
- // (this is necessary to avoid crazy behavior on OSX Lion due to overscroll bouncing)
- if ($("#doc-col").height() < $("#side-nav").height()) {
- navBarShouldBeFixed = false;
- }
-
- var scrollLeft = $(window).scrollLeft();
- // When the sidenav is fixed and user scrolls horizontally, reposition the sidenav to match
- if (navBarIsFixed && (scrollLeft != prevScrollLeft)) {
- updateSideNavPosition();
- prevScrollLeft = scrollLeft;
- }
-
- // Don't continue if the header is sufficently far away
- // (to avoid intensive resizing that slows scrolling)
- if (navBarIsFixed && navBarShouldBeFixed) {
- return;
- }
-
- if (navBarIsFixed != navBarShouldBeFixed) {
- if (navBarShouldBeFixed) {
- // make it fixed
- var width = $('#devdoc-nav').width();
- $('#devdoc-nav')
- .addClass('fixed')
- .css({'width':width+'px'})
- .prependTo('#body-content');
- // add neato "back to top" button
- $('#devdoc-nav a.totop').css({'display':'block','width':$("#nav").innerWidth()+'px'});
-
- // update the sidenaav position for side scrolling
- updateSideNavPosition();
- } else {
- // make it static again
- $('#devdoc-nav')
- .removeClass('fixed')
- .css({'width':'auto','margin':''})
- .prependTo('#side-nav');
- $('#devdoc-nav a.totop').hide();
- }
- navBarIsFixed = navBarShouldBeFixed;
- }
-
- resizeNav(250); // pass true in order to delay the scrollbar re-initialization for performance
- });
-
-
- var navBarLeftPos;
- if ($('#devdoc-nav').length) {
- setNavBarLeftPos();
- }
-
-
- // Stop expand/collapse behavior when clicking on nav section links (since we're navigating away
- // from the page)
- $('.nav-section-header').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,.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);
- }
- }
-
- resizeNav();
-
- /* 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_";
- }
-
-});
-// END of the onload event
-
-
-
-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, 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;
-}
-
-
-addLoadEvent( 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').outerHeight();
- var subheaderHeight = $('#nav-x').outerHeight();
- var headerVisible = (scrollTop < (headerHeight + subheaderHeight));
-
- // 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 + subheaderHeight - 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, null);
-}
-
-
-
-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) return;
-
- var selectedOffset = $selected.position().top;
- if (selectedOffset + 90 > $nav.height()) { // add 90 so that we scroll up even
- // if the current item is close to the bottom
- api.scrollTo(0, selectedOffset - ($nav.height() / 4), false); // scroll the item into view
- // to be 1/4 of the way from the top
- }
- }
-}
-
-
-
-
-
-
-/* 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, expiration) {
- if (val==undefined) return;
- section = section == null ? "_" : "_"+section+"_";
- if (expiration == null) {
- var date = new Date();
- date.setTime(date.getTime()+(10*365*24*60*60*1000)); // default expiration is one week
- expiration = date.toGMTString();
- }
- var cookieValue = cookie_namespace + section + cookie + "=" + val
- + "; expires=" + expiration+"; path=/";
- document.cookie = cookieValue;
-}
-
-/* ######### END COOKIES! ########## */
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-/*
-
-REMEMBER THE PREVIOUS PAGE FOR EACH TAB
-
-function loadLast(cookiePath) {
- var location = window.location.href;
- if (location.indexOf("/"+cookiePath+"/") != -1) {
- return true;
- }
- var lastPage = readCookie(cookiePath + "_lastpage");
- if (lastPage) {
- window.location = lastPage;
- return false;
- }
- return true;
-}
-
-
-
-$(window).unload(function(){
- var path = getBaseUri(location.pathname);
- if (path.indexOf("/reference/") != -1) {
- writeCookie("lastpage", path, "reference", null);
- } else if (path.indexOf("/guide/") != -1) {
- writeCookie("lastpage", path, "guide", null);
- } else if ((path.indexOf("/resources/") != -1) || (path.indexOf("/training/") != -1)) {
- writeCookie("lastpage", path, "resources", null);
- }
-});
-
-*/
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-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");
- });
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-/* 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);
- }
- var date = new Date();
- date.setTime(date.getTime()+(10*365*24*60*60*1000)); // keep this for 10 years
- writeCookie("nav", nav_pref, "reference", date.toGMTString());
-
- $("#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) {
- var date = new Date();
- expires = date.toGMTString(date.setTime(date.getTime()+(10*365*24*60*60*1000)));
- // keep this for 50 years
- //alert("expires: " + expires)
- writeCookie("pref_lang", lang, null, expires);
-
- // ####### 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.parentNode.parentNode);
- var toggleMe = $(".toggle-content-toggleme",div);
- if (div.hasClass("closed")) { // if it's closed, open it
- toggleMe.slideDown();
- $(".toggle-content-text", obj).toggle();
- div.removeClass("closed").addClass("open");
- $(".toggle-content-img", 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", obj).toggle();
- div.removeClass("open").addClass("closed");
- $(".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;
-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;
-
-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 new_suggestion() {
- var $list = $("#search_filtered");
- var $li = $("<li class='jd-autocomplete'></li>");
- $list.append($li);
-
- $li.mousedown(function() {
- window.location = this.firstChild.getAttribute("href");
- });
- $li.mouseover(function() {
- $('#search_filtered li').removeClass('jd-selected');
- $(this).addClass('jd-selected');
- gSelectedIndex = $('#search_filtered li').index(this);
- });
- $li.append('<a></a>');
- $li.attr('class','show-item');
- return $li;
-}
-
-function sync_selection_table(toroot)
-{
- var $list = $("#search_filtered");
- var $li; //list item jquery object
- var i; //list item iterator
-
- // reset the list
- $("li",$list).remove();
-
- //if we have results, make the table visible and initialize result info
- if ((gMatches.length > 0) || (gGoogleMatches.length > 0)) {
- // reveal suggestion list
- $('#search_filtered_div').removeClass('no-display');
- var listIndex = 0; // list index position
-
- // ########### 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();
- set_item_values(toroot, $li, gMatches[i]);
- set_item_selected($li, i == gSelectedIndex);
- }
- }
-
- // ########### GOOGLE RESULTS #############
- if (gGoogleMatches.length > 0) {
- // show header for list
- $list.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();
- set_item_values(toroot, $li, gGoogleMatches[i]);
- set_item_selected($li, i == gSelectedIndex);
- }
- }
-
- //if we have no results, hide the table
- } else {
- $('#search_filtered_div').addClass('no-display');
- }
-}
-
-function search_changed(e, kd, toroot)
-{
- var search = document.getElementById("search_autocomplete");
- var text = search.value.replace(/(^ +)|( +$)/g, '');
-
- // show/hide the close button
- if (text != '') {
- $(".search .close").removeClass("hide");
- } else {
- $(".search .close").addClass("hide");
- }
-
- // 13 = enter
- if (e.keyCode == 13) {
- $('#search_filtered_div').addClass('no-display');
- if (!$('#search_filtered_div').hasClass('no-display') || (gSelectedIndex < 0)) {
- if ($("#searchResults").is(":hidden") && (search.value != "")) {
- // if results aren't showing (and text not empty), return true to allow search to execute
- 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;
- //
- // For now, we're not using AJAX so we respond to every Enter.
- return true;
- }
- } else if (kd && gSelectedIndex >= 0) {
- window.location = $("a",$('#search_filtered li')[gSelectedIndex]).attr("href");
- return false;
- }
- }
- // 38 -- arrow up
- else if (kd && (e.keyCode == 38)) {
- if ($($("#search_filtered li")[gSelectedIndex-1]).hasClass("header")) {
- $('#search_filtered_div li').removeClass('jd-selected');
- gSelectedIndex--;
- $('#search_filtered_div li:nth-child('+(gSelectedIndex+1)+')').addClass('jd-selected');
- }
- if (gSelectedIndex >= 0) {
- $('#search_filtered_div li').removeClass('jd-selected');
- gSelectedIndex--;
- $('#search_filtered_div li:nth-child('+(gSelectedIndex+1)+')').addClass('jd-selected');
- }
- return false;
- }
- // 40 -- arrow down
- else if (kd && (e.keyCode == 40)) {
- if ($($("#search_filtered li")[gSelectedIndex+1]).hasClass("header")) {
- $('#search_filtered_div li').removeClass('jd-selected');
- gSelectedIndex++;
- $('#search_filtered_div li:nth-child('+(gSelectedIndex+1)+')').addClass('jd-selected');
- }
- if ((gSelectedIndex < $("ul#search_filtered li").length-1) ||
- ($($("#search_filtered li")[gSelectedIndex+1]).hasClass("header"))) {
- $('#search_filtered_div li').removeClass('jd-selected');
- gSelectedIndex++;
- $('#search_filtered_div li:nth-child('+(gSelectedIndex+1)+')').addClass('jd-selected');
- }
- return false;
- }
- // if key-up event and not arrow down/up,
- // read the search query and add suggestsions to gMatches
- else if (!kd && (e.keyCode != 40) && (e.keyCode != 38)) {
- gMatches = new Array();
- matchedCount = 0;
- gGoogleMatches = new Array();
- matchedCountGoogle = 0;
- gSelectedIndex = -1;
-
- // 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_results(text, gMatches);
- for (var i=0; i<gMatches.length; i++) {
- var s = gMatches[i];
- }
-
-
- // Search for Google matches
- /*
- * Commented this out because GOOGLE_DATA not defined for us and code
- * causes an error. This probably has to do with the missing
- * gms_lists.js file in SAC. TODO figure it all out.
- *
- 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_results(text, gGoogleMatches);
- for (var i=0; i<gGoogleMatches.length; i++) {
- var s = gGoogleMatches[i];
- }
- */
-
- highlight_autocomplete_result_labels(text);
- sync_selection_table(toroot);
-
-
- return true; // allow the event to bubble up to the search api
- }
-}
-
-/* Order the result list based on match quality */
-function rank_autocomplete_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++) {
- 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");
- }
- document.getElementById("search_filtered_div").className = "no-display";
- }
-}
-
-function submit_search() {
- var query = document.getElementById('search_autocomplete').value;
- location.hash = 'q=' + query;
- loadSearchResults();
- $("#searchResults").slideDown('slow');
- return false;
-}
-
-
-function hideResults() {
- $("#searchResults").slideUp();
- $(".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) {});
- return false;
-}
-
-
-/* ########################################################## */
-/* ################ CUSTOM SEARCH ENGINE ################## */
-/* ########################################################## */
-
-// TODO, add localized search.
-function getLangPref() {
- return "en";
-}
-
-// Package of functions that does custom search, from DAC redesign.
-(function($) {
- var LANG;
-
- function getSearchLang() {
- if (!LANG) {
- LANG = getLangPref();
-
- // Fix zh-cn to be zh-CN.
- LANG = LANG.replace(/-\w+/, function(m) { return m.toUpperCase(); });
- }
- return LANG;
- }
-
- function customSearch(query, start) {
- var searchParams = {
- // Keys for SAC
- cx:'016258643462168859875:qqpm8fiwgc0',
- key: 'AIzaSyBOWHD3JAF6Q9LIJ4NiahGAF70W7iDAI9M',
-
- // Keys for DAC
- // cx: '000521750095050289010:zpcpi1ea4s8',
- // key: 'AIzaSyCFhbGnjW06dYwvRCU8h_zjdpS4PYYbEe8',
-
- q: query,
- start: start || 1,
- num: 6,
- hl: getSearchLang(),
- fields: 'queries,items(pagemap,link,title,htmlSnippet,formattedUrl)'
- };
-
- return $.get('https://content.googleapis.com/customsearch/v1?' + $.param(searchParams));
- }
-
- function renderResults(el, results) {
- if (!results.items) {
- el.append($('<div>').text('No results'));
- return;
- }
-
- for (var i = 0; i < results.items.length; i++) {
- var item = results.items[i];
- // No thumbnail images in SAC.
- // var hasImage = item.pagemap && item.pagemap.cse_thumbnail;
- var sectionMatch = item.link.match(/source\.android\.com\/(\w*)/);
- var section = (sectionMatch && sectionMatch[1]) || 'blog';
-
- var entry = $('<div>').addClass('dac-custom-search-entry cols');
-
-// No thumbnail images in SAC.
-// if (hasImage) {
-// var image = item.pagemap.cse_thumbnail[0];
-// entry.append($('<div>').addClass('col-1of6')
-// .append($('<div>').addClass('dac-custom-search-image').css('background-image', 'url(' + image.src + ')')));
-// }
-// entry.append($('<div>').addClass(hasImage ? 'col-5of6' : 'col-6of6')
- entry.append($('<div>')
- .append($('<p>').addClass('dac-custom-search-section').text(section))
- .append(
- $('<a>').text(item.title).attr('href', item.link).wrap('<h2>').parent().addClass('dac-custom-search-title')
- )
- .append($('<p>').addClass('dac-custom-search-snippet').html(item.htmlSnippet.replace(/<br>/g, '')))
- .append($('<a>').addClass('dac-custom-search-link').text(item.formattedUrl).attr('href', item.link)));
-
- el.append(entry);
- }
-
- if (results.queries.nextPage) {
- var loadMoreButton = $('<button id="dac-custom-search-load-more">')
- .addClass('dac-custom-search-load-more')
- .text('Load more')
- .click(function() {
- loadMoreResults(el, results);
- });
-
- el.append(loadMoreButton);
- }
- }
-
- function loadMoreResults(el, results) {
- var query = results.queries.request.searchTerms;
- var start = results.queries.nextPage.startIndex;
- var loadMoreButton = el.find('#dac-custom-search-load-more');
-
- loadMoreButton.text('Loading more...');
-
- customSearch(query, start).then(function(results) {
- loadMoreButton.remove();
- renderResults(el, results);
- });
- }
-
- $.fn.customSearch = function(query) {
- var el = $(this);
-
- customSearch(query).then(function(results) {
- el.empty();
- renderResults(el, results);
- });
- };
-})(jQuery);
-
-
-function loadSearchResults() {
-
- // Draw the search results box
- //searchControl.draw(document.getElementById("leftSearchControl"), drawOptions);
- $(searchResults).append('<div class="leftSearchControl"></div>');
-
-
- // Refresh the url and search title
- var query = document.getElementById('search_autocomplete').value || getQuery(location.hash);
- updateResultTitle(query);
- location.hash = 'q=' + query;
-
- // get query and execute the search
- //searchControl.execute(decodeURI(getQuery(location.hash)));
- $(leftSearchControl).customSearch(getQuery(location.hash));
-
- document.getElementById("search_autocomplete").focus();
- addTabListeners();
-}
-// End of loadSearchResults
-
-google.setOnLoadCallback(function(){
-
- var query = decodeURI(getQuery(location.hash));
- if (location.hash.indexOf("q=") == -1 || query == '') {
- // 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');
- $(".search .close").removeClass("hide");
- loadSearchResults();
- }
-}, true);
-
-// when an event on the browser history occurs (back, forward, load) requery hash and do search
-$(window).hashchange( function(){
- // Exit if the hash isn't a search query or there's an error in the query
- if ((location.hash.indexOf("q=") == -1) || (query == "undefined")) {
- // If the results pane is open, close it.
- if (!$("#searchResults").is(":hidden")) {
- hideResults();
- }
- return;
- }
-
- // Otherwise, we have a search to do
- var query = decodeURI(getQuery(location.hash));
- //searchControl.execute(query);
- $('#leftSearchControl').customSearch(query);
- $('#searchResults').slideDown('slow');
- $("#search_autocomplete").focus();
- $(".search .close").removeClass("hide");
-
- updateResultTitle(query);
-});
-
-function updateResultTitle(query) {
- $("#searchTitle").html("Results for <em>" + encodeURIComponent(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);
-}
-
-
-function getQuery(hash) {
- var queryParts = hash.split('=');
- return queryParts[1];
-}
-
-
-/* ######################################################## */
-/* ################# JAVADOC REFERENCE ################### */
-/* ######################################################## */
-
-/* Initialize some droiddoc stuff, but only if we're in the reference */
-if (location.pathname.indexOf("/reference")) {
- if(!location.pathname.indexOf("/reference-gms/packages.html")
- && !location.pathname.indexOf("/reference-gcm/packages.html")
- && !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 (!navBarIsFixed) 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 (!navBarIsFixed) 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);
-// Another piece of functionality that we don't use that produces an error.
-// TODO figure it all out.
-// selectedLevelItem.setAttribute('selected',true);
-}
-
-function changeApiLevel() {
- maxLevel = SINCE_DATA.length;
- var selectedLevel = maxLevel;
-
- selectedLevel = parseInt($("#apiLevelSelector option:selected").val());
- toggleVisisbleApis(selectedLevel, "body");
-
- var date = new Date();
- date.setTime(date.getTime()+(10*365*24*60*60*1000)); // keep this for 10 years
- var expiration = date.toGMTString();
- writeCookie(API_LEVEL_COOKIE, selectedLevel, null, expiration);
-
- 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");
- }
- 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) {
- 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);
- }
- else if(linkText.match("^"+"com.android")=="com.android"){
- linkText = linkText.substr(12, linkText.length);
- }
- mom.children[i] = new_google_node(me, mom, linkText, node_data[1],
- node_data[2], node_data[3]);
- }
-}
-function showGoogleRefTree() {
- init_default_google_navtree(toRoot);
- init_default_gcm_navtree(toRoot);
- resizeNav();
-}
-
-
-function showTradefedRefTree() {
- init_default_tradefed_navtree(toRoot);
- resizeNav();
-}
-
-function init_default_google_navtree(toroot) {
- init_google_navtree("gms-tree-list", toroot, GMS_NAVTREE_DATA);
-}
-
-function init_default_gcm_navtree(toroot) {
- init_google_navtree("gcm-tree-list", toroot, GCM_NAVTREE_DATA);
-}
-
-function init_default_tradefed_navtree(toroot) {
- init_google_navtree("tradefed-tree-list", toroot, NAVTREE_DATA);
-}
-
-/* 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();
- }
-});
diff --git a/tools/droiddoc/templates-sac/assets/js/prettify.js b/tools/droiddoc/templates-sac/assets/js/prettify.js
deleted file mode 100644
index eef5ad7..0000000
--- a/tools/droiddoc/templates-sac/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-sac/class.cs b/tools/droiddoc/templates-sac/class.cs
deleted file mode 100644
index 98633fb..0000000
--- a/tools/droiddoc/templates-sac/class.cs
+++ /dev/null
@@ -1,658 +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
- 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, "<span class='annotation-message'>", "</span><span class='annotation-message'>", "</span>") ?>
-
-</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) ?></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 each:anno = field.showAnnotations ?>
- <?cs call:show_annotations_list(field, "<span class='annotation-message'>", "</span><span class='annotation-message'>", "</span>") ?>
- <?cs /each ?></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) ?></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) ?> </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) ?> </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) ?> </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: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: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: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-sac/classes.cs b/tools/droiddoc/templates-sac/classes.cs
deleted file mode 100644
index 6769f47..0000000
--- a/tools/droiddoc/templates-sac/classes.cs
+++ /dev/null
@@ -1,47 +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
- 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) ?> </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-sac/components/masthead.cs b/tools/droiddoc/templates-sac/components/masthead.cs
deleted file mode 100644
index ee2582f..0000000
--- a/tools/droiddoc/templates-sac/components/masthead.cs
+++ /dev/null
@@ -1,334 +0,0 @@
-<?cs def:custom_masthead() ?>
- <!-- Header -->
- <div id="header">
- <div class="wrap" id="header-wrap">
- <div class="col-3 logo">
- <a href="<?cs var:toroot ?>index.html">
- <img src="<?cs var:toroot ?>assets/images/dac_logo.png" width="123" height="25" alt="Android Developers" />
- </a>
- <div class="btn-quicknav" id="btn-quicknav">
- <a href="#" class="arrow-inactive">Quicknav</a>
- <a href="#" class="arrow-active">Quicknav</a>
- </div>
- </div>
- <ul class="nav-x col-9">
- <li class="design">
- <a href="<?cs var:toroot ?>design/index.html"
- zh-TW-lang="設計"
- zh-CN-lang="设计"
- ru-lang="Проектирование"
- ko-lang="디자인"
- ja-lang="設計"
- es-lang="Diseñar"
- >Design</a></li>
- <li class="develop"><a href="<?cs var:toroot ?>develop/index.html"
- zh-TW-lang="開發"
- zh-CN-lang="开发"
- ru-lang="Разработка"
- ko-lang="개발"
- ja-lang="開発"
- es-lang="Desarrollar"
- >Develop</a></li>
- <li class="distribute last"><a href="<?cs var:toroot ?>distribute/index.html"
- zh-TW-lang="發佈"
- zh-CN-lang="分发"
- ru-lang="Распространение"
- ko-lang="배포"
- ja-lang="配布"
- es-lang="Distribuir"
- >Distribute</a></li>
- </ul>
-
- <!-- New Search -->
- <div class="menu-container">
- <div class="moremenu">
- <div id="more-btn"></div>
- </div>
- <div class="morehover" id="moremenu">
- <div class="top"></div>
- <div class="mid">
- <div class="header">Links</div>
- <ul>
- <li><a href="https://play.google.com/apps/publish/">Google Play Developer Console</a></li>
- <li><a href="http://android-developers.blogspot.com/">Android Developers Blog</a></li>
- <li><a href="<?cs var:toroot ?>about/index.html">About Android</a></li>
- </ul>
- <div class="header">Android Sites</div>
- <ul>
- <li><a href="http://www.android.com">Android.com</a></li>
- <li class="active"><a>Android Developers</a></li>
- <li><a href="http://source.android.com">Android Open Source Project</a></li>
- </ul>
-
-<?cs ############ TODO: Remove when we're happy with Devsite ############# ?>
- <?cs # Use differenc lang switcher for devsite and gae server ?>
- <?cs if:devsite ?>
- <div class="header">Language</div>
- <?cs elif: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 devsite vs. gae version of lang switcher ?>
-
-
- <br class="clearfix" />
- </div>
- <div class="bottom"></div>
- </div>
- <div class="search" id="search-container">
- <div class="search-inner">
- <div id="search-btn"></div>
- <div class="left"></div>
- <form onsubmit="return submit_search()">
- <input id="search_autocomplete" type="text" value="" autocomplete="off" name="q"
-onfocus="search_focus_changed(this, true)" onblur="search_focus_changed(this, false)"
-onkeydown="return search_changed(event, true, '<?cs var:toroot ?>')"
-onkeyup="return search_changed(event, false, '<?cs var:toroot ?>')" />
- </form>
- <div class="right"></div>
- <a class="close hide">close</a>
- <div class="left"></div>
- <div class="right"></div>
- </div>
- </div>
- <div id="search_filtered_wrapper">
- <div id="search_filtered_div" class="no-display">
- <ul id="search_filtered">
- </ul>
- </div>
- </div>
-
- </div>
- <!-- /New Search>
-
-
- <!-- Expanded quicknav -->
- <div id="quicknav" class="col-9">
- <ul>
- <li class="design">
- <ul>
- <li><a href="<?cs var:toroot ?>design/index.html">Get Started</a></li>
- <li><a href="<?cs var:toroot ?>design/style/index.html">Style</a></li>
- <li><a href="<?cs var:toroot ?>design/patterns/index.html">Patterns</a></li>
- <li><a href="<?cs var:toroot ?>design/building-blocks/index.html">Building Blocks</a></li>
- <li><a href="<?cs var:toroot ?>design/downloads/index.html">Downloads</a></li>
- <li><a href="<?cs var:toroot ?>design/videos/index.html">Videos</a></li>
- </ul>
- </li>
- <li class="develop">
- <ul>
- <li><a href="<?cs var:toroot ?>training/index.html"
- zh-TW-lang="訓練課程"
- zh-CN-lang="培训"
- ru-lang="Курсы"
- ko-lang="교육"
- ja-lang="トレーニング"
- es-lang="Capacitación"
- >Training</a></li>
- <li><a href="<?cs var:toroot ?>guide/components/index.html"
- zh-TW-lang="API 指南"
- zh-CN-lang="API 指南"
- ru-lang="Руководства по API"
- ko-lang="API 가이드"
- ja-lang="API ガイド"
- es-lang="Guías de la API"
- >API Guides</a></li>
- <li><a href="<?cs var:toroot ?>reference/packages.html"
- zh-TW-lang="參考資源"
- zh-CN-lang="参考"
- ru-lang="Справочник"
- ko-lang="참조문서"
- ja-lang="リファレンス"
- es-lang="Referencia"
- >Reference</a></li>
- <li><a href="<?cs var:toroot ?>tools/index.html"
- zh-TW-lang="相關工具"
- zh-CN-lang="工具"
- ru-lang="Инструменты"
- ko-lang="도구"
- ja-lang="ツール"
- es-lang="Herramientas"
- >Tools</a>
- <ul><li><a href="<?cs var:toroot ?>sdk/index.html">Get the SDK</a></li></ul>
- </li>
- <li><a href="<?cs var:toroot ?>google/index.html">Google Services</a>
- </li>
- </ul>
- </li>
- <li class="distribute last">
- <ul>
- <li><a href="<?cs var:toroot ?>distribute/index.html">Google Play</a></li>
- <li><a href="<?cs var:toroot ?>distribute/googleplay/publish/index.html">Publishing</a></li>
- <li><a href="<?cs var:toroot ?>distribute/googleplay/promote/index.html">Promoting</a></li>
- <li><a href="<?cs var:toroot ?>distribute/googleplay/quality/index.html">App Quality</a></li>
- <li><a href="<?cs var:toroot ?>distribute/googleplay/spotlight/index.html">Spotlight</a></li>
- <li><a href="<?cs var:toroot ?>distribute/open.html">Open Distribution</a></li>
- </ul>
- </li>
- </ul>
- </div>
- <!-- /Expanded quicknav -->
- </div>
- </div>
- <!-- /Header -->
-
-
- <div id="searchResults" class="wrap" style="display:none;">
- <h2 id="searchTitle">Results</h2>
- <div id="leftSearchControl" class="search-control">Loading...</div>
- </div>
-
-
-
-<?cs if:training || guide || reference || tools || develop || google ?>
- <!-- Secondary x-nav -->
- <div id="nav-x">
- <div class="wrap">
- <ul class="nav-x col-9 develop" style="width:100%">
- <li class="training"><a href="<?cs var:toroot ?>training/index.html"
- zh-TW-lang="訓練課程"
- zh-CN-lang="培训"
- ru-lang="Курсы"
- ko-lang="교육"
- ja-lang="トレーニング"
- es-lang="Capacitación"
- >Training</a></li>
- <li class="guide"><a href="<?cs var:toroot ?>guide/components/index.html"
- zh-TW-lang="API 指南"
- zh-CN-lang="API 指南"
- ru-lang="Руководства по API"
- ko-lang="API 가이드"
- ja-lang="API ガイド"
- es-lang="Guías de la API"
- >API Guides</a></li>
- <li class="reference"><a href="<?cs var:toroot ?>reference/packages.html"
- zh-TW-lang="參考資源"
- zh-CN-lang="参考"
- ru-lang="Справочник"
- ko-lang="참조문서"
- ja-lang="リファレンス"
- es-lang="Referencia"
- >Reference</a></li>
- <li class="tools"><a href="<?cs var:toroot ?>tools/index.html"
- zh-TW-lang="相關工具"
- zh-CN-lang="工具"
- ru-lang="Инструменты"
- ko-lang="도구"
- ja-lang="ツール"
- es-lang="Herramientas"
- >Tools</a></li>
- <li class="google"><a href="<?cs var:toroot ?>google/index.html"
- >Google Services</a>
- </li>
- </ul>
- </div>
-
- </div>
- <!-- /Sendondary x-nav -->
-<?cs /if ?>
- <?cs
-/def ?>
-
-
-
-
-<?cs def:sac_masthead() ?>
- <!-- Header -->
- <div id="header">
- <div class="wrap" id="header-wrap">
- <div class="col-3 saclogo">
- <a href="<?cs var:toroot ?>index.html">
- <img src="<?cs var:toroot ?>assets/images/sac_logo.png"
- srcset="<?cs var:toroot ?>assets/images/sac_logo@2x.png 2x"
- width="123" height="25" alt="Android Open Source Project" />
- </a>
- </div>
- <ul class="nav-x col-9">
- <li class="source">
- <a href="<?cs var:toroot ?>source/index.html" <?cs
- if:source ?>class="selected"<?cs /if ?>
- >Source</a></li>
- <li class="devices"><a href="<?cs var:toroot ?>devices/index.html" <?cs
- if:devices ?>class="selected"<?cs /if ?>
- >Devices</a></li>
- <li class="security"><a href="<?cs var:toroot ?>security/index.html" <?cs
- if:security ?>class="selected"<?cs /if ?>
- >Security</a></li>
- <li class="compatibility last"><a href="<?cs var:toroot ?>compatibility/index.html" <?cs
- if:compatibility ?>class="selected"<?cs /if ?>
- >Compatibility</a></li>
- </ul>
- <!-- New Search -->
- <div class="menu-container">
- <div class="moremenu">
- <div id="more-btn"></div>
- </div>
- <div class="morehover" id="moremenu">
- <div class="top"></div>
- <div class="mid">
- <div class="header">Android Sites</div>
- <ul>
- <li class="active"><a>Android Open Source Project</a></li>
- <li><a href="http://www.android.com">Android.com</a></li>
- <li><a href="http://developer.android.com">Android Developers</a></li>
- </ul>
- <!-- <div class="header">Support</div>
- <ul>
- <li><a href="<?cs var:toroot ?>support.html">Developer Support</a></li>
- </ul> -->
- <br class="clearfix" />
- </div>
- <div class="bottom"></div>
- </div>
-
- <div class="search" id="search-container">
- <div class="search-inner">
- <div id="search-btn"></div>
- <div class="left"></div>
- <form onsubmit="return submit_search()">
- <input id="search_autocomplete" type="text" value="" autocomplete="off" name="q"
-onfocus="search_focus_changed(this, true)" onblur="search_focus_changed(this, false)"
-onkeydown="return search_changed(event, true, '<?cs var:toroot ?>')"
-onkeyup="return search_changed(event, false, '<?cs var:toroot ?>')" />
- </form>
- <div class="right"></div>
- <a class="close hide">close</a>
- <div class="left"></div>
- <div class="right"></div>
- </div>
- </div>
- <div id="search_filtered_wrapper">
- <div id="search_filtered_div" class="no-display">
- <ul id="search_filtered">
- </ul>
- </div>
- </div>
-
- </div>
- <!-- /New Search> -->
- </div>
- </div>
- <!-- /Header -->
-
- <div id="searchResults" class="wrap" style="display:none;">
- <h2 id="searchTitle">Results</h2>
- <div id="leftSearchControl" class="search-control">Loading...</div>
- </div>
-
- <?cs
-/def ?>
diff --git a/tools/droiddoc/templates-sac/customizations.cs b/tools/droiddoc/templates-sac/customizations.cs
deleted file mode 100644
index 01d3d72..0000000
--- a/tools/droiddoc/templates-sac/customizations.cs
+++ /dev/null
@@ -1,471 +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">
-<a class="totop" href="#top" data-g-event="left-nav-top">to top</a>
-
-<?cs
- include:"../../../../../frameworks/base/docs/html/sdk/sdk_toc.cs" ?>
-
-
- </div>
- </div> <!-- end side-nav -->
-<?cs /def ?>
-<?cs
-def:resources_tab_nav() ?>
- <div class="wrap clearfix" id="body-content">
- <a
- <div class="col-4" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement">
- <div id="devdoc-nav" class="scroll-pane">
-<a class="totop" href="#top" data-g-event="left-nav-top">to top</a>
-
-<?cs
- include:"../../../../../frameworks/base/docs/html/resources/resources_toc.cs" ?>
-
-
- </div>
- </div> <!-- end side-nav -->
- <script>
- $(document).ready(function() {
- scrollIntoView("devdoc-nav");
- });
- </script>
-<?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">
-<a class="totop" href="#top" data-g-event="left-nav-top">to top</a>
-<?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: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">
-<a class="totop" href="#top" data-g-event="left-nav-top">to top</a>
-
-
-<?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:guide_nav() ?>
- <div class="wrap clearfix" id="body-content">
- <div class="col-4" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement">
- <div id="devdoc-nav" class="scroll-pane">
-<a class="totop" href="#top" data-g-event="left-nav-top">to top</a>
-
-
-<?cs
- include:"../../../../../frameworks/base/docs/html/guide/guide_toc.cs" ?>
-
-
- </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">
-<a class="totop" href="#top" data-g-event="left-nav-top">to top</a>
-
-
-<?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">
-<a class="totop" href="#top" data-g-event="left-nav-top">to top</a>
-
-<?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:google_nav() ?>
- <div class="wrap clearfix" id="body-content">
- <div class="col-4" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement">
- <div id="devdoc-nav" class="scroll-pane">
-<a class="totop" href="#top" data-g-event="left-nav-top">to top</a>
-
-<?cs
- include:"../../../../../frameworks/base/docs/html/google/google_toc.cs" ?>
-
-
- </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">
-<a class="totop" href="#top" data-g-event="left-nav-top">to top</a>
-
-<?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:dist_more_nav() ?>
- <div class="wrap clearfix" id="body-content">
- <div class="col-4" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement">
- <div id="devdoc-nav" class="scroll-pane">
-<a class="totop" href="#top" data-g-event="left-nav-top">to top</a>
-
-
-<?cs
- include:"../../../../../frameworks/base/docs/html/distribute/more/more_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">
-
-<a class="totop" href="#top" data-g-event="left-nav-top">to top</a>
- <div id="api-nav-header">
- <div id="api-level-toggle">
- <label for="apiLevelCheckbox" class="disabled">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("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("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:custom_left_nav() ?><?cs
- if:fullpage ?><?cs
- call:fullpage() ?><?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:more ?><?cs
- call:dist_more_nav() ?><?cs
- elif:distribute ?><?cs
- call:distribute_nav() ?><?cs
- elif:about ?><?cs
- call:about_nav() ?><?cs
- else ?><?cs
- call:default_left_nav() ?> <?cs
- /if ?><?cs
-/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 ?>source/index.html">About Android</a> |
- <a href="<?cs var:toroot ?>source/community.html">Community</a> |
- <a href="<?cs var:toroot ?>legal.html">Legal</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.gms && !reference.gcm?>
- 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 ?>
-
-
-
-<?cs #------------------- s.a.c specific templating ---------------------------?>
-
-<?cs
-def:sac_left_nav() ?>
- <?cs if:devices ?>
- <?cs call:devices_nav() ?>
- <?cs elif:compatibility ?>
- <?cs call:compatibility_nav() ?>
- <?cs elif:source ?>
- <?cs call:source_nav() ?>
- <?cs elif:security ?>
- <?cs call:security_nav() ?>
- <?cs elif:reference ?>
- <?cs call:default_left_nav() ?>
- <?cs /if ?>
-<?cs /def ?>
-
-<?cs
-def:devices_nav() ?>
- <div class="wrap clearfix" id="body-content">
- <div class="col-4" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement">
- <div id="devdoc-nav" class="scroll-pane">
-<a class="totop" href="#top" data-g-event="left-nav-top">to top</a>
-
-<?cs
- include:"../../../../../docs/source.android.com/src/devices/devices_toc.cs" ?>
-
- </div>
- <script type="text/javascript">
- showTradefedRefTree();
- </script>
- </div> <!-- end side-nav -->
- <script>
- $(document).ready(function() {
- scrollIntoView("devdoc-nav");
- });
- </script>
-<?cs /def ?>
-
-<?cs
-def:compatibility_nav() ?>
- <div class="wrap clearfix" id="body-content">
- <div class="col-4" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement">
- <div id="devdoc-nav" class="scroll-pane">
-<a class="totop" href="#top" data-g-event="left-nav-top">to top</a>
-
-<?cs
- include:"../../../../../docs/source.android.com/src/compatibility/compatibility_toc.cs" ?>
-
- </div>
- </div> <!-- end side-nav -->
- <script>
- $(document).ready(function() {
- scrollIntoView("devdoc-nav");
- });
- </script>
-<?cs /def ?>
-
-<?cs
-def:source_nav() ?>
- <div class="wrap clearfix" id="body-content">
- <div class="col-4" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement">
- <div id="devdoc-nav" class="scroll-pane">
-<a class="totop" href="#top" data-g-event="left-nav-top">to top</a>
-
-<?cs
- include:"../../../../../docs/source.android.com/src/source/source_toc.cs" ?>
-
- </div>
- </div> <!-- end side-nav -->
- <script>
- $(document).ready(function() {
- scrollIntoView("devdoc-nav");
- });
- </script>
-<?cs /def ?>
-
-<?cs
-def:security_nav() ?>
- <div class="wrap clearfix" id="body-content">
- <div class="col-4" id="side-nav" itemscope itemtype="http://schema.org/SiteNavigationElement">
- <div id="devdoc-nav" class="scroll-pane">
-<a class="totop" href="#top" data-g-event="left-nav-top">to top</a>
-
-<?cs
- include:"../../../../../docs/source.android.com/src/security/security_toc.cs" ?>
-
- </div>
- </div> <!-- end side-nav -->
- <script>
- $(document).ready(function() {
- scrollIntoView("devdoc-nav");
- });
- </script>
-<?cs /def ?>
-
-
diff --git a/tools/droiddoc/templates-sac/data.hdf b/tools/droiddoc/templates-sac/data.hdf
deleted file mode 100644
index 9411b78..0000000
--- a/tools/droiddoc/templates-sac/data.hdf
+++ /dev/null
@@ -1,4 +0,0 @@
-template {
- which = normal
-}
-
diff --git a/tools/droiddoc/templates-sac/designpage.cs b/tools/droiddoc/templates-sac/designpage.cs
deleted file mode 100644
index c5f03ff..0000000
--- a/tools/droiddoc/templates-sac/designpage.cs
+++ /dev/null
@@ -1,90 +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>
- </body>
-</html>
diff --git a/tools/droiddoc/templates-sac/docpage.cs b/tools/droiddoc/templates-sac/docpage.cs
deleted file mode 100644
index 3d120b6..0000000
--- a/tools/droiddoc/templates-sac/docpage.cs
+++ /dev/null
@@ -1,164 +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:(google || reference.gms || reference.gcm) ?>google<?cs /if ?>
- <?cs if:(guide||develop||training||reference||tools||sdk) ?>develop<?cs if:guide ?> guide<?cs /if ?><?cs
- elif:about ?>about<?cs
- elif:design ?>design<?cs
- elif:distribute ?>distribute<?cs
- /if ?><?cs
- if:page.trainingcourse ?> trainingcourse<?cs /if ?>" itemscope itemtype="http://schema.org/Article">
-<a name="top"></a>
-<?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 ?> >
-
-<?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 else ?>
- <?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's 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-sac"
- 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">
- </div>
- <?cs if:!fullscreen ?>
- <div class="paging-links layout-content-col col-4">
- <?cs if:(design||training||guide||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-sac/footer.cs b/tools/droiddoc/templates-sac/footer.cs
deleted file mode 100644
index e43adb0..0000000
--- a/tools/droiddoc/templates-sac/footer.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-<div id="footer" class="wrap" <?cs if:fullpage ?>style="width:940px"<?cs /if ?>>
- <style>.feedback { float: right !Important }</style>
- <div class="feedback">
- <a href="#" class="button" onclick=" try {
- userfeedback.api.startFeedback({'productId':'715571','authuser':'1'});return false;}catch(e){}">Site Feedback</a>
- </div>
- <div id="copyright">
- <?cs call:custom_cc_copyright() ?>
- </div>
- <div id="footerlinks">
- <?cs call:custom_footerlinks() ?>
- </div>
diff --git a/tools/droiddoc/templates-sac/gcm_navtree_data.cs b/tools/droiddoc/templates-sac/gcm_navtree_data.cs
deleted file mode 100644
index 6f33d88..0000000
--- a/tools/droiddoc/templates-sac/gcm_navtree_data.cs
+++ /dev/null
@@ -1,3 +0,0 @@
-var GCM_NAVTREE_DATA =
-<?cs var:reference_tree ?>
-;
diff --git a/tools/droiddoc/templates-sac/gms_navtree_data.cs b/tools/droiddoc/templates-sac/gms_navtree_data.cs
deleted file mode 100644
index 66b7d55..0000000
--- a/tools/droiddoc/templates-sac/gms_navtree_data.cs
+++ /dev/null
@@ -1,3 +0,0 @@
-var GMS_NAVTREE_DATA =
-<?cs var:reference_tree ?>
-;
diff --git a/tools/droiddoc/templates-sac/head_tag.cs b/tools/droiddoc/templates-sac/head_tag.cs
deleted file mode 100644
index b672b25..0000000
--- a/tools/droiddoc/templates-sac/head_tag.cs
+++ /dev/null
@@ -1,62 +0,0 @@
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-<?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 Open Source Project</title>
-
-<!-- STYLESHEETS -->
-<link rel="stylesheet"
-href="<?cs if:android.whichdoc != 'online' ?>http:<?cs /if ?>//fonts.googleapis.com/css?family=Roboto:regular,medium,thin,italic,mediumitalic,bold" title="roboto">
-<link href="<?cs var:toroot ?>assets/css/default.css" rel="stylesheet" type="text/css">
-
-<?cs if:reference && !(reference.gms || reference.gcm || sac) ?>
-<!-- FULLSCREEN STYLESHEET -->
-<link href="<?cs var:toroot ?>assets/css/fullscreen.css" rel="stylesheet" class="fullscreen"
-type="text/css">
-<?cs /if ?>
-
-<!-- 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 ?>
-<script type="text/javascript">
- var toRoot = "<?cs var:toroot ?>";
- <?cs if:devsite ?>
- var devsite = true;
- <?cs else ?>
- var devsite = false;
- <?cs /if ?>
-</script>
-<script src="<?cs var:toroot ?>assets/js/docs.js" type="text/javascript"></script>
-<?cs if:reference.gms || reference.gcm || google?>
-<script src="<?cs var:toroot ?>gms_navtree_data.js" async type="text/javascript"></script>
-<script src="<?cs var:toroot ?>gcm_navtree_data.js" async type="text/javascript"></script>
-<?cs elif:devices ?>
-<script src="<?cs var:toroot ?>navtree_data.js" type="text/javascript"></script>
-<?cs elif:reference ?>
-<script src="<?cs var:toroot ?>navtree_data.js" async type="text/javascript"></script>
-<?cs /if ?>
-
-<script type="text/javascript" src="//www.gstatic.com/feedback/api.js"></script>
-
-<script type="text/javascript">
- var _gaq = _gaq || [];
- _gaq.push(['_setAccount', 'UA-45455297-1']);
- _gaq.push(['_trackPageview']);
-
- (function() {
- var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
- ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
- var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
- })();
-</script>
-</head>
diff --git a/tools/droiddoc/templates-sac/header.cs b/tools/droiddoc/templates-sac/header.cs
deleted file mode 100644
index ebb7bc0..0000000
--- a/tools/droiddoc/templates-sac/header.cs
+++ /dev/null
@@ -1,7 +0,0 @@
-<?cs if:sac ?>
- <?cs call:sac_masthead() ?>
- <?cs call:sac_left_nav() ?>
-<?cs else ?>
- <?cs call:custom_masthead() ?>
- <?cs call:custom_left_nav() ?>
-<?cs /if ?>
diff --git a/tools/droiddoc/templates-sac/header_tabs.cs b/tools/droiddoc/templates-sac/header_tabs.cs
deleted file mode 100644
index 38c9da8..0000000
--- a/tools/droiddoc/templates-sac/header_tabs.cs
+++ /dev/null
@@ -1,2 +0,0 @@
-
-<!-- CURRENTLY NOT USED... ALL TABS ARE IN masthead.cs -->
diff --git a/tools/droiddoc/templates-sac/jd_lists_unified.cs b/tools/droiddoc/templates-sac/jd_lists_unified.cs
deleted file mode 100644
index 417a5c1..0000000
--- a/tools/droiddoc/templates-sac/jd_lists_unified.cs
+++ /dev/null
@@ -1 +0,0 @@
-<?cs var:reference_tree ?>
diff --git a/tools/droiddoc/templates-sac/navtree_data.cs b/tools/droiddoc/templates-sac/navtree_data.cs
deleted file mode 100644
index 73aa199..0000000
--- a/tools/droiddoc/templates-sac/navtree_data.cs
+++ /dev/null
@@ -1,3 +0,0 @@
-var NAVTREE_DATA =
-<?cs var:reference_tree ?>
-;
diff --git a/tools/droiddoc/templates-sac/nosidenavpage.cs b/tools/droiddoc/templates-sac/nosidenavpage.cs
deleted file mode 100644
index 8e59693..0000000
--- a/tools/droiddoc/templates-sac/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-sac/package.cs b/tools/droiddoc/templates-sac/package.cs
deleted file mode 100644
index abd49f1..0000000
--- a/tools/droiddoc/templates-sac/package.cs
+++ /dev/null
@@ -1,62 +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
- 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-sac/packages.cs b/tools/droiddoc/templates-sac/packages.cs
deleted file mode 100644
index 44680c3..0000000
--- a/tools/droiddoc/templates-sac/packages.cs
+++ /dev/null
@@ -1,43 +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
- 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-sac/sampleindex.cs b/tools/droiddoc/templates-sac/sampleindex.cs
deleted file mode 100644
index a173363..0000000
--- a/tools/droiddoc/templates-sac/sampleindex.cs
+++ /dev/null
@@ -1,53 +0,0 @@
-<?cs include:"doctype.cs" ?>
-<?cs include:"macros.cs" ?>
-<?cs set:resources="true" ?>
-<html<?cs if:devsite ?> devsite<?cs /if ?>>
-<?cs include:"head_tag.cs" ?>
-<?cs include:"header.cs" ?>
-<body class="gc-documentation">
-
-
-<a name="top"></a>
-<div class="g-unit" id="doc-content">
- <div id="jd-header" class="guide-header">
- <span class="crumb">
- <a href="<?cs var:toroot ?>resources/browser.html?tag=sample">Sample Code</a> >
- </span>
- <h1><?cs var:page.title ?></h1>
- </div>
-
-<div id="jd-content">
-<p><a href="../index.html">← Back</a></p>
-
-<?cs var:summary ?>
-
- <?cs if:subcount(subdirs) ?>
- <h2>Subdirectories</h2>
- <ul class="nolist">
- <?cs each:dir=subdirs ?>
- <li><a href="<?cs var:dir.name ?>/index.html"><?cs
- var:dir.name ?>/</a></li>
- <?cs /each ?>
- </ul>
- <?cs /if ?>
-
- <?cs if:subcount(files) ?>
- <h2>Files</h2>
- <ul class="nolist">
- <?cs each:file=files ?>
- <li><a href="<?cs var:file.href ?>"><?cs
- var:file.name ?></a></li>
- <?cs /each ?>
- </ul>
- <?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-sac/sdkpage.cs b/tools/droiddoc/templates-sac/sdkpage.cs
deleted file mode 100644
index decfd26..0000000
--- a/tools/droiddoc/templates-sac/sdkpage.cs
+++ /dev/null
@@ -1,491 +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>Size</th>
- <th>MD5 Checksum</th>
- </tr>
- <tr>
- <td>Windows</td>
- <td>
- <a onClick="return onDownload(this)"
- href="http://dl.google.com/android/ndk/<?cs var:ndk.win_download ?>"><?cs var:ndk.win_download ?></a>
- </td>
- <td><?cs var:ndk.win_bytes ?> bytes</td>
- <td><?cs var:ndk.win_checksum ?></td>
- </tr>
- <tr>
- <td>Mac OS X (intel)</td>
- <td>
- <a onClick="return onDownload(this)"
- href="http://dl.google.com/android/ndk/<?cs var:ndk.mac_download ?>"><?cs var:ndk.mac_download ?></a>
- </td>
- <td><?cs var:ndk.mac_bytes ?> bytes</td>
- <td><?cs var:ndk.mac_checksum ?></td>
- </tr>
- <tr>
- <td>Linux 32/64-bit (x86)</td>
- <td>
- <a onClick="return onDownload(this)"
- href="http://dl.google.com/android/ndk/<?cs var:ndk.linux_download ?>"><?cs var:ndk.linux_download ?></a>
- </td>
- <td><?cs var:ndk.linux_bytes ?> bytes</td>
- <td><?cs var:ndk.linux_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) ?>
-
-
-
-
-<h4><a href='' class="expandable"
- onclick="toggleExpandable(this,'.pax');hideExpandable('.myide,.reqs');return false;"
- >DOWNLOAD FOR OTHER PLATFORMS</a></h4>
-
-
-<div class="pax col-13 online" style="display:none;margin:0;">
-
-
-<p class="table-caption"><strong>ADT Bundle</strong></p>
- <table class="download">
- <tr>
- <th>Platform</th>
- <th>Package</th>
- <th>Size</th>
- <th>MD5 Checksum</th>
- </tr>
- <tr>
- <td>Windows 32-bit</td>
- <td>
- <a onClick="return onDownload(this)" id="win-bundle32"
- href="http://dl.google.com/android/adt/<?cs var:sdk.win32_bundle_download ?>"><?cs var:sdk.win32_bundle_download ?></a>
- </td>
- <td><?cs var:sdk.win32_bundle_bytes ?> bytes</td>
- <td><?cs var:sdk.win32_bundle_checksum ?></td>
- </tr>
- <tr>
- <td>Windows 64-bit</td>
- <td>
- <a onClick="return onDownload(this)" id="win-bundle64"
- href="http://dl.google.com/android/adt/<?cs var:sdk.win64_bundle_download ?>"><?cs var:sdk.win64_bundle_download ?></a>
- </td>
- <td><?cs var:sdk.win64_bundle_bytes ?> bytes</td>
- <td><?cs var:sdk.win64_bundle_checksum ?></td>
- </tr>
- <tr>
- <td><nobr>Mac OS X 64-bit</nobr></td>
- <td>
- <a onClick="return onDownload(this)" id="mac-bundle64"
- href="http://dl.google.com/android/adt/<?cs var:sdk.mac64_bundle_download ?>"><?cs var:sdk.mac64_bundle_download ?></a>
- </td>
- <td><?cs var:sdk.mac64_bundle_bytes ?> bytes</td>
- <td><?cs var:sdk.mac64_bundle_checksum ?></td>
- </tr>
- <tr>
- <td>Linux 32-bit</td>
- <td>
- <a onClick="return onDownload(this)" id="linux-bundle32"
- href="http://dl.google.com/android/adt/<?cs var:sdk.linux32_bundle_download ?>"><?cs var:sdk.linux32_bundle_download ?></a>
- </td>
- <td><?cs var:sdk.linux32_bundle_bytes ?> bytes</td>
- <td><?cs var:sdk.linux32_bundle_checksum ?></td>
- </tr>
- <tr>
- <td>Linux 64-bit</td>
- <td>
- <a onClick="return onDownload(this)" id="linux-bundle64"
- href="http://dl.google.com/android/adt/<?cs var:sdk.linux64_bundle_download ?>"><?cs var:sdk.linux64_bundle_download ?></a>
- </td>
- <td><?cs var:sdk.linux64_bundle_bytes ?> bytes</td>
- <td><?cs var:sdk.linux64_bundle_checksum ?></td>
- </tr>
- </table>
-
-
-<p class="table-caption"><strong>SDK Tools Only</strong></p>
- <table class="download">
- <tr>
- <th>Platform</th>
- <th>Package</th>
- <th>Size</th>
- <th>MD5 Checksum</th>
- </tr>
- <tr>
- <td rowspan="2">Windows</td>
- <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>
- <!-- blank TD from Windows rowspan -->
- <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>
- <td>Mac OS X</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>
-
-</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("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) {
- os = "Linux";
- bundlename = '#linux-bundle';
- $toolslink = $('#linux-tools');
- }
-
- if (os) {
- $('#not-supported').hide();
-
- /* set up primary adt download button */
- $('#download-bundle-button').show();
- $('#download-bundle-button').append("Download the SDK <br/><span class='small'>ADT Bundle for " + os + "</span>");
- $('#download-bundle-button').click(function() {return onDownload(this,true,true);}).attr('href', bundlename);
-
- /* set up sdk tools only button */
- $('#download-tools-button').show();
- $('#download-tools-button').append("Download the SDK Tools for " + os);
- $('#download-tools-button').click(function() {return onDownload(this,true);}).attr('href', $toolslink.attr('href'));
- } else {
- $('.pax').show();
- }
-
-
- function onDownload(link, button, bundle) {
-
- /* set text for download button */
- if (button) {
- $("#downloadForRealz").html($(link).text());
- } else {
- $("#downloadForRealz").html("Download " + $(link).text());
- }
-
- /* if it's a bundle, show the 32/64-bit picker */
- if (bundle) {
- $("#downloadForRealz").attr('bundle','true');
- if ($("#downloadForRealz").text().indexOf("Mac") == -1) {
- $("p#bitpicker").show();
- } else {
- /* mac is always 64 bit, so set it checked */
- $("p#bitpicker input[value=64]").attr('checked', true);
- }
- /* save link name until the bit version is chosen */
- $("#downloadForRealz").attr('name',$(link).attr('href'));
- } else {
- /* if not using bundle, set download button to ignore bitpicker and set url */
- $("#downloadForRealz").attr('bundle','false');
- $("#downloadForRealz").attr('href',$(link).attr('href'));
- /* set picker checked as a fake default */
- $("p#bitpicker input[value=64]").attr('checked', true);
- $("a#next-link").html("Setting Up an Existing IDE").attr('href',toRoot + 'sdk/installing/index.html');
- }
-
- $("#tos").fadeIn('fast');
- $("#landing").fadeOut('fast');
-
- location.hash = "download";
- return false;
- }
-
-
- function onAgreeChecked() {
- /* verify that the TOS is agreed and a bit version is chosen */
- if ($("input#agree").is(":checked") && $("#bitpicker input:checked").length) {
-
- /* if downloading the bundle */
- if ($("#downloadForRealz").attr('bundle')) {
- /* construct the name of the link we want based on the bit version */
- linkId = $("a#downloadForRealz").attr("name") + $("#bitpicker input:checked").val();
- /* set the real url for download */
- $("a#downloadForRealz").attr("href", $(linkId).attr("href"));
- }
-
- /* reveal the download button */
- $("a#downloadForRealz").removeClass('disabled');
- } else {
- $("a#downloadForRealz").addClass('disabled');
- }
- }
-
- function onDownloadForRealz(link) {
- if ($("input#agree").is(':checked') && $("#bitpicker input:checked").length) {
- $("div.sdk-terms").slideUp();
- $("#sdk-terms-form,.sdk-terms-intro").fadeOut('slow');
- $("#next-steps").fadeIn('slow');
- $("h1#tos-header").text('Get Ready to Code!');
- return true;
- } else {
- $("label#agreeLabel,#bitpicker input").parent().stop().animate({color: "#258AAF"}, 200,
- function() {$("label#agreeLabel,#bitpicker input").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" ?>
-
-</body>
-</html>
-
-
-
diff --git a/tools/droiddoc/templates-sac/timestamp.cs b/tools/droiddoc/templates-sac/timestamp.cs
deleted file mode 100644
index 4bf502a..0000000
--- a/tools/droiddoc/templates-sac/timestamp.cs
+++ /dev/null
@@ -1 +0,0 @@
-var BUILD_TIMESTAMP = "<?cs var:page.now ?>";
diff --git a/tools/droiddoc/templates-sac/trailer.cs b/tools/droiddoc/templates-sac/trailer.cs
deleted file mode 100644
index 337f8d3..0000000
--- a/tools/droiddoc/templates-sac/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/droiddoc/test/stubs/run.sh b/tools/droiddoc/test/stubs/run.sh
index 2ea15a6..7c8a894 100755
--- a/tools/droiddoc/test/stubs/run.sh
+++ b/tools/droiddoc/test/stubs/run.sh
@@ -14,7 +14,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-DIR=build/tools/droiddoc/test/stubs
+DIR=build/make/tools/droiddoc/test/stubs
pushd $TOP
diff --git a/tools/fs_config/Android.bp b/tools/fs_config/Android.bp
new file mode 100644
index 0000000..797cfe2
--- /dev/null
+++ b/tools/fs_config/Android.bp
@@ -0,0 +1,63 @@
+// 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.
+
+cc_binary_host {
+ name: "fs_config",
+ srcs: ["fs_config.c"],
+ shared_libs: [
+ "libcutils",
+ "libselinux",
+ ],
+ cflags: ["-Werror"],
+}
+
+// -----------------------------------------------------------------------------
+// Unit tests.
+// -----------------------------------------------------------------------------
+
+test_c_flags = [
+ "-fstack-protector-all",
+ "-g",
+ "-Wall",
+ "-Wextra",
+ "-Werror",
+ "-fno-builtin",
+ "-DANDROID_FILESYSTEM_CONFIG=\"android_filesystem_config_test_data.h\"",
+]
+
+//#################################
+// test executable
+cc_test_host {
+ name: "fs_config_generate_test",
+ srcs: ["fs_config_generate.c"],
+ shared_libs: ["libcutils"],
+ cflags: test_c_flags,
+ relative_install_path: "fs_config-unit-tests",
+ no_named_install_directory: true,
+ gtest: false,
+
+}
+
+//#################################
+// gTest tool
+cc_test_host {
+ name: "fs_config-unit-tests",
+ cflags: test_c_flags + ["-DHOST"],
+ shared_libs: [
+ "liblog",
+ "libcutils",
+ "libbase",
+ ],
+ srcs: ["fs_config_test.cpp"],
+}
diff --git a/tools/fs_config/Android.mk b/tools/fs_config/Android.mk
index ab7f92d..a01e702 100644
--- a/tools/fs_config/Android.mk
+++ b/tools/fs_config/Android.mk
@@ -14,15 +14,6 @@
LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := fs_config.c
-LOCAL_MODULE := fs_config
-LOCAL_SHARED_LIBRARIES := libcutils libselinux
-LOCAL_CFLAGS := -Werror
-
-include $(BUILD_HOST_EXECUTABLE)
-
# One can override the default android_filesystem_config.h file in one of two ways:
#
# 1. The old way:
@@ -253,23 +244,24 @@
ifneq ($(TARGET_FS_CONFIG_GEN),)
##################################
-# Build the oemaid library when fs config files are present.
-# Intentionally break build if you require generated AIDS
+# Build the oemaid header library when fs config files are present.
+# Intentionally break build if you require generated AIDs
# header file, but are not using any fs config files.
include $(CLEAR_VARS)
-LOCAL_MODULE := liboemaids
+LOCAL_MODULE := oemaids_headers
LOCAL_EXPORT_C_INCLUDE_DIRS := $(dir $(my_gen_oem_aid))
LOCAL_EXPORT_C_INCLUDE_DEPS := $(my_gen_oem_aid)
-include $(BUILD_STATIC_LIBRARY)
+include $(BUILD_HEADER_LIBRARY)
##################################
-# Generate the system/etc/passwd text file for the target
+# Generate the vendor/etc/passwd text file for the target
# This file may be empty if no AIDs are defined in
# TARGET_FS_CONFIG_GEN files.
include $(CLEAR_VARS)
LOCAL_MODULE := passwd
LOCAL_MODULE_CLASS := ETC
+LOCAL_VENDOR_MODULE := true
include $(BUILD_SYSTEM)/base_rules.mk
@@ -278,16 +270,17 @@
$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_FS_HDR := $(system_android_filesystem_config)
$(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/fs_config_generator.py $(TARGET_FS_CONFIG_GEN) $(system_android_filesystem_config)
@mkdir -p $(dir $@)
- $(hide) $< passwd --aid-header=$(PRIVATE_ANDROID_FS_HDR) $(PRIVATE_TARGET_FS_CONFIG_GEN) > $@
+ $(hide) $< passwd --required-prefix=vendor_ --aid-header=$(PRIVATE_ANDROID_FS_HDR) $(PRIVATE_TARGET_FS_CONFIG_GEN) > $@
##################################
-# Generate the system/etc/group text file for the target
+# Generate the vendor/etc/group text file for the target
# This file may be empty if no AIDs are defined in
# TARGET_FS_CONFIG_GEN files.
include $(CLEAR_VARS)
LOCAL_MODULE := group
LOCAL_MODULE_CLASS := ETC
+LOCAL_VENDOR_MODULE := true
include $(BUILD_SYSTEM)/base_rules.mk
@@ -296,7 +289,7 @@
$(LOCAL_BUILT_MODULE): PRIVATE_ANDROID_FS_HDR := $(system_android_filesystem_config)
$(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/fs_config_generator.py $(TARGET_FS_CONFIG_GEN) $(system_android_filesystem_config)
@mkdir -p $(dir $@)
- $(hide) $< group --aid-header=$(PRIVATE_ANDROID_FS_HDR) $(PRIVATE_TARGET_FS_CONFIG_GEN) > $@
+ $(hide) $< group --required-prefix=vendor_ --aid-header=$(PRIVATE_ANDROID_FS_HDR) $(PRIVATE_TARGET_FS_CONFIG_GEN) > $@
system_android_filesystem_config :=
endif
@@ -306,36 +299,3 @@
fs_config_generate_bin :=
my_gen_oem_aid :=
fs_config_generate_extra_partition_list :=
-
-# -----------------------------------------------------------------------------
-# Unit tests.
-# -----------------------------------------------------------------------------
-
-test_c_flags := \
- -fstack-protector-all \
- -g \
- -Wall \
- -Wextra \
- -Werror \
- -fno-builtin \
- -DANDROID_FILESYSTEM_CONFIG='"android_filesystem_config_test_data.h"'
-
-##################################
-# test executable
-include $(CLEAR_VARS)
-LOCAL_MODULE := fs_config_generate_test
-LOCAL_SRC_FILES := fs_config_generate.c
-LOCAL_SHARED_LIBRARIES := libcutils
-LOCAL_CFLAGS := $(test_c_flags)
-LOCAL_MODULE_RELATIVE_PATH := fs_config-unit-tests
-LOCAL_GTEST := false
-include $(BUILD_HOST_NATIVE_TEST)
-
-##################################
-# gTest tool
-include $(CLEAR_VARS)
-LOCAL_MODULE := fs_config-unit-tests
-LOCAL_CFLAGS += $(test_c_flags) -DHOST
-LOCAL_SHARED_LIBRARIES := liblog libcutils libbase
-LOCAL_SRC_FILES := fs_config_test.cpp
-include $(BUILD_HOST_NATIVE_TEST)
diff --git a/tools/fs_config/README b/tools/fs_config/README
index 5af407f..cc2a68f 100644
--- a/tools/fs_config/README
+++ b/tools/fs_config/README
@@ -122,7 +122,7 @@
For OEMs wishing to use the define AIDs in their native code, one can access the generated header
file like so:
1. In your C code just #include "generated_oem_aid.h" and start using the declared identifiers.
- 2. In your Makefile add this static library like so: LOCAL_STATIC_LIBRARIES := liboemaids
+ 2. In your Makefile add this static library like so: LOCAL_HEADER_LIBRARIES := oemaids_headers
Unit Tests:
diff --git a/tools/fs_config/fs_config.c b/tools/fs_config/fs_config.c
index 48f300b..2952875 100644
--- a/tools/fs_config/fs_config.c
+++ b/tools/fs_config/fs_config.c
@@ -67,17 +67,18 @@
}
static void usage() {
- fprintf(stderr, "Usage: fs_config [-D product_out_path] [-S context_file] [-C]\n");
+ fprintf(stderr, "Usage: fs_config [-D product_out_path] [-S context_file] [-R root] [-C]\n");
}
int main(int argc, char** argv) {
char buffer[1024];
const char* context_file = NULL;
const char* product_out_path = NULL;
+ char* root_path = NULL;
struct selabel_handle* sehnd = NULL;
int print_capabilities = 0;
int opt;
- while((opt = getopt(argc, argv, "CS:D:")) != -1) {
+ while((opt = getopt(argc, argv, "CS:R:D:")) != -1) {
switch(opt) {
case 'C':
print_capabilities = 1;
@@ -85,6 +86,9 @@
case 'S':
context_file = optarg;
break;
+ case 'R':
+ root_path = optarg;
+ break;
case 'D':
product_out_path = optarg;
break;
@@ -98,6 +102,14 @@
sehnd = get_sehnd(context_file);
}
+ if (root_path != NULL) {
+ size_t root_len = strlen(root_path);
+ /* Trim any trailing slashes from the root path. */
+ while (root_len && root_path[--root_len] == '/') {
+ root_path[root_len] = '\0';
+ }
+ }
+
while (fgets(buffer, 1023, stdin) != NULL) {
int is_dir = 0;
int i;
@@ -122,6 +134,10 @@
unsigned uid = 0, gid = 0, mode = 0;
uint64_t capabilities;
fs_config(buffer, is_dir, product_out_path, &uid, &gid, &mode, &capabilities);
+ if (root_path != NULL && strcmp(buffer, root_path) == 0) {
+ /* The root of the filesystem needs to be an empty string. */
+ strcpy(buffer, "");
+ }
printf("%s %d %d %o", buffer, uid, gid, mode);
if (sehnd != NULL) {
diff --git a/tools/fs_config/fs_config_generator.py b/tools/fs_config/fs_config_generator.py
index c8d1dd3..4839578 100755
--- a/tools/fs_config/fs_config_generator.py
+++ b/tools/fs_config/fs_config_generator.py
@@ -146,18 +146,27 @@
found (str): The file found in, not required to be specified.
Raises:
+ ValueError: if the friendly name is longer than 31 characters as
+ that is bionic's internal buffer size for name.
ValueError: if value is not a valid string number as processed by
int(x, 0)
"""
self.identifier = identifier
self.value = value
self.found = found
- self.normalized_value = str(int(value, 0))
+ try:
+ self.normalized_value = str(int(value, 0))
+ except ValueException:
+ raise ValueError('Invalid "value", not aid number, got: \"%s\"' % value)
# Where we calculate the friendly name
friendly = identifier[len(AID.PREFIX):].lower()
self.friendly = AID._fixup_friendly(friendly)
+ if len(self.friendly) > 31:
+ raise ValueError('AID names must be under 32 characters "%s"' % self.friendly)
+
+
def __eq__(self, other):
return self.identifier == other.identifier \
@@ -639,10 +648,8 @@
try:
aid = AID(section_name, value, file_name)
- except ValueError:
- sys.exit(
- error_message('Invalid "value", not aid number, got: \"%s\"' %
- value))
+ except ValueError as exception:
+ sys.exit(error_message(exception))
# Values must be within OEM range
if not Utils.in_any_range(int(aid.value, 0), self._oem_ranges):
@@ -1209,10 +1216,6 @@
class PasswdGen(BaseGenerator):
"""Generates the /etc/passwd file per man (5) passwd."""
- _GENERATED = ('#\n# THIS IS AN AUTOGENERATED FILE! DO NOT MODIFY!\n#')
-
- _FILE_COMMENT = '# Defined in file: \"%s\"'
-
def __init__(self):
self._old_file = None
@@ -1228,22 +1231,31 @@
help='An android_filesystem_config.h file'
'to parse AIDs and OEM Ranges from')
+ opt_group.add_argument(
+ '--required-prefix',
+ required=False,
+ help='A prefix that the names are required to contain.')
+
def __call__(self, args):
hdr_parser = AIDHeaderParser(args['aid_header'])
parser = FSConfigFileParser(args['fsconfig'], hdr_parser.oem_ranges)
+ required_prefix = args['required_prefix']
+
aids = parser.aids
# nothing to do if no aids defined
if len(aids) == 0:
return
- print PasswdGen._GENERATED
-
for aid in aids:
- self._print_formatted_line(aid)
+ if required_prefix is None or aid.friendly.startswith(required_prefix):
+ self._print_formatted_line(aid)
+ else:
+ sys.exit("%s: AID '%s' must start with '%s'" %
+ (args['fsconfig'], aid.friendly, required_prefix))
def _print_formatted_line(self, aid):
"""Prints the aid to stdout in the passwd format. Internal use only.
@@ -1262,7 +1274,6 @@
"""
if self._old_file != aid.found:
self._old_file = aid.found
- print PasswdGen._FILE_COMMENT % aid.found
try:
logon, uid = Utils.get_login_and_uid_cleansed(aid)
@@ -1288,7 +1299,6 @@
"""
if self._old_file != aid.found:
self._old_file = aid.found
- print PasswdGen._FILE_COMMENT % aid.found
try:
logon, uid = Utils.get_login_and_uid_cleansed(aid)
diff --git a/tools/fs_get_stats/Android.bp b/tools/fs_get_stats/Android.bp
new file mode 100644
index 0000000..67742b8
--- /dev/null
+++ b/tools/fs_get_stats/Android.bp
@@ -0,0 +1,9 @@
+cc_binary_host {
+ name: "fs_get_stats",
+ srcs: ["fs_get_stats.c"],
+ cflags: ["-Wall", "-Werror"],
+ shared_libs: [
+ "libcutils",
+ "liblog",
+ ],
+}
diff --git a/tools/fs_get_stats/Android.mk b/tools/fs_get_stats/Android.mk
deleted file mode 100644
index 4501c1f..0000000
--- a/tools/fs_get_stats/Android.mk
+++ /dev/null
@@ -1,11 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := fs_get_stats.c
-
-LOCAL_MODULE := fs_get_stats
-
-LOCAL_SHARED_LIBRARIES := libcutils liblog
-
-include $(BUILD_HOST_EXECUTABLE)
diff --git a/tools/generate-notice-files.py b/tools/generate-notice-files.py
index adbf7c2..b754174 100755
--- a/tools/generate-notice-files.py
+++ b/tools/generate-notice-files.py
@@ -253,15 +253,12 @@
filesets = [sorted(files_with_same_hash[md5]) for md5 in sorted(files_with_same_hash.keys())]
- print "Combining NOTICE files into text"
combine_notice_files_text(filesets, input_dir, txt_output_file, file_title)
if html_output_file is not None:
- print "Combining NOTICE files into HTML"
combine_notice_files_html(filesets, input_dir, html_output_file)
if xml_output_file is not None:
- print "Combining NOTICE files into XML"
combine_notice_files_xml(files_with_same_hash, input_dir, xml_output_file)
if __name__ == "__main__":
diff --git a/tools/ijar/Android.bp b/tools/ijar/Android.bp
deleted file mode 100644
index a244a2d..0000000
--- a/tools/ijar/Android.bp
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2015 The Android Open Source Project
-//
-// The rest of files in this directory comes from
-// https://github.com/bazelbuild/bazel/tree/master/third_party/ijar
-
-cc_binary_host {
- srcs: [
- "classfile.cc",
- "ijar.cc",
- "zip.cc",
- ],
- cflags: [
- "-Wall",
- "-Werror",
- ],
- host_ldlibs: ["-lz"],
- name: "ijar",
-}
diff --git a/tools/ijar/LICENSE b/tools/ijar/LICENSE
deleted file mode 100644
index 6b0b127..0000000
--- a/tools/ijar/LICENSE
+++ /dev/null
@@ -1,203 +0,0 @@
-
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright [yyyy] [name of copyright owner]
-
- 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.
-
diff --git a/tools/ijar/README.txt b/tools/ijar/README.txt
deleted file mode 100644
index d5a6a0f..0000000
--- a/tools/ijar/README.txt
+++ /dev/null
@@ -1,120 +0,0 @@
-
-ijar: A tool for generating interface .jars from normal .jars
-=============================================================
-
-Alan Donovan, 26 May 2007.
-
-Rationale:
-
- In order to improve the speed of compilation of Java programs in
- Bazel, the output of build steps is cached.
-
- This works very nicely for C++ compilation: a compilation unit
- includes a .cc source file and typically dozens of header files.
- Header files change relatively infrequently, so the need for a
- rebuild is usually driven by a change in the .cc file. Even after
- syncing a slightly newer version of the tree and doing a rebuild,
- many hits in the cache are still observed.
-
- In Java, by contrast, a compilation unit involves a set of .java
- source files, plus a set of .jar files containing already-compiled
- JVM .class files. Class files serve a dual purpose: from the JVM's
- perspective, they are containers of executable code, but from the
- compiler's perspective, they are interface definitions. The problem
- here is that .jar files are very much more sensitive to change than
- C++ header files, so even a change that is insignificant to the
- compiler (such as the addition of a print statement to a method in a
- prerequisite class) will cause the jar to change, and any code that
- depends on this jar's interface will be recompiled unnecessarily.
-
- The purpose of ijar is to produce, from a .jar file, a much smaller,
- simpler .jar file containing only the parts that are significant for
- the purposes of compilation. In other words, an interface .jar
- file. By changing ones compilation dependencies to be the interface
- jar files, unnecessary recompilation is avoided when upstream
- changes don't affect the interface.
-
-Details:
-
- ijar is a tool that reads a .jar file and emits a .jar file
- containing only the parts that are relevant to Java compilation.
- For example, it throws away:
-
- - Files whose name does not end in ".class".
- - All executable method code.
- - All private methods and fields.
- - All constants and attributes except the minimal set necessary to
- describe the class interface.
- - All debugging information
- (LineNumberTable, SourceFile, LocalVariableTables attributes).
-
- It also sets to zero the file modification times in the index of the
- .jar file.
-
-Implementation:
-
- ijar is implemented in C++, and runs very quickly. For example
- (when optimized) it takes only 530ms to process a 42MB
- .jar file containing 5878 classe, resulting in an interface .jar
- file of only 11.4MB in size. For more usual .jar sizes of a few
- megabytes, a runtime of 50ms is typical.
-
- The implementation strategy is to mmap both the input jar and the
- newly-created _interface.jar, and to scan through the former and
- emit the latter in a single pass. There are a couple of locations
- where some kind of "backpatching" is required:
-
- - in the .zip file format, for each file, the size field precedes
- the data. We emit a zero but note its location, generate and emit
- the stripped classfile, then poke the correct size into the
- location.
-
- - for JVM .class files, the header (including the constant table)
- precedes the body, but cannot be emitted before it because it's
- not until we emit the body that we know which constants are
- referenced and which are garbage. So we emit the body into a
- temporary buffer, then emit the header to the output jar, followed
- by the contents of the temp buffer.
-
- Also note that the zip file format has unnecessary duplication of
- the index metadata: it has header+data for each file, then another
- set of (similar) headers at the end. Rather than save the metadata
- explicitly in some datastructure, we just record the addresses of
- the already-emitted zip metadata entries in the output file, and
- then read from there as necessary.
-
-Notes:
-
- This code has no dependency except on the STL and on zlib.
-
- Almost all of the getX/putX/ReadX/WriteX functions in the code
- advance their first argument pointer, which is passed by reference.
-
- It's tempting to discard package-private classes and class members.
- However, this would be incorrect because they are a necessary part
- of the package interface, as a Java package is often compiled in
- multiple stages. For example: in Bazel, both java tests and java
- code inhabit the same Java package but are compiled separately.
-
-Assumptions:
-
- We assume that jar files are uncompressed v1.0 zip files (created
- with 'jar c0f') with a zero general_purpose_bit_flag.
-
- We assume that javap/javac don't need the correct CRC checksums in
- the .jar file.
-
- We assume that it's better simply to abort in the face of unknown
- input than to risk leaving out something important from the output
- (although in the case of annotations, it should be safe to ignore
- ones we don't understand).
-
-TODO:
- Maybe: ensure a canonical sort order is used for every list (jar
- entries, class members, attributes, etc.) This isn't essential
- because we can assume the compiler is deterministic and the order in
- the source files changes little. Also, it would require two passes. :(
-
- Maybe: delete dynamically-allocated memory.
-
- Add (a lot) more tests. Include a test of idempotency.
diff --git a/tools/ijar/classfile.cc b/tools/ijar/classfile.cc
deleted file mode 100644
index d33e0db..0000000
--- a/tools/ijar/classfile.cc
+++ /dev/null
@@ -1,1788 +0,0 @@
-// Copyright 2001,2007 Alan Donovan. All rights reserved.
-//
-// Author: Alan Donovan <adonovan@google.com>
-//
-// 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.
-//
-// classfile.cc -- classfile parsing and stripping.
-//
-
-// TODO(adonovan) don't pass pointers by reference; this is not
-// compatible with Google C++ style.
-
-// See README.txt for details.
-//
-// For definition of JVM class file format, see:
-// Java SE 8 Edition:
-// http://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4
-
-#define __STDC_FORMAT_MACROS 1
-#define __STDC_LIMIT_MACROS 1
-#include <inttypes.h> // for PRIx32
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <set>
-#include <string>
-#include <vector>
-
-#include "common.h"
-
-namespace devtools_ijar {
-
-// See Table 4.3 in JVM Spec.
-enum CONSTANT {
- CONSTANT_Class = 7,
- CONSTANT_FieldRef = 9,
- CONSTANT_Methodref = 10,
- CONSTANT_Interfacemethodref = 11,
- CONSTANT_String = 8,
- CONSTANT_Integer = 3,
- CONSTANT_Float = 4,
- CONSTANT_Long = 5,
- CONSTANT_Double = 6,
- CONSTANT_NameAndType = 12,
- CONSTANT_Utf8 = 1,
- CONSTANT_MethodHandle = 15,
- CONSTANT_MethodType = 16,
- CONSTANT_InvokeDynamic = 18
-};
-
-// See Tables 4.1, 4.4, 4.5 in JVM Spec.
-enum ACCESS {
- ACC_PUBLIC = 0x0001,
- ACC_PRIVATE = 0x0002,
- ACC_PROTECTED = 0x0004,
- ACC_STATIC = 0x0008,
- ACC_FINAL = 0x0010,
- ACC_SYNCHRONIZED = 0x0020,
- ACC_VOLATILE = 0x0040,
- ACC_TRANSIENT = 0x0080,
- ACC_INTERFACE = 0x0200,
- ACC_ABSTRACT = 0x0400
-};
-
-// See Table 4.7.20-A in Java 8 JVM Spec.
-enum TARGET_TYPE {
- // Targets for type parameter declarations (ElementType.TYPE_PARAMETER):
- CLASS_TYPE_PARAMETER = 0x00,
- METHOD_TYPE_PARAMETER = 0x01,
-
- // Targets for type uses that may be externally visible in classes and members
- // (ElementType.TYPE_USE):
- CLASS_EXTENDS = 0x10,
- CLASS_TYPE_PARAMETER_BOUND = 0x11,
- METHOD_TYPE_PARAMETER_BOUND = 0x12,
- FIELD = 0x13,
- METHOD_RETURN = 0x14,
- METHOD_RECEIVER = 0x15,
- METHOD_FORMAL_PARAMETER = 0x16,
- THROWS = 0x17,
-
- // TARGET_TYPE >= 0x40 is reserved for type uses that occur only within code
- // blocks. Ijar doesn't need to know about these.
-};
-
-struct Constant;
-
-// TODO(adonovan) these globals are unfortunate
-static std::vector<Constant*> const_pool_in; // input constant pool
-static std::vector<Constant*> const_pool_out; // output constant_pool
-static std::set<std::string> used_class_names;
-static Constant * class_name;
-
-// Returns the Constant object, given an index into the input constant pool.
-// Note: constant(0) == NULL; this invariant is exploited by the
-// InnerClassesAttribute, inter alia.
-inline Constant *constant(int idx) {
- if (idx < 0 || (unsigned)idx >= const_pool_in.size()) {
- fprintf(stderr, "Illegal constant pool index: %d\n", idx);
- abort();
- }
- return const_pool_in[idx];
-}
-
-/**********************************************************************
- * *
- * Constants *
- * *
- **********************************************************************/
-
-// See sec.4.4 of JVM spec.
-struct Constant {
-
- explicit Constant(u1 tag) :
- slot_(0),
- tag_(tag) {}
-
- virtual ~Constant() {}
-
- // For UTF-8 string constants, returns the encoded string.
- // Otherwise, returns an undefined string value suitable for debugging.
- virtual std::string Display() = 0;
-
- virtual void Write(u1 *&p) = 0;
-
- // Called by slot() when a constant has been identified as required
- // in the output classfile's constant pool. This is a hook allowing
- // constants to register their dependency on other constants, by
- // calling slot() on them in turn.
- virtual void Keep() {}
-
- bool Kept() {
- return slot_ != 0;
- }
-
- // Returns the index of this constant in the output class's constant
- // pool, assigning a slot if not already done.
- u2 slot() {
- if (slot_ == 0) {
- Keep();
- slot_ = const_pool_out.size(); // BugBot's "narrowing" warning
- // is bogus. The number of
- // output constants can't exceed
- // the number of input constants.
- if (slot_ == 0) {
- fprintf(stderr, "Constant::slot() called before output phase.\n");
- abort();
- }
- const_pool_out.push_back(this);
- if (tag_ == CONSTANT_Long || tag_ == CONSTANT_Double) {
- const_pool_out.push_back(NULL);
- }
- }
- return slot_;
- }
-
- u2 slot_; // zero => "this constant is unreachable garbage"
- u1 tag_;
-};
-
-// Extracts class names from a signature and puts them into the global
-// variable used_class_names.
-//
-// desc: the descriptor class names should be extracted from.
-// p: the position where the extraction should tart.
-void ExtractClassNames(const std::string& desc, size_t* p);
-
-// See sec.4.4.1 of JVM spec.
-struct Constant_Class : Constant
-{
- explicit Constant_Class(u2 name_index) :
- Constant(CONSTANT_Class),
- name_index_(name_index) {}
-
- void Write(u1 *&p) {
- put_u1(p, tag_);
- put_u2be(p, constant(name_index_)->slot());
- }
-
- std::string Display() {
- return constant(name_index_)->Display();
- }
-
- void Keep() { constant(name_index_)->slot(); }
-
- u2 name_index_;
-};
-
-// See sec.4.4.2 of JVM spec.
-struct Constant_FMIref : Constant
-{
- Constant_FMIref(u1 tag,
- u2 class_index,
- u2 name_type_index) :
- Constant(tag),
- class_index_(class_index),
- name_type_index_(name_type_index) {}
-
- void Write(u1 *&p) {
- put_u1(p, tag_);
- put_u2be(p, constant(class_index_)->slot());
- put_u2be(p, constant(name_type_index_)->slot());
- }
-
- std::string Display() {
- return constant(class_index_)->Display() + "::" +
- constant(name_type_index_)->Display();
- }
-
- void Keep() {
- constant(class_index_)->slot();
- constant(name_type_index_)->slot();
- }
-
- u2 class_index_;
- u2 name_type_index_;
-};
-
-// See sec.4.4.3 of JVM spec.
-struct Constant_String : Constant
-{
- explicit Constant_String(u2 string_index) :
- Constant(CONSTANT_String),
- string_index_(string_index) {}
-
- void Write(u1 *&p) {
- put_u1(p, tag_);
- put_u2be(p, constant(string_index_)->slot());
- }
-
- std::string Display() {
- return "\"" + constant(string_index_)->Display() + "\"";
- }
-
- void Keep() { constant(string_index_)->slot(); }
-
- u2 string_index_;
-};
-
-// See sec.4.4.4 of JVM spec.
-struct Constant_IntegerOrFloat : Constant
-{
- Constant_IntegerOrFloat(u1 tag, u4 bytes) :
- Constant(tag),
- bytes_(bytes) {}
-
- void Write(u1 *&p) {
- put_u1(p, tag_);
- put_u4be(p, bytes_);
- }
-
- std::string Display() { return "int/float"; }
-
- u4 bytes_;
-};
-
-// See sec.4.4.5 of JVM spec.
-struct Constant_LongOrDouble : Constant_IntegerOrFloat
-{
- Constant_LongOrDouble(u1 tag, u4 high_bytes, u4 low_bytes) :
- Constant_IntegerOrFloat(tag, high_bytes),
- low_bytes_(low_bytes) {}
-
- void Write(u1 *&p) {
- put_u1(p, tag_);
- put_u4be(p, bytes_);
- put_u4be(p, low_bytes_);
- }
-
- std::string Display() { return "long/double"; }
-
- u4 low_bytes_;
-};
-
-// See sec.4.4.6 of JVM spec.
-struct Constant_NameAndType : Constant
-{
- Constant_NameAndType(u2 name_index, u2 descr_index) :
- Constant(CONSTANT_NameAndType),
- name_index_(name_index),
- descr_index_(descr_index) {}
-
- void Write(u1 *&p) {
- put_u1(p, tag_);
- put_u2be(p, constant(name_index_)->slot());
- put_u2be(p, constant(descr_index_)->slot());
- }
-
- std::string Display() {
- return constant(name_index_)->Display() + "::" +
- constant(descr_index_)->Display();
- }
-
- void Keep() {
- constant(name_index_)->slot();
- constant(descr_index_)->slot();
- }
-
- u2 name_index_;
- u2 descr_index_;
-};
-
-// See sec.4.4.7 of JVM spec.
-struct Constant_Utf8 : Constant
-{
- Constant_Utf8(u4 length, const u1 *utf8) :
- Constant(CONSTANT_Utf8),
- length_(length),
- utf8_(utf8) {}
-
- void Write(u1 *&p) {
- put_u1(p, tag_);
- put_u2be(p, length_);
- put_n(p, utf8_, length_);
- }
-
- std::string Display() {
- return std::string((const char*) utf8_, length_);
- }
-
- u4 length_;
- const u1 *utf8_;
-};
-
-// See sec.4.4.8 of JVM spec.
-struct Constant_MethodHandle : Constant
-{
- Constant_MethodHandle(u1 reference_kind, u2 reference_index) :
- Constant(CONSTANT_MethodHandle),
- reference_kind_(reference_kind),
- reference_index_(reference_index) {}
-
- void Write(u1 *&p) {
- put_u1(p, tag_);
- put_u1(p, reference_kind_);
- put_u2be(p, reference_index_);
- }
-
- std::string Display() {
- return "Constant_MethodHandle::" + std::to_string(reference_kind_) + "::"
- + constant(reference_index_)->Display();
- }
-
- u1 reference_kind_;
- u2 reference_index_;
-};
-
-// See sec.4.4.9 of JVM spec.
-struct Constant_MethodType : Constant
-{
- explicit Constant_MethodType(u2 descriptor_index) :
- Constant(CONSTANT_MethodType),
- descriptor_index_(descriptor_index) {}
-
- void Write(u1 *&p) {
- put_u1(p, tag_);
- put_u2be(p, descriptor_index_);
- }
-
- std::string Display() {
- return "Constant_MethodType::" + constant(descriptor_index_)->Display();
- }
-
- u2 descriptor_index_;
-};
-
-// See sec.4.4.10 of JVM spec.
-struct Constant_InvokeDynamic : Constant
-{
- Constant_InvokeDynamic(u2 bootstrap_method_attr_index, u2 name_and_type_index) :
- Constant(CONSTANT_InvokeDynamic),
- bootstrap_method_attr_index_(bootstrap_method_attr_index),
- name_and_type_index_(name_and_type_index) {}
-
- void Write(u1 *&p) {
- put_u1(p, tag_);
- put_u2be(p, bootstrap_method_attr_index_);
- put_u2be(p, name_and_type_index_);
- }
-
- std::string Display() {
- return "Constant_InvokeDynamic::"
- + std::to_string(bootstrap_method_attr_index_) + "::"
- + constant(name_and_type_index_)->Display();
- }
-
- u2 bootstrap_method_attr_index_;
- u2 name_and_type_index_;
-};
-
-/**********************************************************************
- * *
- * Attributes *
- * *
- **********************************************************************/
-
-// See sec.4.7 of JVM spec.
-struct Attribute {
-
- virtual ~Attribute() {}
- virtual void Write(u1 *&p) = 0;
- virtual void ExtractClassNames() {}
-
- void WriteProlog(u1 *&p, u2 length) {
- put_u2be(p, attribute_name_->slot());
- put_u4be(p, length);
- }
-
- Constant *attribute_name_;
-};
-
-// See sec.4.7.5 of JVM spec.
-struct ExceptionsAttribute : Attribute {
-
- static ExceptionsAttribute* Read(const u1 *&p, Constant *attribute_name) {
- ExceptionsAttribute *attr = new ExceptionsAttribute;
- attr->attribute_name_ = attribute_name;
- u2 number_of_exceptions = get_u2be(p);
- for (int ii = 0; ii < number_of_exceptions; ++ii) {
- attr->exceptions_.push_back(constant(get_u2be(p)));
- }
- return attr;
- }
-
- void Write(u1 *&p) {
- WriteProlog(p, exceptions_.size() * 2 + 2);
- put_u2be(p, exceptions_.size());
- for (size_t ii = 0; ii < exceptions_.size(); ++ii) {
- put_u2be(p, exceptions_[ii]->slot());
- }
- }
-
- std::vector<Constant*> exceptions_;
-};
-
-// See sec.4.7.6 of JVM spec.
-struct InnerClassesAttribute : Attribute {
-
- struct Entry {
- Constant *inner_class_info;
- Constant *outer_class_info;
- Constant *inner_name;
- u2 inner_class_access_flags;
- };
-
- virtual ~InnerClassesAttribute() {
- for (size_t i = 0; i < entries_.size(); i++) {
- delete entries_[i];
- }
- }
-
- static InnerClassesAttribute* Read(const u1 *&p, Constant *attribute_name) {
- InnerClassesAttribute *attr = new InnerClassesAttribute;
- attr->attribute_name_ = attribute_name;
-
- u2 number_of_classes = get_u2be(p);
- for (int ii = 0; ii < number_of_classes; ++ii) {
- Entry *entry = new Entry;
- entry->inner_class_info = constant(get_u2be(p));
- entry->outer_class_info = constant(get_u2be(p));
- entry->inner_name = constant(get_u2be(p));
- entry->inner_class_access_flags = get_u2be(p);
-
- attr->entries_.push_back(entry);
- }
- return attr;
- }
-
- void Write(u1 *&p) {
- std::set<int> kept_entries;
- // We keep an entry if the constant referring to the inner class is already
- // kept. Then we mark its outer class and its class name as kept, too, then
- // iterate until a fixed point is reached.
- size_t entry_count;
- int iteration = 0;
-
- do {
- entry_count = kept_entries.size();
- for (size_t i_entry = 0; i_entry < entries_.size(); ++i_entry) {
- Entry* entry = entries_[i_entry];
- if (entry->inner_class_info->Kept() ||
- used_class_names.find(entry->inner_class_info->Display())
- != used_class_names.end() ||
- entry->outer_class_info == class_name ||
- entry->outer_class_info == NULL ||
- entry->inner_name == NULL) {
- kept_entries.insert(i_entry);
-
- // These are zero for anonymous inner classes
- if (entry->outer_class_info != NULL) {
- entry->outer_class_info->slot();
- }
-
- if (entry->inner_name != NULL) {
- entry->inner_name->slot();
- }
- }
- }
- iteration += 1;
- } while (entry_count != kept_entries.size());
-
- if (kept_entries.size() == 0) {
- return;
- }
-
- WriteProlog(p, 2 + kept_entries.size() * 8);
- put_u2be(p, kept_entries.size());
-
- for (std::set<int>::iterator it = kept_entries.begin();
- it != kept_entries.end();
- ++it) {
- Entry *entry = entries_[*it];
- put_u2be(p, entry->inner_class_info == NULL
- ? 0
- : entry->inner_class_info->slot());
- put_u2be(p, entry->outer_class_info == NULL
- ? 0
- : entry->outer_class_info->slot());
- put_u2be(p, entry->inner_name == NULL
- ? 0
- : entry->inner_name->slot());
- put_u2be(p, entry->inner_class_access_flags);
- }
- }
-
- std::vector<Entry*> entries_;
-};
-
-// See sec.4.7.7 of JVM spec.
-// We preserve EnclosingMethod attributes to be able to identify local and
-// anonymous classes. These classes will be stripped of most content, as they
-// represent implementation details that shoudn't leak into the ijars. Omitting
-// EnclosingMethod attributes can lead to type-checking failures in the presence
-// of generics (see b/9070939).
-struct EnclosingMethodAttribute : Attribute {
-
- static EnclosingMethodAttribute* Read(const u1 *&p,
- Constant *attribute_name) {
- EnclosingMethodAttribute *attr = new EnclosingMethodAttribute;
- attr->attribute_name_ = attribute_name;
- attr->class_ = constant(get_u2be(p));
- attr->method_ = constant(get_u2be(p));
- return attr;
- }
-
- void Write(u1 *&p) {
- WriteProlog(p, 4);
- put_u2be(p, class_->slot());
- put_u2be(p, method_ == NULL ? 0 : method_->slot());
- }
-
- Constant *class_;
- Constant *method_;
-};
-
-// See sec.4.7.16.1 of JVM spec.
-// Used by AnnotationDefault and other attributes.
-struct ElementValue {
- virtual ~ElementValue() {}
- virtual void Write(u1 *&p) = 0;
- virtual void ExtractClassNames() {}
- static ElementValue* Read(const u1 *&p);
- u1 tag_;
- u4 length_;
-};
-
-struct BaseTypeElementValue : ElementValue {
- void Write(u1 *&p) {
- put_u1(p, tag_);
- put_u2be(p, const_value_->slot());
- }
- static BaseTypeElementValue *Read(const u1 *&p) {
- BaseTypeElementValue *value = new BaseTypeElementValue;
- value->const_value_ = constant(get_u2be(p));
- return value;
- }
- Constant *const_value_;
-};
-
-struct EnumTypeElementValue : ElementValue {
- void Write(u1 *&p) {
- put_u1(p, tag_);
- put_u2be(p, type_name_->slot());
- put_u2be(p, const_name_->slot());
- }
- static EnumTypeElementValue *Read(const u1 *&p) {
- EnumTypeElementValue *value = new EnumTypeElementValue;
- value->type_name_ = constant(get_u2be(p));
- value->const_name_ = constant(get_u2be(p));
- return value;
- }
- Constant *type_name_;
- Constant *const_name_;
-};
-
-struct ClassTypeElementValue : ElementValue {
- void Write(u1 *&p) {
- put_u1(p, tag_);
- put_u2be(p, class_info_->slot());
- }
-
- virtual void ExtractClassNames() {
- size_t idx = 0;
- devtools_ijar::ExtractClassNames(class_info_->Display(), &idx);
- }
-
- static ClassTypeElementValue *Read(const u1 *&p) {
- ClassTypeElementValue *value = new ClassTypeElementValue;
- value->class_info_ = constant(get_u2be(p));
- return value;
- }
- Constant *class_info_;
-};
-
-struct ArrayTypeElementValue : ElementValue {
- virtual ~ArrayTypeElementValue() {
- for (size_t i = 0; i < values_.size(); i++) {
- delete values_[i];
- }
- }
-
- virtual void ExtractClassNames() {
- for (size_t i = 0; i < values_.size(); i++) {
- values_[i]->ExtractClassNames();
- }
- }
-
- void Write(u1 *&p) {
- put_u1(p, tag_);
- put_u2be(p, values_.size());
- for (size_t ii = 0; ii < values_.size(); ++ii) {
- values_[ii]->Write(p);
- }
- }
- static ArrayTypeElementValue *Read(const u1 *&p) {
- ArrayTypeElementValue *value = new ArrayTypeElementValue;
- u2 num_values = get_u2be(p);
- for (int ii = 0; ii < num_values; ++ii) {
- value->values_.push_back(ElementValue::Read(p));
- }
- return value;
- }
- std::vector<ElementValue*> values_;
-};
-
-// See sec.4.7.16 of JVM spec.
-struct Annotation {
- virtual ~Annotation() {
- for (size_t i = 0; i < element_value_pairs_.size(); i++) {
- delete element_value_pairs_[i]->element_value_;
- delete element_value_pairs_[i];
- }
- }
-
- void ExtractClassNames() {
- for (size_t i = 0; i < element_value_pairs_.size(); i++) {
- element_value_pairs_[i]->element_value_->ExtractClassNames();
- }
- }
-
- void Write(u1 *&p) {
- put_u2be(p, type_->slot());
- put_u2be(p, element_value_pairs_.size());
- for (size_t ii = 0; ii < element_value_pairs_.size(); ++ii) {
- put_u2be(p, element_value_pairs_[ii]->element_name_->slot());
- element_value_pairs_[ii]->element_value_->Write(p);
- }
- }
- static Annotation *Read(const u1 *&p) {
- Annotation *value = new Annotation;
- value->type_ = constant(get_u2be(p));
- u2 num_element_value_pairs = get_u2be(p);
- for (int ii = 0; ii < num_element_value_pairs; ++ii) {
- ElementValuePair *pair = new ElementValuePair;
- pair->element_name_ = constant(get_u2be(p));
- pair->element_value_ = ElementValue::Read(p);
- value->element_value_pairs_.push_back(pair);
- }
- return value;
- }
- Constant *type_;
- struct ElementValuePair {
- Constant *element_name_;
- ElementValue *element_value_;
- };
- std::vector<ElementValuePair*> element_value_pairs_;
-};
-
-// See sec 4.7.20 of Java 8 JVM Spec
-//
-// Each entry in the annotations table represents a single run-time visible
-// annotation on a type used in a declaration or expression. The type_annotation
-// structure has the following format:
-//
-// type_annotation {
-// u1 target_type;
-// union {
-// type_parameter_target;
-// supertype_target;
-// type_parameter_bound_target;
-// empty_target;
-// method_formal_parameter_target;
-// throws_target;
-// localvar_target;
-// catch_target;
-// offset_target;
-// type_argument_target;
-// } target_info;
-// type_path target_path;
-// u2 type_index;
-// u2 num_element_value_pairs;
-// {
-// u2 element_name_index;
-// element_value value;
-// }
-// element_value_pairs[num_element_value_pairs];
-// }
-//
-struct TypeAnnotation {
- virtual ~TypeAnnotation() {
- delete target_info_;
- delete type_path_;
- delete annotation_;
- }
-
- void ExtractClassNames() {
- annotation_->ExtractClassNames();
- }
-
- void Write(u1 *&p) {
- put_u1(p, target_type_);
- target_info_->Write(p);
- type_path_->Write(p);
- annotation_->Write(p);
- }
-
- static TypeAnnotation *Read(const u1 *&p) {
- TypeAnnotation *value = new TypeAnnotation;
- value->target_type_ = get_u1(p);
- value->target_info_ = ReadTargetInfo(p, value->target_type_);
- value->type_path_ = TypePath::Read(p);
- value->annotation_ = Annotation::Read(p);
- return value;
- }
-
- struct TargetInfo {
- virtual ~TargetInfo() {}
- virtual void Write(u1 *&p) = 0;
- };
-
- struct TypeParameterTargetInfo : TargetInfo {
- void Write(u1 *&p) {
- put_u1(p, type_parameter_index_);
- }
- static TypeParameterTargetInfo *Read(const u1 *&p) {
- TypeParameterTargetInfo *value = new TypeParameterTargetInfo;
- value->type_parameter_index_ = get_u1(p);
- return value;
- }
- u1 type_parameter_index_;
- };
-
- struct ClassExtendsInfo : TargetInfo {
- void Write(u1 *&p) {
- put_u2be(p, supertype_index_);
- }
- static ClassExtendsInfo *Read(const u1 *&p) {
- ClassExtendsInfo *value = new ClassExtendsInfo;
- value->supertype_index_ = get_u2be(p);
- return value;
- }
- u2 supertype_index_;
- };
-
- struct TypeParameterBoundInfo : TargetInfo {
- void Write(u1 *&p) {
- put_u1(p, type_parameter_index_);
- put_u1(p, bound_index_);
- }
- static TypeParameterBoundInfo *Read(const u1 *&p) {
- TypeParameterBoundInfo *value = new TypeParameterBoundInfo;
- value->type_parameter_index_ = get_u1(p);
- value->bound_index_ = get_u1(p);
- return value;
- }
- u1 type_parameter_index_;
- u1 bound_index_;
- };
-
- struct EmptyInfo : TargetInfo {
- void Write(u1 *&) {}
- static EmptyInfo *Read(const u1 *&) {
- return new EmptyInfo;
- }
- };
-
- struct MethodFormalParameterInfo : TargetInfo {
- void Write(u1 *&p) {
- put_u1(p, method_formal_parameter_index_);
- }
- static MethodFormalParameterInfo *Read(const u1 *&p) {
- MethodFormalParameterInfo *value = new MethodFormalParameterInfo;
- value->method_formal_parameter_index_ = get_u1(p);
- return value;
- }
- u1 method_formal_parameter_index_;
- };
-
- struct ThrowsTypeInfo : TargetInfo {
- void Write(u1 *&p) {
- put_u2be(p, throws_type_index_);
- }
- static ThrowsTypeInfo *Read(const u1 *&p) {
- ThrowsTypeInfo *value = new ThrowsTypeInfo;
- value->throws_type_index_ = get_u2be(p);
- return value;
- }
- u2 throws_type_index_;
- };
-
- static TargetInfo *ReadTargetInfo(const u1 *&p, u1 target_type) {
- switch (target_type) {
- case CLASS_TYPE_PARAMETER:
- case METHOD_TYPE_PARAMETER:
- return TypeParameterTargetInfo::Read(p);
- case CLASS_EXTENDS:
- return ClassExtendsInfo::Read(p);
- case CLASS_TYPE_PARAMETER_BOUND:
- case METHOD_TYPE_PARAMETER_BOUND:
- return TypeParameterBoundInfo::Read(p);
- case FIELD:
- case METHOD_RETURN:
- case METHOD_RECEIVER:
- return new EmptyInfo;
- case METHOD_FORMAL_PARAMETER:
- return MethodFormalParameterInfo::Read(p);
- case THROWS:
- return ThrowsTypeInfo::Read(p);
- default:
- fprintf(stderr, "Illegal type annotation target type: %d\n",
- target_type);
- abort();
- }
- }
-
- struct TypePath {
- void Write(u1 *&p) {
- put_u1(p, path_.size());
- for (TypePathEntry entry : path_) {
- put_u1(p, entry.type_path_kind_);
- put_u1(p, entry.type_argument_index_);
- }
- }
- static TypePath *Read(const u1 *&p) {
- TypePath *value = new TypePath;
- u1 path_length = get_u1(p);
- for (int ii = 0; ii < path_length; ++ii) {
- TypePathEntry entry;
- entry.type_path_kind_ = get_u1(p);
- entry.type_argument_index_ = get_u1(p);
- value->path_.push_back(entry);
- }
- return value;
- }
-
- struct TypePathEntry {
- u1 type_path_kind_;
- u1 type_argument_index_;
- };
- std::vector<TypePathEntry> path_;
- };
-
- u1 target_type_;
- TargetInfo *target_info_;
- TypePath *type_path_;
- Annotation *annotation_;
-};
-
-struct AnnotationTypeElementValue : ElementValue {
- virtual ~AnnotationTypeElementValue() {
- delete annotation_;
- }
-
- void Write(u1 *&p) {
- put_u1(p, tag_);
- annotation_->Write(p);
- }
- static AnnotationTypeElementValue *Read(const u1 *&p) {
- AnnotationTypeElementValue *value = new AnnotationTypeElementValue;
- value->annotation_ = Annotation::Read(p);
- return value;
- }
-
- Annotation *annotation_;
-};
-
-ElementValue* ElementValue::Read(const u1 *&p) {
- const u1* start = p;
- ElementValue *result;
- u1 tag = get_u1(p);
- if (tag != 0 && strchr("BCDFIJSZs", (char) tag) != NULL) {
- result = BaseTypeElementValue::Read(p);
- } else if ((char) tag == 'e') {
- result = EnumTypeElementValue::Read(p);
- } else if ((char) tag == 'c') {
- result = ClassTypeElementValue::Read(p);
- } else if ((char) tag == '[') {
- result = ArrayTypeElementValue::Read(p);
- } else if ((char) tag == '@') {
- result = AnnotationTypeElementValue::Read(p);
- } else {
- fprintf(stderr, "Illegal element_value::tag: %d\n", tag);
- abort();
- }
- result->tag_ = tag;
- result->length_ = p - start;
- return result;
-}
-
-// See sec.4.7.20 of JVM spec.
-// We preserve AnnotationDefault attributes because they are required
-// in order to make use of an annotation in new code.
-struct AnnotationDefaultAttribute : Attribute {
- virtual ~AnnotationDefaultAttribute() {
- delete default_value_;
- }
-
- static AnnotationDefaultAttribute* Read(const u1 *&p,
- Constant *attribute_name) {
- AnnotationDefaultAttribute *attr = new AnnotationDefaultAttribute;
- attr->attribute_name_ = attribute_name;
- attr->default_value_ = ElementValue::Read(p);
- return attr;
- }
-
- void Write(u1 *&p) {
- WriteProlog(p, default_value_->length_);
- default_value_->Write(p);
- }
-
- virtual void ExtractClassNames() {
- default_value_->ExtractClassNames();
- }
-
- ElementValue *default_value_;
-};
-
-// See sec.4.7.2 of JVM spec.
-// We preserve ConstantValue attributes because they are required for
-// compile-time constant propagation.
-struct ConstantValueAttribute : Attribute {
-
- static ConstantValueAttribute* Read(const u1 *&p, Constant *attribute_name) {
- ConstantValueAttribute *attr = new ConstantValueAttribute;
- attr->attribute_name_ = attribute_name;
- attr->constantvalue_ = constant(get_u2be(p));
- return attr;
- }
-
- void Write(u1 *&p) {
- WriteProlog(p, 2);
- put_u2be(p, constantvalue_->slot());
- }
-
- Constant *constantvalue_;
-};
-
-// See sec.4.7.9 of JVM spec.
-// We preserve Signature attributes because they are required by the
-// compiler for type-checking of generics.
-struct SignatureAttribute : Attribute {
-
- static SignatureAttribute* Read(const u1 *&p, Constant *attribute_name) {
- SignatureAttribute *attr = new SignatureAttribute;
- attr->attribute_name_ = attribute_name;
- attr->signature_ = constant(get_u2be(p));
- return attr;
- }
-
- void Write(u1 *&p) {
- WriteProlog(p, 2);
- put_u2be(p, signature_->slot());
- }
-
- virtual void ExtractClassNames() {
- size_t signature_idx = 0;
- devtools_ijar::ExtractClassNames(signature_->Display(), &signature_idx);
- }
-
- Constant *signature_;
-};
-
-// See sec.4.7.15 of JVM spec.
-// We preserve Deprecated attributes because they are required by the
-// compiler to generate warning messages.
-struct DeprecatedAttribute : Attribute {
-
- static DeprecatedAttribute* Read(const u1 *&, Constant *attribute_name) {
- DeprecatedAttribute *attr = new DeprecatedAttribute;
- attr->attribute_name_ = attribute_name;
- return attr;
- }
-
- void Write(u1 *&p) {
- WriteProlog(p, 0);
- }
-};
-
-// See sec.4.7.16-17 of JVM spec v3. Includes RuntimeVisible and
-// RuntimeInvisible.
-//
-// We preserve all annotations.
-struct AnnotationsAttribute : Attribute {
- virtual ~AnnotationsAttribute() {
- for (size_t i = 0; i < annotations_.size(); i++) {
- delete annotations_[i];
- }
- }
-
- static AnnotationsAttribute* Read(const u1 *&p, Constant *attribute_name) {
- AnnotationsAttribute *attr = new AnnotationsAttribute;
- attr->attribute_name_ = attribute_name;
- u2 num_annotations = get_u2be(p);
- for (int ii = 0; ii < num_annotations; ++ii) {
- Annotation *annotation = Annotation::Read(p);
- attr->annotations_.push_back(annotation);
- }
- return attr;
- }
-
- virtual void ExtractClassNames() {
- for (size_t i = 0; i < annotations_.size(); i++) {
- annotations_[i]->ExtractClassNames();
- }
- }
-
- void Write(u1 *&p) {
- WriteProlog(p, -1);
- u1 *payload_start = p - 4;
- put_u2be(p, annotations_.size());
- for (size_t ii = 0; ii < annotations_.size(); ++ii) {
- annotations_[ii]->Write(p);
- }
- put_u4be(payload_start, p - 4 - payload_start); // backpatch length
- }
-
- std::vector<Annotation*> annotations_;
-};
-
-// See sec.4.7.18-19 of JVM spec. Includes RuntimeVisible and
-// RuntimeInvisible.
-//
-// We preserve all annotations.
-struct ParameterAnnotationsAttribute : Attribute {
-
- static ParameterAnnotationsAttribute* Read(const u1 *&p,
- Constant *attribute_name) {
- ParameterAnnotationsAttribute *attr = new ParameterAnnotationsAttribute;
- attr->attribute_name_ = attribute_name;
- u1 num_parameters = get_u1(p);
- for (int ii = 0; ii < num_parameters; ++ii) {
- std::vector<Annotation*> annotations;
- u2 num_annotations = get_u2be(p);
- for (int ii = 0; ii < num_annotations; ++ii) {
- Annotation *annotation = Annotation::Read(p);
- annotations.push_back(annotation);
- }
- attr->parameter_annotations_.push_back(annotations);
- }
- return attr;
- }
-
- virtual void ExtractClassNames() {
- for (size_t i = 0; i < parameter_annotations_.size(); i++) {
- const std::vector<Annotation*>& annotations = parameter_annotations_[i];
- for (size_t j = 0; j < annotations.size(); j++) {
- annotations[j]->ExtractClassNames();
- }
- }
- }
-
- void Write(u1 *&p) {
- WriteProlog(p, -1);
- u1 *payload_start = p - 4;
- put_u1(p, parameter_annotations_.size());
- for (size_t ii = 0; ii < parameter_annotations_.size(); ++ii) {
- std::vector<Annotation *> &annotations = parameter_annotations_[ii];
- put_u2be(p, annotations.size());
- for (size_t jj = 0; jj < annotations.size(); ++jj) {
- annotations[jj]->Write(p);
- }
- }
- put_u4be(payload_start, p - 4 - payload_start); // backpatch length
- }
-
- std::vector<std::vector<Annotation*> > parameter_annotations_;
-};
-
-// See sec.4.7.20 of Java 8 JVM spec. Includes RuntimeVisibleTypeAnnotations
-// and RuntimeInvisibleTypeAnnotations.
-struct TypeAnnotationsAttribute : Attribute {
- static TypeAnnotationsAttribute* Read(const u1 *&p, Constant *attribute_name,
- u4) {
- auto attr = new TypeAnnotationsAttribute;
- attr->attribute_name_ = attribute_name;
- u2 num_annotations = get_u2be(p);
- for (int ii = 0; ii < num_annotations; ++ii) {
- TypeAnnotation *annotation = TypeAnnotation::Read(p);
- attr->type_annotations_.push_back(annotation);
- }
- return attr;
- }
-
- virtual void ExtractClassNames() {
- for (size_t i = 0; i < type_annotations_.size(); i++) {
- type_annotations_[i]->ExtractClassNames();
- }
- }
-
- void Write(u1 *&p) {
- WriteProlog(p, -1);
- u1 *payload_start = p - 4;
- put_u2be(p, type_annotations_.size());
- for (TypeAnnotation *annotation : type_annotations_) {
- annotation->Write(p);
- }
- put_u4be(payload_start, p - 4 - payload_start); // backpatch length
- }
-
- std::vector<TypeAnnotation*> type_annotations_;
-};
-
-struct GeneralAttribute : Attribute {
- static GeneralAttribute* Read(const u1 *&p, Constant *attribute_name,
- u4 attribute_length) {
- auto attr = new GeneralAttribute;
- attr->attribute_name_ = attribute_name;
- attr->attribute_length_ = attribute_length;
- attr->attribute_content_ = p;
- p += attribute_length;
- return attr;
- }
-
- void Write(u1 *&p) {
- WriteProlog(p, attribute_length_);
- put_n(p, attribute_content_, attribute_length_);
- }
-
- u4 attribute_length_;
- const u1 *attribute_content_;
-};
-
-/**********************************************************************
- * *
- * ClassFile *
- * *
- **********************************************************************/
-
-struct HasAttrs {
- std::vector<Attribute*> attributes;
-
- void WriteAttrs(u1 *&p);
- void ReadAttrs(const u1 *&p);
-
- virtual ~HasAttrs() {
- for (size_t i = 0; i < attributes.size(); i++) {
- delete attributes[i];
- }
- }
-
- void ExtractClassNames() {
- for (size_t i = 0; i < attributes.size(); i++) {
- attributes[i]->ExtractClassNames();
- }
- }
-};
-
-// A field or method.
-// See sec.4.5 and 4.6 of JVM spec.
-struct Member : HasAttrs {
- u2 access_flags;
- Constant *name;
- Constant *descriptor;
-
- static Member* Read(const u1 *&p) {
- Member *m = new Member;
- m->access_flags = get_u2be(p);
- m->name = constant(get_u2be(p));
- m->descriptor = constant(get_u2be(p));
- m->ReadAttrs(p);
- return m;
- }
-
- void Write(u1 *&p) {
- put_u2be(p, access_flags);
- put_u2be(p, name->slot());
- put_u2be(p, descriptor->slot());
- WriteAttrs(p);
- }
-};
-
-// See sec.4.1 of JVM spec.
-struct ClassFile : HasAttrs {
-
- size_t length;
-
- // Header:
- u4 magic;
- u2 major;
- u2 minor;
-
- // Body:
- u2 access_flags;
- Constant *this_class;
- Constant *super_class;
- std::vector<Constant*> interfaces;
- std::vector<Member*> fields;
- std::vector<Member*> methods;
-
- virtual ~ClassFile() {
- for (size_t i = 0; i < fields.size(); i++) {
- delete fields[i];
- }
-
- for (size_t i = 0; i < methods.size(); i++) {
- delete methods[i];
- }
-
- // Constants do not need to be deleted; they are owned by the constant pool.
- }
-
- void WriteClass(u1 *&p);
-
- bool ReadConstantPool(const u1 *&p);
-
- void StripIfAnonymous();
-
- void WriteHeader(u1 *&p) {
- put_u4be(p, magic);
- put_u2be(p, major);
- put_u2be(p, minor);
-
- put_u2be(p, const_pool_out.size());
- for (u2 ii = 1; ii < const_pool_out.size(); ++ii) {
- if (const_pool_out[ii] != NULL) { // NB: NULLs appear after long/double.
- const_pool_out[ii]->Write(p);
- }
- }
- }
-
- void WriteBody(u1 *&p) {
- put_u2be(p, access_flags);
- put_u2be(p, this_class->slot());
- put_u2be(p, super_class == NULL ? 0 : super_class->slot());
- put_u2be(p, interfaces.size());
- for (size_t ii = 0; ii < interfaces.size(); ++ii) {
- put_u2be(p, interfaces[ii]->slot());
- }
- put_u2be(p, fields.size());
- for (size_t ii = 0; ii < fields.size(); ++ii) {
- fields[ii]->Write(p);
- }
- put_u2be(p, methods.size());
- for (size_t ii = 0; ii < methods.size(); ++ii) {
- methods[ii]->Write(p);
- }
-
- Attribute* inner_classes = NULL;
-
- // Make the inner classes attribute the last, so that it can know which
- // constants were needed
- for (size_t ii = 0; ii < attributes.size(); ii++) {
- if (attributes[ii]->attribute_name_->Display() == "InnerClasses") {
- inner_classes = attributes[ii];
- attributes.erase(attributes.begin() + ii);
- break;
- }
- }
-
- if (inner_classes != NULL) {
- attributes.push_back(inner_classes);
- }
-
- WriteAttrs(p);
- }
-
-};
-
-void HasAttrs::ReadAttrs(const u1 *&p) {
- u2 attributes_count = get_u2be(p);
- for (int ii = 0; ii < attributes_count; ii++) {
- Constant *attribute_name = constant(get_u2be(p));
- u4 attribute_length = get_u4be(p);
-
- std::string attr_name = attribute_name->Display();
- if (attr_name == "SourceFile" ||
- attr_name == "LineNumberTable" ||
- attr_name == "LocalVariableTable" ||
- attr_name == "LocalVariableTypeTable" ||
- attr_name == "Code" ||
- attr_name == "Synthetic" ||
- attr_name == "BootstrapMethods") {
- p += attribute_length; // drop these attributes
- } else if (attr_name == "Exceptions") {
- attributes.push_back(ExceptionsAttribute::Read(p, attribute_name));
- } else if (attr_name == "Signature") {
- attributes.push_back(SignatureAttribute::Read(p, attribute_name));
- } else if (attr_name == "Deprecated") {
- attributes.push_back(DeprecatedAttribute::Read(p, attribute_name));
- } else if (attr_name == "EnclosingMethod") {
- attributes.push_back(EnclosingMethodAttribute::Read(p, attribute_name));
- } else if (attr_name == "InnerClasses") {
- // TODO(bazel-team): omit private inner classes
- attributes.push_back(InnerClassesAttribute::Read(p, attribute_name));
- } else if (attr_name == "AnnotationDefault") {
- attributes.push_back(AnnotationDefaultAttribute::Read(p, attribute_name));
- } else if (attr_name == "ConstantValue") {
- attributes.push_back(ConstantValueAttribute::Read(p, attribute_name));
- } else if (attr_name == "RuntimeVisibleAnnotations" ||
- attr_name == "RuntimeInvisibleAnnotations") {
- attributes.push_back(AnnotationsAttribute::Read(p, attribute_name));
- } else if (attr_name == "RuntimeVisibleParameterAnnotations" ||
- attr_name == "RuntimeInvisibleParameterAnnotations") {
- attributes.push_back(
- ParameterAnnotationsAttribute::Read(p, attribute_name));
- } else if (attr_name == "Scala" ||
- attr_name == "ScalaSig" ||
- attr_name == "ScalaInlineInfo") {
- // These are opaque blobs, so can be handled with a general
- // attribute handler
- attributes.push_back(GeneralAttribute::Read(p, attribute_name,
- attribute_length));
- } else if (attr_name == "RuntimeVisibleTypeAnnotations" ||
- attr_name == "RuntimeInvisibleTypeAnnotations") {
- // JSR 308: annotations on types. JDK 7 has no use for these yet, but the
- // Checkers Framework relies on them.
- attributes.push_back(TypeAnnotationsAttribute::Read(p, attribute_name,
- attribute_length));
- } else {
- // Skip over unknown attributes with a warning. The JVM spec
- // says this is ok, so long as we handle the mandatory attributes.
- fprintf(stderr, "ijar: skipping unknown attribute: \"%s\".\n",
- attr_name.c_str());
- p += attribute_length;
- }
- }
-}
-
-void HasAttrs::WriteAttrs(u1 *&p) {
- u1* p_size = p;
-
- put_u2be(p, 0);
- int n_written_attrs = 0;
- for (size_t ii = 0; ii < attributes.size(); ii++) {
- u1* before = p;
- attributes[ii]->Write(p);
- if (p != before) {
- n_written_attrs++;
- }
- }
-
- put_u2be(p_size, n_written_attrs);
-}
-
-// See sec.4.4 of JVM spec.
-bool ClassFile::ReadConstantPool(const u1 *&p) {
-
- const_pool_in.clear();
- const_pool_in.push_back(NULL); // dummy first item
-
- u2 cp_count = get_u2be(p);
- for (int ii = 1; ii < cp_count; ++ii) {
- u1 tag = get_u1(p);
-
- if (devtools_ijar::verbose) {
- fprintf(stderr, "cp[%d/%d] = tag %d\n", ii, cp_count, tag);
- }
-
- switch(tag) {
- case CONSTANT_Class: {
- u2 name_index = get_u2be(p);
- const_pool_in.push_back(new Constant_Class(name_index));
- break;
- }
- case CONSTANT_FieldRef:
- case CONSTANT_Methodref:
- case CONSTANT_Interfacemethodref: {
- u2 class_index = get_u2be(p);
- u2 nti = get_u2be(p);
- const_pool_in.push_back(new Constant_FMIref(tag, class_index, nti));
- break;
- }
- case CONSTANT_String: {
- u2 string_index = get_u2be(p);
- const_pool_in.push_back(new Constant_String(string_index));
- break;
- }
- case CONSTANT_NameAndType: {
- u2 name_index = get_u2be(p);
- u2 descriptor_index = get_u2be(p);
- const_pool_in.push_back(
- new Constant_NameAndType(name_index, descriptor_index));
- break;
- }
- case CONSTANT_Utf8: {
- u2 length = get_u2be(p);
- if (devtools_ijar::verbose) {
- fprintf(stderr, "Utf8: \"%s\" (%d)\n",
- std::string((const char*) p, length).c_str(), length);
- }
-
- const_pool_in.push_back(new Constant_Utf8(length, p));
- p += length;
- break;
- }
- case CONSTANT_Integer:
- case CONSTANT_Float: {
- u4 bytes = get_u4be(p);
- const_pool_in.push_back(new Constant_IntegerOrFloat(tag, bytes));
- break;
- }
- case CONSTANT_Long:
- case CONSTANT_Double: {
- u4 high_bytes = get_u4be(p);
- u4 low_bytes = get_u4be(p);
- const_pool_in.push_back(
- new Constant_LongOrDouble(tag, high_bytes, low_bytes));
- // Longs and doubles occupy two constant pool slots.
- // ("In retrospect, making 8-byte constants take two "constant
- // pool entries was a poor choice." --JVM Spec.)
- const_pool_in.push_back(NULL);
- ii++;
- break;
- }
- case CONSTANT_MethodHandle: {
- u1 reference_kind = get_u1(p);
- u2 reference_index = get_u2be(p);
- const_pool_in.push_back(
- new Constant_MethodHandle(reference_kind, reference_index));
- break;
- }
- case CONSTANT_MethodType: {
- u2 descriptor_index = get_u2be(p);
- const_pool_in.push_back(new Constant_MethodType(descriptor_index));
- break;
- }
- case CONSTANT_InvokeDynamic: {
- u2 bootstrap_method_attr = get_u2be(p);
- u2 name_name_type_index = get_u2be(p);
- const_pool_in.push_back(new Constant_InvokeDynamic(
- bootstrap_method_attr, name_name_type_index));
- break;
- }
- default: {
- fprintf(stderr, "Unknown constant: %02x. Passing class through.\n",
- tag);
- return false;
- }
- }
- }
-
- return true;
-}
-
-// Anonymous inner classes are stripped to opaque classes that only extend
-// Object. None of their methods or fields are accessible anyway.
-void ClassFile::StripIfAnonymous() {
- int enclosing_index = -1;
- int inner_classes_index = -1;
-
- for (size_t ii = 0; ii < attributes.size(); ++ii) {
- if (attributes[ii]->attribute_name_->Display() == "EnclosingMethod") {
- enclosing_index = ii;
- } else if (attributes[ii]->attribute_name_->Display() == "InnerClasses") {
- inner_classes_index = ii;
- }
- }
-
- // Presence of an EnclosingMethod attribute indicates a local or anonymous
- // class, which can be stripped.
- if (enclosing_index > -1) {
- // Clear the signature to only extend java.lang.Object.
- super_class = NULL;
- interfaces.clear();
-
- // Clear away all fields (implementation details).
- for (size_t ii = 0; ii < fields.size(); ++ii) {
- delete fields[ii];
- }
- fields.clear();
-
- // Clear away all methods (implementation details).
- for (size_t ii = 0; ii < methods.size(); ++ii) {
- delete methods[ii];
- }
- methods.clear();
-
- // Only preserve the InnerClasses attribute to comply with the spec.
- Attribute *attr = NULL;
- for (size_t ii = 0; ii < attributes.size(); ++ii) {
- if (static_cast<int>(ii) != inner_classes_index) {
- delete attributes[ii];
- } else {
- attr = attributes[ii];
- }
- }
- attributes.clear();
- if (attr != NULL) {
- attributes.push_back(attr);
- }
- }
-}
-
-static ClassFile *ReadClass(const void *classdata, size_t length) {
- const u1 *p = (u1*) classdata;
-
- ClassFile *clazz = new ClassFile;
-
- clazz->length = length;
-
- clazz->magic = get_u4be(p);
- if (clazz->magic != 0xCAFEBABE) {
- fprintf(stderr, "Bad magic %" PRIx32 "\n", clazz->magic);
- abort();
- }
- clazz->major = get_u2be(p);
- clazz->minor = get_u2be(p);
-
- if (!clazz->ReadConstantPool(p)) {
- delete clazz;
- return NULL;
- }
-
- clazz->access_flags = get_u2be(p);
- clazz->this_class = constant(get_u2be(p));
- class_name = clazz->this_class;
-
- u2 super_class_id = get_u2be(p);
- clazz->super_class = super_class_id == 0 ? NULL : constant(super_class_id);
-
- u2 interfaces_count = get_u2be(p);
- for (int ii = 0; ii < interfaces_count; ++ii) {
- clazz->interfaces.push_back(constant(get_u2be(p)));
- }
-
- u2 fields_count = get_u2be(p);
- for (int ii = 0; ii < fields_count; ++ii) {
- Member *field = Member::Read(p);
-
- if (!(field->access_flags & ACC_PRIVATE)) { // drop private fields
- clazz->fields.push_back(field);
- }
- }
-
- u2 methods_count = get_u2be(p);
- for (int ii = 0; ii < methods_count; ++ii) {
- Member *method = Member::Read(p);
-
- // drop class initializers
- if (method->name->Display() == "<clinit>") continue;
-
- if (!(method->access_flags & ACC_PRIVATE)) { // drop private methods
- clazz->methods.push_back(method);
- }
- }
-
- clazz->ReadAttrs(p);
- clazz->StripIfAnonymous();
-
- return clazz;
-}
-
-// In theory, '/' is also reserved, but it's okay if we just parse package
-// identifiers as part of the class name. Note that signatures are UTF-8, but
-// this works just as well as in plain ASCII.
-static const char *SIGNATURE_NON_IDENTIFIER_CHARS = ".;[<>:";
-
-void Expect(const std::string& desc, size_t* p, char expected) {
- if (desc[*p] != expected) {
- fprintf(stderr, "Expected '%c' in '%s' at %zd in signature\n",
- expected, desc.substr(*p).c_str(), *p);
- exit(1);
- }
-
- *p += 1;
-}
-
-// These functions form a crude recursive descent parser for descriptors and
-// signatures in class files (see JVM spec 4.3).
-//
-// This parser is a bit more liberal than the spec, but this should be fine,
-// because it accepts all valid class files and croaks only on invalid ones.
-void ParseFromClassTypeSignature(const std::string& desc, size_t* p);
-void ParseSimpleClassTypeSignature(const std::string& desc, size_t* p);
-void ParseClassTypeSignatureSuffix(const std::string& desc, size_t* p);
-void ParseIdentifier(const std::string& desc, size_t* p);
-void ParseTypeArgumentsOpt(const std::string& desc, size_t* p);
-void ParseMethodDescriptor(const std::string& desc, size_t* p);
-
-void ParseClassTypeSignature(const std::string& desc, size_t* p) {
- Expect(desc, p, 'L');
- ParseSimpleClassTypeSignature(desc, p);
- ParseClassTypeSignatureSuffix(desc, p);
- Expect(desc, p, ';');
-}
-
-void ParseSimpleClassTypeSignature(const std::string& desc, size_t* p) {
- ParseIdentifier(desc, p);
- ParseTypeArgumentsOpt(desc, p);
-}
-
-void ParseClassTypeSignatureSuffix(const std::string& desc, size_t* p) {
- while (desc[*p] == '.') {
- *p += 1;
- ParseSimpleClassTypeSignature(desc, p);
- }
-}
-
-void ParseIdentifier(const std::string& desc, size_t* p) {
- size_t next = desc.find_first_of(SIGNATURE_NON_IDENTIFIER_CHARS, *p);
- std::string id = desc.substr(*p, next - *p);
- used_class_names.insert(id);
- *p = next;
-}
-
-void ParseTypeArgumentsOpt(const std::string& desc, size_t* p) {
- if (desc[*p] != '<') {
- return;
- }
-
- *p += 1;
- while (desc[*p] != '>') {
- switch (desc[*p]) {
- case '*':
- *p += 1;
- break;
-
- case '+':
- case '-':
- *p += 1;
- ExtractClassNames(desc, p);
- break;
-
- default:
- ExtractClassNames(desc, p);
- break;
- }
- }
-
- *p += 1;
-}
-
-void ParseMethodDescriptor(const std::string& desc, size_t* p) {
- Expect(desc, p, '(');
- while (desc[*p] != ')') {
- ExtractClassNames(desc, p);
- }
-
- Expect(desc, p, ')');
- ExtractClassNames(desc, p);
-}
-
-void ParseFormalTypeParameters(const std::string& desc, size_t* p) {
- Expect(desc, p, '<');
- while (desc[*p] != '>') {
- ParseIdentifier(desc, p);
- Expect(desc, p, ':');
- if (desc[*p] != ':' && desc[*p] != '>') {
- ExtractClassNames(desc, p);
- }
-
- while (desc[*p] == ':') {
- Expect(desc, p, ':');
- ExtractClassNames(desc, p);
- }
- }
-
- Expect(desc, p, '>');
-}
-
-void ExtractClassNames(const std::string& desc, size_t* p) {
- switch (desc[*p]) {
- case '<':
- ParseFormalTypeParameters(desc, p);
- ExtractClassNames(desc, p);
- break;
-
- case 'L':
- ParseClassTypeSignature(desc, p);
- break;
-
- case '[':
- *p += 1;
- ExtractClassNames(desc, p);
- break;
-
- case 'T':
- *p += 1;
- ParseIdentifier(desc, p);
- Expect(desc, p, ';');
- break;
-
- case '(':
- ParseMethodDescriptor(desc, p);
- break;
-
- case 'B':
- case 'C':
- case 'D':
- case 'F':
- case 'I':
- case 'J':
- case 'S':
- case 'Z':
- case 'V':
- *p += 1;
- break;
-
- default:
- fprintf(stderr, "Invalid signature %s\n", desc.substr(*p).c_str());
- }
-}
-
-void ClassFile::WriteClass(u1 *&p) {
- used_class_names.clear();
- std::vector<Member *> members;
- members.insert(members.end(), fields.begin(), fields.end());
- members.insert(members.end(), methods.begin(), methods.end());
- ExtractClassNames();
- for (size_t i = 0; i < members.size(); i++) {
- Member *member = members[i];
- size_t idx = 0;
- devtools_ijar::ExtractClassNames(member->descriptor->Display(), &idx);
- member->ExtractClassNames();
- }
-
- // We have to write the body out before the header in order to reference
- // the essential constants and populate the output constant pool:
- u1 *body = new u1[length];
- u1 *q = body;
- WriteBody(q); // advances q
- u4 body_length = q - body;
-
- WriteHeader(p); // advances p
- put_n(p, body, body_length);
- delete[] body;
-}
-
-
-void StripClass(u1 *&classdata_out, const u1 *classdata_in, size_t in_length) {
- ClassFile *clazz = ReadClass(classdata_in, in_length);
- if (clazz == NULL) {
- // Class is invalid. Simply copy it to the output and call it a day.
- put_n(classdata_out, classdata_in, in_length);
- } else {
-
- // Constant pool item zero is a dummy entry. Setting it marks the
- // beginning of the output phase; calls to Constant::slot() will
- // fail if called prior to this.
- const_pool_out.push_back(NULL);
- clazz->WriteClass(classdata_out);
-
- delete clazz;
- }
-
- // Now clean up all the mess we left behind.
-
- for (size_t i = 0; i < const_pool_in.size(); i++) {
- delete const_pool_in[i];
- }
-
- const_pool_in.clear();
- const_pool_out.clear();
-}
-
-} // namespace devtools_ijar
diff --git a/tools/ijar/common.h b/tools/ijar/common.h
deleted file mode 100644
index 118041b..0000000
--- a/tools/ijar/common.h
+++ /dev/null
@@ -1,102 +0,0 @@
-// Copyright 2001,2007 Alan Donovan. All rights reserved.
-//
-// Author: Alan Donovan <adonovan@google.com>
-//
-// 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.h -- common definitions.
-//
-
-#ifndef INCLUDED_DEVTOOLS_IJAR_COMMON_H
-#define INCLUDED_DEVTOOLS_IJAR_COMMON_H
-
-#include <stddef.h>
-#include <stdint.h>
-#include <string.h>
-
-namespace devtools_ijar {
-
-typedef unsigned long long u8;
-typedef uint32_t u4;
-typedef uint16_t u2;
-typedef uint8_t u1;
-
-// be = big endian, le = little endian
-
-inline u1 get_u1(const u1 *&p) {
- return *p++;
-}
-
-inline u2 get_u2be(const u1 *&p) {
- u4 x = (p[0] << 8) | p[1];
- p += 2;
- return x;
-}
-
-inline u2 get_u2le(const u1 *&p) {
- u4 x = (p[1] << 8) | p[0];
- p += 2;
- return x;
-}
-
-inline u4 get_u4be(const u1 *&p) {
- u4 x = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
- p += 4;
- return x;
-}
-
-inline u4 get_u4le(const u1 *&p) {
- u4 x = (p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0];
- p += 4;
- return x;
-}
-
-inline void put_u1(u1 *&p, u1 x) {
- *p++ = x;
-}
-
-inline void put_u2be(u1 *&p, u2 x) {
- *p++ = x >> 8;
- *p++ = x & 0xff;
-}
-
-inline void put_u2le(u1 *&p, u2 x) {
- *p++ = x & 0xff;
- *p++ = x >> 8;;
-}
-
-inline void put_u4be(u1 *&p, u4 x) {
- *p++ = x >> 24;
- *p++ = (x >> 16) & 0xff;
- *p++ = (x >> 8) & 0xff;
- *p++ = x & 0xff;
-}
-
-inline void put_u4le(u1 *&p, u4 x) {
- *p++ = x & 0xff;
- *p++ = (x >> 8) & 0xff;
- *p++ = (x >> 16) & 0xff;
- *p++ = x >> 24;
-}
-
-// Copy n bytes from src to p, and advance p.
-inline void put_n(u1 *&p, const u1 *src, size_t n) {
- memcpy(p, src, n);
- p += n;
-}
-
-extern bool verbose;
-
-} // namespace devtools_ijar
-
-#endif // INCLUDED_DEVTOOLS_IJAR_COMMON_H
diff --git a/tools/ijar/ijar.cc b/tools/ijar/ijar.cc
deleted file mode 100644
index 1925b48..0000000
--- a/tools/ijar/ijar.cc
+++ /dev/null
@@ -1,182 +0,0 @@
-// Copyright 2001,2007 Alan Donovan. All rights reserved.
-//
-// Author: Alan Donovan <adonovan@google.com>
-//
-// 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.
-//
-// ijar.cpp -- .jar -> _interface.jar tool.
-//
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <limits.h>
-#include <errno.h>
-#include <memory>
-
-#include "zip.h"
-
-namespace devtools_ijar {
-
-bool verbose = false;
-
-// Reads a JVM class from classdata_in (of the specified length), and
-// writes out a simplified class to classdata_out, advancing the
-// pointer.
-void StripClass(u1 *&classdata_out, const u1 *classdata_in, size_t in_length);
-
-const char* CLASS_EXTENSION = ".class";
-const size_t CLASS_EXTENSION_LENGTH = strlen(CLASS_EXTENSION);
-
-// ZipExtractorProcessor that select only .class file and use
-// StripClass to generate an interface class, storing as a new file
-// in the specified ZipBuilder.
-class JarStripperProcessor : public ZipExtractorProcessor {
- public:
- JarStripperProcessor() {}
- virtual ~JarStripperProcessor() {}
-
- virtual void Process(const char* filename, const u4 attr,
- const u1* data, const size_t size);
- virtual bool Accept(const char* filename, const u4 attr);
-
- private:
- // Not owned by JarStripperProcessor, see SetZipBuilder().
- ZipBuilder* builder;
-
- public:
- // Set the ZipBuilder to add the ijar class to the output zip file.
- // This pointer should not be deleted while this class is still in use and
- // it should be set before any call to the Process() method.
- void SetZipBuilder(ZipBuilder* builder) {
- this->builder = builder;
- }
-};
-
-bool JarStripperProcessor::Accept(const char* filename, const u4) {
- ssize_t offset = strlen(filename) - CLASS_EXTENSION_LENGTH;
- if (offset >= 0) {
- return strcmp(filename + offset, CLASS_EXTENSION) == 0;
- }
- return false;
-}
-
-void JarStripperProcessor::Process(const char* filename, const u4,
- const u1* data, const size_t size) {
- if (verbose) {
- fprintf(stderr, "INFO: StripClass: %s\n", filename);
- }
- u1 *q = builder->NewFile(filename, 0);
- u1 *classdata_out = q;
- StripClass(q, data, size); // actually process it
- size_t out_length = q - classdata_out;
- builder->FinishFile(out_length);
-}
-
-// Opens "file_in" (a .jar file) for reading, and writes an interface
-// .jar to "file_out".
-void OpenFilesAndProcessJar(const char *file_out, const char *file_in) {
- JarStripperProcessor processor;
- std::unique_ptr<ZipExtractor> in(ZipExtractor::Create(file_in, &processor));
- if (in.get() == NULL) {
- fprintf(stderr, "Unable to open Zip file %s: %s\n", file_in,
- strerror(errno));
- abort();
- }
- u8 output_length = in->CalculateOutputLength();
- std::unique_ptr<ZipBuilder> out(ZipBuilder::Create(file_out, output_length));
- if (out.get() == NULL) {
- fprintf(stderr, "Unable to open output file %s: %s\n", file_out,
- strerror(errno));
- abort();
- }
- processor.SetZipBuilder(out.get());
-
- // Process all files in the zip
- if (in->ProcessAll() < 0) {
- fprintf(stderr, "%s\n", in->GetError());
- abort();
- }
-
- // Add dummy file, since javac doesn't like truly empty jars.
- if (out->GetNumberFiles() == 0) {
- out->WriteEmptyFile("dummy");
- }
- // Finish writing the output file
- if (out->Finish() < 0) {
- fprintf(stderr, "%s\n", out->GetError());
- abort();
- }
- // Get all file size
- size_t in_length = in->GetSize();
- size_t out_length = out->GetSize();
- if (verbose) {
- fprintf(stderr, "INFO: produced interface jar: %s -> %s (%d%%).\n",
- file_in, file_out,
- static_cast<int>(100.0 * out_length / in_length));
- }
-}
-
-} // namespace devtools_ijar
-
-//
-// main method
-//
-static void usage() {
- fprintf(stderr, "Usage: ijar [-v] x.jar [x_interface.jar>]\n");
- fprintf(stderr, "Creates an interface jar from the specified jar file.\n");
- exit(1);
-}
-
-int main(int argc, char **argv) {
- const char *filename_in = NULL;
- const char *filename_out = NULL;
-
- for (int ii = 1; ii < argc; ++ii) {
- if (strcmp(argv[ii], "-v") == 0) {
- devtools_ijar::verbose = true;
- } else if (filename_in == NULL) {
- filename_in = argv[ii];
- } else if (filename_out == NULL) {
- filename_out = argv[ii];
- } else {
- usage();
- }
- }
-
- if (filename_in == NULL) {
- usage();
- }
-
- // Guess output filename from input:
- char filename_out_buf[PATH_MAX];
- if (filename_out == NULL) {
- size_t len = strlen(filename_in);
- if (len > 4 && strncmp(filename_in + len - 4, ".jar", 4) == 0) {
- strcpy(filename_out_buf, filename_in);
- strcpy(filename_out_buf + len - 4, "-interface.jar");
- filename_out = filename_out_buf;
- } else {
- fprintf(stderr, "Can't determine output filename since input filename "
- "doesn't end with '.jar'.\n");
- return 1;
- }
- }
-
- if (devtools_ijar::verbose) {
- fprintf(stderr, "INFO: writing to '%s'.\n", filename_out);
- }
-
- devtools_ijar::OpenFilesAndProcessJar(filename_out, filename_in);
- return 0;
-}
diff --git a/tools/ijar/zip.cc b/tools/ijar/zip.cc
deleted file mode 100644
index 3aa06db..0000000
--- a/tools/ijar/zip.cc
+++ /dev/null
@@ -1,1032 +0,0 @@
-// Copyright 2007 Alan Donovan. All rights reserved.
-//
-// Author: Alan Donovan <adonovan@google.com>
-//
-// 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.cc -- .zip (.jar) file reading/writing routines.
-//
-
-// See README.txt for details.
-//
-// See http://www.pkware.com/documents/casestudies/APPNOTE.TXT
-// for definition of PKZIP file format.
-
-#define _FILE_OFFSET_BITS 64 // Support zip files larger than 2GB
-
-#include <errno.h>
-#include <fcntl.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/mman.h>
-#include <unistd.h>
-#include <limits.h>
-#include <limits>
-#include <vector>
-
-#include "zip.h"
-#include <zlib.h>
-
-#define LOCAL_FILE_HEADER_SIGNATURE 0x04034b50
-#define CENTRAL_FILE_HEADER_SIGNATURE 0x02014b50
-#define END_OF_CENTRAL_DIR_SIGNATURE 0x06054b50
-#define DATA_DESCRIPTOR_SIGNATURE 0x08074b50
-
-// version to extract: 1.0 - default value from APPNOTE.TXT.
-// Output JAR files contain no extra ZIP features, so this is enough.
-#define ZIP_VERSION_TO_EXTRACT 10
-#define COMPRESSION_METHOD_STORED 0 // no compression
-#define COMPRESSION_METHOD_DEFLATED 8
-
-#define GENERAL_PURPOSE_BIT_FLAG_COMPRESSED (1 << 3)
-#define GENERAL_PURPOSE_BIT_FLAG_UTF8_ENCODED (1 << 11)
-#define GENERAL_PURPOSE_BIT_FLAG_COMPRESSION_SPEED ((1 << 2) | (1 << 1))
-#define GENERAL_PURPOSE_BIT_FLAG_SUPPORTED \
- (GENERAL_PURPOSE_BIT_FLAG_COMPRESSED \
- | GENERAL_PURPOSE_BIT_FLAG_UTF8_ENCODED \
- | GENERAL_PURPOSE_BIT_FLAG_COMPRESSION_SPEED)
-
-namespace devtools_ijar {
-// In the absence of ZIP64 support, zip files are limited to 4GB.
-// http://www.info-zip.org/FAQ.html#limits
-static const u8 kMaximumOutputSize = std::numeric_limits<uint32_t>::max();
-
-static bool ProcessCentralDirEntry(const u1 *&p,
- size_t *compressed_size,
- size_t *uncompressed_size,
- char *filename,
- size_t filename_size,
- u4 *attr,
- u4 *offset);
-
-//
-// A class representing a ZipFile for reading. Its public API is exposed
-// using the ZipExtractor abstract class.
-//
-class InputZipFile : public ZipExtractor {
- public:
- InputZipFile(ZipExtractorProcessor *processor, int fd, off_t in_length,
- off_t in_offset, const u1* zipdata_in, const u1* central_dir);
- virtual ~InputZipFile();
-
- virtual const char* GetError() {
- if (errmsg[0] == 0) {
- return NULL;
- }
- return errmsg;
- }
-
- virtual bool ProcessNext();
- virtual void Reset();
- virtual size_t GetSize() {
- return in_length_;
- }
-
- virtual u8 CalculateOutputLength();
-
- private:
- ZipExtractorProcessor *processor;
-
- int fd_in; // Input file descripor
-
- // InputZipFile is responsible for maintaining the following
- // pointers. They are allocated by the Create() method before
- // the object is actually created using mmap.
- const u1 * const zipdata_in_; // start of input file mmap
- const u1 * zipdata_in_mapped_; // start of still mapped region
- const u1 * const central_dir_; // central directory in input file
-
- size_t in_length_; // size of the input file
- size_t in_offset_; // offset the input file
-
- const u1 *p; // input cursor
-
- const u1* central_dir_current_; // central dir input cursor
-
- // Buffer size is initially INITIAL_BUFFER_SIZE. It doubles in size every
- // time it is found too small, until it reaches MAX_BUFFER_SIZE. If that is
- // not enough, we bail out. We only decompress class files, so they should
- // be smaller than 64K anyway, but we give a little leeway.
- // MAX_BUFFER_SIZE must be bigger than the size of the biggest file in the
- // ZIP. It is set to 128M here so we can uncompress the Bazel server with
- // this library.
- static const size_t INITIAL_BUFFER_SIZE = 256 * 1024; // 256K
- static const size_t MAX_BUFFER_SIZE = 128 * 1024 * 1024;
- static const size_t MAX_MAPPED_REGION = 32 * 1024 * 1024;
-
- // These metadata fields are the fields of the ZIP header of the file being
- // processed.
- u2 extract_version_;
- u2 general_purpose_bit_flag_;
- u2 compression_method_;
- u4 uncompressed_size_;
- u4 compressed_size_;
- u2 file_name_length_;
- u2 extra_field_length_;
- const u1 *file_name_;
- const u1 *extra_field_;
-
- // Administration of memory reserved for decompressed data. We use the same
- // buffer for each file to avoid some malloc()/free() calls and free the
- // memory only in the dtor. C-style memory management is used so that we
- // can call realloc.
- u1 *uncompressed_data_;
- size_t uncompressed_data_allocated_;
-
- // Copy of the last filename entry - Null-terminated.
- char filename[PATH_MAX];
- // The external file attribute field
- u4 attr;
-
- // last error
- char errmsg[4*PATH_MAX];
-
- int error(const char *fmt, ...) {
- va_list ap;
- va_start(ap, fmt);
- vsnprintf(errmsg, 4*PATH_MAX, fmt, ap);
- va_end(ap);
- return -1;
- }
-
- // Check that at least n bytes remain in the input file, otherwise
- // abort with an error message. "state" is the name of the field
- // we're about to read, for diagnostics.
- int EnsureRemaining(size_t n, const char *state) {
- size_t in_offset = p - zipdata_in_;
- size_t remaining = in_length_ - in_offset;
- if (n > remaining) {
- return error("Premature end of file (at offset %zd, state=%s); "
- "expected %zd more bytes but found %zd.\n",
- in_offset, state, n, remaining);
- }
- return 0;
- }
-
- // Read one entry from input zip file
- int ProcessLocalFileEntry(size_t compressed_size, size_t uncompressed_size);
-
- // Uncompress a file from the archive using zlib. The pointer returned
- // is owned by InputZipFile, so it must not be freed. Advances the input
- // cursor to the first byte after the compressed data.
- u1* UncompressFile();
-
- // Skip a file
- int SkipFile(const bool compressed);
-
- // Process a file
- int ProcessFile(const bool compressed);
-};
-
-//
-// A class implementing ZipBuilder that represent an open zip file for writing.
-//
-class OutputZipFile : public ZipBuilder {
- public:
- OutputZipFile(int fd, u1 * const zipdata_out) :
- fd_out(fd),
- zipdata_out_(zipdata_out),
- q(zipdata_out) {
- errmsg[0] = 0;
- }
-
- virtual const char* GetError() {
- if (errmsg[0] == 0) {
- return NULL;
- }
- return errmsg;
- }
-
- virtual ~OutputZipFile() { Finish(); }
- virtual u1* NewFile(const char* filename, const u4 attr);
- virtual int FinishFile(size_t filelength, bool compress = false,
- bool compute_crc = false);
- virtual int WriteEmptyFile(const char *filename);
- virtual size_t GetSize() {
- return Offset(q);
- }
- virtual int GetNumberFiles() {
- return entries_.size();
- }
- virtual int Finish();
-
- private:
- struct LocalFileEntry {
- // Start of the local header (in the output buffer).
- size_t local_header_offset;
-
- // Sizes of the file entry
- size_t uncompressed_length;
- size_t compressed_length;
-
- // Compression method
- u2 compression_method;
-
- // CRC32
- u4 crc32;
-
- // external attributes field
- u4 external_attr;
-
- // Start/length of the file_name in the local header.
- u1 *file_name;
- u2 file_name_length;
-
- // Start/length of the extra_field in the local header.
- const u1 *extra_field;
- u2 extra_field_length;
- };
-
- int fd_out; // file descriptor for the output file
-
- // OutputZipFile is responsible for maintaining the following
- // pointers. They are allocated by the Create() method before
- // the object is actually created using mmap.
- u1 * const zipdata_out_; // start of output file mmap
- u1 *q; // output cursor
-
- u1 *header_ptr; // Current pointer to "compression method" entry.
-
- // List of entries to write the central directory
- std::vector<LocalFileEntry*> entries_;
-
- // last error
- char errmsg[4*PATH_MAX];
-
- int error(const char *fmt, ...) {
- va_list ap;
- va_start(ap, fmt);
- vsnprintf(errmsg, 4*PATH_MAX, fmt, ap);
- va_end(ap);
- return -1;
- }
-
- // Write the ZIP central directory structure for each local file
- // entry in "entries".
- void WriteCentralDirectory();
-
- // Returns the offset of the pointer relative to the start of the
- // output zip file.
- size_t Offset(const u1 *const x) {
- return x - zipdata_out_;
- }
-
- // Write ZIP file header in the output. Since the compressed size is not
- // known in advance, it must be recorded later. This method returns a pointer
- // to "compressed size" in the file header that should be passed to
- // WriteFileSizeInLocalFileHeader() later.
- u1* WriteLocalFileHeader(const char *filename, const u4 attr);
-
- // Fill in the "compressed size" and "uncompressed size" fields in a local
- // file header previously written by WriteLocalFileHeader().
- size_t WriteFileSizeInLocalFileHeader(u1 *header_ptr,
- size_t out_length,
- bool compress = false,
- const u4 crc = 0);
-};
-
-//
-// Implementation of InputZipFile
-//
-bool InputZipFile::ProcessNext() {
- // Process the next entry in the central directory. Also make sure that the
- // content pointer is in sync.
- size_t compressed, uncompressed;
- u4 offset;
- if (!ProcessCentralDirEntry(central_dir_current_, &compressed, &uncompressed,
- filename, PATH_MAX, &attr, &offset)) {
- return false;
- }
-
- // There might be an offset specified in the central directory that does
- // not match the file offset, if so, correct the pointer.
- if (offset != 0 && (p != (zipdata_in_ + in_offset_ + offset))) {
- p = zipdata_in_ + offset;
- }
-
- if (EnsureRemaining(4, "signature") < 0) {
- return false;
- }
- u4 signature = get_u4le(p);
- if (signature == LOCAL_FILE_HEADER_SIGNATURE) {
- if (ProcessLocalFileEntry(compressed, uncompressed) < 0) {
- return false;
- }
- } else {
- error("local file header signature for file %s not found\n", filename);
- return false;
- }
-
- return true;
-}
-
-int InputZipFile::ProcessLocalFileEntry(
- size_t compressed_size, size_t uncompressed_size) {
- if (EnsureRemaining(26, "extract_version") < 0) {
- return -1;
- }
- extract_version_ = get_u2le(p);
- general_purpose_bit_flag_ = get_u2le(p);
-
- if ((general_purpose_bit_flag_ & ~GENERAL_PURPOSE_BIT_FLAG_SUPPORTED) != 0) {
- return error("Unsupported value (0x%04x) in general purpose bit flag.\n",
- general_purpose_bit_flag_);
- }
-
- compression_method_ = get_u2le(p);
-
- if (compression_method_ != COMPRESSION_METHOD_DEFLATED &&
- compression_method_ != COMPRESSION_METHOD_STORED) {
- return error("Unsupported compression method (%d).\n",
- compression_method_);
- }
-
- // skip over: last_mod_file_time, last_mod_file_date, crc32
- p += 2 + 2 + 4;
- compressed_size_ = get_u4le(p);
- uncompressed_size_ = get_u4le(p);
- file_name_length_ = get_u2le(p);
- extra_field_length_ = get_u2le(p);
-
- if (EnsureRemaining(file_name_length_, "file_name") < 0) {
- return -1;
- }
- file_name_ = p;
- p += file_name_length_;
-
- if (EnsureRemaining(extra_field_length_, "extra_field") < 0) {
- return -1;
- }
- extra_field_ = p;
- p += extra_field_length_;
-
- bool is_compressed = compression_method_ == COMPRESSION_METHOD_DEFLATED;
-
- // If the zip is compressed, compressed and uncompressed size members are
- // zero in the local file header. If not, check that they are the same as the
- // lengths from the central directory, otherwise, just believe the central
- // directory
- if (compressed_size_ == 0) {
- compressed_size_ = compressed_size;
- } else {
- if (compressed_size_ != compressed_size) {
- return error("central directory and file header inconsistent\n");
- }
- }
-
- if (uncompressed_size_ == 0) {
- uncompressed_size_ = uncompressed_size;
- } else {
- if (uncompressed_size_ != uncompressed_size) {
- return error("central directory and file header inconsistent\n");
- }
- }
-
- if (processor->Accept(filename, attr)) {
- if (ProcessFile(is_compressed) < 0) {
- return -1;
- }
- } else {
- if (SkipFile(is_compressed) < 0) {
- return -1;
- }
- }
-
- if (general_purpose_bit_flag_ & GENERAL_PURPOSE_BIT_FLAG_COMPRESSED) {
- // Skip the data descriptor. Some implementations do not put the signature
- // here, so check if the next 4 bytes are a signature, and if so, skip the
- // next 12 bytes (for CRC, compressed/uncompressed size), otherwise skip
- // the next 8 bytes (because the value just read was the CRC).
- u4 signature = get_u4le(p);
- if (signature == DATA_DESCRIPTOR_SIGNATURE) {
- p += 4 * 3;
- } else {
- p += 4 * 2;
- }
- }
-
- if (p > zipdata_in_mapped_ + MAX_MAPPED_REGION) {
- munmap(const_cast<u1 *>(zipdata_in_mapped_), MAX_MAPPED_REGION);
- zipdata_in_mapped_ += MAX_MAPPED_REGION;
- }
-
- return 0;
-}
-
-int InputZipFile::SkipFile(const bool compressed) {
- if (!compressed) {
- // In this case, compressed_size_ == uncompressed_size_ (since the file is
- // uncompressed), so we can use either.
- if (compressed_size_ != uncompressed_size_) {
- return error("compressed size != uncompressed size, although the file "
- "is uncompressed.\n");
- }
- }
-
- if (EnsureRemaining(compressed_size_, "file_data") < 0) {
- return -1;
- }
- p += compressed_size_;
- return 0;
-}
-
-u1* InputZipFile::UncompressFile() {
- size_t in_offset = p - zipdata_in_;
- size_t remaining = in_length_ - in_offset;
- z_stream stream;
-
- stream.zalloc = Z_NULL;
- stream.zfree = Z_NULL;
- stream.opaque = Z_NULL;
- stream.avail_in = remaining;
- stream.next_in = (Bytef *) p;
-
- int ret = inflateInit2(&stream, -MAX_WBITS);
- if (ret != Z_OK) {
- error("inflateInit: %d\n", ret);
- return NULL;
- }
-
- int uncompressed_until_now = 0;
-
- while (true) {
- stream.avail_out = uncompressed_data_allocated_ - uncompressed_until_now;
- stream.next_out = uncompressed_data_ + uncompressed_until_now;
- int old_avail_out = stream.avail_out;
-
- ret = inflate(&stream, Z_SYNC_FLUSH);
- int uncompressed_now = old_avail_out - stream.avail_out;
- uncompressed_until_now += uncompressed_now;
-
- switch (ret) {
- case Z_STREAM_END: {
- // zlib said that there is no more data to decompress.
-
- u1 *new_p = reinterpret_cast<u1*>(stream.next_in);
- compressed_size_ = new_p - p;
- uncompressed_size_ = uncompressed_until_now;
- p = new_p;
- inflateEnd(&stream);
- return uncompressed_data_;
- }
-
- case Z_OK: {
- // zlib said that there is no more room in the buffer allocated for
- // the decompressed data. Enlarge that buffer and try again.
-
- if (uncompressed_data_allocated_ == MAX_BUFFER_SIZE) {
- error("ijar does not support decompressing files "
- "larger than %dMB.\n",
- (int) (MAX_BUFFER_SIZE/(1024*1024)));
- return NULL;
- }
-
- uncompressed_data_allocated_ *= 2;
- if (uncompressed_data_allocated_ > MAX_BUFFER_SIZE) {
- uncompressed_data_allocated_ = MAX_BUFFER_SIZE;
- }
-
- uncompressed_data_ = reinterpret_cast<u1*>(
- realloc(uncompressed_data_, uncompressed_data_allocated_));
- break;
- }
-
- case Z_DATA_ERROR:
- case Z_BUF_ERROR:
- case Z_STREAM_ERROR:
- case Z_NEED_DICT:
- default: {
- error("zlib returned error code %d during inflate.\n", ret);
- return NULL;
- }
- }
- }
-}
-
-int InputZipFile::ProcessFile(const bool compressed) {
- const u1 *file_data;
- if (compressed) {
- file_data = UncompressFile();
- if (file_data == NULL) {
- return -1;
- }
- } else {
- // In this case, compressed_size_ == uncompressed_size_ (since the file is
- // uncompressed), so we can use either.
- if (compressed_size_ != uncompressed_size_) {
- return error("compressed size != uncompressed size, although the file "
- "is uncompressed.\n");
- }
-
- if (EnsureRemaining(compressed_size_, "file_data") < 0) {
- return -1;
- }
- file_data = p;
- p += compressed_size_;
- }
- processor->Process(filename, attr, file_data, uncompressed_size_);
- return 0;
-}
-
-
-// Reads and returns some metadata of the next file from the central directory:
-// - compressed size
-// - uncompressed size
-// - whether the entry is a class file (to be included in the output).
-// Precondition: p points to the beginning of an entry in the central dir
-// Postcondition: p points to the beginning of the next entry in the central dir
-// Returns true if the central directory contains another file and false if not.
-// Of course, in the latter case, the size output variables are not changed.
-// Note that the central directory is always followed by another data structure
-// that has a signature, so parsing it this way is safe.
-static bool ProcessCentralDirEntry(
- const u1 *&p, size_t *compressed_size, size_t *uncompressed_size,
- char *filename, size_t filename_size, u4 *attr, u4 *offset) {
- u4 signature = get_u4le(p);
- if (signature != CENTRAL_FILE_HEADER_SIGNATURE) {
- return false;
- }
-
- p += 16; // skip to 'compressed size' field
- *compressed_size = get_u4le(p);
- *uncompressed_size = get_u4le(p);
- u2 file_name_length = get_u2le(p);
- u2 extra_field_length = get_u2le(p);
- u2 file_comment_length = get_u2le(p);
- p += 4; // skip to external file attributes field
- *attr = get_u4le(p);
- *offset = get_u4le(p);
- {
- size_t len = (file_name_length < filename_size)
- ? file_name_length
- : (filename_size - 1);
- memcpy(reinterpret_cast<void*>(filename), p, len);
- filename[len] = 0;
- }
- p += file_name_length;
- p += extra_field_length;
- p += file_comment_length;
- return true;
-}
-
-// Gives a maximum bound on the size of the interface JAR. Basically, adds
-// the difference between the compressed and uncompressed sizes to the size
-// of the input file.
-u8 InputZipFile::CalculateOutputLength() {
- const u1* current = central_dir_;
-
- u8 compressed_size = 0;
- u8 uncompressed_size = 0;
- u8 skipped_compressed_size = 0;
- u4 attr;
- u4 offset;
- char filename[PATH_MAX];
-
- while (true) {
- size_t file_compressed, file_uncompressed;
- if (!ProcessCentralDirEntry(current,
- &file_compressed, &file_uncompressed,
- filename, PATH_MAX, &attr, &offset)) {
- break;
- }
-
- if (processor->Accept(filename, attr)) {
- compressed_size += (u8) file_compressed;
- uncompressed_size += (u8) file_uncompressed;
- } else {
- skipped_compressed_size += file_compressed;
- }
- }
-
- // The worst case is when the output is simply the input uncompressed. The
- // metadata in the zip file will stay the same, so the file will grow by the
- // difference between the compressed and uncompressed sizes.
- return (u8) in_length_ - skipped_compressed_size
- + (uncompressed_size - compressed_size);
-}
-
-// Given the data in the zip file, returns the offset of the central directory
-// and the number of files contained in it.
-bool FindZipCentralDirectory(const u1* bytes, size_t in_length,
- u4* offset, const u1** central_dir) {
- static const int MAX_COMMENT_LENGTH = 0xffff;
- static const int CENTRAL_DIR_LOCATOR_SIZE = 22;
- // Maximum distance of start of central dir locator from end of file
- static const int MAX_DELTA = MAX_COMMENT_LENGTH + CENTRAL_DIR_LOCATOR_SIZE;
- const u1* last_pos_to_check = in_length < MAX_DELTA
- ? bytes
- : bytes + (in_length - MAX_DELTA);
- const u1* current;
- bool found = false;
-
- for (current = bytes + in_length - CENTRAL_DIR_LOCATOR_SIZE;
- current >= last_pos_to_check;
- current-- ) {
- const u1* p = current;
- if (get_u4le(p) != END_OF_CENTRAL_DIR_SIGNATURE) {
- continue;
- }
-
- p += 16; // skip to comment length field
- u2 comment_length = get_u2le(p);
-
- // Does the comment go exactly till the end of the file?
- if (current + comment_length + CENTRAL_DIR_LOCATOR_SIZE
- != bytes + in_length) {
- continue;
- }
-
- // Hooray, we found it!
- found = true;
- break;
- }
-
- if (!found) {
- fprintf(stderr, "file is invalid or corrupted (missing end of central "
- "directory record)\n");
- return false;
- }
-
- const u1* end_of_central_dir = current;
- get_u4le(current); // central directory locator signature, already checked
- u2 number_of_this_disk = get_u2le(current);
- u2 disk_with_central_dir = get_u2le(current);
- u2 central_dir_entries_on_this_disk = get_u2le(current);
- u2 central_dir_entries = get_u2le(current);
- u4 central_dir_size = get_u4le(current);
- u4 central_dir_offset = get_u4le(current);
- u2 file_comment_length = get_u2le(current);
- current += file_comment_length; // set current to the end of the central dir
-
- if (number_of_this_disk != 0
- || disk_with_central_dir != 0
- || central_dir_entries_on_this_disk != central_dir_entries) {
- fprintf(stderr, "multi-disk JAR files are not supported\n");
- return false;
- }
-
- // Do not change output values before determining that they are OK.
- *offset = central_dir_offset;
- // Central directory start can then be used to determine the actual
- // starts of the zip file (which can be different in case of a non-zip
- // header like for auto-extractable binaries).
- *central_dir = end_of_central_dir - central_dir_size;
- return true;
-}
-
-void InputZipFile::Reset() {
- central_dir_current_ = central_dir_;
- zipdata_in_mapped_ = zipdata_in_;
- p = zipdata_in_ + in_offset_;
-}
-
-int ZipExtractor::ProcessAll() {
- while (ProcessNext()) {}
- if (GetError() != NULL) {
- return -1;
- }
- return 0;
-}
-
-ZipExtractor* ZipExtractor::Create(const char* filename,
- ZipExtractorProcessor *processor) {
- int fd_in = open(filename, O_RDONLY);
- if (fd_in < 0) {
- return NULL;
- }
-
- off_t length = lseek(fd_in, 0, SEEK_END);
- if (length < 0) {
- return NULL;
- }
-
- void *zipdata_in = mmap(NULL, length, PROT_READ, MAP_PRIVATE, fd_in, 0);
- if (zipdata_in == MAP_FAILED) {
- return NULL;
- }
-
- u4 central_dir_offset;
- const u1 *central_dir = NULL;
-
- if (!devtools_ijar::FindZipCentralDirectory(
- static_cast<const u1*>(zipdata_in), length,
- ¢ral_dir_offset, ¢ral_dir)) {
- errno = EIO; // we don't really have a good error number
- return NULL;
- }
- const u1 *zipdata_start = static_cast<const u1*>(zipdata_in);
- off_t offset = - static_cast<off_t>(zipdata_start
- + central_dir_offset
- - central_dir);
-
- return new InputZipFile(processor, fd_in, length, offset,
- zipdata_start, central_dir);
-}
-
-InputZipFile::InputZipFile(ZipExtractorProcessor *processor, int fd,
- off_t in_length, off_t in_offset,
- const u1* zipdata_in, const u1* central_dir)
- : processor(processor), fd_in(fd),
- zipdata_in_(zipdata_in), zipdata_in_mapped_(zipdata_in),
- central_dir_(central_dir), in_length_(in_length), in_offset_(in_offset),
- p(zipdata_in + in_offset), central_dir_current_(central_dir) {
- uncompressed_data_allocated_ = INITIAL_BUFFER_SIZE;
- uncompressed_data_ =
- reinterpret_cast<u1*>(malloc(uncompressed_data_allocated_));
- errmsg[0] = 0;
-}
-
-InputZipFile::~InputZipFile() {
- free(uncompressed_data_);
- close(fd_in);
-}
-
-
-//
-// Implementation of OutputZipFile
-//
-int OutputZipFile::WriteEmptyFile(const char *filename) {
- const u1* file_name = (const u1*) filename;
- size_t file_name_length = strlen(filename);
-
- LocalFileEntry *entry = new LocalFileEntry;
- entry->local_header_offset = Offset(q);
- entry->external_attr = 0;
- entry->crc32 = 0;
-
- // Output the ZIP local_file_header:
- put_u4le(q, LOCAL_FILE_HEADER_SIGNATURE);
- put_u2le(q, 10); // extract_version
- put_u2le(q, 0); // general_purpose_bit_flag
- put_u2le(q, 0); // compression_method
- put_u2le(q, 0); // last_mod_file_time
- put_u2le(q, 0); // last_mod_file_date
- put_u4le(q, entry->crc32); // crc32
- put_u4le(q, 0); // compressed_size
- put_u4le(q, 0); // uncompressed_size
- put_u2le(q, file_name_length);
- put_u2le(q, 0); // extra_field_length
- put_n(q, file_name, file_name_length);
-
- entry->file_name_length = file_name_length;
- entry->extra_field_length = 0;
- entry->compressed_length = 0;
- entry->uncompressed_length = 0;
- entry->compression_method = 0;
- entry->extra_field = (const u1 *)"";
- entry->file_name = (u1*) strdup((const char *) file_name);
- entries_.push_back(entry);
-
- return 0;
-}
-
-void OutputZipFile::WriteCentralDirectory() {
- // central directory:
- const u1 *central_directory_start = q;
- for (size_t ii = 0; ii < entries_.size(); ++ii) {
- LocalFileEntry *entry = entries_[ii];
- put_u4le(q, CENTRAL_FILE_HEADER_SIGNATURE);
- put_u2le(q, 0); // version made by
-
- put_u2le(q, ZIP_VERSION_TO_EXTRACT); // version to extract
- put_u2le(q, 0); // general purpose bit flag
- put_u2le(q, entry->compression_method); // compression method:
- put_u2le(q, 0); // last_mod_file_time
- put_u2le(q, 0); // last_mod_file_date
- put_u4le(q, entry->crc32); // crc32
- put_u4le(q, entry->compressed_length); // compressed_size
- put_u4le(q, entry->uncompressed_length); // uncompressed_size
- put_u2le(q, entry->file_name_length);
- put_u2le(q, entry->extra_field_length);
-
- put_u2le(q, 0); // file comment length
- put_u2le(q, 0); // disk number start
- put_u2le(q, 0); // internal file attributes
- put_u4le(q, entry->external_attr); // external file attributes
- // relative offset of local header:
- put_u4le(q, entry->local_header_offset);
-
- put_n(q, entry->file_name, entry->file_name_length);
- put_n(q, entry->extra_field, entry->extra_field_length);
- }
- u4 central_directory_size = q - central_directory_start;
-
- put_u4le(q, END_OF_CENTRAL_DIR_SIGNATURE);
- put_u2le(q, 0); // number of this disk
- put_u2le(q, 0); // number of the disk with the start of the central directory
- put_u2le(q, entries_.size()); // # central dir entries on this disk
- put_u2le(q, entries_.size()); // total # entries in the central directory
- put_u4le(q, central_directory_size); // size of the central directory
- put_u4le(q, Offset(central_directory_start)); // offset of start of central
- // directory wrt starting disk
- put_u2le(q, 0); // .ZIP file comment length
-}
-
-u1* OutputZipFile::WriteLocalFileHeader(const char* filename, const u4 attr) {
- off_t file_name_length_ = strlen(filename);
- LocalFileEntry *entry = new LocalFileEntry;
- entry->local_header_offset = Offset(q);
- entry->file_name_length = file_name_length_;
- entry->file_name = new u1[file_name_length_];
- entry->external_attr = attr;
- memcpy(entry->file_name, filename, file_name_length_);
- entry->extra_field_length = 0;
- entry->extra_field = (const u1 *)"";
- entry->crc32 = 0;
-
- // Output the ZIP local_file_header:
- put_u4le(q, LOCAL_FILE_HEADER_SIGNATURE);
- put_u2le(q, ZIP_VERSION_TO_EXTRACT); // version to extract
- put_u2le(q, 0); // general purpose bit flag
- u1 *header_ptr = q;
- put_u2le(q, COMPRESSION_METHOD_STORED); // compression method = placeholder
- put_u2le(q, 0); // last_mod_file_time
- put_u2le(q, 0); // last_mod_file_date
- put_u4le(q, entry->crc32); // crc32
- put_u4le(q, 0); // compressed_size = placeholder
- put_u4le(q, 0); // uncompressed_size = placeholder
- put_u2le(q, entry->file_name_length);
- put_u2le(q, entry->extra_field_length);
-
- put_n(q, entry->file_name, entry->file_name_length);
- put_n(q, entry->extra_field, entry->extra_field_length);
- entries_.push_back(entry);
-
- return header_ptr;
-}
-
-// Try to compress a file entry in memory using the deflate algorithm.
-// It will compress buf (of size length) unless the compressed size is bigger
-// than the input size. The result will overwrite the content of buf and the
-// final size is returned.
-size_t TryDeflate(u1 *buf, size_t length) {
- u1 *outbuf = reinterpret_cast<u1 *>(malloc(length));
- z_stream stream;
-
- // Initialize the z_stream strcut for reading from buf and wrinting in outbuf.
- stream.zalloc = Z_NULL;
- stream.zfree = Z_NULL;
- stream.opaque = Z_NULL;
- stream.total_in = length;
- stream.avail_in = length;
- stream.total_out = length;
- stream.avail_out = length;
- stream.next_in = buf;
- stream.next_out = outbuf;
-
- // deflateInit2 negative windows size prevent the zlib wrapper to be used.
- if (deflateInit2(&stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED,
- -MAX_WBITS, 8, Z_DEFAULT_STRATEGY) != Z_OK) {
- // Failure to compress => return the buffer uncompressed
- free(outbuf);
- return length;
- }
-
- if (deflate(&stream, Z_FINISH) == Z_STREAM_END) {
- // Compression successful and fits in outbuf, let's copy the result in buf.
- length = stream.total_out;
- memcpy(buf, outbuf, length);
- }
-
- deflateEnd(&stream);
- free(outbuf);
-
- // Return the length of the resulting buffer
- return length;
-}
-
-size_t OutputZipFile::WriteFileSizeInLocalFileHeader(u1 *header_ptr,
- size_t out_length,
- bool compress,
- const u4 crc) {
- size_t compressed_size = out_length;
- if (compress) {
- compressed_size = TryDeflate(q, out_length);
- }
- // compression method
- if (compressed_size < out_length) {
- put_u2le(header_ptr, COMPRESSION_METHOD_DEFLATED);
- } else {
- put_u2le(header_ptr, COMPRESSION_METHOD_STORED);
- }
- header_ptr += 4;
- put_u4le(header_ptr, crc); // crc32
- put_u4le(header_ptr, compressed_size); // compressed_size
- put_u4le(header_ptr, out_length); // uncompressed_size
- return compressed_size;
-}
-
-int OutputZipFile::Finish() {
- if (fd_out > 0) {
- WriteCentralDirectory();
- if (ftruncate(fd_out, GetSize()) < 0) {
- return error("ftruncate(fd_out, GetSize()): %s", strerror(errno));
- }
- if (close(fd_out) < 0) {
- return error("close(fd_out): %s", strerror(errno));
- }
- fd_out = -1;
- }
- return 0;
-}
-
-u1* OutputZipFile::NewFile(const char* filename, const u4 attr) {
- header_ptr = WriteLocalFileHeader(filename, attr);
- return q;
-}
-
-int OutputZipFile::FinishFile(size_t filelength, bool compress,
- bool compute_crc) {
- u4 crc = 0;
- if (compute_crc) {
- crc = crc32(crc, q, filelength);
- }
- size_t compressed_size =
- WriteFileSizeInLocalFileHeader(header_ptr, filelength, compress, crc);
- entries_.back()->crc32 = crc;
- entries_.back()->compressed_length = compressed_size;
- entries_.back()->uncompressed_length = filelength;
- if (compressed_size < filelength) {
- entries_.back()->compression_method = COMPRESSION_METHOD_DEFLATED;
- } else {
- entries_.back()->compression_method = COMPRESSION_METHOD_STORED;
- }
- q += compressed_size;
- return 0;
-}
-
-ZipBuilder* ZipBuilder::Create(const char* zip_file, u8 estimated_size) {
- if (estimated_size > kMaximumOutputSize) {
- fprintf(stderr,
- "Uncompressed input jar has size %llu, "
- "which exceeds the maximum supported output size %llu.\n"
- "Assuming that ijar will be smaller and hoping for the best.\n",
- estimated_size, kMaximumOutputSize);
- estimated_size = kMaximumOutputSize;
- }
-
- int fd_out = open(zip_file, O_CREAT|O_RDWR|O_TRUNC, 0644);
- if (fd_out < 0) {
- return NULL;
- }
-
- // Create mmap-able sparse file
- if (ftruncate(fd_out, estimated_size) < 0) {
- return NULL;
- }
-
- // Ensure that any buffer overflow in JarStripper will result in
- // SIGSEGV or SIGBUS by over-allocating beyond the end of the file.
- size_t mmap_length = std::min(estimated_size + sysconf(_SC_PAGESIZE),
- (u8) std::numeric_limits<size_t>::max());
-
- void *zipdata_out = mmap(NULL, mmap_length, PROT_WRITE,
- MAP_SHARED, fd_out, 0);
- if (zipdata_out == MAP_FAILED) {
- fprintf(stderr, "output_length=%llu\n", estimated_size);
- return NULL;
- }
-
- return new OutputZipFile(fd_out, (u1*) zipdata_out);
-}
-
-u8 ZipBuilder::EstimateSize(char **files) {
- struct stat statst;
- // Digital signature field size = 6, End of central directory = 22, Total = 28
- u8 size = 28;
- // Count the size of all the files in the input to estimate the size of the
- // output.
- for (int i = 0; files[i] != NULL; i++) {
- if (stat(files[i], &statst) != 0) {
- fprintf(stderr, "File %s does not seem to exist.", files[i]);
- return 0;
- }
- size += statst.st_size;
- // Add sizes of Zip meta data
- // local file header = 30 bytes
- // data descriptor = 12 bytes
- // central directory descriptor = 46 bytes
- // Total: 88bytes
- size += 88;
- // The filename is stored twice (once in the central directory
- // and once in the local file header).
- size += strlen(files[i]) * 2;
- }
- return size;
-}
-
-} // namespace devtools_ijar
diff --git a/tools/ijar/zip.h b/tools/ijar/zip.h
deleted file mode 100644
index dda2c6e..0000000
--- a/tools/ijar/zip.h
+++ /dev/null
@@ -1,173 +0,0 @@
-// Copyright 2015 Google Inc. All rights reserved.
-//
-// 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.h -- .zip (.jar) file reading/writing routines.
-//
-// This file specifies the interface to use the ZIP implementation of ijar.
-//
-
-#ifndef INCLUDED_THIRD_PARTY_IJAR_ZIP_H
-#define INCLUDED_THIRD_PARTY_IJAR_ZIP_H
-
-#include <sys/stat.h>
-
-#include "common.h"
-
-namespace devtools_ijar {
-
-// Tells if this is a directory entry from the mode. This method
-// is safer than zipattr_to_mode(attr) & S_IFDIR because the unix
-// mode might not be set in DOS zip files.
-inline bool zipattr_is_dir(u4 attr) { return (attr & 0x10) != 0; }
-
-// Convert a Unix file mode to a ZIP file attribute
-inline u4 mode_to_zipattr(mode_t m) {
- return (((u4) m) << 16) + ((m & S_IFDIR) != 0 ? 0x10 : 0);
-}
-
-// Convert a ZIP file attribute to a Unix file mode
-inline mode_t zipattr_to_mode(u4 attr) {
- return ((mode_t) ((attr >> 16) & 0xffff));
-}
-
-//
-// Class interface for building ZIP files
-//
-class ZipBuilder {
- public:
- virtual ~ZipBuilder() {}
-
- // Returns the text for the last error, or null on no last error.
- virtual const char* GetError() = 0;
-
- // Add a new file to the ZIP, the file will have path "filename"
- // and external attributes "attr". This function returns a pointer
- // to a memory buffer to write the data of the file into. This buffer
- // is owned by ZipBuilder and should not be free'd by the caller. The
- // file length is then specified when the files is finished written
- // using the FinishFile(size_t) function.
- // On failure, returns NULL and GetError() will return an non-empty message.
- virtual u1* NewFile(const char* filename, const u4 attr) = 0;
-
- // Finish writing a file and specify its length. After calling this method
- // one should not reuse the pointer given by NewFile. The file can be
- // compressed using the deflate algorithm by setting `compress` to true.
- // By default, CRC32 are not computed as java tooling doesn't care, but
- // computing it can be activated by setting `compute_crc` to true.
- // On failure, returns -1 and GetError() will return an non-empty message.
- virtual int FinishFile(size_t filelength,
- bool compress = false,
- bool compute_crc = false) = 0;
-
- // Write an empty file, it is equivalent to:
- // NewFile(filename, 0);
- // FinishFile(0);
- // On failure, returns -1 and GetError() will return an non-empty message.
- virtual int WriteEmptyFile(const char* filename) = 0;
-
- // Finish writing the ZIP file. This method can be called only once
- // (subsequent calls will do nothing) and none of
- // NewFile/FinishFile/WriteEmptyFile should be called after calling Finish. If
- // this method was not called when the object is destroyed, it will be called.
- // It is here as a convenience to get information on the final generated ZIP
- // file.
- // On failure, returns -1 and GetError() will return an non-empty message.
- virtual int Finish() = 0;
-
- // Get the current size of the ZIP file. This size will not be matching the
- // final ZIP file until Finish() has been called because Finish() is actually
- // writing the central directory of the ZIP File.
- virtual size_t GetSize() = 0;
-
- // Returns the current number of files stored in the ZIP.
- virtual int GetNumberFiles() = 0;
-
- // Create a new ZipBuilder writing the file zip_file and the size of the
- // output will be at most estimated_size. Use ZipBuilder::EstimateSize() or
- // ZipExtractor::CalculateOuputLength() to have an estimated_size depending on
- // a list of file to store.
- // On failure, returns NULL. Refer to errno for error code.
- static ZipBuilder* Create(const char* zip_file, u8 estimated_size);
-
- // Estimate the maximum size of the ZIP files containing files in the "files"
- // null-terminated array.
- // Returns 0 on error.
- static u8 EstimateSize(char **files);
-};
-
-//
-// An abstract class to process data from a ZipExtractor.
-// Derive from this class if you wish to process data from a ZipExtractor.
-//
-class ZipExtractorProcessor {
- public:
- virtual ~ZipExtractorProcessor() {}
-
- // Tells whether to skip or process the file "filename". "attr" is the
- // external file attributes and can be converted to unix mode using the
- // zipattr_to_mode() function. This method is suppoed to returns true
- // if the file should be processed and false if it should be skipped.
- virtual bool Accept(const char* filename, const u4 attr) = 0;
-
- // Process a file accepted by Accept. The file "filename" has external
- // attributes "attr" and length "size". The file content is accessible
- // in the buffer pointed by "data".
- virtual void Process(const char* filename, const u4 attr,
- const u1* data, const size_t size) = 0;
-};
-
-//
-// Class interface for reading ZIP files
-//
-class ZipExtractor {
- public:
- virtual ~ZipExtractor() {}
-
- // Returns the text for the last error, or null on no last error.
- virtual const char* GetError() = 0;
-
- // Process the next files, returns false if the end of ZIP file has been
- // reached. The processor provided by the Create method will be called
- // if a file is encountered. If false is returned, check the return value
- // of GetError() for potential errors.
- virtual bool ProcessNext() = 0;
-
- // Process the all files, returns -1 on error (GetError() will be populated
- // on error).
- virtual int ProcessAll();
-
- // Reset the file pointer to the beginning.
- virtual void Reset() = 0;
-
- // Return the size of the ZIP file.
- virtual size_t GetSize() = 0;
-
- // Return the size of the resulting zip file by keeping only file
- // accepted by the processor and storing them uncompressed. This
- // method can be used to create a ZipBuilder for storing a subset
- // of the input files.
- // On error, 0 is returned and GetError() returns a non-empty message.
- virtual u8 CalculateOutputLength() = 0;
-
- // Create a ZipExtractor that extract the zip file "filename" and process
- // it with "processor".
- // On error, a null pointer is returned and the value of errno should be
- // checked.
- static ZipExtractor* Create(const char* filename,
- ZipExtractorProcessor *processor);
-};
-
-} // namespace devtools_ijar
-
-#endif // INCLUDED_THIRD_PARTY_IJAR_ZIP_H
diff --git a/tools/ijar/zip_main.cc b/tools/ijar/zip_main.cc
deleted file mode 100644
index 3f4a50c..0000000
--- a/tools/ijar/zip_main.cc
+++ /dev/null
@@ -1,312 +0,0 @@
-// Copyright 2015 Google Inc. All rights reserved.
-//
-// Author: Alan Donovan <adonovan@google.com>
-//
-// 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 / Unzip file using ijar zip implementation.
-//
-// Note that this Zip implementation intentionally don't compute CRC-32
-// because it is useless computation for jar because Java doesn't care.
-// CRC-32 of all files in the zip file will be set to 0.
-//
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <limits.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <sys/mman.h>
-#include <errno.h>
-#include <memory>
-
-#include "zip.h"
-
-namespace devtools_ijar {
-
-#define SYSCALL(expr) do { \
- if ((expr) < 0) { \
- perror(#expr); \
- abort(); \
- } \
- } while (0)
-
-//
-// A ZipExtractorProcessor that extract all files in the ZIP file.
-//
-class UnzipProcessor : public ZipExtractorProcessor {
- public:
- // Create a processor who will extract the files into output_root
- // if "extract" is set to true and will print the list of files and
- // their unix modes if "verbose" is set to true.
- UnzipProcessor(const char *output_root, bool verbose, bool extract)
- : output_root_(output_root), verbose_(verbose), extract_(extract) {}
- virtual ~UnzipProcessor() {}
-
- virtual void Process(const char* filename, const u4 attr,
- const u1* data, const size_t size);
- virtual bool Accept(const char* filename, const u4 attr) {
- return true;
- }
-
- private:
- const char *output_root_;
- const bool verbose_;
- const bool extract_;
-};
-
-// Concatene 2 path, path1 and path2, using / as a directory separator and
-// puting the result in "out". "size" specify the size of the output buffer
-void concat_path(char* out, const size_t size,
- const char *path1, const char *path2) {
- int len1 = strlen(path1);
- size_t l = len1;
- strncpy(out, path1, size - 1);
- out[size-1] = 0;
- if (l < size - 1 && path1[len1] != '/' && path2[0] != '/') {
- out[l] = '/';
- l++;
- out[l] = 0;
- }
- if (l < size - 1) {
- strncat(out, path2, size - 1 - l);
- }
-}
-
-// Do a recursive mkdir of all folders of path except the last path
-// segment (if path ends with a / then the last path segment is empty).
-// All folders are created using "mode" for creation mode.
-void mkdirs(const char *path, mode_t mode) {
- char path_[PATH_MAX];
- struct stat statst;
- strncpy(path_, path, PATH_MAX);
- path_[PATH_MAX-1] = 0;
- char *pointer = path_;
- while ((pointer = strchr(pointer, '/')) != NULL) {
- if (path_ != pointer) { // skip leading slash
- *pointer = 0;
- if (stat(path_, &statst) != 0) {
- if (mkdir(path_, mode) < 0) {
- fprintf(stderr, "Cannot create folder %s: %s\n",
- path_, strerror(errno));
- abort();
- }
- }
- *pointer = '/';
- }
- pointer++;
- }
-}
-
-void UnzipProcessor::Process(const char* filename, const u4 attr,
- const u1* data, const size_t size) {
- mode_t mode = zipattr_to_mode(attr);
- mode_t perm = mode & 0777;
- bool isdir = (mode & S_IFDIR) != 0;
- if (attr == 0) {
- // Fallback when the external attribute is not set.
- isdir = filename[strlen(filename)-1] == '/';
- perm = 0777;
- }
- if (verbose_) {
- printf("%c %o %s\n", isdir ? 'd' : 'f', perm, filename);
- }
- if (extract_) {
- char path[PATH_MAX];
- int fd;
- concat_path(path, PATH_MAX, output_root_, filename);
- mkdirs(path, perm);
- if (!isdir) {
- fd = open(path, O_CREAT | O_WRONLY, perm);
- if (fd < 0) {
- fprintf(stderr, "Cannot open file %s for writing: %s\n",
- path, strerror(errno));
- abort();
- }
- SYSCALL(write(fd, data, size));
- SYSCALL(close(fd));
- }
- }
-}
-
-// Get the basename of path and store it in output. output_size
-// is the size of the output buffer.
-void basename(const char *path, char *output, size_t output_size) {
- const char *pointer = strrchr(path, '/');
- if (pointer == NULL) {
- pointer = path;
- } else {
- pointer++; // Skip the leading slash.
- }
- strncpy(output, pointer, output_size);
- output[output_size-1] = 0;
-}
-
-
-// Execute the extraction (or just listing if just v is provided)
-int extract(char *zipfile, bool verbose, bool extract) {
- char output_root[PATH_MAX];
- getcwd(output_root, PATH_MAX);
-
- UnzipProcessor processor(output_root, verbose, extract);
- std::unique_ptr<ZipExtractor> extractor(ZipExtractor::Create(zipfile,
- &processor));
- if (extractor.get() == NULL) {
- fprintf(stderr, "Unable to open zip file %s: %s.\n", zipfile,
- strerror(errno));
- return -1;
- }
-
- if (extractor->ProcessAll() < 0) {
- fprintf(stderr, "%s.\n", extractor->GetError());
- return -1;
- }
- return 0;
-}
-
-// Execute the create operation
-int create(char *zipfile, char **files, bool flatten, bool verbose,
- bool compress) {
- struct stat statst;
- u8 size = ZipBuilder::EstimateSize(files);
- if (size == 0) {
- return -1;
- }
- std::unique_ptr<ZipBuilder> builder(ZipBuilder::Create(zipfile, size));
- if (builder.get() == NULL) {
- fprintf(stderr, "Unable to create zip file %s: %s.\n",
- zipfile, strerror(errno));
- return -1;
- }
- for (int i = 0; files[i] != NULL; i++) {
- stat(files[i], &statst);
- char path[PATH_MAX];
- bool isdir = (statst.st_mode & S_IFDIR) != 0;
-
- if (flatten && isdir) {
- continue;
- }
-
- // Compute the path, flattening it if requested
- if (flatten) {
- basename(files[i], path, PATH_MAX);
- } else {
- strncpy(path, files[i], PATH_MAX);
- path[PATH_MAX-1] = 0;
- size_t len = strlen(path);
- if (isdir && len < PATH_MAX - 1) {
- // Add the trailing slash for folders
- path[len] = '/';
- path[len+1] = 0;
- }
- }
-
- if (verbose) {
- mode_t perm = statst.st_mode & 0777;
- printf("%c %o %s\n", isdir ? 'd' : 'f', perm, path);
- }
-
- u1 *buffer = builder->NewFile(path, mode_to_zipattr(statst.st_mode));
- if (isdir || statst.st_size == 0) {
- builder->FinishFile(0);
- } else {
- // mmap the input file and memcpy
- int fd = open(files[i], O_RDONLY);
- if (fd < 0) {
- fprintf(stderr, "Can't open file %s for reading: %s.\n",
- files[i], strerror(errno));
- return -1;
- }
- void *data = mmap(NULL, statst.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
- if (data == MAP_FAILED) {
- fprintf(stderr, "Can't mmap file %s for reading: %s.\n",
- files[i], strerror(errno));
- return -1;
- }
- memcpy(buffer, data, statst.st_size);
- munmap(data, statst.st_size);
- builder->FinishFile(statst.st_size, compress, true);
- }
- }
- if (builder->Finish() < 0) {
- fprintf(stderr, "%s\n", builder->GetError());
- return -1;
- }
- return 0;
-}
-
-} // namespace devtools_ijar
-
-//
-// main method
-//
-static void usage(char *progname) {
- fprintf(stderr, "Usage: %s [vxc[fC]] x.zip [file1...filen]\n", progname);
- fprintf(stderr, " v verbose - list all file in x.zip\n");
- fprintf(stderr, " x extract - extract file in x.zip in current directory\n");
- fprintf(stderr, " c create - add files to x.zip\n");
- fprintf(stderr, " f flatten - flatten files to use with create operation\n");
- fprintf(stderr,
- " C compress - compress files when using the create operation\n");
- fprintf(stderr, "x and c cannot be used in the same command-line.\n");
- exit(1);
-}
-
-int main(int argc, char **argv) {
- bool extract = false;
- bool verbose = false;
- bool create = false;
- bool compress = false;
- bool flatten = false;
-
- if (argc < 3) {
- usage(argv[0]);
- }
-
- for (int i = 0; argv[1][i] != 0; i++) {
- switch (argv[1][i]) {
- case 'x':
- extract = true;
- break;
- case 'v':
- verbose = true;
- break;
- case 'c':
- create = true;
- break;
- case 'f':
- flatten = true;
- break;
- case 'C':
- compress = true;
- break;
- default:
- usage(argv[0]);
- }
- }
- if (create) {
- if (extract) {
- usage(argv[0]);
- }
- // Create a zip
- return devtools_ijar::create(argv[2], argv + 3, flatten, verbose, compress);
- } else {
- if (flatten) {
- usage(argv[0]);
- }
- // Extraction / list mode
- return devtools_ijar::extract(argv[2], verbose, extract);
- }
-}
diff --git a/tools/java-event-log-tags.py b/tools/java-event-log-tags.py
index f364751..37cd712 100755
--- a/tools/java-event-log-tags.py
+++ b/tools/java-event-log-tags.py
@@ -51,30 +51,37 @@
print >> sys.stderr, "unhandled option %s" % (o,)
sys.exit(1)
-if len(args) != 2:
- print "need exactly two input files, not %d" % (len(args),)
+if len(args) != 1 and len(args) != 2:
+ print "need one or two input files, not %d" % (len(args),)
print __doc__
sys.exit(1)
fn = args[0]
tagfile = event_log_tags.TagFile(fn)
-# Load the merged tag file (which should have numbers assigned for all
-# tags. Use the numbers from the merged file to fill in any missing
-# numbers from the input file.
-merged_fn = args[1]
-merged_tagfile = event_log_tags.TagFile(merged_fn)
-merged_by_name = dict([(t.tagname, t) for t in merged_tagfile.tags])
-for t in tagfile.tags:
- if t.tagnum is None:
- if t.tagname in merged_by_name:
- t.tagnum = merged_by_name[t.tagname].tagnum
- else:
- # We're building something that's not being included in the
- # product, so its tags don't appear in the merged file. Assign
- # them all an arbitrary number so we can emit the java and
- # compile the (unused) package.
- t.tagnum = 999999
+if len(args) > 1:
+ # Load the merged tag file (which should have numbers assigned for all
+ # tags. Use the numbers from the merged file to fill in any missing
+ # numbers from the input file.
+ merged_fn = args[1]
+ merged_tagfile = event_log_tags.TagFile(merged_fn)
+ merged_by_name = dict([(t.tagname, t) for t in merged_tagfile.tags])
+ for t in tagfile.tags:
+ if t.tagnum is None:
+ if t.tagname in merged_by_name:
+ t.tagnum = merged_by_name[t.tagname].tagnum
+ else:
+ # We're building something that's not being included in the
+ # product, so its tags don't appear in the merged file. Assign
+ # them all an arbitrary number so we can emit the java and
+ # compile the (unused) package.
+ t.tagnum = 999999
+else:
+ # Not using the merged tag file, so all tags must have manually assigned
+ # numbers
+ for t in tagfile.tags:
+ if t.tagnum is None:
+ tagfilef.AddError("tag \"%s\" has no number" % (tagname,), tag.linenum)
if "java_package" not in tagfile.options:
tagfile.AddError("java_package option not specified", linenum=0)
diff --git a/tools/libhost/Android.bp b/tools/libhost/Android.bp
index e5a5ecf..4c9100f 100644
--- a/tools/libhost/Android.bp
+++ b/tools/libhost/Android.bp
@@ -10,6 +10,7 @@
name: "libhost",
target: {
windows: {
+ cflags: ["-Wno-unused-parameter"],
enabled: true,
},
},
diff --git a/tools/libhost/CopyFile.c b/tools/libhost/CopyFile.c
index bd65f1e..f9bda86 100644
--- a/tools/libhost/CopyFile.c
+++ b/tools/libhost/CopyFile.c
@@ -352,7 +352,12 @@
* need to trash it so we can create one.
*/
#if defined(_WIN32)
-extern int copySymlink(const char* src, const char* dst, const struct stat* pSrcStat, unsigned int options) __attribute__((error("no symlinks on Windows")));
+extern int copySymlink(const char* src, const char* dst, const struct stat* pSrcStat, unsigned int options)
+#ifdef __clang__
+ __attribute__((unavailable("no symlinks on Windows")));
+#else
+ __attribute__((error("no symlinks on Windows")));
+#endif
#else
static int copySymlink(const char* src, const char* dst, const struct stat* pSrcStat, unsigned int options)
{
@@ -574,8 +579,10 @@
} else {
retVal = copyDirectory(src, dst, &srcStat, options);
}
+#if !defined(_WIN32)
} else if (S_ISLNK(srcStat.st_mode)) {
retVal = copySymlink(src, dst, &srcStat, options);
+#endif
} else if (S_ISREG(srcStat.st_mode)) {
retVal = copyRegular(src, dst, &srcStat, options);
} else {
diff --git a/tools/makeparallel/Android.bp b/tools/makeparallel/Android.bp
index cb81817..898db68 100644
--- a/tools/makeparallel/Android.bp
+++ b/tools/makeparallel/Android.bp
@@ -18,9 +18,4 @@
"makeparallel.cpp",
],
cflags: ["-Wall", "-Werror"],
- target: {
- linux: {
- host_ldlibs: ["-lrt", "-lpthread"],
- },
- },
}
diff --git a/tools/post_process_props.py b/tools/post_process_props.py
index 9355e4b..9ddd5d7 100755
--- a/tools/post_process_props.py
+++ b/tools/post_process_props.py
@@ -64,7 +64,7 @@
buildprops = prop.to_dict()
for key, value in buildprops.iteritems():
# Check build properties' length.
- if len(value) > PROP_VALUE_MAX:
+ if len(value) > PROP_VALUE_MAX and not key.startswith("ro."):
check_pass = False
sys.stderr.write("error: %s cannot exceed %d bytes: " %
(key, PROP_VALUE_MAX))
diff --git a/tools/releasetools/add_img_to_target_files.py b/tools/releasetools/add_img_to_target_files.py
index 1a08cb6..f68976e 100755
--- a/tools/releasetools/add_img_to_target_files.py
+++ b/tools/releasetools/add_img_to_target_files.py
@@ -45,20 +45,12 @@
from __future__ import print_function
-import sys
-
-if sys.hexversion < 0x02070000:
- print("Python 2.7 or newer is required.", file=sys.stderr)
- sys.exit(1)
-
import datetime
-import errno
-import hashlib
import os
import shlex
import shutil
import subprocess
-import tempfile
+import sys
import uuid
import zipfile
@@ -67,6 +59,10 @@
import rangelib
import sparse_img
+if sys.hexversion < 0x02070000:
+ print("Python 2.7 or newer is required.", file=sys.stderr)
+ sys.exit(1)
+
OPTIONS = common.OPTIONS
OPTIONS.add_missing = False
@@ -77,6 +73,10 @@
OPTIONS.is_signing = False
+# Partitions that should have their care_map added to META/care_map.txt.
+PARTITIONS_WITH_CARE_MAP = ('system', 'vendor', 'product')
+
+
class OutputFile(object):
def __init__(self, output_zip, input_dir, prefix, name):
self._output_zip = output_zip
@@ -96,13 +96,19 @@
def GetCareMap(which, imgname):
- """Generate care_map of system (or vendor) partition"""
+ """Returns the care_map string for the given partition.
- assert which in ("system", "vendor")
+ Args:
+ which: The partition name, must be listed in PARTITIONS_WITH_CARE_MAP.
+ imgname: The filename of the image.
+
+ Returns:
+ (which, care_map_ranges): care_map_ranges is the raw string of the care_map
+ RangeSet.
+ """
+ assert which in PARTITIONS_WITH_CARE_MAP
simg = sparse_img.SparseImage(imgname)
- care_map_list = [which]
-
care_map_ranges = simg.care_map
key = which + "_adjusted_partition_size"
adjusted_blocks = OPTIONS.info_dict.get(key)
@@ -111,17 +117,16 @@
care_map_ranges = care_map_ranges.intersect(rangelib.RangeSet(
"0-%d" % (adjusted_blocks,)))
- care_map_list.append(care_map_ranges.to_string_raw())
- return care_map_list
+ return [which, care_map_ranges.to_string_raw()]
-def AddSystem(output_zip, prefix="IMAGES/", recovery_img=None, boot_img=None):
+def AddSystem(output_zip, recovery_img=None, boot_img=None):
"""Turn the contents of SYSTEM into a system image and store it in
output_zip. Returns the name of the system image file."""
- img = OutputFile(output_zip, OPTIONS.input_tmp, prefix, "system.img")
+ img = OutputFile(output_zip, OPTIONS.input_tmp, "IMAGES", "system.img")
if os.path.exists(img.input_name):
- print("system.img already exists in %s, no need to rebuild..." % (prefix,))
+ print("system.img already exists; no need to rebuild...")
return img.input_name
def output_sink(fn, data):
@@ -140,51 +145,66 @@
common.MakeRecoveryPatch(OPTIONS.input_tmp, output_sink, recovery_img,
boot_img, info_dict=OPTIONS.info_dict)
- block_list = OutputFile(output_zip, OPTIONS.input_tmp, prefix, "system.map")
+ block_list = OutputFile(output_zip, OPTIONS.input_tmp, "IMAGES", "system.map")
CreateImage(OPTIONS.input_tmp, OPTIONS.info_dict, "system", img,
block_list=block_list)
return img.name
-def AddSystemOther(output_zip, prefix="IMAGES/"):
+def AddSystemOther(output_zip):
"""Turn the contents of SYSTEM_OTHER into a system_other image
and store it in output_zip."""
- img = OutputFile(output_zip, OPTIONS.input_tmp, prefix, "system_other.img")
+ img = OutputFile(output_zip, OPTIONS.input_tmp, "IMAGES", "system_other.img")
if os.path.exists(img.input_name):
- print("system_other.img already exists in %s, no need to rebuild..." % (
- prefix,))
+ print("system_other.img already exists; no need to rebuild...")
return
CreateImage(OPTIONS.input_tmp, OPTIONS.info_dict, "system_other", img)
-def AddVendor(output_zip, prefix="IMAGES/"):
+def AddVendor(output_zip):
"""Turn the contents of VENDOR into a vendor image and store in it
output_zip."""
- img = OutputFile(output_zip, OPTIONS.input_tmp, prefix, "vendor.img")
+ img = OutputFile(output_zip, OPTIONS.input_tmp, "IMAGES", "vendor.img")
if os.path.exists(img.input_name):
- print("vendor.img already exists in %s, no need to rebuild..." % (prefix,))
+ print("vendor.img already exists; no need to rebuild...")
return img.input_name
- block_list = OutputFile(output_zip, OPTIONS.input_tmp, prefix, "vendor.map")
+ block_list = OutputFile(output_zip, OPTIONS.input_tmp, "IMAGES", "vendor.map")
CreateImage(OPTIONS.input_tmp, OPTIONS.info_dict, "vendor", img,
block_list=block_list)
return img.name
-def AddDtbo(output_zip, prefix="IMAGES/"):
+def AddProduct(output_zip):
+ """Turn the contents of PRODUCT into a product image and store it in
+ output_zip."""
+
+ img = OutputFile(output_zip, OPTIONS.input_tmp, "IMAGES", "product.img")
+ if os.path.exists(img.input_name):
+ print("product.img already exists; no need to rebuild...")
+ return img.input_name
+
+ block_list = OutputFile(
+ output_zip, OPTIONS.input_tmp, "IMAGES", "product.map")
+ CreateImage(
+ OPTIONS.input_tmp, OPTIONS.info_dict, "product", img,
+ block_list=block_list)
+ return img.name
+
+
+def AddDtbo(output_zip):
"""Adds the DTBO image.
- Uses the image under prefix if it already exists. Otherwise looks for the
+ Uses the image under IMAGES/ if it already exists. Otherwise looks for the
image under PREBUILT_IMAGES/, signs it as needed, and returns the image name.
"""
-
- img = OutputFile(output_zip, OPTIONS.input_tmp, prefix, "dtbo.img")
+ img = OutputFile(output_zip, OPTIONS.input_tmp, "IMAGES", "dtbo.img")
if os.path.exists(img.input_name):
- print("dtbo.img already exists in %s, no need to rebuild..." % (prefix,))
+ print("dtbo.img already exists; no need to rebuild...")
return img.input_name
dtbo_prebuilt_path = os.path.join(
@@ -215,22 +235,6 @@
def CreateImage(input_dir, info_dict, what, output_file, block_list=None):
print("creating " + what + ".img...")
- # The name of the directory it is making an image out of matters to
- # mkyaffs2image. It wants "system" but we have a directory named
- # "SYSTEM", so create a symlink.
- temp_dir = tempfile.mkdtemp()
- OPTIONS.tempfiles.append(temp_dir)
- try:
- os.symlink(os.path.join(input_dir, what.upper()),
- os.path.join(temp_dir, what))
- except OSError as e:
- # bogus error on my mac version?
- # File "./build/tools/releasetools/img_from_target_files"
- # os.path.join(OPTIONS.input_tmp, "system"))
- # OSError: [Errno 17] File exists
- if e.errno == errno.EEXIST:
- pass
-
image_props = build_image.ImagePropFromGlobalDict(info_dict, what)
fstab = info_dict["fstab"]
mount_point = "/" + what
@@ -272,7 +276,7 @@
hash_seed = "hash_seed-" + uuid_seed
image_props["hash_seed"] = str(uuid.uuid5(uuid.NAMESPACE_URL, hash_seed))
- succ = build_image.BuildImage(os.path.join(temp_dir, what),
+ succ = build_image.BuildImage(os.path.join(input_dir, what.upper()),
image_props, output_file.name)
assert succ, "build " + what + ".img image failed"
@@ -294,7 +298,7 @@
info_dict[adjusted_blocks_key] = int(adjusted_blocks_value)/4096 - 1
-def AddUserdata(output_zip, prefix="IMAGES/"):
+def AddUserdata(output_zip):
"""Create a userdata image and store it in output_zip.
In most case we just create and store an empty userdata.img;
@@ -303,10 +307,9 @@
in OPTIONS.info_dict.
"""
- img = OutputFile(output_zip, OPTIONS.input_tmp, prefix, "userdata.img")
+ img = OutputFile(output_zip, OPTIONS.input_tmp, "IMAGES", "userdata.img")
if os.path.exists(img.input_name):
- print("userdata.img already exists in %s, no need to rebuild..." % (
- prefix,))
+ print("userdata.img already exists; no need to rebuild...")
return
# Skip userdata.img if no size.
@@ -322,21 +325,10 @@
timestamp = (datetime.datetime(2009, 1, 1) - epoch).total_seconds()
image_props["timestamp"] = int(timestamp)
- # The name of the directory it is making an image out of matters to
- # mkyaffs2image. So we create a temp dir, and within it we create an
- # empty dir named "data", or a symlink to the DATA dir,
- # and build the image from that.
- temp_dir = tempfile.mkdtemp()
- OPTIONS.tempfiles.append(temp_dir)
- user_dir = os.path.join(temp_dir, "data")
- empty = (OPTIONS.info_dict.get("userdata_img_with_data") != "true")
- if empty:
- # Create an empty dir.
- os.mkdir(user_dir)
+ if OPTIONS.info_dict.get("userdata_img_with_data") == "true":
+ user_dir = os.path.join(OPTIONS.input_tmp, "DATA")
else:
- # Symlink to the DATA dir.
- os.symlink(os.path.join(OPTIONS.input_tmp, "DATA"),
- user_dir)
+ user_dir = common.MakeTempDir()
fstab = OPTIONS.info_dict["fstab"]
if fstab:
@@ -373,21 +365,31 @@
cmd.extend(["--include_descriptors_from_image", img_path])
-def AddVBMeta(output_zip, boot_img_path, system_img_path, vendor_img_path,
- dtbo_img_path, prefix="IMAGES/"):
- """Create a VBMeta image and store it in output_zip."""
- img = OutputFile(output_zip, OPTIONS.input_tmp, prefix, "vbmeta.img")
+def AddVBMeta(output_zip, partitions):
+ """Creates a VBMeta image and store it in output_zip.
+
+ Args:
+ output_zip: The output zip file, which needs to be already open.
+ partitions: A dict that's keyed by partition names with image paths as
+ values. Only valid partition names are accepted, which include 'boot',
+ 'recovery', 'system', 'vendor', 'dtbo'.
+ """
+ img = OutputFile(output_zip, OPTIONS.input_tmp, "IMAGES", "vbmeta.img")
+ if os.path.exists(img.input_name):
+ print("vbmeta.img already exists; not rebuilding...")
+ return img.input_name
+
avbtool = os.getenv('AVBTOOL') or OPTIONS.info_dict["avb_avbtool"]
cmd = [avbtool, "make_vbmeta_image", "--output", img.name]
common.AppendAVBSigningArgs(cmd, "vbmeta")
- public_key_dir = tempfile.mkdtemp(prefix="avbpubkey-")
- OPTIONS.tempfiles.append(public_key_dir)
-
- AppendVBMetaArgsForPartition(cmd, "boot", boot_img_path, public_key_dir)
- AppendVBMetaArgsForPartition(cmd, "system", system_img_path, public_key_dir)
- AppendVBMetaArgsForPartition(cmd, "vendor", vendor_img_path, public_key_dir)
- AppendVBMetaArgsForPartition(cmd, "dtbo", dtbo_img_path, public_key_dir)
+ public_key_dir = common.MakeTempDir(prefix="avbpubkey-")
+ for partition, path in partitions.items():
+ assert partition in common.AVB_PARTITIONS, 'Unknown partition: %s' % (
+ partition,)
+ assert os.path.exists(path), 'Failed to find %s for partition %s' % (
+ path, partition)
+ AppendVBMetaArgsForPartition(cmd, partition, path, public_key_dir)
args = OPTIONS.info_dict.get("avb_vbmeta_args")
if args and args.strip():
@@ -403,9 +405,9 @@
if os.path.exists(image_path):
continue
found = False
- for dir in ['IMAGES', 'RADIO', 'VENDOR_IMAGES', 'PREBUILT_IMAGES']:
+ for dir_name in ['IMAGES', 'RADIO', 'VENDOR_IMAGES', 'PREBUILT_IMAGES']:
alt_path = os.path.join(
- OPTIONS.input_tmp, dir, os.path.basename(image_path))
+ OPTIONS.input_tmp, dir_name, os.path.basename(image_path))
if os.path.exists(alt_path):
split_args[index + 1] = alt_path
found = True
@@ -419,11 +421,13 @@
img.Write()
-def AddPartitionTable(output_zip, prefix="IMAGES/"):
+def AddPartitionTable(output_zip):
"""Create a partition table image and store it in output_zip."""
- img = OutputFile(output_zip, OPTIONS.input_tmp, prefix, "partition-table.img")
- bpt = OutputFile(output_zip, OPTIONS.input_tmp, prefix, "partition-table.bpt")
+ img = OutputFile(
+ output_zip, OPTIONS.input_tmp, "IMAGES", "partition-table.img")
+ bpt = OutputFile(
+ output_zip, OPTIONS.input_tmp, "IMAGES", "partition-table.bpt")
# use BPTTOOL from environ, or "bpttool" if empty or not set.
bpttool = os.getenv("BPTTOOL") or "bpttool"
@@ -448,12 +452,12 @@
bpt.Write()
-def AddCache(output_zip, prefix="IMAGES/"):
+def AddCache(output_zip):
"""Create an empty cache image and store it in output_zip."""
- img = OutputFile(output_zip, OPTIONS.input_tmp, prefix, "cache.img")
+ img = OutputFile(output_zip, OPTIONS.input_tmp, "IMAGES", "cache.img")
if os.path.exists(img.input_name):
- print("cache.img already exists in %s, no need to rebuild..." % (prefix,))
+ print("cache.img already exists; no need to rebuild...")
return
image_props = build_image.ImagePropFromGlobalDict(OPTIONS.info_dict, "cache")
@@ -469,13 +473,7 @@
timestamp = (datetime.datetime(2009, 1, 1) - epoch).total_seconds()
image_props["timestamp"] = int(timestamp)
- # The name of the directory it is making an image out of matters to
- # mkyaffs2image. So we create a temp dir, and within it we create an
- # empty dir named "cache", and build the image from that.
- temp_dir = tempfile.mkdtemp()
- OPTIONS.tempfiles.append(temp_dir)
- user_dir = os.path.join(temp_dir, "cache")
- os.mkdir(user_dir)
+ user_dir = common.MakeTempDir()
fstab = OPTIONS.info_dict["fstab"]
if fstab:
@@ -487,17 +485,133 @@
img.Write()
+def AddRadioImagesForAbOta(output_zip, ab_partitions):
+ """Adds the radio images needed for A/B OTA to the output file.
+
+ It parses the list of A/B partitions, looks for the missing ones from RADIO/
+ or VENDOR_IMAGES/ dirs, and copies them to IMAGES/ of the output file (or
+ dir).
+
+ It also ensures that on returning from the function all the listed A/B
+ partitions must have their images available under IMAGES/.
+
+ Args:
+ output_zip: The output zip file (needs to be already open), or None to
+ write images to OPTIONS.input_tmp/.
+ ab_partitions: The list of A/B partitions.
+
+ Raises:
+ AssertionError: If it can't find an image.
+ """
+ for partition in ab_partitions:
+ img_name = partition.strip() + ".img"
+ prebuilt_path = os.path.join(OPTIONS.input_tmp, "IMAGES", img_name)
+ if os.path.exists(prebuilt_path):
+ print("%s already exists, no need to overwrite..." % (img_name,))
+ continue
+
+ img_radio_path = os.path.join(OPTIONS.input_tmp, "RADIO", img_name)
+ if os.path.exists(img_radio_path):
+ if output_zip:
+ common.ZipWrite(output_zip, img_radio_path, "IMAGES/" + img_name)
+ else:
+ shutil.copy(img_radio_path, prebuilt_path)
+ continue
+
+ # Walk through VENDOR_IMAGES/ since files could be under subdirs.
+ img_vendor_dir = os.path.join(OPTIONS.input_tmp, "VENDOR_IMAGES")
+ for root, _, files in os.walk(img_vendor_dir):
+ if img_name in files:
+ if output_zip:
+ common.ZipWrite(output_zip, os.path.join(root, img_name),
+ "IMAGES/" + img_name)
+ else:
+ shutil.copy(os.path.join(root, img_name), prebuilt_path)
+ break
+
+ # Assert that the image is present under IMAGES/ now.
+ if output_zip:
+ # Zip spec says: All slashes MUST be forward slashes.
+ img_path = 'IMAGES/' + img_name
+ assert img_path in output_zip.namelist(), "cannot find " + img_name
+ else:
+ img_path = os.path.join(OPTIONS.input_tmp, "IMAGES", img_name)
+ assert os.path.exists(img_path), "cannot find " + img_name
+
+
+def AddCareMapTxtForAbOta(output_zip, ab_partitions, image_paths):
+ """Generates and adds care_map.txt for system and vendor partitions.
+
+ Args:
+ output_zip: The output zip file (needs to be already open), or None to
+ write images to OPTIONS.input_tmp/.
+ ab_partitions: The list of A/B partitions.
+ image_paths: A map from the partition name to the image path.
+ """
+ care_map_list = []
+ for partition in ab_partitions:
+ partition = partition.strip()
+ if partition not in PARTITIONS_WITH_CARE_MAP:
+ continue
+
+ verity_block_device = "{}_verity_block_device".format(partition)
+ avb_hashtree_enable = "avb_{}_hashtree_enable".format(partition)
+ if (verity_block_device in OPTIONS.info_dict or
+ OPTIONS.info_dict.get(avb_hashtree_enable) == "true"):
+ image_path = image_paths[partition]
+ assert os.path.exists(image_path)
+ care_map_list += GetCareMap(partition, image_path)
+
+ if care_map_list:
+ care_map_path = "META/care_map.txt"
+ if output_zip and care_map_path not in output_zip.namelist():
+ common.ZipWriteStr(output_zip, care_map_path, '\n'.join(care_map_list))
+ else:
+ with open(os.path.join(OPTIONS.input_tmp, care_map_path), 'w') as fp:
+ fp.write('\n'.join(care_map_list))
+ if output_zip:
+ OPTIONS.replace_updated_files_list.append(care_map_path)
+
+
+def AddPackRadioImages(output_zip, images):
+ """Copies images listed in META/pack_radioimages.txt from RADIO/ to IMAGES/.
+
+ Args:
+ output_zip: The output zip file (needs to be already open), or None to
+ write images to OPTIONS.input_tmp/.
+ images: A list of image names.
+
+ Raises:
+ AssertionError: If a listed image can't be found.
+ """
+ for image in images:
+ img_name = image.strip()
+ _, ext = os.path.splitext(img_name)
+ if not ext:
+ img_name += ".img"
+
+ prebuilt_path = os.path.join(OPTIONS.input_tmp, "IMAGES", img_name)
+ if os.path.exists(prebuilt_path):
+ print("%s already exists, no need to overwrite..." % (img_name,))
+ continue
+
+ img_radio_path = os.path.join(OPTIONS.input_tmp, "RADIO", img_name)
+ assert os.path.exists(img_radio_path), \
+ "Failed to find %s at %s" % (img_name, img_radio_path)
+
+ if output_zip:
+ common.ZipWrite(output_zip, img_radio_path, "IMAGES/" + img_name)
+ else:
+ shutil.copy(img_radio_path, prebuilt_path)
+
+
def ReplaceUpdatedFiles(zip_filename, files_list):
- """Update all the zip entries listed in the files_list.
+ """Updates all the ZIP entries listed in files_list.
For now the list includes META/care_map.txt, and the related files under
SYSTEM/ after rebuilding recovery.
"""
-
- cmd = ["zip", "-d", zip_filename] + files_list
- p = common.Run(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
- p.communicate()
-
+ common.ZipDelete(zip_filename, files_list)
output_zip = zipfile.ZipFile(zip_filename, "a",
compression=zipfile.ZIP_DEFLATED,
allowZip64=True)
@@ -509,116 +623,121 @@
def AddImagesToTargetFiles(filename):
+ """Creates and adds images (boot/recovery/system/...) to a target_files.zip.
+
+ It works with either a zip file (zip mode), or a directory that contains the
+ files to be packed into a target_files.zip (dir mode). The latter is used when
+ being called from build/make/core/Makefile.
+
+ The images will be created under IMAGES/ in the input target_files.zip.
+
+ Args:
+ filename: the target_files.zip, or the zip root directory.
+ """
if os.path.isdir(filename):
OPTIONS.input_tmp = os.path.abspath(filename)
- input_zip = None
else:
- OPTIONS.input_tmp, input_zip = common.UnzipTemp(filename)
+ OPTIONS.input_tmp = common.UnzipTemp(filename)
if not OPTIONS.add_missing:
if os.path.isdir(os.path.join(OPTIONS.input_tmp, "IMAGES")):
print("target_files appears to already contain images.")
sys.exit(1)
- # vendor.img is 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.img being available, which could be used
- # when generating vbmeta.img for AVB.
+ OPTIONS.info_dict = common.LoadInfoDict(OPTIONS.input_tmp, OPTIONS.input_tmp)
+
+ has_recovery = OPTIONS.info_dict.get("no_recovery") != "true"
+
+ # {vendor,product}.img is 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}.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_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_other = os.path.isdir(os.path.join(OPTIONS.input_tmp,
"SYSTEM_OTHER"))
- if input_zip:
- OPTIONS.info_dict = common.LoadInfoDict(input_zip, OPTIONS.input_tmp)
-
- common.ZipClose(input_zip)
+ # Set up the output destination. It writes to the given directory for dir
+ # mode; otherwise appends to the given ZIP.
+ if os.path.isdir(filename):
+ output_zip = None
+ else:
output_zip = zipfile.ZipFile(filename, "a",
compression=zipfile.ZIP_DEFLATED,
allowZip64=True)
- else:
- OPTIONS.info_dict = common.LoadInfoDict(filename, filename)
- output_zip = None
- images_dir = os.path.join(OPTIONS.input_tmp, "IMAGES")
- if not os.path.isdir(images_dir):
- os.makedirs(images_dir)
- images_dir = None
- has_recovery = (OPTIONS.info_dict.get("no_recovery") != "true")
+ # Always make input_tmp/IMAGES available, since we may stage boot / recovery
+ # images there even under zip mode. The directory will be cleaned up as part
+ # of OPTIONS.input_tmp.
+ images_dir = os.path.join(OPTIONS.input_tmp, "IMAGES")
+ if not os.path.isdir(images_dir):
+ os.makedirs(images_dir)
- if OPTIONS.info_dict.get("avb_enable") == "true":
- fp = None
- if "build.prop" in OPTIONS.info_dict:
- build_prop = OPTIONS.info_dict["build.prop"]
- if "ro.build.fingerprint" in build_prop:
- fp = build_prop["ro.build.fingerprint"]
- elif "ro.build.thumbprint" in build_prop:
- fp = build_prop["ro.build.thumbprint"]
- if fp:
- OPTIONS.info_dict["avb_salt"] = hashlib.sha256(fp).hexdigest()
+ # A map between partition names and their paths, which could be used when
+ # generating AVB vbmeta image.
+ partitions = dict()
def banner(s):
print("\n\n++++ " + s + " ++++\n\n")
- prebuilt_path = os.path.join(OPTIONS.input_tmp, "IMAGES", "boot.img")
- boot_image = None
- if os.path.exists(prebuilt_path):
- banner("boot")
- print("boot.img already exists in IMAGES/, no need to rebuild...")
- if OPTIONS.rebuild_recovery:
- boot_image = common.GetBootableImage(
- "IMAGES/boot.img", "boot.img", OPTIONS.input_tmp, "BOOT")
- else:
- banner("boot")
- boot_image = common.GetBootableImage(
- "IMAGES/boot.img", "boot.img", OPTIONS.input_tmp, "BOOT")
- if boot_image:
+ banner("boot")
+ # common.GetBootableImage() returns the image directly if present.
+ boot_image = common.GetBootableImage(
+ "IMAGES/boot.img", "boot.img", OPTIONS.input_tmp, "BOOT")
+ # boot.img may be unavailable in some targets (e.g. aosp_arm64).
+ if boot_image:
+ partitions['boot'] = os.path.join(OPTIONS.input_tmp, "IMAGES", "boot.img")
+ if not os.path.exists(partitions['boot']):
+ boot_image.WriteToDir(OPTIONS.input_tmp)
if output_zip:
boot_image.AddToZip(output_zip)
- else:
- boot_image.WriteToDir(OPTIONS.input_tmp)
recovery_image = None
if has_recovery:
banner("recovery")
- prebuilt_path = os.path.join(OPTIONS.input_tmp, "IMAGES", "recovery.img")
- if os.path.exists(prebuilt_path):
- print("recovery.img already exists in IMAGES/, no need to rebuild...")
- if OPTIONS.rebuild_recovery:
- recovery_image = common.GetBootableImage(
- "IMAGES/recovery.img", "recovery.img", OPTIONS.input_tmp,
- "RECOVERY")
- else:
- recovery_image = common.GetBootableImage(
- "IMAGES/recovery.img", "recovery.img", OPTIONS.input_tmp, "RECOVERY")
- if recovery_image:
- if output_zip:
- recovery_image.AddToZip(output_zip)
- else:
- recovery_image.WriteToDir(OPTIONS.input_tmp)
+ recovery_image = common.GetBootableImage(
+ "IMAGES/recovery.img", "recovery.img", OPTIONS.input_tmp, "RECOVERY")
+ assert recovery_image, "Failed to create recovery.img."
+ partitions['recovery'] = os.path.join(
+ OPTIONS.input_tmp, "IMAGES", "recovery.img")
+ if not os.path.exists(partitions['recovery']):
+ recovery_image.WriteToDir(OPTIONS.input_tmp)
+ if output_zip:
+ recovery_image.AddToZip(output_zip)
banner("recovery (two-step image)")
# The special recovery.img for two-step package use.
recovery_two_step_image = common.GetBootableImage(
"IMAGES/recovery-two-step.img", "recovery-two-step.img",
OPTIONS.input_tmp, "RECOVERY", two_step_image=True)
- if recovery_two_step_image:
+ assert recovery_two_step_image, "Failed to create recovery-two-step.img."
+ recovery_two_step_image_path = os.path.join(
+ OPTIONS.input_tmp, "IMAGES", "recovery-two-step.img")
+ if not os.path.exists(recovery_two_step_image_path):
+ recovery_two_step_image.WriteToDir(OPTIONS.input_tmp)
if output_zip:
recovery_two_step_image.AddToZip(output_zip)
- else:
- recovery_two_step_image.WriteToDir(OPTIONS.input_tmp)
banner("system")
- system_img_path = AddSystem(
+ partitions['system'] = AddSystem(
output_zip, recovery_img=recovery_image, boot_img=boot_image)
- vendor_img_path = None
+
if has_vendor:
banner("vendor")
- vendor_img_path = AddVendor(output_zip)
+ partitions['vendor'] = AddVendor(output_zip)
+
+ if has_product:
+ banner("product")
+ partitions['product'] = AddProduct(output_zip)
+
if has_system_other:
banner("system_other")
AddSystemOther(output_zip)
+
if not OPTIONS.is_signing:
banner("userdata")
AddUserdata(output_zip)
@@ -629,107 +748,36 @@
banner("partition-table")
AddPartitionTable(output_zip)
- dtbo_img_path = None
if OPTIONS.info_dict.get("has_dtbo") == "true":
banner("dtbo")
- dtbo_img_path = AddDtbo(output_zip)
+ partitions['dtbo'] = AddDtbo(output_zip)
if OPTIONS.info_dict.get("avb_enable") == "true":
banner("vbmeta")
- boot_contents = boot_image.WriteToTemp()
- AddVBMeta(output_zip, boot_contents.name, system_img_path,
- vendor_img_path, dtbo_img_path)
+ AddVBMeta(output_zip, partitions)
- # For devices using A/B update, copy over images from RADIO/ and/or
- # VENDOR_IMAGES/ to IMAGES/ and make sure we have all the needed
- # images ready under IMAGES/. All images should have '.img' as extension.
banner("radio")
- ab_partitions = os.path.join(OPTIONS.input_tmp, "META", "ab_partitions.txt")
- if os.path.exists(ab_partitions):
- with open(ab_partitions, 'r') as f:
- lines = f.readlines()
- # For devices using A/B update, generate care_map for system and vendor
- # partitions (if present), then write this file to target_files package.
- care_map_list = []
- for line in lines:
- if line.strip() == "system" and (
- "system_verity_block_device" in OPTIONS.info_dict or
- OPTIONS.info_dict.get("avb_system_hashtree_enable") == "true"):
- assert os.path.exists(system_img_path)
- care_map_list += GetCareMap("system", system_img_path)
- if line.strip() == "vendor" and (
- "vendor_verity_block_device" in OPTIONS.info_dict or
- OPTIONS.info_dict.get("avb_vendor_hashtree_enable") == "true"):
- assert os.path.exists(vendor_img_path)
- care_map_list += GetCareMap("vendor", vendor_img_path)
+ ab_partitions_txt = os.path.join(OPTIONS.input_tmp, "META",
+ "ab_partitions.txt")
+ if os.path.exists(ab_partitions_txt):
+ with open(ab_partitions_txt, 'r') as f:
+ ab_partitions = f.readlines()
- img_name = line.strip() + ".img"
- prebuilt_path = os.path.join(OPTIONS.input_tmp, "IMAGES", img_name)
- if os.path.exists(prebuilt_path):
- print("%s already exists, no need to overwrite..." % (img_name,))
- continue
+ # For devices using A/B update, copy over images from RADIO/ and/or
+ # VENDOR_IMAGES/ to IMAGES/ and make sure we have all the needed
+ # images ready under IMAGES/. All images should have '.img' as extension.
+ AddRadioImagesForAbOta(output_zip, ab_partitions)
- img_radio_path = os.path.join(OPTIONS.input_tmp, "RADIO", img_name)
- img_vendor_dir = os.path.join(
- OPTIONS.input_tmp, "VENDOR_IMAGES")
- if os.path.exists(img_radio_path):
- if output_zip:
- common.ZipWrite(output_zip, img_radio_path,
- os.path.join("IMAGES", img_name))
- else:
- shutil.copy(img_radio_path, prebuilt_path)
- else:
- for root, _, files in os.walk(img_vendor_dir):
- if img_name in files:
- if output_zip:
- common.ZipWrite(output_zip, os.path.join(root, img_name),
- os.path.join("IMAGES", img_name))
- else:
- shutil.copy(os.path.join(root, img_name), prebuilt_path)
- break
-
- if output_zip:
- # Zip spec says: All slashes MUST be forward slashes.
- img_path = 'IMAGES/' + img_name
- assert img_path in output_zip.namelist(), "cannot find " + img_name
- else:
- img_path = os.path.join(OPTIONS.input_tmp, "IMAGES", img_name)
- assert os.path.exists(img_path), "cannot find " + img_name
-
- if care_map_list:
- care_map_path = "META/care_map.txt"
- if output_zip and care_map_path not in output_zip.namelist():
- common.ZipWriteStr(output_zip, care_map_path, '\n'.join(care_map_list))
- else:
- with open(os.path.join(OPTIONS.input_tmp, care_map_path), 'w') as fp:
- fp.write('\n'.join(care_map_list))
- if output_zip:
- OPTIONS.replace_updated_files_list.append(care_map_path)
+ # Generate care_map.txt for system and vendor partitions (if present), then
+ # write this file to target_files package.
+ AddCareMapTxtForAbOta(output_zip, ab_partitions, partitions)
# Radio images that need to be packed into IMAGES/, and product-img.zip.
- pack_radioimages = os.path.join(
+ pack_radioimages_txt = os.path.join(
OPTIONS.input_tmp, "META", "pack_radioimages.txt")
- if os.path.exists(pack_radioimages):
- with open(pack_radioimages, 'r') as f:
- lines = f.readlines()
- for line in lines:
- img_name = line.strip()
- _, ext = os.path.splitext(img_name)
- if not ext:
- img_name += ".img"
- prebuilt_path = os.path.join(OPTIONS.input_tmp, "IMAGES", img_name)
- if os.path.exists(prebuilt_path):
- print("%s already exists, no need to overwrite..." % (img_name,))
- continue
-
- img_radio_path = os.path.join(OPTIONS.input_tmp, "RADIO", img_name)
- assert os.path.exists(img_radio_path), \
- "Failed to find %s at %s" % (img_name, img_radio_path)
- if output_zip:
- common.ZipWrite(output_zip, img_radio_path,
- os.path.join("IMAGES", img_name))
- else:
- shutil.copy(img_radio_path, prebuilt_path)
+ if os.path.exists(pack_radioimages_txt):
+ with open(pack_radioimages_txt, 'r') as f:
+ AddPackRadioImages(output_zip, f.readlines())
if output_zip:
common.ZipClose(output_zip)
diff --git a/tools/releasetools/blockimgdiff.py b/tools/releasetools/blockimgdiff.py
index b8123c0..24c5b2d 100644
--- a/tools/releasetools/blockimgdiff.py
+++ b/tools/releasetools/blockimgdiff.py
@@ -15,7 +15,7 @@
from __future__ import print_function
import array
-import common
+import copy
import functools
import heapq
import itertools
@@ -26,9 +26,10 @@
import subprocess
import sys
import threading
-
from collections import deque, OrderedDict
from hashlib import sha1
+
+import common
from rangelib import RangeSet
@@ -190,8 +191,6 @@
self.tgt_sha1 = tgt_sha1
self.src_sha1 = src_sha1
self.style = style
- self.intact = (getattr(tgt_ranges, "monotonic", False) and
- getattr(src_ranges, "monotonic", False))
# We use OrderedDict rather than dict so that the output is repeatable;
# otherwise it would depend on the hash values of the Transfer objects.
@@ -204,6 +203,18 @@
self.id = len(by_id)
by_id.append(self)
+ self._patch = None
+
+ @property
+ def patch(self):
+ return self._patch
+
+ @patch.setter
+ def patch(self, patch):
+ if patch:
+ assert self.style == "diff"
+ self._patch = patch
+
def NetStashChange(self):
return (sum(sr.size() for (_, sr) in self.stash_before) -
sum(sr.size() for (_, sr) in self.use_stash))
@@ -213,6 +224,7 @@
self.use_stash = []
self.style = "new"
self.src_ranges = RangeSet()
+ self.patch = None
def __str__(self):
return (str(self.id) + ": <" + str(self.src_ranges) + " " + self.style +
@@ -223,19 +235,93 @@
class HeapItem(object):
def __init__(self, item):
self.item = item
- # Negate the score since python's heap is a min-heap and we want
- # the maximum score.
+ # Negate the score since python's heap is a min-heap and we want the
+ # maximum score.
self.score = -item.score
+
def clear(self):
self.item = None
+
def __bool__(self):
- return self.item is None
+ return self.item is not None
+
+ # Python 2 uses __nonzero__, while Python 3 uses __bool__.
+ __nonzero__ = __bool__
+
+ # The rest operations are generated by functools.total_ordering decorator.
def __eq__(self, other):
return self.score == other.score
+
def __le__(self, other):
return self.score <= other.score
+class ImgdiffStats(object):
+ """A class that collects imgdiff stats.
+
+ It keeps track of the files that will be applied imgdiff while generating
+ BlockImageDiff. It also logs the ones that cannot use imgdiff, with specific
+ reasons. The stats is only meaningful when imgdiff not being disabled by the
+ caller of BlockImageDiff. In addition, only files with supported types
+ (BlockImageDiff.FileTypeSupportedByImgdiff()) are allowed to be logged.
+ """
+
+ USED_IMGDIFF = "APK files diff'd with imgdiff"
+ USED_IMGDIFF_LARGE_APK = "Large APK files split and diff'd with imgdiff"
+
+ # Reasons for not applying imgdiff on APKs.
+ SKIPPED_TRIMMED = "Not used imgdiff due to trimmed RangeSet"
+ SKIPPED_NONMONOTONIC = "Not used imgdiff due to having non-monotonic ranges"
+ SKIPPED_SHARED_BLOCKS = "Not used imgdiff due to using shared blocks"
+ SKIPPED_INCOMPLETE = "Not used imgdiff due to incomplete RangeSet"
+
+ # The list of valid reasons, which will also be the dumped order in a report.
+ REASONS = (
+ USED_IMGDIFF,
+ USED_IMGDIFF_LARGE_APK,
+ SKIPPED_TRIMMED,
+ SKIPPED_NONMONOTONIC,
+ SKIPPED_SHARED_BLOCKS,
+ SKIPPED_INCOMPLETE,
+ )
+
+ def __init__(self):
+ self.stats = {}
+
+ def Log(self, filename, reason):
+ """Logs why imgdiff can or cannot be applied to the given filename.
+
+ Args:
+ filename: The filename string.
+ reason: One of the reason constants listed in REASONS.
+
+ Raises:
+ AssertionError: On unsupported filetypes or invalid reason.
+ """
+ assert BlockImageDiff.FileTypeSupportedByImgdiff(filename)
+ assert reason in self.REASONS
+
+ if reason not in self.stats:
+ self.stats[reason] = set()
+ self.stats[reason].add(filename)
+
+ def Report(self):
+ """Prints a report of the collected imgdiff stats."""
+
+ def print_header(header, separator):
+ print(header)
+ print(separator * len(header) + '\n')
+
+ print_header(' Imgdiff Stats Report ', '=')
+ for key in self.REASONS:
+ if key not in self.stats:
+ continue
+ values = self.stats[key]
+ section_header = ' {} (count: {}) '.format(key, len(values))
+ print_header(section_header, '-')
+ print(''.join([' {}\n'.format(name) for name in values]))
+
+
# BlockImageDiff works on two image objects. An image object is
# anything that provides the following attributes:
#
@@ -291,6 +377,7 @@
self.touched_src_ranges = RangeSet()
self.touched_src_sha1 = None
self.disable_imgdiff = disable_imgdiff
+ self.imgdiff_stats = ImgdiffStats() if not disable_imgdiff else None
assert version in (3, 4)
@@ -312,6 +399,65 @@
def max_stashed_size(self):
return self._max_stashed_size
+ @staticmethod
+ def FileTypeSupportedByImgdiff(filename):
+ """Returns whether the file type is supported by imgdiff."""
+ return filename.lower().endswith(('.apk', '.jar', '.zip'))
+
+ def CanUseImgdiff(self, name, tgt_ranges, src_ranges, large_apk=False):
+ """Checks whether we can apply imgdiff for the given RangeSets.
+
+ For files in ZIP format (e.g., APKs, JARs, etc.) we would like to use
+ 'imgdiff -z' if possible. Because it usually produces significantly smaller
+ patches than bsdiff.
+
+ This is permissible if all of the following conditions hold.
+ - The imgdiff hasn't been disabled by the caller (e.g. squashfs);
+ - The file type is supported by imgdiff;
+ - The source and target blocks are monotonic (i.e. the data is stored with
+ blocks in increasing order);
+ - Both files don't contain shared blocks;
+ - Both files have complete lists of blocks;
+ - We haven't removed any blocks from the source set.
+
+ If all these conditions are satisfied, concatenating all the blocks in the
+ RangeSet in order will produce a valid ZIP file (plus possibly extra zeros
+ in the last block). imgdiff is fine with extra zeros at the end of the file.
+
+ Args:
+ name: The filename to be diff'd.
+ tgt_ranges: The target RangeSet.
+ src_ranges: The source RangeSet.
+ large_apk: Whether this is to split a large APK.
+
+ Returns:
+ A boolean result.
+ """
+ if self.disable_imgdiff or not self.FileTypeSupportedByImgdiff(name):
+ return False
+
+ if not tgt_ranges.monotonic or not src_ranges.monotonic:
+ self.imgdiff_stats.Log(name, ImgdiffStats.SKIPPED_NONMONOTONIC)
+ return False
+
+ if (tgt_ranges.extra.get('uses_shared_blocks') or
+ src_ranges.extra.get('uses_shared_blocks')):
+ self.imgdiff_stats.Log(name, ImgdiffStats.SKIPPED_SHARED_BLOCKS)
+ return False
+
+ if tgt_ranges.extra.get('incomplete') or src_ranges.extra.get('incomplete'):
+ self.imgdiff_stats.Log(name, ImgdiffStats.SKIPPED_INCOMPLETE)
+ return False
+
+ if tgt_ranges.extra.get('trimmed') or src_ranges.extra.get('trimmed'):
+ self.imgdiff_stats.Log(name, ImgdiffStats.SKIPPED_TRIMMED)
+ return False
+
+ reason = (ImgdiffStats.USED_IMGDIFF_LARGE_APK if large_apk
+ else ImgdiffStats.USED_IMGDIFF)
+ self.imgdiff_stats.Log(name, reason)
+ return True
+
def Compute(self, prefix):
# When looking for a source file to use as the diff input for a
# target file, we try:
@@ -340,10 +486,15 @@
# Double-check our work.
self.AssertSequenceGood()
+ self.AssertSha1Good()
self.ComputePatches(prefix)
self.WriteTransfers(prefix)
+ # Report the imgdiff stats.
+ if common.OPTIONS.verbose and not self.disable_imgdiff:
+ self.imgdiff_stats.Report()
+
def WriteTransfers(self, prefix):
def WriteSplitTransfers(out, style, target_blocks):
"""Limit the size of operand in command 'new' and 'zero' to 1024 blocks.
@@ -396,7 +547,7 @@
# <# blocks> - <stash refs...>
size = xf.src_ranges.size()
- src_str = [str(size)]
+ src_str_buffer = [str(size)]
unstashed_src_ranges = xf.src_ranges
mapped_stashes = []
@@ -406,7 +557,7 @@
sr = xf.src_ranges.map_within(sr)
mapped_stashes.append(sr)
assert sh in stashes
- src_str.append("%s:%s" % (sh, sr.to_string_raw()))
+ src_str_buffer.append("%s:%s" % (sh, sr.to_string_raw()))
stashes[sh] -= 1
if stashes[sh] == 0:
free_string.append("free %s\n" % (sh,))
@@ -414,17 +565,17 @@
stashes.pop(sh)
if unstashed_src_ranges:
- src_str.insert(1, unstashed_src_ranges.to_string_raw())
+ src_str_buffer.insert(1, unstashed_src_ranges.to_string_raw())
if xf.use_stash:
mapped_unstashed = xf.src_ranges.map_within(unstashed_src_ranges)
- src_str.insert(2, mapped_unstashed.to_string_raw())
+ src_str_buffer.insert(2, mapped_unstashed.to_string_raw())
mapped_stashes.append(mapped_unstashed)
self.AssertPartition(RangeSet(data=(0, size)), mapped_stashes)
else:
- src_str.insert(1, "-")
+ src_str_buffer.insert(1, "-")
self.AssertPartition(RangeSet(data=(0, size)), mapped_stashes)
- src_str = " ".join(src_str)
+ src_str = " ".join(src_str_buffer)
# version 3+:
# zero <rangeset>
@@ -545,11 +696,11 @@
max_allowed = OPTIONS.cache_size * OPTIONS.stash_threshold
print("max stashed blocks: %d (%d bytes), "
"limit: %d bytes (%.2f%%)\n" % (
- max_stashed_blocks, self._max_stashed_size, max_allowed,
- self._max_stashed_size * 100.0 / max_allowed))
+ max_stashed_blocks, self._max_stashed_size, max_allowed,
+ self._max_stashed_size * 100.0 / max_allowed))
else:
print("max stashed blocks: %d (%d bytes), limit: <unknown>\n" % (
- max_stashed_blocks, self._max_stashed_size))
+ max_stashed_blocks, self._max_stashed_size))
def ReviseStashSize(self):
print("Revising stash size...")
@@ -675,6 +826,7 @@
# These are identical; we don't need to generate a patch,
# just issue copy commands on the device.
xf.style = "move"
+ xf.patch = None
tgt_size = xf.tgt_ranges.size() * self.tgt.blocksize
if xf.src_ranges != xf.tgt_ranges:
print("%10d %10d (%6.2f%%) %7s %s %s (from %s)" % (
@@ -683,24 +835,18 @@
xf.tgt_name + " (from " + xf.src_name + ")"),
str(xf.tgt_ranges), str(xf.src_ranges)))
else:
- # For files in zip format (eg, APKs, JARs, etc.) we would
- # like to use imgdiff -z if possible (because it usually
- # produces significantly smaller patches than bsdiff).
- # This is permissible if:
- #
- # - imgdiff is not disabled, and
- # - the source and target files are monotonic (ie, the
- # data is stored with blocks in increasing order), and
- # - we haven't removed any blocks from the source set.
- #
- # If these conditions are satisfied then appending all the
- # blocks in the set together in order will produce a valid
- # zip file (plus possibly extra zeros in the last block),
- # which is what imgdiff needs to operate. (imgdiff is
- # fine with extra zeros at the end of the file.)
- imgdiff = (not self.disable_imgdiff and xf.intact and
- xf.tgt_name.split(".")[-1].lower()
- in ("apk", "jar", "zip"))
+ if xf.patch:
+ # We have already generated the patch with imgdiff. Check if the
+ # transfer is intact.
+ assert not self.disable_imgdiff
+ imgdiff = True
+ if (xf.src_ranges.extra.get('trimmed') or
+ xf.tgt_ranges.extra.get('trimmed')):
+ imgdiff = False
+ xf.patch = None
+ else:
+ imgdiff = self.CanUseImgdiff(
+ xf.tgt_name, xf.tgt_ranges, xf.src_ranges)
xf.style = "imgdiff" if imgdiff else "bsdiff"
diff_queue.append((index, imgdiff, patch_num))
patch_num += 1
@@ -717,9 +863,6 @@
diff_total = len(diff_queue)
patches = [None] * diff_total
error_messages = []
- if sys.stdout.isatty():
- global diff_done
- diff_done = 0
# Using multiprocessing doesn't give additional benefits, due to the
# pattern of the code. The diffing work is done by subprocess.call, which
@@ -735,13 +878,20 @@
if not diff_queue:
return
xf_index, imgdiff, patch_index = diff_queue.pop()
+ xf = self.transfers[xf_index]
- xf = self.transfers[xf_index]
- src_ranges = xf.src_ranges
- tgt_ranges = xf.tgt_ranges
+ if sys.stdout.isatty():
+ diff_left = len(diff_queue)
+ progress = (diff_total - diff_left) * 100 / diff_total
+ # '\033[K' is to clear to EOL.
+ print(' [%3d%%] %s\033[K' % (progress, xf.tgt_name), end='\r')
+ sys.stdout.flush()
- # Needs lock since WriteRangeDataToFd() is stateful (calling seek).
- with lock:
+ patch = xf.patch
+ if not patch:
+ src_ranges = xf.src_ranges
+ tgt_ranges = xf.tgt_ranges
+
src_file = common.MakeTempFile(prefix="src-")
with open(src_file, "wb") as fd:
self.src.WriteRangeDataToFd(src_ranges, fd)
@@ -750,26 +900,22 @@
with open(tgt_file, "wb") as fd:
self.tgt.WriteRangeDataToFd(tgt_ranges, fd)
- try:
- patch = compute_patch(src_file, tgt_file, imgdiff)
- except ValueError as e:
- with lock:
- error_messages.append(
+ message = []
+ try:
+ patch = compute_patch(src_file, tgt_file, imgdiff)
+ except ValueError as e:
+ message.append(
"Failed to generate %s for %s: tgt=%s, src=%s:\n%s" % (
"imgdiff" if imgdiff else "bsdiff",
xf.tgt_name if xf.tgt_name == xf.src_name else
- xf.tgt_name + " (from " + xf.src_name + ")",
+ xf.tgt_name + " (from " + xf.src_name + ")",
xf.tgt_ranges, xf.src_ranges, e.message))
+ if message:
+ with lock:
+ error_messages.extend(message)
with lock:
patches[patch_index] = (xf_index, patch)
- if sys.stdout.isatty():
- global diff_done
- diff_done += 1
- progress = diff_done * 100 / diff_total
- # '\033[K' is to clear to EOL.
- print(' [%d%%] %s\033[K' % (progress, xf.tgt_name), end='\r')
- sys.stdout.flush()
threads = [threading.Thread(target=diff_worker)
for _ in range(self.threads)]
@@ -782,7 +928,9 @@
print('\n')
if error_messages:
+ print('ERROR:')
print('\n'.join(error_messages))
+ print('\n\n\n')
sys.exit(1)
else:
patches = []
@@ -799,11 +947,26 @@
if common.OPTIONS.verbose:
tgt_size = xf.tgt_ranges.size() * self.tgt.blocksize
print("%10d %10d (%6.2f%%) %7s %s %s %s" % (
- xf.patch_len, tgt_size, xf.patch_len * 100.0 / tgt_size,
- xf.style,
- xf.tgt_name if xf.tgt_name == xf.src_name else (
- xf.tgt_name + " (from " + xf.src_name + ")"),
- xf.tgt_ranges, xf.src_ranges))
+ xf.patch_len, tgt_size, xf.patch_len * 100.0 / tgt_size,
+ xf.style,
+ xf.tgt_name if xf.tgt_name == xf.src_name else (
+ xf.tgt_name + " (from " + xf.src_name + ")"),
+ xf.tgt_ranges, xf.src_ranges))
+
+ def AssertSha1Good(self):
+ """Check the SHA-1 of the src & tgt blocks in the transfer list.
+
+ Double check the SHA-1 value to avoid the issue in b/71908713, where
+ SparseImage.RangeSha1() messed up with the hash calculation in multi-thread
+ environment. That specific problem has been fixed by protecting the
+ underlying generator function 'SparseImage._GetRangeData()' with lock.
+ """
+ for xf in self.transfers:
+ tgt_sha1 = self.tgt.RangeSha1(xf.tgt_ranges)
+ assert xf.tgt_sha1 == tgt_sha1
+ if xf.style == "diff":
+ src_sha1 = self.src.RangeSha1(xf.src_ranges)
+ assert xf.src_sha1 == src_sha1
def AssertSequenceGood(self):
# Simulate the sequences of transfers we will output, and check that:
@@ -902,7 +1065,7 @@
out_of_order += 1
assert xf.src_ranges.overlaps(u.tgt_ranges)
xf.src_ranges = xf.src_ranges.subtract(u.tgt_ranges)
- xf.intact = False
+ xf.src_ranges.extra['trimmed'] = True
if xf.style == "diff" and not xf.src_ranges:
# nothing left to diff from; treat as new data
@@ -1021,7 +1184,8 @@
while sinks:
new_sinks = OrderedDict()
for u in sinks:
- if u not in G: continue
+ if u not in G:
+ continue
s2.appendleft(u)
del G[u]
for iu in u.incoming:
@@ -1034,7 +1198,8 @@
while sources:
new_sources = OrderedDict()
for u in sources:
- if u not in G: continue
+ if u not in G:
+ continue
s1.append(u)
del G[u]
for iu in u.outgoing:
@@ -1043,7 +1208,8 @@
new_sources[iu] = None
sources = new_sources
- if not G: break
+ if not G:
+ break
# Find the "best" vertex to put next. "Best" is the one that
# maximizes the net difference in source blocks saved we get by
@@ -1100,14 +1266,16 @@
intersections = OrderedDict()
for s, e in a.tgt_ranges:
for i in range(s, e):
- if i >= len(source_ranges): break
+ if i >= len(source_ranges):
+ break
# Add all the Transfers in source_ranges[i] to the (ordered) set.
if source_ranges[i] is not None:
for j in source_ranges[i]:
intersections[j] = None
for b in intersections:
- if a is b: continue
+ if a is b:
+ continue
# If the blocks written by A are read by B, then B needs to go before A.
i = a.tgt_ranges.intersect(b.src_ranges)
@@ -1124,8 +1292,8 @@
def FindTransfers(self):
"""Parse the file_map to generate all the transfers."""
- def AddSplitTransfers(tgt_name, src_name, tgt_ranges, src_ranges,
- style, by_id):
+ def AddSplitTransfersWithFixedSizeChunks(tgt_name, src_name, tgt_ranges,
+ src_ranges, style, by_id):
"""Add one or multiple Transfer()s by splitting large files.
For BBOTA v3, we need to stash source blocks for resumable feature.
@@ -1140,21 +1308,7 @@
Compared to the fixed 1024-block limit, it reduces the overall package
size by 30% for volantis, and 20% for angler and bullhead."""
- # Possibly split large files into smaller chunks.
pieces = 0
- cache_size = common.OPTIONS.cache_size
- split_threshold = 0.125
- max_blocks_per_transfer = int(cache_size * split_threshold /
- self.tgt.blocksize)
-
- # Change nothing for small files.
- if (tgt_ranges.size() <= max_blocks_per_transfer and
- src_ranges.size() <= max_blocks_per_transfer):
- Transfer(tgt_name, src_name, tgt_ranges, src_ranges,
- self.tgt.RangeSha1(tgt_ranges), self.src.RangeSha1(src_ranges),
- style, by_id)
- return
-
while (tgt_ranges.size() > max_blocks_per_transfer and
src_ranges.size() > max_blocks_per_transfer):
tgt_split_name = "%s-%d" % (tgt_name, pieces)
@@ -1180,6 +1334,38 @@
self.tgt.RangeSha1(tgt_ranges), self.src.RangeSha1(src_ranges),
style, by_id)
+ def AddSplitTransfers(tgt_name, src_name, tgt_ranges, src_ranges, style,
+ by_id):
+ """Find all the zip files and split the others with a fixed chunk size.
+
+ This function will construct a list of zip archives, which will later be
+ split by imgdiff to reduce the final patch size. For the other files,
+ we will plainly split them based on a fixed chunk size with the potential
+ patch size penalty.
+ """
+
+ assert style == "diff"
+
+ # Change nothing for small files.
+ if (tgt_ranges.size() <= max_blocks_per_transfer and
+ src_ranges.size() <= max_blocks_per_transfer):
+ Transfer(tgt_name, src_name, tgt_ranges, src_ranges,
+ self.tgt.RangeSha1(tgt_ranges), self.src.RangeSha1(src_ranges),
+ style, by_id)
+ return
+
+ # Split large APKs with imgdiff, if possible. We're intentionally checking
+ # file types one more time (CanUseImgdiff() checks that as well), before
+ # calling the costly RangeSha1()s.
+ if (self.FileTypeSupportedByImgdiff(tgt_name) and
+ self.tgt.RangeSha1(tgt_ranges) != self.src.RangeSha1(src_ranges)):
+ if self.CanUseImgdiff(tgt_name, tgt_ranges, src_ranges, True):
+ large_apks.append((tgt_name, src_name, tgt_ranges, src_ranges))
+ return
+
+ AddSplitTransfersWithFixedSizeChunks(tgt_name, src_name, tgt_ranges,
+ src_ranges, style, by_id)
+
def AddTransfer(tgt_name, src_name, tgt_ranges, src_ranges, style, by_id,
split=False):
"""Wrapper function for adding a Transfer()."""
@@ -1226,8 +1412,9 @@
if tgt_changed < tgt_size * crop_threshold:
assert tgt_changed + tgt_skipped.size() == tgt_size
- print('%10d %10d (%6.2f%%) %s' % (tgt_skipped.size(), tgt_size,
- tgt_skipped.size() * 100.0 / tgt_size, tgt_name))
+ print('%10d %10d (%6.2f%%) %s' % (
+ tgt_skipped.size(), tgt_size,
+ tgt_skipped.size() * 100.0 / tgt_size, tgt_name))
AddSplitTransfers(
"%s-skipped" % (tgt_name,),
"%s-skipped" % (src_name,),
@@ -1248,10 +1435,136 @@
AddSplitTransfers(
tgt_name, src_name, tgt_ranges, src_ranges, style, by_id)
+ def ParseAndValidateSplitInfo(patch_size, tgt_ranges, src_ranges,
+ split_info):
+ """Parse the split_info and return a list of info tuples.
+
+ Args:
+ patch_size: total size of the patch file.
+ tgt_ranges: Ranges of the target file within the original image.
+ src_ranges: Ranges of the source file within the original image.
+ split_info format:
+ imgdiff version#
+ count of pieces
+ <patch_size_1> <tgt_size_1> <src_ranges_1>
+ ...
+ <patch_size_n> <tgt_size_n> <src_ranges_n>
+
+ Returns:
+ [patch_start, patch_len, split_tgt_ranges, split_src_ranges]
+ """
+
+ version = int(split_info[0])
+ assert version == 2
+ count = int(split_info[1])
+ assert len(split_info) - 2 == count
+
+ split_info_list = []
+ patch_start = 0
+ tgt_remain = copy.deepcopy(tgt_ranges)
+ # each line has the format <patch_size>, <tgt_size>, <src_ranges>
+ for line in split_info[2:]:
+ info = line.split()
+ assert len(info) == 3
+ patch_length = int(info[0])
+
+ split_tgt_size = int(info[1])
+ assert split_tgt_size % 4096 == 0
+ assert split_tgt_size / 4096 <= tgt_remain.size()
+ split_tgt_ranges = tgt_remain.first(split_tgt_size / 4096)
+ tgt_remain = tgt_remain.subtract(split_tgt_ranges)
+
+ # Find the split_src_ranges within the image file from its relative
+ # position in file.
+ split_src_indices = RangeSet.parse_raw(info[2])
+ split_src_ranges = RangeSet()
+ for r in split_src_indices:
+ curr_range = src_ranges.first(r[1]).subtract(src_ranges.first(r[0]))
+ assert not split_src_ranges.overlaps(curr_range)
+ split_src_ranges = split_src_ranges.union(curr_range)
+
+ split_info_list.append((patch_start, patch_length,
+ split_tgt_ranges, split_src_ranges))
+ patch_start += patch_length
+
+ # Check that the sizes of all the split pieces add up to the final file
+ # size for patch and target.
+ assert tgt_remain.size() == 0
+ assert patch_start == patch_size
+ return split_info_list
+
+ def SplitLargeApks():
+ """Split the large apks files.
+
+ Example: Chrome.apk will be split into
+ src-0: Chrome.apk-0, tgt-0: Chrome.apk-0
+ src-1: Chrome.apk-1, tgt-1: Chrome.apk-1
+ ...
+
+ After the split, the target pieces are continuous and block aligned; and
+ the source pieces are mutually exclusive. During the split, we also
+ generate and save the image patch between src-X & tgt-X. This patch will
+ be valid because the block ranges of src-X & tgt-X will always stay the
+ same afterwards; but there's a chance we don't use the patch if we
+ convert the "diff" command into "new" or "move" later.
+ """
+
+ while True:
+ with transfer_lock:
+ if not large_apks:
+ return
+ tgt_name, src_name, tgt_ranges, src_ranges = large_apks.pop(0)
+
+ src_file = common.MakeTempFile(prefix="src-")
+ tgt_file = common.MakeTempFile(prefix="tgt-")
+ with open(src_file, "wb") as src_fd:
+ self.src.WriteRangeDataToFd(src_ranges, src_fd)
+ with open(tgt_file, "wb") as tgt_fd:
+ self.tgt.WriteRangeDataToFd(tgt_ranges, tgt_fd)
+
+ patch_file = common.MakeTempFile(prefix="patch-")
+ patch_info_file = common.MakeTempFile(prefix="split_info-")
+ cmd = ["imgdiff", "-z",
+ "--block-limit={}".format(max_blocks_per_transfer),
+ "--split-info=" + patch_info_file,
+ src_file, tgt_file, patch_file]
+ p = common.Run(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+ imgdiff_output, _ = p.communicate()
+ assert p.returncode == 0, \
+ "Failed to create imgdiff patch between {} and {}:\n{}".format(
+ src_name, tgt_name, imgdiff_output)
+
+ with open(patch_info_file) as patch_info:
+ lines = patch_info.readlines()
+
+ patch_size_total = os.path.getsize(patch_file)
+ split_info_list = ParseAndValidateSplitInfo(patch_size_total,
+ tgt_ranges, src_ranges,
+ lines)
+ for index, (patch_start, patch_length, split_tgt_ranges,
+ split_src_ranges) in enumerate(split_info_list):
+ with open(patch_file) as f:
+ f.seek(patch_start)
+ patch_content = f.read(patch_length)
+
+ split_src_name = "{}-{}".format(src_name, index)
+ split_tgt_name = "{}-{}".format(tgt_name, index)
+ split_large_apks.append((split_tgt_name,
+ split_src_name,
+ split_tgt_ranges,
+ split_src_ranges,
+ patch_content))
+
print("Finding transfers...")
+ large_apks = []
+ split_large_apks = []
+ cache_size = common.OPTIONS.cache_size
+ split_threshold = 0.125
+ max_blocks_per_transfer = int(cache_size * split_threshold /
+ self.tgt.blocksize)
empty = RangeSet()
- for tgt_fn, tgt_ranges in self.tgt.file_map.items():
+ for tgt_fn, tgt_ranges in sorted(self.tgt.file_map.items()):
if tgt_fn == "__ZERO":
# the special "__ZERO" domain is all the blocks not contained
# in any file and that are filled with zeros. We have a
@@ -1294,6 +1607,24 @@
AddTransfer(tgt_fn, None, tgt_ranges, empty, "new", self.transfers)
+ transfer_lock = threading.Lock()
+ threads = [threading.Thread(target=SplitLargeApks)
+ for _ in range(self.threads)]
+ for th in threads:
+ th.start()
+ while threads:
+ threads.pop().join()
+
+ # Sort the split transfers for large apks to generate a determinate package.
+ split_large_apks.sort()
+ for (tgt_name, src_name, tgt_ranges, src_ranges,
+ patch) in split_large_apks:
+ transfer_split = Transfer(tgt_name, src_name, tgt_ranges, src_ranges,
+ self.tgt.RangeSha1(tgt_ranges),
+ self.src.RangeSha1(src_ranges),
+ "diff", self.transfers)
+ transfer_split.patch = patch
+
def AbbreviateSourceNames(self):
for k in self.src.file_map.keys():
b = os.path.basename(k)
diff --git a/tools/releasetools/build_image.py b/tools/releasetools/build_image.py
index ccfa35f..ca96d01 100755
--- a/tools/releasetools/build_image.py
+++ b/tools/releasetools/build_image.py
@@ -15,63 +15,79 @@
# limitations under the License.
"""
-Build image output_image_file from input_directory, properties_file, and target_out_dir
+Builds output_image from the given input_directory, properties_file,
+and writes the image to target_output_directory.
-Usage: build_image input_directory properties_file output_image_file target_out_dir
-
+Usage: build_image.py input_directory properties_file output_image \\
+ target_output_directory
"""
+
+from __future__ import print_function
+
import os
import os.path
import re
-import subprocess
-import sys
-import common
import shlex
import shutil
+import subprocess
+import sys
+
+import common
import sparse_img
-import tempfile
+
OPTIONS = common.OPTIONS
FIXED_SALT = "aee087a5be3b982978c923f566a94613496b417f2af592639bc80d141e34dfe7"
BLOCK_SIZE = 4096
-def RunCommand(cmd):
+
+def RunCommand(cmd, verbose=None):
"""Echo and run the given command.
Args:
cmd: the command represented as a list of strings.
+ verbose: show commands being executed.
Returns:
A tuple of the output and the exit code.
"""
- print "Running: ", " ".join(cmd)
+ if verbose is None:
+ verbose = OPTIONS.verbose
+ if verbose:
+ print("Running: " + " ".join(cmd))
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
output, _ = p.communicate()
- print "%s" % (output.rstrip(),)
+
+ if verbose:
+ print(output.rstrip())
return (output, p.returncode)
+
def GetVerityFECSize(partition_size):
cmd = ["fec", "-s", str(partition_size)]
- output, exit_code = RunCommand(cmd)
+ output, exit_code = RunCommand(cmd, False)
if exit_code != 0:
return False, 0
return True, int(output)
+
def GetVerityTreeSize(partition_size):
cmd = ["build_verity_tree", "-s", str(partition_size)]
- output, exit_code = RunCommand(cmd)
+ output, exit_code = RunCommand(cmd, False)
if exit_code != 0:
return False, 0
return True, int(output)
+
def GetVerityMetadataSize(partition_size):
cmd = ["system/extras/verity/build_verity_metadata.py", "size",
str(partition_size)]
- output, exit_code = RunCommand(cmd)
+ output, exit_code = RunCommand(cmd, False)
if exit_code != 0:
return False, 0
return True, int(output)
+
def GetVeritySize(partition_size, fec_supported):
success, verity_tree_size = GetVerityTreeSize(partition_size)
if not success:
@@ -87,16 +103,19 @@
return verity_size + fec_size
return verity_size
+
def GetSimgSize(image_file):
simg = sparse_img.SparseImage(image_file, build_map=False)
return simg.blocksize * simg.total_blocks
+
def ZeroPadSimg(image_file, pad_size):
blocks = pad_size // BLOCK_SIZE
print("Padding %d blocks (%d bytes)" % (blocks, pad_size))
simg = sparse_img.SparseImage(image_file, mode="r+b", build_map=False)
simg.AppendFillChunk(0, blocks)
+
def AVBCalcMaxImageSize(avbtool, footer_type, partition_size, additional_args):
"""Calculates max image size for a given partition size.
@@ -109,8 +128,8 @@
Returns:
The maximum image size or 0 if an error occurred.
"""
- cmd =[avbtool, "add_%s_footer" % footer_type,
- "--partition_size", partition_size, "--calc_max_image_size"]
+ cmd = [avbtool, "add_%s_footer" % footer_type,
+ "--partition_size", partition_size, "--calc_max_image_size"]
cmd.extend(shlex.split(additional_args))
(output, exit_code) = RunCommand(cmd)
@@ -119,6 +138,7 @@
else:
return int(output)
+
def AVBAddFooter(image_path, avbtool, footer_type, partition_size,
partition_name, key_path, algorithm, salt,
additional_args):
@@ -134,14 +154,15 @@
algorithm: Name of algorithm to use or None.
salt: The salt to use (a hexadecimal string) or None.
additional_args: Additional arguments to pass to 'avbtool
- add_hashtree_image'.
+ add_hashtree_image'.
+
Returns:
True if the operation succeeded.
"""
- cmd =[avbtool, "add_%s_footer" % footer_type,
- "--partition_size", partition_size,
- "--partition_name", partition_name,
- "--image", image_path]
+ cmd = [avbtool, "add_%s_footer" % footer_type,
+ "--partition_size", partition_size,
+ "--partition_name", partition_name,
+ "--image", image_path]
if key_path and algorithm:
cmd.extend(["--key", key_path, "--algorithm", algorithm])
@@ -153,12 +174,15 @@
(_, exit_code) = RunCommand(cmd)
return exit_code == 0
+
def AdjustPartitionSizeForVerity(partition_size, fec_supported):
"""Modifies the provided partition size to account for the verity metadata.
This information is used to size the created image appropriately.
+
Args:
partition_size: the size of the partition to be verified.
+
Returns:
A tuple of the size of the partition adjusted for verity metadata, and
the size of verity metadata.
@@ -189,46 +213,57 @@
else:
hi = i
+ if OPTIONS.verbose:
+ print("Adjusted partition size for verity, partition_size: {},"
+ " verity_size: {}".format(result, verity_size))
AdjustPartitionSizeForVerity.results[key] = (result, verity_size)
return (result, verity_size)
+
AdjustPartitionSizeForVerity.results = {}
+
def BuildVerityFEC(sparse_image_path, verity_path, verity_fec_path,
padding_size):
cmd = ["fec", "-e", "-p", str(padding_size), sparse_image_path,
verity_path, verity_fec_path]
output, exit_code = RunCommand(cmd)
if exit_code != 0:
- print "Could not build FEC data! Error: %s" % output
+ print("Could not build FEC data! Error: %s" % output)
return False
return True
+
def BuildVerityTree(sparse_image_path, verity_image_path, prop_dict):
cmd = ["build_verity_tree", "-A", FIXED_SALT, sparse_image_path,
verity_image_path]
output, exit_code = RunCommand(cmd)
if exit_code != 0:
- print "Could not build verity tree! Error: %s" % output
+ print("Could not build verity tree! Error: %s" % output)
return False
root, salt = output.split()
prop_dict["verity_root_hash"] = root
prop_dict["verity_salt"] = salt
return True
+
def BuildVerityMetadata(image_size, verity_metadata_path, root_hash, salt,
- block_device, signer_path, key, signer_args):
+ block_device, signer_path, key, signer_args,
+ verity_disable):
cmd = ["system/extras/verity/build_verity_metadata.py", "build",
str(image_size), verity_metadata_path, root_hash, salt, block_device,
signer_path, key]
if signer_args:
cmd.append("--signer_args=\"%s\"" % (' '.join(signer_args),))
+ if verity_disable:
+ cmd.append("--verity_disable")
output, exit_code = RunCommand(cmd)
if exit_code != 0:
- print "Could not build verity metadata! Error: %s" % output
+ print("Could not build verity metadata! Error: %s" % output)
return False
return True
+
def Append2Simg(sparse_image_path, unsparse_image_path, error_message):
"""Appends the unsparse image to the given sparse image.
@@ -241,18 +276,23 @@
cmd = ["append2simg", sparse_image_path, unsparse_image_path]
output, exit_code = RunCommand(cmd)
if exit_code != 0:
- print "%s: %s" % (error_message, output)
+ print("%s: %s" % (error_message, output))
return False
return True
+
def Append(target, file_to_append, error_message):
- print "appending %s to %s" % (file_to_append, target)
- with open(target, "a") as out_file:
- with open(file_to_append, "r") as input_file:
+ """Appends file_to_append to target."""
+ try:
+ with open(target, "a") as out_file, open(file_to_append, "r") as input_file:
for line in input_file:
out_file.write(line)
+ except IOError:
+ print(error_message)
+ return False
return True
+
def BuildVerifiedImage(data_image_path, verity_image_path,
verity_metadata_path, verity_fec_path,
padding_size, fec_supported):
@@ -274,6 +314,7 @@
return False
return True
+
def UnsparseImage(sparse_image_path, replace=True):
img_dir = os.path.dirname(sparse_image_path)
unsparse_image_path = "unsparse_" + os.path.basename(sparse_image_path)
@@ -284,12 +325,15 @@
else:
return True, unsparse_image_path
inflate_command = ["simg2img", sparse_image_path, unsparse_image_path]
- (_, exit_code) = RunCommand(inflate_command)
+ (inflate_output, exit_code) = RunCommand(inflate_command)
if exit_code != 0:
+ print("Error: '%s' failed with exit code %d:\n%s" % (
+ inflate_command, exit_code, inflate_output))
os.remove(unsparse_image_path)
return False, None
return True, unsparse_image_path
+
def MakeVerityEnabledImage(out_file, fec_supported, prop_dict):
"""Creates an image that is verifiable using dm-verity.
@@ -311,7 +355,7 @@
signer_args = OPTIONS.verity_signer_args
# make a tempdir
- tempdir_name = tempfile.mkdtemp(suffix="_verity_images")
+ tempdir_name = common.MakeTempDir(suffix="_verity_images")
# get partial image paths
verity_image_path = os.path.join(tempdir_name, "verity.img")
@@ -320,15 +364,15 @@
# build the verity tree and get the root hash and salt
if not BuildVerityTree(out_file, verity_image_path, prop_dict):
- shutil.rmtree(tempdir_name, ignore_errors=True)
return False
# build the metadata blocks
root_hash = prop_dict["verity_root_hash"]
salt = prop_dict["verity_salt"]
+ verity_disable = "verity_disable" in prop_dict
if not BuildVerityMetadata(image_size, verity_metadata_path, root_hash, salt,
- block_dev, signer_path, signer_key, signer_args):
- shutil.rmtree(tempdir_name, ignore_errors=True)
+ block_dev, signer_path, signer_key, signer_args,
+ verity_disable):
return False
# build the full verified image
@@ -344,23 +388,59 @@
verity_fec_path,
padding_size,
fec_supported):
- shutil.rmtree(tempdir_name, ignore_errors=True)
return False
- shutil.rmtree(tempdir_name, ignore_errors=True)
return True
-def ConvertBlockMapToBaseFs(block_map_file):
- fd, base_fs_file = tempfile.mkstemp(prefix="script_gen_",
- suffix=".base_fs")
- os.close(fd)
+def ConvertBlockMapToBaseFs(block_map_file):
+ base_fs_file = common.MakeTempFile(prefix="script_gen_", suffix=".base_fs")
convert_command = ["blk_alloc_to_base_fs", block_map_file, base_fs_file]
(_, exit_code) = RunCommand(convert_command)
- if exit_code != 0:
- os.remove(base_fs_file)
- return None
- return base_fs_file
+ return base_fs_file if exit_code == 0 else None
+
+
+def CheckHeadroom(ext4fs_output, prop_dict):
+ """Checks if there's enough headroom space available.
+
+ Headroom is the reserved space on system image (via PRODUCT_SYSTEM_HEADROOM),
+ which is useful for devices with low disk space that have system image
+ variation between builds. The 'partition_headroom' in prop_dict is the size
+ in bytes, while the numbers in 'ext4fs_output' are for 4K-blocks.
+
+ Args:
+ ext4fs_output: The output string from mke2fs command.
+ prop_dict: The property dict.
+
+ Returns:
+ The check result.
+
+ Raises:
+ AssertionError: On invalid input.
+ """
+ assert ext4fs_output is not None
+ assert prop_dict.get('fs_type', '').startswith('ext4')
+ assert 'partition_headroom' in prop_dict
+ assert 'mount_point' in prop_dict
+
+ ext4fs_stats = re.compile(
+ r'Created filesystem with .* (?P<used_blocks>[0-9]+)/'
+ r'(?P<total_blocks>[0-9]+) blocks')
+ last_line = ext4fs_output.strip().split('\n')[-1]
+ m = ext4fs_stats.match(last_line)
+ used_blocks = int(m.groupdict().get('used_blocks'))
+ total_blocks = int(m.groupdict().get('total_blocks'))
+ headroom_blocks = int(prop_dict['partition_headroom']) / BLOCK_SIZE
+ adjusted_blocks = total_blocks - headroom_blocks
+ if used_blocks > adjusted_blocks:
+ mount_point = prop_dict["mount_point"]
+ print("Error: Not enough room on %s (total: %d blocks, used: %d blocks, "
+ "headroom: %d blocks, available: %d blocks)" % (
+ mount_point, total_blocks, used_blocks, headroom_blocks,
+ adjusted_blocks))
+ return False
+ return True
+
def BuildImage(in_dir, prop_dict, out_file, target_out=None):
"""Build an image to out_file from in_dir with property prop_dict.
@@ -369,7 +449,8 @@
in_dir: path of input directory.
prop_dict: property dictionary.
out_file: path of the output image file.
- target_out: path of the product out directory to read device specific FS config files.
+ target_out: path of the product out directory to read device specific FS
+ config files.
Returns:
True iff the image is built successfully.
@@ -378,17 +459,15 @@
# /system and the ramdisk, and can be mounted at the root of the file system.
origin_in = in_dir
fs_config = prop_dict.get("fs_config")
- base_fs_file = None
- if (prop_dict.get("system_root_image") == "true"
- and prop_dict["mount_point"] == "system"):
- in_dir = tempfile.mkdtemp()
- # Change the mount point to "/"
+ if (prop_dict.get("system_root_image") == "true" and
+ prop_dict["mount_point"] == "system"):
+ in_dir = common.MakeTempDir()
+ # Change the mount point to "/".
prop_dict["mount_point"] = "/"
if fs_config:
# We need to merge the fs_config files of system and ramdisk.
- fd, merged_fs_config = tempfile.mkstemp(prefix="root_fs_config",
- suffix=".txt")
- os.close(fd)
+ merged_fs_config = common.MakeTempFile(prefix="root_fs_config",
+ suffix=".txt")
with open(merged_fs_config, "w") as fw:
if "ramdisk_fs_config" in prop_dict:
with open(prop_dict["ramdisk_fs_config"]) as fr:
@@ -399,7 +478,7 @@
build_command = []
fs_type = prop_dict.get("fs_type", "")
- run_fsck = False
+ run_e2fsck = False
fs_spans_partition = True
if fs_type.startswith("squash"):
@@ -413,8 +492,8 @@
# verified.
if verity_supported and is_verity_partition:
partition_size = int(prop_dict.get("partition_size"))
- (adjusted_size, verity_size) = AdjustPartitionSizeForVerity(partition_size,
- verity_fec_supported)
+ (adjusted_size, verity_size) = AdjustPartitionSizeForVerity(
+ partition_size, verity_fec_supported)
if not adjusted_size:
return False
prop_dict["partition_size"] = str(adjusted_size)
@@ -433,8 +512,8 @@
partition_size = prop_dict["partition_size"]
# avb_add_hash_footer_args or avb_add_hashtree_footer_args.
additional_args = prop_dict["avb_add_" + avb_footer_type + "_footer_args"]
- max_image_size = AVBCalcMaxImageSize(avbtool, avb_footer_type, partition_size,
- additional_args)
+ max_image_size = AVBCalcMaxImageSize(avbtool, avb_footer_type,
+ partition_size, additional_args)
if max_image_size == 0:
return False
prop_dict["partition_size"] = str(max_image_size)
@@ -444,7 +523,7 @@
build_command = [prop_dict["ext_mkuserimg"]]
if "extfs_sparse_flag" in prop_dict:
build_command.append(prop_dict["extfs_sparse_flag"])
- run_fsck = True
+ run_e2fsck = True
build_command.extend([in_dir, out_file, fs_type,
prop_dict["mount_point"]])
build_command.append(prop_dict["partition_size"])
@@ -466,6 +545,8 @@
build_command.extend(["-L", prop_dict["mount_point"]])
if "extfs_inode_count" in prop_dict:
build_command.extend(["-i", prop_dict["extfs_inode_count"]])
+ if "extfs_rsv_pct" in prop_dict:
+ build_command.extend(["-M", prop_dict["extfs_rsv_pct"]])
if "flash_erase_block_size" in prop_dict:
build_command.extend(["-e", prop_dict["flash_erase_block_size"]])
if "flash_logical_block_size" in prop_dict:
@@ -476,6 +557,8 @@
build_command.extend(["-U", prop_dict["uuid"]])
if "hash_seed" in prop_dict:
build_command.extend(["-S", prop_dict["hash_seed"]])
+ if "ext4_share_dup_blocks" in prop_dict:
+ build_command.append("-c")
if "selinux_fc" in prop_dict:
build_command.append(prop_dict["selinux_fc"])
elif fs_type.startswith("squash"):
@@ -492,17 +575,28 @@
build_command.extend(["-c", prop_dict["selinux_fc"]])
if "block_list" in prop_dict:
build_command.extend(["-B", prop_dict["block_list"]])
+ if "squashfs_block_size" in prop_dict:
+ build_command.extend(["-b", prop_dict["squashfs_block_size"]])
if "squashfs_compressor" in prop_dict:
build_command.extend(["-z", prop_dict["squashfs_compressor"]])
if "squashfs_compressor_opt" in prop_dict:
build_command.extend(["-zo", prop_dict["squashfs_compressor_opt"]])
- if "squashfs_block_size" in prop_dict:
- build_command.extend(["-b", prop_dict["squashfs_block_size"]])
- if "squashfs_disable_4k_align" in prop_dict and prop_dict.get("squashfs_disable_4k_align") == "true":
+ if prop_dict.get("squashfs_disable_4k_align") == "true":
build_command.extend(["-a"])
elif fs_type.startswith("f2fs"):
build_command = ["mkf2fsuserimg.sh"]
build_command.extend([out_file, prop_dict["partition_size"]])
+ if fs_config:
+ build_command.extend(["-C", fs_config])
+ build_command.extend(["-f", in_dir])
+ if target_out:
+ build_command.extend(["-D", target_out])
+ if "selinux_fc" in prop_dict:
+ build_command.extend(["-s", prop_dict["selinux_fc"]])
+ build_command.extend(["-t", prop_dict["mount_point"]])
+ if "timestamp" in prop_dict:
+ build_command.extend(["-T", str(prop_dict["timestamp"])])
+ build_command.extend(["-L", prop_dict["mount_point"]])
else:
print("Error: unknown filesystem type '%s'" % (fs_type))
return False
@@ -517,56 +611,15 @@
shutil.rmtree(staging_system, ignore_errors=True)
shutil.copytree(origin_in, staging_system, symlinks=True)
- has_reserved_blocks = prop_dict.get("has_ext4_reserved_blocks") == "true"
- ext4fs_output = None
-
- try:
- if fs_type.startswith("ext4"):
- (ext4fs_output, exit_code) = RunCommand(build_command)
- else:
- (_, exit_code) = RunCommand(build_command)
- finally:
- if in_dir != origin_in:
- # Clean up temporary directories and files.
- shutil.rmtree(in_dir, ignore_errors=True)
- if fs_config:
- os.remove(fs_config)
- if base_fs_file is not None:
- os.remove(base_fs_file)
+ (mkfs_output, exit_code) = RunCommand(build_command)
if exit_code != 0:
+ print("Error: '%s' failed with exit code %d:\n%s" % (
+ build_command, exit_code, mkfs_output))
return False
- # Bug: 21522719, 22023465
- # There are some reserved blocks on ext4 FS (lesser of 4096 blocks and 2%).
- # We need to deduct those blocks from the available space, since they are
- # not writable even with root privilege. It only affects devices using
- # file-based OTA and a kernel version of 3.10 or greater (currently just
- # sprout).
- # Separately, check if there's enough headroom space available. This is useful for
- # devices with low disk space that have system image variation between builds.
- if (has_reserved_blocks or "partition_headroom" in prop_dict) and fs_type.startswith("ext4"):
- assert ext4fs_output is not None
- ext4fs_stats = re.compile(
- r'Created filesystem with .* (?P<used_blocks>[0-9]+)/'
- r'(?P<total_blocks>[0-9]+) blocks')
- m = ext4fs_stats.match(ext4fs_output.strip().split('\n')[-1])
- used_blocks = int(m.groupdict().get('used_blocks'))
- total_blocks = int(m.groupdict().get('total_blocks'))
- reserved_blocks = 0
- headroom_blocks = 0
- adjusted_blocks = total_blocks
- if has_reserved_blocks:
- reserved_blocks = min(4096, int(total_blocks * 0.02))
- adjusted_blocks -= reserved_blocks
- if "partition_headroom" in prop_dict:
- headroom_blocks = int(prop_dict.get('partition_headroom')) / BLOCK_SIZE
- adjusted_blocks -= headroom_blocks
- if used_blocks > adjusted_blocks:
- mount_point = prop_dict.get("mount_point")
- print("Error: Not enough room on %s (total: %d blocks, used: %d blocks, "
- "reserved: %d blocks, headroom: %d blocks, available: %d blocks)" % (
- mount_point, total_blocks, used_blocks, reserved_blocks,
- headroom_blocks, adjusted_blocks))
+ # Check if there's enough headroom space available for ext4 image.
+ if "partition_headroom" in prop_dict and fs_type.startswith("ext4"):
+ if not CheckHeadroom(mkfs_output, prop_dict):
return False
if not fs_spans_partition:
@@ -580,7 +633,7 @@
if verity_supported and is_verity_partition:
ZeroPadSimg(out_file, partition_size - image_size)
- # create the verified image if this is to be verified
+ # Create the verified image if this is to be verified.
if verity_supported and is_verity_partition:
if not MakeVerityEnabledImage(out_file, verity_fec_supported, prop_dict):
return False
@@ -596,22 +649,28 @@
salt = prop_dict.get("avb_salt")
# avb_add_hash_footer_args or avb_add_hashtree_footer_args
additional_args = prop_dict["avb_add_" + avb_footer_type + "_footer_args"]
- if not AVBAddFooter(out_file, avbtool, avb_footer_type, original_partition_size,
- partition_name, key_path, algorithm, salt, additional_args):
+ if not AVBAddFooter(out_file, avbtool, avb_footer_type,
+ original_partition_size, partition_name, key_path,
+ algorithm, salt, additional_args):
return False
- if run_fsck and prop_dict.get("skip_fsck") != "true":
+ if run_e2fsck and prop_dict.get("skip_fsck") != "true":
success, unsparse_image = UnsparseImage(out_file, replace=False)
if not success:
return False
# Run e2fsck on the inflated image file
e2fsck_command = ["e2fsck", "-f", "-n", unsparse_image]
- (_, exit_code) = RunCommand(e2fsck_command)
+ (e2fsck_output, exit_code) = RunCommand(e2fsck_command)
os.remove(unsparse_image)
- return exit_code == 0
+ if exit_code != 0:
+ print("Error: '%s' failed with exit code %d:\n%s" % (
+ e2fsck_command, exit_code, e2fsck_output))
+ return False
+
+ return True
def ImagePropFromGlobalDict(glob_dict, mount_point):
@@ -629,8 +688,18 @@
d["timestamp"] = bp["ro.build.date.utc"]
def copy_prop(src_p, dest_p):
+ """Copy a property from the global dictionary.
+
+ Args:
+ src_p: The source property in the global dictionary.
+ dest_p: The destination property.
+ Returns:
+ True if property was found and copied, False otherwise.
+ """
if src_p in glob_dict:
d[dest_p] = str(glob_dict[src_p])
+ return True
+ return False
common_props = (
"extfs_sparse_flag",
@@ -642,6 +711,7 @@
"verity_key",
"verity_signer_cmd",
"verity_fec",
+ "verity_disable",
"avb_enable",
"avb_avbtool",
"avb_salt",
@@ -662,20 +732,24 @@
copy_prop("system_fs_type", "fs_type")
copy_prop("system_headroom", "partition_headroom")
copy_prop("system_size", "partition_size")
- copy_prop("system_journal_size", "journal_size")
+ if not copy_prop("system_journal_size", "journal_size"):
+ d["journal_size"] = "0"
copy_prop("system_verity_block_device", "verity_block_device")
copy_prop("system_root_image", "system_root_image")
copy_prop("ramdisk_dir", "ramdisk_dir")
copy_prop("ramdisk_fs_config", "ramdisk_fs_config")
- copy_prop("has_ext4_reserved_blocks", "has_ext4_reserved_blocks")
+ copy_prop("ext4_share_dup_blocks", "ext4_share_dup_blocks")
copy_prop("system_squashfs_compressor", "squashfs_compressor")
copy_prop("system_squashfs_compressor_opt", "squashfs_compressor_opt")
copy_prop("system_squashfs_block_size", "squashfs_block_size")
copy_prop("system_squashfs_disable_4k_align", "squashfs_disable_4k_align")
copy_prop("system_base_fs_file", "base_fs_file")
copy_prop("system_extfs_inode_count", "extfs_inode_count")
+ if not copy_prop("system_extfs_rsv_pct", "extfs_rsv_pct"):
+ d["extfs_rsv_pct"] = "0"
elif mount_point == "system_other":
- # We inherit the selinux policies of /system since we contain some of its files.
+ # We inherit the selinux policies of /system since we contain some of its
+ # files.
d["mount_point"] = "system"
copy_prop("avb_system_hashtree_enable", "avb_hashtree_enable")
copy_prop("avb_system_add_hashtree_footer_args",
@@ -685,20 +759,22 @@
copy_prop("fs_type", "fs_type")
copy_prop("system_fs_type", "fs_type")
copy_prop("system_size", "partition_size")
- copy_prop("system_journal_size", "journal_size")
+ if not copy_prop("system_journal_size", "journal_size"):
+ d["journal_size"] = "0"
copy_prop("system_verity_block_device", "verity_block_device")
- copy_prop("has_ext4_reserved_blocks", "has_ext4_reserved_blocks")
copy_prop("system_squashfs_compressor", "squashfs_compressor")
copy_prop("system_squashfs_compressor_opt", "squashfs_compressor_opt")
copy_prop("system_squashfs_block_size", "squashfs_block_size")
copy_prop("system_base_fs_file", "base_fs_file")
copy_prop("system_extfs_inode_count", "extfs_inode_count")
+ if not copy_prop("system_extfs_rsv_pct", "extfs_rsv_pct"):
+ d["extfs_rsv_pct"] = "0"
elif mount_point == "data":
# Copy the generic fs type first, override with specific one if available.
copy_prop("fs_type", "fs_type")
copy_prop("userdata_fs_type", "fs_type")
copy_prop("userdata_size", "partition_size")
- copy_prop("flash_logical_block_size","flash_logical_block_size")
+ copy_prop("flash_logical_block_size", "flash_logical_block_size")
copy_prop("flash_erase_block_size", "flash_erase_block_size")
elif mount_point == "cache":
copy_prop("cache_fs_type", "fs_type")
@@ -711,21 +787,45 @@
copy_prop("avb_vendor_algorithm", "avb_algorithm")
copy_prop("vendor_fs_type", "fs_type")
copy_prop("vendor_size", "partition_size")
- copy_prop("vendor_journal_size", "journal_size")
+ if not copy_prop("vendor_journal_size", "journal_size"):
+ d["journal_size"] = "0"
copy_prop("vendor_verity_block_device", "verity_block_device")
- copy_prop("has_ext4_reserved_blocks", "has_ext4_reserved_blocks")
+ copy_prop("ext4_share_dup_blocks", "ext4_share_dup_blocks")
copy_prop("vendor_squashfs_compressor", "squashfs_compressor")
copy_prop("vendor_squashfs_compressor_opt", "squashfs_compressor_opt")
copy_prop("vendor_squashfs_block_size", "squashfs_block_size")
copy_prop("vendor_squashfs_disable_4k_align", "squashfs_disable_4k_align")
copy_prop("vendor_base_fs_file", "base_fs_file")
copy_prop("vendor_extfs_inode_count", "extfs_inode_count")
+ if not copy_prop("vendor_extfs_rsv_pct", "extfs_rsv_pct"):
+ d["extfs_rsv_pct"] = "0"
+ elif mount_point == "product":
+ copy_prop("avb_product_hashtree_enable", "avb_hashtree_enable")
+ copy_prop("avb_product_add_hashtree_footer_args",
+ "avb_add_hashtree_footer_args")
+ copy_prop("avb_product_key_path", "avb_key_path")
+ copy_prop("avb_product_algorithm", "avb_algorithm")
+ copy_prop("product_fs_type", "fs_type")
+ copy_prop("product_size", "partition_size")
+ if not copy_prop("product_journal_size", "journal_size"):
+ d["journal_size"] = "0"
+ copy_prop("product_verity_block_device", "verity_block_device")
+ copy_prop("product_squashfs_compressor", "squashfs_compressor")
+ copy_prop("product_squashfs_compressor_opt", "squashfs_compressor_opt")
+ copy_prop("product_squashfs_block_size", "squashfs_block_size")
+ copy_prop("product_squashfs_disable_4k_align", "squashfs_disable_4k_align")
+ copy_prop("product_base_fs_file", "base_fs_file")
+ copy_prop("product_extfs_inode_count", "extfs_inode_count")
+ if not copy_prop("product_extfs_rsv_pct", "extfs_rsv_pct"):
+ d["extfs_rsv_pct"] = "0"
elif mount_point == "oem":
copy_prop("fs_type", "fs_type")
copy_prop("oem_size", "partition_size")
- copy_prop("oem_journal_size", "journal_size")
- copy_prop("has_ext4_reserved_blocks", "has_ext4_reserved_blocks")
+ if not copy_prop("oem_journal_size", "journal_size"):
+ d["journal_size"] = "0"
copy_prop("oem_extfs_inode_count", "extfs_inode_count")
+ if not copy_prop("oem_extfs_rsv_pct", "extfs_rsv_pct"):
+ d["extfs_rsv_pct"] = "0"
d["partition_name"] = mount_point
return d
@@ -746,7 +846,7 @@
def main(argv):
if len(argv) != 4:
- print __doc__
+ print(__doc__)
sys.exit(1)
in_dir = argv[0]
@@ -774,17 +874,22 @@
mount_point = "vendor"
elif image_filename == "oem.img":
mount_point = "oem"
+ elif image_filename == "product.img":
+ mount_point = "product"
else:
- print >> sys.stderr, "error: unknown image file name ", image_filename
- exit(1)
+ print("error: unknown image file name ", image_filename, file=sys.stderr)
+ sys.exit(1)
image_properties = ImagePropFromGlobalDict(glob_dict, mount_point)
if not BuildImage(in_dir, image_properties, out_file, target_out):
- print >> sys.stderr, "error: failed to build %s from %s" % (out_file,
- in_dir)
- exit(1)
+ print("error: failed to build %s from %s" % (out_file, in_dir),
+ file=sys.stderr)
+ sys.exit(1)
if __name__ == '__main__':
- main(sys.argv[1:])
+ try:
+ main(sys.argv[1:])
+ finally:
+ common.Cleanup()
diff --git a/tools/releasetools/check_ota_package_signature.py b/tools/releasetools/check_ota_package_signature.py
index 548b619..3cac90a 100755
--- a/tools/releasetools/check_ota_package_signature.py
+++ b/tools/releasetools/check_ota_package_signature.py
@@ -21,16 +21,19 @@
from __future__ import print_function
import argparse
-import common
import re
import subprocess
import sys
+import tempfile
+import zipfile
from hashlib import sha1
from hashlib import sha256
+import common
-def cert_uses_sha256(cert):
+
+def CertUsesSha256(cert):
"""Check if the cert uses SHA-256 hashing algorithm."""
cmd = ['openssl', 'x509', '-text', '-noout', '-in', cert]
@@ -46,7 +49,7 @@
return algorithm.group(1).startswith('sha256')
-def verify_package(cert, package):
+def VerifyPackage(cert, package):
"""Verify the given package with the certificate.
(Comments from bootable/recovery/verifier.cpp:)
@@ -90,17 +93,14 @@
print('Signed data length: %d' % (signed_len,))
print('Signature start: %d' % (signature_start,))
- use_sha256 = cert_uses_sha256(cert)
+ use_sha256 = CertUsesSha256(cert)
print('Use SHA-256: %s' % (use_sha256,))
- if use_sha256:
- h = sha256()
- else:
- h = sha1()
+ h = sha256() if use_sha256 else sha1()
h.update(package_bytes[:signed_len])
package_digest = h.hexdigest().lower()
- print('Digest: %s\n' % (package_digest,))
+ print('Digest: %s' % (package_digest,))
# Get the signature from the input package.
signature = package_bytes[signature_start:-6]
@@ -141,7 +141,39 @@
assert package_digest == digest_string, "Verification failed."
# Verified successfully upon reaching here.
- print('VERIFIED\n')
+ print('\nWhole package signature VERIFIED\n')
+
+
+def VerifyAbOtaPayload(cert, package):
+ """Verifies the payload and metadata signatures in an A/B OTA payload."""
+ package_zip = zipfile.ZipFile(package, 'r')
+ if 'payload.bin' not in package_zip.namelist():
+ common.ZipClose(package_zip)
+ return
+
+ print('Verifying A/B OTA payload signatures...')
+
+ # Dump pubkey from the certificate.
+ pubkey = common.MakeTempFile(prefix="key-", suffix=".pem")
+ with open(pubkey, 'wb') as pubkey_fp:
+ pubkey_fp.write(common.ExtractPublicKey(cert))
+
+ package_dir = common.MakeTempDir(prefix='package-')
+
+ # Signature verification with delta_generator.
+ payload_file = package_zip.extract('payload.bin', package_dir)
+ cmd = ['delta_generator',
+ '--in_file=' + payload_file,
+ '--public_key=' + pubkey]
+ proc = common.Run(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+ stdoutdata, _ = proc.communicate()
+ assert proc.returncode == 0, \
+ 'Failed to verify payload with delta_generator: %s\n%s' % (package,
+ stdoutdata)
+ common.ZipClose(package_zip)
+
+ # Verified successfully upon reaching here.
+ print('\nPayload signatures VERIFIED\n\n')
def main():
@@ -150,7 +182,8 @@
parser.add_argument('package', help='The OTA package to be verified.')
args = parser.parse_args()
- verify_package(args.certificate, args.package)
+ VerifyPackage(args.certificate, args.package)
+ VerifyAbOtaPayload(args.certificate, args.package)
if __name__ == '__main__':
@@ -159,3 +192,5 @@
except AssertionError as err:
print('\n ERROR: %s\n' % (err,))
sys.exit(1)
+ finally:
+ common.Cleanup()
diff --git a/tools/releasetools/check_target_files_signatures.py b/tools/releasetools/check_target_files_signatures.py
index c4877e0..b9f39a6 100755
--- a/tools/releasetools/check_target_files_signatures.py
+++ b/tools/releasetools/check_target_files_signatures.py
@@ -39,25 +39,26 @@
"""
+import os
+import re
+import subprocess
import sys
+import zipfile
+
+import common
if sys.hexversion < 0x02070000:
print >> sys.stderr, "Python 2.7 or newer is required."
sys.exit(1)
-import os
-import re
-import shutil
-import subprocess
-import zipfile
-import common
-
-# Work around a bug in python's zipfile module that prevents opening
-# of zipfiles if any entry has an extra field of between 1 and 3 bytes
-# (which is common with zipaligned APKs). This overrides the
-# ZipInfo._decodeExtra() method (which contains the bug) with an empty
-# version (since we don't need to decode the extra field anyway).
+# Work around a bug in Python's zipfile module that prevents opening of zipfiles
+# if any entry has an extra field of between 1 and 3 bytes (which is common with
+# zipaligned APKs). This overrides the ZipInfo._decodeExtra() method (which
+# contains the bug) with an empty version (since we don't need to decode the
+# extra field anyway).
+# Issue #14315: https://bugs.python.org/issue14315, fixed in Python 2.7.8 and
+# Python 3.5.0 alpha 1.
class MyZipInfo(zipfile.ZipInfo):
def _decodeExtra(self):
pass
@@ -242,46 +243,41 @@
# This is the list of wildcards of files we extract from |filename|.
apk_extensions = ['*.apk']
- self.certmap, compressed_extension = common.ReadApkCerts(zipfile.ZipFile(filename, "r"))
+ self.certmap, compressed_extension = common.ReadApkCerts(
+ zipfile.ZipFile(filename, "r"))
if compressed_extension:
apk_extensions.append("*.apk" + compressed_extension)
- d, z = common.UnzipTemp(filename, apk_extensions)
- try:
- self.apks = {}
- self.apks_by_basename = {}
- for dirpath, _, filenames in os.walk(d):
- for fn in filenames:
- # Decompress compressed APKs before we begin processing them.
- if compressed_extension and fn.endswith(compressed_extension):
- # First strip the compressed extension from the file.
- uncompressed_fn = fn[:-len(compressed_extension)]
+ d = common.UnzipTemp(filename, apk_extensions)
+ self.apks = {}
+ self.apks_by_basename = {}
+ for dirpath, _, filenames in os.walk(d):
+ for fn in filenames:
+ # Decompress compressed APKs before we begin processing them.
+ if compressed_extension and fn.endswith(compressed_extension):
+ # First strip the compressed extension from the file.
+ uncompressed_fn = fn[:-len(compressed_extension)]
- # Decompress the compressed file to the output file.
- common.Gunzip(os.path.join(dirpath, fn),
- os.path.join(dirpath, uncompressed_fn))
+ # Decompress the compressed file to the output file.
+ common.Gunzip(os.path.join(dirpath, fn),
+ os.path.join(dirpath, uncompressed_fn))
- # Finally, delete the compressed file and use the uncompressed file
- # for further processing. Note that the deletion is not strictly required,
- # but is done here to ensure that we're not using too much space in
- # the temporary directory.
- os.remove(os.path.join(dirpath, fn))
- fn = uncompressed_fn
+ # Finally, delete the compressed file and use the uncompressed file
+ # for further processing. Note that the deletion is not strictly
+ # required, but is done here to ensure that we're not using too much
+ # space in the temporary directory.
+ os.remove(os.path.join(dirpath, fn))
+ fn = uncompressed_fn
+ if fn.endswith(".apk"):
+ fullname = os.path.join(dirpath, fn)
+ displayname = fullname[len(d)+1:]
+ apk = APK(fullname, displayname)
+ self.apks[apk.filename] = apk
+ self.apks_by_basename[os.path.basename(apk.filename)] = apk
- if fn.endswith(".apk"):
- fullname = os.path.join(dirpath, fn)
- displayname = fullname[len(d)+1:]
- apk = APK(fullname, displayname)
- self.apks[apk.filename] = apk
- self.apks_by_basename[os.path.basename(apk.filename)] = apk
-
- self.max_pkg_len = max(self.max_pkg_len, len(apk.package))
- self.max_fn_len = max(self.max_fn_len, len(apk.filename))
- finally:
- shutil.rmtree(d)
-
- z.close()
+ self.max_pkg_len = max(self.max_pkg_len, len(apk.package))
+ self.max_fn_len = max(self.max_fn_len, len(apk.filename))
def CheckSharedUids(self):
"""Look for any instances where packages signed with different
@@ -291,7 +287,7 @@
if apk.shared_uid:
apks_by_uid.setdefault(apk.shared_uid, []).append(apk)
- for uid in sorted(apks_by_uid.keys()):
+ for uid in sorted(apks_by_uid):
apks = apks_by_uid[uid]
for apk in apks[1:]:
if apk.certs != apks[0].certs:
@@ -466,3 +462,5 @@
print " ERROR: %s" % (e,)
print
sys.exit(1)
+ finally:
+ common.Cleanup()
diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py
index f3096c9..6defb2b 100644
--- a/tools/releasetools/common.py
+++ b/tools/releasetools/common.py
@@ -25,17 +25,17 @@
import re
import shlex
import shutil
+import string
import subprocess
import sys
import tempfile
import threading
import time
import zipfile
+from hashlib import sha1, sha256
import blockimgdiff
-
-from hashlib import sha1 as sha1
-
+import sparse_img
class Options(object):
def __init__(self):
@@ -76,6 +76,11 @@
# Values for "certificate" in apkcerts that mean special things.
SPECIAL_CERT_STRINGS = ("PRESIGNED", "EXTERNAL")
+
+# The partitions allowed to be signed by AVB (Android verified boot 2.0).
+AVB_PARTITIONS = ('boot', 'recovery', 'system', 'vendor', 'product', 'dtbo')
+
+
class ErrorCode(object):
"""Define error_codes for failures that happen during the actual
update package installation.
@@ -121,6 +126,11 @@
return subprocess.Popen(args, **kwargs)
+def RoundUpTo4K(value):
+ rounded_up = value + 4095
+ return rounded_up - (rounded_up % 4096)
+
+
def CloseInheritedPipes():
""" Gmake in MAC OS has file descriptor (PIPE) leak. We close those fds
before doing other work."""
@@ -211,21 +221,6 @@
vendor_base_fs_file,))
del d["vendor_base_fs_file"]
- try:
- data = read_helper("META/imagesizes.txt")
- for line in data.split("\n"):
- if not line:
- continue
- name, value = line.split(" ", 1)
- if not value:
- continue
- if name == "blocksize":
- d[name] = value
- else:
- d[name + "_size"] = value
- except KeyError:
- pass
-
def makeint(key):
if key in d:
d[key] = int(d[key], 0)
@@ -252,15 +247,30 @@
else:
d["fstab"] = None
- d["build.prop"] = LoadBuildProp(read_helper)
+ d["build.prop"] = LoadBuildProp(read_helper, 'SYSTEM/build.prop')
+ d["vendor.build.prop"] = LoadBuildProp(read_helper, 'VENDOR/build.prop')
+
+ # Set up the salt (based on fingerprint or thumbprint) that will be used when
+ # adding AVB footer.
+ if d.get("avb_enable") == "true":
+ fp = None
+ if "build.prop" in d:
+ build_prop = d["build.prop"]
+ if "ro.build.fingerprint" in build_prop:
+ fp = build_prop["ro.build.fingerprint"]
+ elif "ro.build.thumbprint" in build_prop:
+ fp = build_prop["ro.build.thumbprint"]
+ if fp:
+ d["avb_salt"] = sha256(fp).hexdigest()
+
return d
-def LoadBuildProp(read_helper):
+def LoadBuildProp(read_helper, prop_file):
try:
- data = read_helper("SYSTEM/build.prop")
+ data = read_helper(prop_file)
except KeyError:
- print("Warning: could not find SYSTEM/build.prop in %s" % (zip,))
+ print("Warning: could not read %s" % (prop_file,))
data = ""
return LoadDictionaryFromLines(data.split("\n"))
@@ -447,10 +457,17 @@
else:
cmd.extend(["--output", img.name])
+ # "boot" or "recovery", without extension.
+ partition_name = os.path.basename(sourcedir).lower()
+
+ if (partition_name == "recovery" and
+ info_dict.get("include_recovery_dtbo") == "true"):
+ fn = os.path.join(sourcedir, "recovery_dtbo")
+ cmd.extend(["--recovery_dtbo", fn])
+
p = Run(cmd, stdout=subprocess.PIPE)
p.communicate()
- assert p.returncode == 0, "mkbootimg of %s image failed" % (
- os.path.basename(sourcedir),)
+ assert p.returncode == 0, "mkbootimg of %s image failed" % (partition_name,)
if (info_dict.get("boot_signer", None) == "true" and
info_dict.get("verity_key", None)):
@@ -459,7 +476,7 @@
if two_step_image:
path = "/boot"
else:
- path = "/" + os.path.basename(sourcedir).lower()
+ path = "/" + partition_name
cmd = [OPTIONS.boot_signer_path]
cmd.extend(OPTIONS.boot_signer_args)
cmd.extend([path, img.name,
@@ -471,7 +488,7 @@
# Sign the image if vboot is non-empty.
elif info_dict.get("vboot", None):
- path = "/" + os.path.basename(sourcedir).lower()
+ path = "/" + partition_name
img_keyblock = tempfile.NamedTemporaryFile()
# We have switched from the prebuilt futility binary to using the tool
# (futility-host) built from the source. Override the setting in the old
@@ -493,20 +510,21 @@
img_unsigned.close()
img_keyblock.close()
- # AVB: if enabled, calculate and add hash to boot.img.
+ # AVB: if enabled, calculate and add hash to boot.img or recovery.img.
if info_dict.get("avb_enable") == "true":
avbtool = os.getenv('AVBTOOL') or info_dict["avb_avbtool"]
- part_size = info_dict["boot_size"]
+ part_size = info_dict[partition_name + "_size"]
cmd = [avbtool, "add_hash_footer", "--image", img.name,
- "--partition_size", str(part_size), "--partition_name", "boot"]
- AppendAVBSigningArgs(cmd, "boot")
- args = info_dict.get("avb_boot_add_hash_footer_args")
+ "--partition_size", str(part_size), "--partition_name",
+ partition_name]
+ AppendAVBSigningArgs(cmd, partition_name)
+ args = info_dict.get("avb_" + partition_name + "_add_hash_footer_args")
if args and args.strip():
cmd.extend(shlex.split(args))
p = Run(cmd, stdout=subprocess.PIPE)
p.communicate()
assert p.returncode == 0, "avbtool add_hash_footer of %s failed" % (
- os.path.basename(OPTIONS.input_tmp))
+ partition_name,)
img.seek(os.SEEK_SET, 0)
data = img.read()
@@ -565,18 +583,15 @@
def UnzipTemp(filename, pattern=None):
- """Unzip the given archive into a temporary directory and return the name.
+ """Unzips the given archive into a temporary directory and returns the name.
- If filename is of the form "foo.zip+bar.zip", unzip foo.zip into a
- temp dir, then unzip bar.zip into that_dir/BOOTABLE_IMAGES.
+ If filename is of the form "foo.zip+bar.zip", unzip foo.zip into a temp dir,
+ then unzip bar.zip into that_dir/BOOTABLE_IMAGES.
- Returns (tempdir, zipobj) where zipobj is a zipfile.ZipFile (of the
- main file), open for reading.
+ Returns:
+ The name of the temporary directory.
"""
- tmp = tempfile.mkdtemp(prefix="targetfiles-")
- OPTIONS.tempfiles.append(tmp)
-
def unzip_to_dir(filename, dirname):
cmd = ["unzip", "-o", "-q", filename, "-d", dirname]
if pattern is not None:
@@ -587,6 +602,7 @@
raise ExternalError("failed to unzip input target-files \"%s\"" %
(filename,))
+ tmp = MakeTempDir(prefix="targetfiles-")
m = re.match(r"^(.*[.]zip)\+(.*[.]zip)$", filename, re.IGNORECASE)
if m:
unzip_to_dir(m.group(1), tmp)
@@ -595,7 +611,66 @@
else:
unzip_to_dir(filename, tmp)
- return tmp, zipfile.ZipFile(filename, "r")
+ return tmp
+
+
+def GetSparseImage(which, tmpdir, input_zip, allow_shared_blocks):
+ """Returns a SparseImage object suitable for passing to BlockImageDiff.
+
+ This function loads the specified sparse image from the given path, and
+ performs additional processing for OTA purpose. For example, it always adds
+ block 0 to clobbered blocks list. It also detects files that cannot be
+ reconstructed from the block list, for whom we should avoid applying imgdiff.
+
+ Args:
+ which: The partition name, which must be "system" or "vendor".
+ tmpdir: The directory that contains the prebuilt image and block map file.
+ input_zip: The target-files ZIP archive.
+ allow_shared_blocks: Whether having shared blocks is allowed.
+
+ Returns:
+ A SparseImage object, with file_map info loaded.
+ """
+ assert which in ("system", "vendor")
+
+ path = os.path.join(tmpdir, "IMAGES", which + ".img")
+ mappath = os.path.join(tmpdir, "IMAGES", which + ".map")
+
+ # The image and map files must have been created prior to calling
+ # ota_from_target_files.py (since LMP).
+ assert os.path.exists(path) and os.path.exists(mappath)
+
+ # In ext4 filesystems, block 0 might be changed even being mounted R/O. We add
+ # it to clobbered_blocks so that it will be written to the target
+ # unconditionally. Note that they are still part of care_map. (Bug: 20939131)
+ clobbered_blocks = "0"
+
+ image = sparse_img.SparseImage(path, mappath, clobbered_blocks,
+ allow_shared_blocks=allow_shared_blocks)
+
+ # block.map may contain less blocks, because mke2fs may skip allocating blocks
+ # if they contain all zeros. We can't reconstruct such a file from its block
+ # list. Tag such entries accordingly. (Bug: 65213616)
+ for entry in image.file_map:
+ # "/system/framework/am.jar" => "SYSTEM/framework/am.jar".
+ arcname = string.replace(entry, which, which.upper(), 1)[1:]
+ # Skip artificial names, such as "__ZERO", "__NONZERO-1".
+ if arcname not in input_zip.namelist():
+ continue
+
+ info = input_zip.getinfo(arcname)
+ ranges = image.file_map[entry]
+
+ # If a RangeSet has been tagged as using shared blocks while loading the
+ # image, its block list must be already incomplete due to that reason. Don't
+ # give it 'incomplete' tag to avoid messing up the imgdiff stats.
+ if ranges.extra.get('uses_shared_blocks'):
+ continue
+
+ if RoundUpTo4K(info.file_size) > ranges.size() * 4096:
+ ranges.extra['incomplete'] = True
+
+ return image
def GetKeyPasswords(keylist):
@@ -734,10 +809,18 @@
def CheckSize(data, target, info_dict):
- """Check the data string passed against the max size limit, if
- any, for the given target. Raise exception if the data is too big.
- Print a warning if the data is nearing the maximum size."""
+ """Checks the data string passed against the max size limit.
+ For non-AVB images, raise exception if the data is too big. Print a warning
+ if the data is nearing the maximum size.
+
+ For AVB images, the actual image size should be identical to the limit.
+
+ Args:
+ data: A string that contains all the data for the partition.
+ target: The partition name. The ".img" suffix is optional.
+ info_dict: The dict to be looked up for relevant info.
+ """
if target.endswith(".img"):
target = target[:-4]
mount_point = "/" + target
@@ -757,22 +840,41 @@
return
size = len(data)
- pct = float(size) * 100.0 / limit
- msg = "%s size (%d) is %.2f%% of limit (%d)" % (target, size, pct, limit)
- if pct >= 99.0:
- raise ExternalError(msg)
- elif pct >= 95.0:
- print("\n WARNING: %s\n" % (msg,))
- elif OPTIONS.verbose:
- print(" ", msg)
+ # target could be 'userdata' or 'cache'. They should follow the non-AVB image
+ # path.
+ if info_dict.get("avb_enable") == "true" and target in AVB_PARTITIONS:
+ if size != limit:
+ raise ExternalError(
+ "Mismatching image size for %s: expected %d actual %d" % (
+ target, limit, size))
+ else:
+ pct = float(size) * 100.0 / limit
+ msg = "%s size (%d) is %.2f%% of limit (%d)" % (target, size, pct, limit)
+ if pct >= 99.0:
+ raise ExternalError(msg)
+ elif pct >= 95.0:
+ print("\n WARNING: %s\n" % (msg,))
+ elif OPTIONS.verbose:
+ print(" ", msg)
def ReadApkCerts(tf_zip):
- """Given a target_files ZipFile, parse the META/apkcerts.txt file
- and return a tuple with the following elements: (1) a dictionary that maps
- packages to certs (based on the "certificate" and "private_key" attributes
- in the file. (2) A string representing the extension of compressed APKs in
- the target files (e.g ".gz" ".bro")."""
+ """Parses the APK certs info from a given target-files zip.
+
+ Given a target-files ZipFile, parses the META/apkcerts.txt entry and returns a
+ tuple with the following elements: (1) a dictionary that maps packages to
+ certs (based on the "certificate" and "private_key" attributes in the file;
+ (2) a string representing the extension of compressed APKs in the target files
+ (e.g ".gz", ".bro").
+
+ Args:
+ tf_zip: The input target_files ZipFile (already open).
+
+ Returns:
+ (certmap, ext): certmap is a dictionary that maps packages to certs; ext is
+ the extension string of compressed APKs (e.g. ".gz"), or None if there's
+ no compressed APKs.
+ """
certmap = {}
compressed_extension = None
@@ -788,41 +890,51 @@
line = line.strip()
if not line:
continue
- m = re.match(r'^name="(?P<NAME>.*)"\s+certificate="(?P<CERT>.*)"\s+'
- r'private_key="(?P<PRIVKEY>.*?)"(\s+compressed="(?P<COMPRESSED>.*)")?$',
- line)
- if m:
- matches = m.groupdict()
- cert = matches["CERT"]
- privkey = matches["PRIVKEY"]
- name = matches["NAME"]
- this_compressed_extension = matches["COMPRESSED"]
- public_key_suffix_len = len(OPTIONS.public_key_suffix)
- private_key_suffix_len = len(OPTIONS.private_key_suffix)
- if cert in SPECIAL_CERT_STRINGS and not privkey:
- certmap[name] = cert
- elif (cert.endswith(OPTIONS.public_key_suffix) and
- privkey.endswith(OPTIONS.private_key_suffix) and
- cert[:-public_key_suffix_len] == privkey[:-private_key_suffix_len]):
- certmap[name] = cert[:-public_key_suffix_len]
- else:
- raise ValueError("failed to parse line from apkcerts.txt:\n" + line)
- if this_compressed_extension:
- # Only count the installed files.
- filename = name + '.' + this_compressed_extension
- if filename not in installed_files:
- continue
- # Make sure that all the values in the compression map have the same
- # extension. We don't support multiple compression methods in the same
- # system image.
- if compressed_extension:
- if this_compressed_extension != compressed_extension:
- raise ValueError("multiple compressed extensions : %s vs %s",
- (compressed_extension, this_compressed_extension))
- else:
- compressed_extension = this_compressed_extension
+ m = re.match(
+ r'^name="(?P<NAME>.*)"\s+certificate="(?P<CERT>.*)"\s+'
+ r'private_key="(?P<PRIVKEY>.*?)"(\s+compressed="(?P<COMPRESSED>.*)")?$',
+ line)
+ if not m:
+ continue
- return (certmap, ("." + compressed_extension) if compressed_extension else None)
+ matches = m.groupdict()
+ cert = matches["CERT"]
+ privkey = matches["PRIVKEY"]
+ name = matches["NAME"]
+ this_compressed_extension = matches["COMPRESSED"]
+
+ public_key_suffix_len = len(OPTIONS.public_key_suffix)
+ private_key_suffix_len = len(OPTIONS.private_key_suffix)
+ if cert in SPECIAL_CERT_STRINGS and not privkey:
+ certmap[name] = cert
+ elif (cert.endswith(OPTIONS.public_key_suffix) and
+ privkey.endswith(OPTIONS.private_key_suffix) and
+ cert[:-public_key_suffix_len] == privkey[:-private_key_suffix_len]):
+ certmap[name] = cert[:-public_key_suffix_len]
+ else:
+ raise ValueError("Failed to parse line from apkcerts.txt:\n" + line)
+
+ if not this_compressed_extension:
+ continue
+
+ # Only count the installed files.
+ filename = name + '.' + this_compressed_extension
+ if filename not in installed_files:
+ continue
+
+ # Make sure that all the values in the compression map have the same
+ # extension. We don't support multiple compression methods in the same
+ # system image.
+ if compressed_extension:
+ if this_compressed_extension != compressed_extension:
+ raise ValueError(
+ "Multiple compressed extensions: {} vs {}".format(
+ compressed_extension, this_compressed_extension))
+ else:
+ compressed_extension = this_compressed_extension
+
+ return (certmap,
+ ("." + compressed_extension) if compressed_extension else None)
COMMON_DOCSTRING = """
@@ -930,12 +1042,24 @@
return fn
+def MakeTempDir(prefix='tmp', suffix=''):
+ """Makes a temporary dir that will be cleaned up with a call to Cleanup().
+
+ Returns:
+ The absolute pathname of the new directory.
+ """
+ dir_name = tempfile.mkdtemp(suffix=suffix, prefix=prefix)
+ OPTIONS.tempfiles.append(dir_name)
+ return dir_name
+
+
def Cleanup():
for i in OPTIONS.tempfiles:
if os.path.isdir(i):
- shutil.rmtree(i)
+ shutil.rmtree(i, ignore_errors=True)
else:
os.remove(i)
+ del OPTIONS.tempfiles[:]
class PasswordManager(object):
@@ -1122,6 +1246,28 @@
zipfile.ZIP64_LIMIT = saved_zip64_limit
+def ZipDelete(zip_filename, entries):
+ """Deletes entries from a ZIP file.
+
+ Since deleting entries from a ZIP file is not supported, it shells out to
+ 'zip -d'.
+
+ Args:
+ zip_filename: The name of the ZIP file.
+ entries: The name of the entry, or the list of names to be deleted.
+
+ Raises:
+ AssertionError: In case of non-zero return from 'zip'.
+ """
+ if isinstance(entries, basestring):
+ entries = [entries]
+ cmd = ["zip", "-d", zip_filename] + entries
+ proc = Run(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+ stdoutdata, _ = proc.communicate()
+ assert proc.returncode == 0, "Failed to delete %s:\n%s" % (entries,
+ stdoutdata)
+
+
def ZipClose(zip_file):
# http://b/18015246
# zipfile also refers to ZIP64_LIMIT during close() when it writes out the
@@ -1306,7 +1452,7 @@
p.kill()
th.join()
- if err or p.returncode != 0:
+ if p.returncode != 0:
print("WARNING: failure running %s:\n%s\n" % (
diff_program, "".join(err)))
self.patch = None
@@ -1384,20 +1530,16 @@
self.disable_imgdiff = disable_imgdiff
if version is None:
- version = 1
- if OPTIONS.info_dict:
- version = max(
- int(i) for i in
- OPTIONS.info_dict.get("blockimgdiff_versions", "1").split(","))
+ version = max(
+ int(i) for i in
+ OPTIONS.info_dict.get("blockimgdiff_versions", "1").split(","))
assert version >= 3
self.version = version
b = blockimgdiff.BlockImageDiff(tgt, src, threads=OPTIONS.worker_threads,
version=self.version,
disable_imgdiff=self.disable_imgdiff)
- tmpdir = tempfile.mkdtemp()
- OPTIONS.tempfiles.append(tmpdir)
- self.path = os.path.join(tmpdir, partition)
+ self.path = os.path.join(MakeTempDir(), partition)
b.Compute(self.path)
self._required_cache = b.max_stashed_size
self.touched_src_ranges = b.touched_src_ranges
@@ -1570,11 +1712,11 @@
# decompression_time: 15s | 25s | 25s
if not self.src:
- bro_cmd = ['bro', '--quality', '6',
- '--input', '{}.new.dat'.format(self.path),
- '--output', '{}.new.dat.br'.format(self.path)]
+ brotli_cmd = ['brotli', '--quality=6',
+ '--output={}.new.dat.br'.format(self.path),
+ '{}.new.dat'.format(self.path)]
print("Compressing {}.new.dat with brotli".format(self.partition))
- p = Run(bro_cmd, stdout=subprocess.PIPE)
+ p = Run(brotli_cmd, stdout=subprocess.PIPE)
p.communicate()
assert p.returncode == 0,\
'compression of {}.new.dat failed'.format(self.partition)
@@ -1645,50 +1787,93 @@
def ParseCertificate(data):
- """Parse a PEM-format certificate."""
- cert = []
+ """Parses and converts a PEM-encoded certificate into DER-encoded.
+
+ This gives the same result as `openssl x509 -in <filename> -outform DER`.
+
+ Returns:
+ The decoded certificate string.
+ """
+ cert_buffer = []
save = False
for line in data.split("\n"):
if "--END CERTIFICATE--" in line:
break
if save:
- cert.append(line)
+ cert_buffer.append(line)
if "--BEGIN CERTIFICATE--" in line:
save = True
- cert = "".join(cert).decode('base64')
+ cert = "".join(cert_buffer).decode('base64')
return cert
+
+def ExtractPublicKey(cert):
+ """Extracts the public key (PEM-encoded) from the given certificate file.
+
+ Args:
+ cert: The certificate filename.
+
+ Returns:
+ The public key string.
+
+ Raises:
+ AssertionError: On non-zero return from 'openssl'.
+ """
+ # The behavior with '-out' is different between openssl 1.1 and openssl 1.0.
+ # While openssl 1.1 writes the key into the given filename followed by '-out',
+ # openssl 1.0 (both of 1.0.1 and 1.0.2) doesn't. So we collect the output from
+ # stdout instead.
+ cmd = ['openssl', 'x509', '-pubkey', '-noout', '-in', cert]
+ proc = Run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ pubkey, stderrdata = proc.communicate()
+ assert proc.returncode == 0, \
+ 'Failed to dump public key from certificate: %s\n%s' % (cert, stderrdata)
+ return pubkey
+
+
def MakeRecoveryPatch(input_dir, output_sink, recovery_img, boot_img,
info_dict=None):
- """Generate a binary patch that creates the recovery image starting
- with the boot image. (Most of the space in these images is just the
- kernel, which is identical for the two, so the resulting patch
- should be efficient.) Add it to the output zip, along with a shell
- script that is run from init.rc on first boot to actually do the
- patching and install the new recovery image.
+ """Generates the recovery-from-boot patch and writes the script to output.
- recovery_img and boot_img should be File objects for the
- corresponding images. info should be the dictionary returned by
- common.LoadInfoDict() on the input target_files.
+ Most of the space in the boot and recovery images is just the kernel, which is
+ identical for the two, so the resulting patch should be efficient. Add it to
+ the output zip, along with a shell script that is run from init.rc on first
+ boot to actually do the patching and install the new recovery image.
+
+ Args:
+ input_dir: The top-level input directory of the target-files.zip.
+ output_sink: The callback function that writes the result.
+ recovery_img: File object for the recovery image.
+ boot_img: File objects for the boot image.
+ info_dict: A dict returned by common.LoadInfoDict() on the input
+ target_files. Will use OPTIONS.info_dict if None has been given.
"""
-
if info_dict is None:
info_dict = OPTIONS.info_dict
- full_recovery_image = info_dict.get("full_recovery_image", None) == "true"
+ full_recovery_image = info_dict.get("full_recovery_image") == "true"
if full_recovery_image:
output_sink("etc/recovery.img", recovery_img.data)
else:
- diff_program = ["imgdiff"]
+ system_root_image = info_dict.get("system_root_image") == "true"
path = os.path.join(input_dir, "SYSTEM", "etc", "recovery-resource.dat")
- if os.path.exists(path):
- diff_program.append("-b")
- diff_program.append(path)
- bonus_args = "-b /system/etc/recovery-resource.dat"
- else:
+ # With system-root-image, boot and recovery images will have mismatching
+ # entries (only recovery has the ramdisk entry) (Bug: 72731506). Use bsdiff
+ # to handle such a case.
+ if system_root_image:
+ diff_program = ["bsdiff"]
bonus_args = ""
+ assert not os.path.exists(path)
+ else:
+ diff_program = ["imgdiff"]
+ if os.path.exists(path):
+ diff_program.append("-b")
+ diff_program.append(path)
+ bonus_args = "-b /system/etc/recovery-resource.dat"
+ else:
+ bonus_args = ""
d = Difference(recovery_img, boot_img, diff_program=diff_program)
_, _, patch = d.ComputePatch()
diff --git a/tools/releasetools/edify_generator.py b/tools/releasetools/edify_generator.py
index 0c44faf..7a81928 100644
--- a/tools/releasetools/edify_generator.py
+++ b/tools/releasetools/edify_generator.py
@@ -77,14 +77,14 @@
with temporary=True) to this one."""
self.script.extend(other.script)
- def AssertOemProperty(self, name, values):
+ def AssertOemProperty(self, name, values, oem_no_mount):
"""Assert that a property on the OEM paritition matches allowed values."""
if not name:
raise ValueError("must specify an OEM property")
if not values:
raise ValueError("must specify the OEM value")
- get_prop_command = None
- if common.OPTIONS.oem_no_mount:
+
+ if oem_no_mount:
get_prop_command = 'getprop("%s")' % name
else:
get_prop_command = 'file_getprop("/oem/oem.prop", "%s")' % name
diff --git a/tools/releasetools/img_from_target_files.py b/tools/releasetools/img_from_target_files.py
index 4422b53..e6e8c9f 100755
--- a/tools/releasetools/img_from_target_files.py
+++ b/tools/releasetools/img_from_target_files.py
@@ -71,8 +71,7 @@
common.Usage(__doc__)
sys.exit(1)
- OPTIONS.input_tmp, input_zip = common.UnzipTemp(
- args[0], ["IMAGES/*", "OTA/*"])
+ OPTIONS.input_tmp = common.UnzipTemp(args[0], ["IMAGES/*", "OTA/*"])
output_zip = zipfile.ZipFile(args[1], "w", compression=zipfile.ZIP_DEFLATED)
CopyInfo(output_zip)
diff --git a/tools/releasetools/ota_from_target_files.py b/tools/releasetools/ota_from_target_files.py
index 3baacdc..10a19b3 100755
--- a/tools/releasetools/ota_from_target_files.py
+++ b/tools/releasetools/ota_from_target_files.py
@@ -21,9 +21,6 @@
Usage: ota_from_target_files [flags] input_target_files output_ota_package
- --board_config <file>
- Deprecated.
-
-k (--package_key) <key> Key to use to sign the package (default is
the value of default_system_dev_certificate from the input
target-files's META/misc_info.txt, or
@@ -46,14 +43,16 @@
Similar to --full_radio. When generating an incremental OTA, always
include a full copy of bootloader image.
- -v (--verify)
- Remount and verify the checksums of the files written to the
- system and vendor (if used) partitions. Incremental builds only.
+ --verify
+ Remount and verify the checksums of the files written to the system and
+ vendor (if used) partitions. Non-A/B incremental OTAs only.
-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.
+ 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,
@@ -61,29 +60,34 @@
very rarely used, since it's expected to have a dedicated OEM partition
for OEM-specific properties. Only meaningful when -o is specified.
- -w (--wipe_user_data)
+ --wipe_user_data
Generate an OTA package that will wipe the user data partition
when installed.
--downgrade
- Intentionally generate an incremental OTA that updates from a newer
- build to an older one (based on timestamp comparison). "post-timestamp"
- will be replaced by "ota-downgrade=yes" in the metadata file. A data
- wipe will always be enforced, so "ota-wipe=yes" will also be included in
- the metadata file. The update-binary in the source build will be used in
- the OTA package, unless --binary flag is specified. Please also check the
- doc for --override_timestamp below.
+ Intentionally generate an incremental OTA that updates from a newer build
+ to an older one (e.g. downgrading from P preview back to O MR1).
+ "ota-downgrade=yes" will be set in the package metadata file. A data wipe
+ will always be enforced when using this flag, so "ota-wipe=yes" will also
+ be included in the metadata file. The update-binary in the source build
+ will be used in the OTA package, unless --binary flag is specified. Please
+ also check the comment for --override_timestamp below.
--override_timestamp
- Intentionally generate an incremental OTA that updates from a newer
- build to an older one (based on timestamp comparison), by overriding the
- timestamp in package metadata. This differs from --downgrade flag: we
- know for sure this is NOT an actual downgrade case, but two builds are
- cut in a reverse order. A legit use case is that we cut a new build C
- (after having A and B), but want to enfore an update path of A -> C -> B.
- Specifying --downgrade may not help since that would enforce a data wipe
- for C -> B update. The value of "post-timestamp" will be set to the newer
- timestamp plus one, so that the package can be pushed and applied.
+ Intentionally generate an incremental OTA that updates from a newer build
+ to an older one (based on timestamp comparison), by setting the downgrade
+ flag in the package metadata. This differs from --downgrade flag, as we
+ don't enforce a data wipe with this flag. Because we know for sure this is
+ NOT an actual downgrade case, but two builds happen to be cut in a reverse
+ order (e.g. from two branches). A legit use case is that we cut a new
+ build C (after having A and B), but want to enfore an update path of A ->
+ C -> B. Specifying --downgrade may not help since that would enforce a
+ data wipe for C -> B update.
+
+ We used to set a fake timestamp in the package metadata for this flow. But
+ now we consolidate the two cases (i.e. an actual downgrade, or a downgrade
+ based on timestamp) with the same "ota-downgrade=yes" flag, with the
+ difference being whether "ota-wipe=yes" is set.
-e (--extra_script) <file>
Insert the contents of file at the end of the update script.
@@ -93,6 +97,24 @@
first, so that any changes made to the system partition are done
using the new recovery (new kernel, etc.).
+ --include_secondary
+ Additionally include the payload for secondary slot images (default:
+ False). Only meaningful when generating A/B OTAs.
+
+ By default, an A/B OTA package doesn't contain the images for the
+ secondary slot (e.g. system_other.img). Specifying this flag allows
+ generating a separate payload that will install secondary slot images.
+
+ Such a package needs to be applied in a two-stage manner, with a reboot
+ in-between. During the first stage, the updater applies the primary
+ payload only. Upon finishing, it reboots the device into the newly updated
+ slot. It then continues to install the secondary payload to the inactive
+ slot, but without switching the active slot at the end (needs the matching
+ support in update_engine, i.e. SWITCH_SLOT_ON_REBOOT flag).
+
+ Due to the special install procedure, the secondary payload will be always
+ generated as a full payload.
+
--block
Generate a block-based OTA for non-A/B device. We have deprecated the
support for file-based OTA since O. Block-based OTA will be used by
@@ -112,9 +134,6 @@
Specifies the threshold that will be used to compute the maximum
allowed stash size (defaults to 0.8).
- --gen_verify
- Generate an OTA package that verifies the partitions.
-
--log_diff <file>
Generate a log file that shows the differences in the source and target
builds for an incremental package. This option is only meaningful when
@@ -130,27 +149,34 @@
--payload_signer_args <args>
Specify the arguments needed for payload signer.
+
+ --skip_postinstall
+ Skip the postinstall hooks when generating an A/B OTA package (default:
+ False). Note that this discards ALL the hooks, including non-optional
+ 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.
"""
from __future__ import print_function
-import sys
-
-if sys.hexversion < 0x02070000:
- print("Python 2.7 or newer is required.", file=sys.stderr)
- sys.exit(1)
-
-import copy
import multiprocessing
import os.path
-import subprocess
import shlex
+import shutil
+import struct
+import subprocess
+import sys
import tempfile
import zipfile
import common
import edify_generator
-import sparse_img
+
+if sys.hexversion < 0x02070000:
+ print("Python 2.7 or newer is required.", file=sys.stderr)
+ sys.exit(1)
+
OPTIONS = common.OPTIONS
OPTIONS.package_key = None
@@ -159,34 +185,350 @@
OPTIONS.patch_threshold = 0.95
OPTIONS.wipe_user_data = False
OPTIONS.downgrade = False
-OPTIONS.timestamp = 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_source = None
OPTIONS.oem_no_mount = False
-OPTIONS.fallback_to_full = True
OPTIONS.full_radio = False
OPTIONS.full_bootloader = False
# Stash size cannot exceed cache_size * threshold.
OPTIONS.cache_size = None
OPTIONS.stash_threshold = 0.8
-OPTIONS.gen_verify = False
OPTIONS.log_diff = None
OPTIONS.payload_signer = None
OPTIONS.payload_signer_args = []
OPTIONS.extracted_input = None
OPTIONS.key_passwords = []
+OPTIONS.skip_postinstall = False
+
METADATA_NAME = 'META-INF/com/android/metadata'
+POSTINSTALL_CONFIG = 'META/postinstall_config.txt'
UNZIP_PATTERN = ['IMAGES/*', 'META/*']
+class BuildInfo(object):
+ """A class that holds the information for a given build.
+
+ This class wraps up the property querying for a given source or target build.
+ It abstracts away the logic of handling OEM-specific properties, and caches
+ the commonly used properties such as fingerprint.
+
+ There are two types of info dicts: a) build-time info dict, which is generated
+ at build time (i.e. included in a target_files zip); b) OEM info dict that is
+ specified at package generation time (via command line argument
+ '--oem_settings'). If a build doesn't use OEM-specific properties (i.e. not
+ having "oem_fingerprint_properties" in build-time info dict), all the queries
+ would be answered based on build-time info dict only. Otherwise if using
+ OEM-specific properties, some of them will be calculated from two info dicts.
+
+ Users can query properties similarly as using a dict() (e.g. info['fstab']),
+ or to query build properties via GetBuildProp() or GetVendorBuildProp().
+
+ Attributes:
+ info_dict: The build-time info dict.
+ is_ab: Whether it's a build that uses A/B OTA.
+ oem_dicts: A list of OEM dicts.
+ oem_props: A list of OEM properties that should be read from OEM dicts; None
+ if the build doesn't use any OEM-specific property.
+ fingerprint: The fingerprint of the build, which would be calculated based
+ on OEM properties if applicable.
+ device: The device name, which could come from OEM dicts if applicable.
+ """
+
+ def __init__(self, info_dict, oem_dicts):
+ """Initializes a BuildInfo instance with the given dicts.
+
+ Arguments:
+ info_dict: The build-time info dict.
+ oem_dicts: A list of OEM dicts (which is parsed from --oem_settings). Note
+ that it always uses the first dict to calculate the fingerprint or the
+ device name. The rest would be used for asserting OEM properties only
+ (e.g. one package can be installed on one of these devices).
+ """
+ self.info_dict = info_dict
+ self.oem_dicts = oem_dicts
+
+ self._is_ab = info_dict.get("ab_update") == "true"
+ self._oem_props = info_dict.get("oem_fingerprint_properties")
+
+ if self._oem_props:
+ assert oem_dicts, "OEM source required for this build"
+
+ # These two should be computed only after setting self._oem_props.
+ self._device = self.GetOemProperty("ro.product.device")
+ self._fingerprint = self.CalculateFingerprint()
+
+ @property
+ def is_ab(self):
+ return self._is_ab
+
+ @property
+ def device(self):
+ return self._device
+
+ @property
+ def fingerprint(self):
+ return self._fingerprint
+
+ @property
+ def oem_props(self):
+ return self._oem_props
+
+ def __getitem__(self, key):
+ return self.info_dict[key]
+
+ def get(self, key, default=None):
+ return self.info_dict.get(key, default)
+
+ def GetBuildProp(self, prop):
+ """Returns the inquired build property."""
+ try:
+ return self.info_dict.get("build.prop", {})[prop]
+ except KeyError:
+ raise common.ExternalError("couldn't find %s in build.prop" % (prop,))
+
+ def GetVendorBuildProp(self, prop):
+ """Returns the inquired vendor build property."""
+ try:
+ return self.info_dict.get("vendor.build.prop", {})[prop]
+ except KeyError:
+ raise common.ExternalError(
+ "couldn't find %s in vendor.build.prop" % (prop,))
+
+ def GetOemProperty(self, key):
+ if self.oem_props is not None and key in self.oem_props:
+ return self.oem_dicts[0][key]
+ return self.GetBuildProp(key)
+
+ def CalculateFingerprint(self):
+ if self.oem_props is None:
+ return self.GetBuildProp("ro.build.fingerprint")
+ return "%s/%s/%s:%s" % (
+ self.GetOemProperty("ro.product.brand"),
+ self.GetOemProperty("ro.product.name"),
+ self.GetOemProperty("ro.product.device"),
+ self.GetBuildProp("ro.build.thumbprint"))
+
+ def WriteMountOemScript(self, script):
+ assert self.oem_props is not None
+ recovery_mount_options = self.info_dict.get("recovery_mount_options")
+ script.Mount("/oem", recovery_mount_options)
+
+ def WriteDeviceAssertions(self, script, oem_no_mount):
+ # Read the property directly if not using OEM properties.
+ if not self.oem_props:
+ script.AssertDevice(self.device)
+ return
+
+ # Otherwise assert OEM properties.
+ if not self.oem_dicts:
+ raise common.ExternalError(
+ "No OEM file provided to answer expected assertions")
+
+ for prop in self.oem_props.split():
+ values = []
+ for oem_dict in self.oem_dicts:
+ if prop in oem_dict:
+ values.append(oem_dict[prop])
+ if not values:
+ raise common.ExternalError(
+ "The OEM file is missing the property %s" % (prop,))
+ script.AssertOemProperty(prop, values, oem_no_mount)
+
+
+class PayloadSigner(object):
+ """A class that wraps the payload signing works.
+
+ When generating a Payload, hashes of the payload and metadata files will be
+ signed with the device key, either by calling an external payload signer or
+ by calling openssl with the package key. This class provides a unified
+ interface, so that callers can just call PayloadSigner.Sign().
+
+ If an external payload signer has been specified (OPTIONS.payload_signer), it
+ calls the signer with the provided args (OPTIONS.payload_signer_args). Note
+ that the signing key should be provided as part of the payload_signer_args.
+ Otherwise without an external signer, it uses the package key
+ (OPTIONS.package_key) and calls openssl for the signing works.
+ """
+
+ def __init__(self):
+ if OPTIONS.payload_signer is None:
+ # Prepare the payload signing key.
+ private_key = OPTIONS.package_key + OPTIONS.private_key_suffix
+ pw = OPTIONS.key_passwords[OPTIONS.package_key]
+
+ cmd = ["openssl", "pkcs8", "-in", private_key, "-inform", "DER"]
+ cmd.extend(["-passin", "pass:" + pw] if pw else ["-nocrypt"])
+ signing_key = common.MakeTempFile(prefix="key-", suffix=".key")
+ cmd.extend(["-out", signing_key])
+
+ get_signing_key = common.Run(cmd, verbose=False, stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT)
+ stdoutdata, _ = get_signing_key.communicate()
+ assert get_signing_key.returncode == 0, \
+ "Failed to get signing key: {}".format(stdoutdata)
+
+ self.signer = "openssl"
+ self.signer_args = ["pkeyutl", "-sign", "-inkey", signing_key,
+ "-pkeyopt", "digest:sha256"]
+ else:
+ self.signer = OPTIONS.payload_signer
+ self.signer_args = OPTIONS.payload_signer_args
+
+ def Sign(self, in_file):
+ """Signs the given input file. Returns the output filename."""
+ out_file = common.MakeTempFile(prefix="signed-", suffix=".bin")
+ cmd = [self.signer] + self.signer_args + ['-in', in_file, '-out', out_file]
+ signing = common.Run(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+ stdoutdata, _ = signing.communicate()
+ assert signing.returncode == 0, \
+ "Failed to sign the input file: {}".format(stdoutdata)
+ return out_file
+
+
+class Payload(object):
+ """Manages the creation and the signing of an A/B OTA Payload."""
+
+ PAYLOAD_BIN = 'payload.bin'
+ PAYLOAD_PROPERTIES_TXT = 'payload_properties.txt'
+ SECONDARY_PAYLOAD_BIN = 'secondary/payload.bin'
+ SECONDARY_PAYLOAD_PROPERTIES_TXT = 'secondary/payload_properties.txt'
+
+ def __init__(self, secondary=False):
+ """Initializes a Payload instance.
+
+ Args:
+ secondary: Whether it's generating a secondary payload (default: False).
+ """
+ # The place where the output from the subprocess should go.
+ self._log_file = sys.stdout if OPTIONS.verbose else subprocess.PIPE
+ self.payload_file = None
+ self.payload_properties = None
+ self.secondary = secondary
+
+ def Generate(self, target_file, source_file=None, additional_args=None):
+ """Generates a payload from the given target-files zip(s).
+
+ Args:
+ target_file: The filename of the target build target-files zip.
+ source_file: The filename of the source build target-files zip; or None if
+ generating a full OTA.
+ additional_args: A list of additional args that should be passed to
+ brillo_update_payload script; or None.
+ """
+ if additional_args is None:
+ additional_args = []
+
+ payload_file = common.MakeTempFile(prefix="payload-", suffix=".bin")
+ cmd = ["brillo_update_payload", "generate",
+ "--payload", payload_file,
+ "--target_image", target_file]
+ if source_file is not None:
+ cmd.extend(["--source_image", source_file])
+ cmd.extend(additional_args)
+ p = common.Run(cmd, stdout=self._log_file, stderr=subprocess.STDOUT)
+ stdoutdata, _ = p.communicate()
+ assert p.returncode == 0, \
+ "brillo_update_payload generate failed: {}".format(stdoutdata)
+
+ self.payload_file = payload_file
+ self.payload_properties = None
+
+ def Sign(self, payload_signer):
+ """Generates and signs the hashes of the payload and metadata.
+
+ Args:
+ payload_signer: A PayloadSigner() instance that serves the signing work.
+
+ Raises:
+ AssertionError: On any failure when calling brillo_update_payload script.
+ """
+ assert isinstance(payload_signer, PayloadSigner)
+
+ # 1. Generate hashes of the payload and metadata files.
+ payload_sig_file = common.MakeTempFile(prefix="sig-", suffix=".bin")
+ metadata_sig_file = common.MakeTempFile(prefix="sig-", suffix=".bin")
+ cmd = ["brillo_update_payload", "hash",
+ "--unsigned_payload", self.payload_file,
+ "--signature_size", "256",
+ "--metadata_hash_file", metadata_sig_file,
+ "--payload_hash_file", payload_sig_file]
+ p1 = common.Run(cmd, stdout=self._log_file, stderr=subprocess.STDOUT)
+ p1.communicate()
+ assert p1.returncode == 0, "brillo_update_payload hash failed"
+
+ # 2. Sign the hashes.
+ signed_payload_sig_file = payload_signer.Sign(payload_sig_file)
+ signed_metadata_sig_file = payload_signer.Sign(metadata_sig_file)
+
+ # 3. Insert the signatures back into the payload file.
+ signed_payload_file = common.MakeTempFile(prefix="signed-payload-",
+ suffix=".bin")
+ cmd = ["brillo_update_payload", "sign",
+ "--unsigned_payload", self.payload_file,
+ "--payload", signed_payload_file,
+ "--signature_size", "256",
+ "--metadata_signature_file", signed_metadata_sig_file,
+ "--payload_signature_file", signed_payload_sig_file]
+ p1 = common.Run(cmd, stdout=self._log_file, stderr=subprocess.STDOUT)
+ p1.communicate()
+ assert p1.returncode == 0, "brillo_update_payload sign failed"
+
+ # 4. Dump the signed payload properties.
+ properties_file = common.MakeTempFile(prefix="payload-properties-",
+ suffix=".txt")
+ cmd = ["brillo_update_payload", "properties",
+ "--payload", signed_payload_file,
+ "--properties_file", properties_file]
+ p1 = common.Run(cmd, stdout=self._log_file, stderr=subprocess.STDOUT)
+ p1.communicate()
+ assert p1.returncode == 0, "brillo_update_payload properties failed"
+
+ if self.secondary:
+ with open(properties_file, "a") as f:
+ f.write("SWITCH_SLOT_ON_REBOOT=0\n")
+
+ if OPTIONS.wipe_user_data:
+ with open(properties_file, "a") as f:
+ f.write("POWERWASH=1\n")
+
+ self.payload_file = signed_payload_file
+ self.payload_properties = properties_file
+
+ def WriteToZip(self, output_zip):
+ """Writes the payload to the given zip.
+
+ Args:
+ output_zip: The output ZipFile instance.
+ """
+ assert self.payload_file is not None
+ assert self.payload_properties is not None
+
+ if self.secondary:
+ payload_arcname = Payload.SECONDARY_PAYLOAD_BIN
+ payload_properties_arcname = Payload.SECONDARY_PAYLOAD_PROPERTIES_TXT
+ else:
+ payload_arcname = Payload.PAYLOAD_BIN
+ payload_properties_arcname = Payload.PAYLOAD_PROPERTIES_TXT
+
+ # Add the signed payload file and properties into the zip. In order to
+ # support streaming, we pack them as ZIP_STORED. So these entries can be
+ # read directly with the offset and length pairs.
+ common.ZipWrite(output_zip, self.payload_file, arcname=payload_arcname,
+ compress_type=zipfile.ZIP_STORED)
+ common.ZipWrite(output_zip, self.payload_properties,
+ arcname=payload_properties_arcname,
+ compress_type=zipfile.ZIP_STORED)
+
+
def SignOutput(temp_zip_name, output_zip_name):
pw = OPTIONS.key_passwords[OPTIONS.package_key]
@@ -194,37 +536,15 @@
whole_file=True)
-def AppendAssertions(script, info_dict, oem_dicts=None):
- oem_props = info_dict.get("oem_fingerprint_properties")
- if not oem_props:
- device = GetBuildProp("ro.product.device", info_dict)
- script.AssertDevice(device)
- else:
- if not oem_dicts:
- raise common.ExternalError(
- "No OEM file provided to answer expected assertions")
- for prop in oem_props.split():
- values = []
- for oem_dict in oem_dicts:
- if oem_dict.get(prop):
- values.append(oem_dict[prop])
- if not values:
- raise common.ExternalError(
- "The OEM file is missing the property %s" % prop)
- script.AssertOemProperty(prop, values)
-
-
-def _LoadOemDicts(script, recovery_mount_options=None):
+def _LoadOemDicts(oem_source):
"""Returns the list of loaded OEM properties dict."""
- oem_dicts = None
- if OPTIONS.oem_source is None:
- raise common.ExternalError("OEM source required for this build")
- if not OPTIONS.oem_no_mount and script:
- script.Mount("/oem", recovery_mount_options)
+ if not oem_source:
+ return None
+
oem_dicts = []
- for oem_file in OPTIONS.oem_source:
- oem_dicts.append(common.LoadDictionaryFromLines(
- open(oem_file).readlines()))
+ for oem_file in oem_source:
+ with open(oem_file) as fp:
+ oem_dicts.append(common.LoadDictionaryFromLines(fp.readlines()))
return oem_dicts
@@ -275,126 +595,145 @@
return False
-def GetOemProperty(name, oem_props, oem_dict, info_dict):
- if oem_props is not None and name in oem_props:
- return oem_dict[name]
- return GetBuildProp(name, info_dict)
+def HasTrebleEnabled(target_files_zip, target_info):
+ return (HasVendorPartition(target_files_zip) and
+ target_info.GetBuildProp("ro.treble.enabled") == "true")
-def CalculateFingerprint(oem_props, oem_dict, info_dict):
- if oem_props is None:
- return GetBuildProp("ro.build.fingerprint", info_dict)
- return "%s/%s/%s:%s" % (
- GetOemProperty("ro.product.brand", oem_props, oem_dict, info_dict),
- GetOemProperty("ro.product.name", oem_props, oem_dict, info_dict),
- GetOemProperty("ro.product.device", oem_props, oem_dict, info_dict),
- GetBuildProp("ro.build.thumbprint", info_dict))
+def 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 GetImage(which, tmpdir):
- """Returns an image object suitable for passing to BlockImageDiff.
-
- 'which' partition must be "system" or "vendor". A prebuilt image and file
- map must already exist in tmpdir.
- """
-
- assert which in ("system", "vendor")
-
- path = os.path.join(tmpdir, "IMAGES", which + ".img")
- mappath = os.path.join(tmpdir, "IMAGES", which + ".map")
-
- # The image and map files must have been created prior to calling
- # ota_from_target_files.py (since LMP).
- assert os.path.exists(path) and os.path.exists(mappath)
-
- # Bug: http://b/20939131
- # In ext4 filesystems, block 0 might be changed even being mounted
- # R/O. We add it to clobbered_blocks so that it will be written to the
- # target unconditionally. Note that they are still part of care_map.
- clobbered_blocks = "0"
-
- return sparse_img.SparseImage(path, mappath, clobbered_blocks)
-
-
-def AddCompatibilityArchive(target_zip, output_zip, system_included=True,
- vendor_included=True):
- """Adds compatibility info from target files into the output zip.
+def AddCompatibilityArchiveIfTrebleEnabled(target_zip, output_zip, target_info,
+ source_info=None):
+ """Adds compatibility info into the output zip if it's Treble-enabled target.
Metadata used for on-device compatibility verification is retrieved from
target_zip then added to compatibility.zip which is added to the output_zip
archive.
- Compatibility archive should only be included for devices with a vendor
- partition as checking provides value when system and vendor are independently
- versioned.
+ Compatibility archive should only be included for devices that have enabled
+ Treble support.
Args:
target_zip: Zip file containing the source files to be included for OTA.
output_zip: Zip file that will be sent for OTA.
- system_included: If True, the system image will be updated and therefore
- its metadata should be included.
- vendor_included: If True, the vendor image will be updated and therefore
- its metadata should be included.
+ target_info: The BuildInfo instance that holds the target build info.
+ source_info: The BuildInfo instance that holds the source build info, if
+ generating an incremental OTA; None otherwise.
"""
- # Determine what metadata we need. Files are names relative to META/.
- compatibility_files = []
- vendor_metadata = ("vendor_manifest.xml", "vendor_matrix.xml")
- system_metadata = ("system_manifest.xml", "system_matrix.xml")
- if vendor_included:
- compatibility_files += vendor_metadata
- if system_included:
- compatibility_files += system_metadata
+ def AddCompatibilityArchive(system_updated, vendor_updated):
+ """Adds compatibility info based on system/vendor update status.
- # Create new archive.
- compatibility_archive = tempfile.NamedTemporaryFile()
- compatibility_archive_zip = zipfile.ZipFile(compatibility_archive, "w",
- compression=zipfile.ZIP_DEFLATED)
+ Args:
+ system_updated: If True, the system image will be updated and therefore
+ its metadata should be included.
+ vendor_updated: If True, the vendor image will be updated and therefore
+ its metadata should be included.
+ """
+ # Determine what metadata we need. Files are names relative to META/.
+ compatibility_files = []
+ vendor_metadata = ("vendor_manifest.xml", "vendor_matrix.xml")
+ system_metadata = ("system_manifest.xml", "system_matrix.xml")
+ if vendor_updated:
+ compatibility_files += vendor_metadata
+ if system_updated:
+ compatibility_files += system_metadata
- # Add metadata.
- for file_name in compatibility_files:
- target_file_name = "META/" + file_name
+ # Create new archive.
+ compatibility_archive = tempfile.NamedTemporaryFile()
+ compatibility_archive_zip = zipfile.ZipFile(
+ compatibility_archive, "w", compression=zipfile.ZIP_DEFLATED)
- if target_file_name in target_zip.namelist():
- data = target_zip.read(target_file_name)
- common.ZipWriteStr(compatibility_archive_zip, file_name, data)
+ # Add metadata.
+ for file_name in compatibility_files:
+ target_file_name = "META/" + file_name
- # Ensure files are written before we copy into output_zip.
- compatibility_archive_zip.close()
+ if target_file_name in target_zip.namelist():
+ data = target_zip.read(target_file_name)
+ common.ZipWriteStr(compatibility_archive_zip, file_name, data)
- # Only add the archive if we have any compatibility info.
- if compatibility_archive_zip.namelist():
- common.ZipWrite(output_zip, compatibility_archive.name,
- arcname="compatibility.zip",
- compress_type=zipfile.ZIP_STORED)
+ # Ensure files are written before we copy into output_zip.
+ compatibility_archive_zip.close()
+
+ # Only add the archive if we have any compatibility info.
+ if compatibility_archive_zip.namelist():
+ common.ZipWrite(output_zip, compatibility_archive.name,
+ arcname="compatibility.zip",
+ compress_type=zipfile.ZIP_STORED)
+
+ # Will only proceed if the target has enabled the Treble support (as well as
+ # having a /vendor partition).
+ if not HasTrebleEnabled(target_zip, target_info):
+ return
+
+ # We don't support OEM thumbprint in Treble world (which calculates
+ # fingerprints in a different way as shown in CalculateFingerprint()).
+ assert not target_info.oem_props
+
+ # Full OTA carries the info for system/vendor both.
+ if source_info is None:
+ AddCompatibilityArchive(True, True)
+ return
+
+ assert not source_info.oem_props
+
+ source_fp = source_info.fingerprint
+ target_fp = target_info.fingerprint
+ system_updated = source_fp != target_fp
+
+ source_fp_vendor = source_info.GetVendorBuildProp(
+ "ro.vendor.build.fingerprint")
+ target_fp_vendor = target_info.GetVendorBuildProp(
+ "ro.vendor.build.fingerprint")
+ vendor_updated = source_fp_vendor != target_fp_vendor
+
+ AddCompatibilityArchive(system_updated, vendor_updated)
-def WriteFullOTAPackage(input_zip, output_zip):
- # TODO: how to determine this? We don't know what version it will
- # be installed on top of. For now, we expect the API just won't
- # change very often. Similarly for fstab, it might have changed
- # in the target build.
- script = edify_generator.EdifyGenerator(3, OPTIONS.info_dict)
+def WriteFullOTAPackage(input_zip, output_file):
+ target_info = BuildInfo(OPTIONS.info_dict, OPTIONS.oem_dicts)
- recovery_mount_options = OPTIONS.info_dict.get("recovery_mount_options")
- oem_props = OPTIONS.info_dict.get("oem_fingerprint_properties")
- oem_dicts = None
- if oem_props:
- oem_dicts = _LoadOemDicts(script, recovery_mount_options)
+ # 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)
- target_fp = CalculateFingerprint(oem_props, oem_dicts and oem_dicts[0],
- OPTIONS.info_dict)
- metadata = {
- "post-build": target_fp,
- "pre-device": GetOemProperty("ro.product.device", oem_props,
- oem_dicts and oem_dicts[0],
- OPTIONS.info_dict),
- "post-timestamp": GetBuildProp("ro.build.date.utc", OPTIONS.info_dict),
- }
+ 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=OPTIONS.info_dict["recovery_api_version"],
+ input_version=target_api_version,
output_zip=output_zip,
script=script,
input_tmp=OPTIONS.input_tmp,
@@ -403,13 +742,12 @@
assert HasRecoveryPatch(input_zip)
- metadata["ota-type"] = "BLOCK"
-
- ts = GetBuildProp("ro.build.date.utc", OPTIONS.info_dict)
- ts_text = GetBuildProp("ro.build.date", 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)
- AppendAssertions(script, OPTIONS.info_dict, oem_dicts)
+ target_info.WriteDeviceAssertions(script, OPTIONS.oem_no_mount)
device_specific.FullOTA_Assertions()
# Two-step package strategy (in chronological order, which is *not*
@@ -435,9 +773,9 @@
recovery_img = common.GetBootableImage("recovery.img", "recovery.img",
OPTIONS.input_tmp, "RECOVERY")
if OPTIONS.two_step:
- if not OPTIONS.info_dict.get("multistage_support", None):
+ if not target_info.get("multistage_support"):
assert False, "two-step packages not supported by this build"
- fs = OPTIONS.info_dict["fstab"]["/misc"]
+ 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}
@@ -459,7 +797,7 @@
script.Comment("Stage 3/3")
# Dump fingerprints
- script.Print("Target: %s" % target_fp)
+ script.Print("Target: {}".format(target_info.fingerprint))
device_specific.FullOTA_InstallBegin()
@@ -470,20 +808,17 @@
if HasVendorPartition(input_zip):
system_progress -= 0.1
- # Place a copy of file_contexts.bin into the OTA package which will be used
- # by the recovery program.
- if "selinux_fc" in OPTIONS.info_dict:
- WritePolicyConfig(OPTIONS.info_dict["selinux_fc"], output_zip)
-
- recovery_mount_options = OPTIONS.info_dict.get("recovery_mount_options")
-
script.ShowProgress(system_progress, 0)
+ # See the notes in WriteBlockIncrementalOTAPackage().
+ allow_shared_blocks = target_info.get('ext4_share_dup_blocks') == "true"
+
# Full OTA is done as an "incremental" against an empty source image. This
# has the effect of writing new data from the package to the entire
# partition, but lets us reuse the updater code that writes incrementals to
# do it.
- system_tgt = GetImage("system", OPTIONS.input_tmp)
+ system_tgt = common.GetSparseImage("system", OPTIONS.input_tmp, input_zip,
+ allow_shared_blocks)
system_tgt.ResetFileMap()
system_diff = common.BlockDifference("system", system_tgt, src=None)
system_diff.WriteScript(script, output_zip)
@@ -494,12 +829,15 @@
if HasVendorPartition(input_zip):
script.ShowProgress(0.1, 0)
- vendor_tgt = GetImage("vendor", OPTIONS.input_tmp)
+ vendor_tgt = common.GetSparseImage("vendor", OPTIONS.input_tmp, input_zip,
+ allow_shared_blocks)
vendor_tgt.ResetFileMap()
vendor_diff = common.BlockDifference("vendor", vendor_tgt)
vendor_diff.WriteScript(script, output_zip)
- common.CheckSize(boot_img.data, "boot.img", OPTIONS.info_dict)
+ AddCompatibilityArchiveIfTrebleEnabled(input_zip, output_zip, target_info)
+
+ common.CheckSize(boot_img.data, "boot.img", target_info)
common.ZipWriteStr(output_zip, "boot.img", boot_img.data)
script.ShowProgress(0.05, 5)
@@ -537,11 +875,15 @@
script.SetProgress(1)
script.AddToZip(input_zip, output_zip, input_path=OPTIONS.updater_binary)
metadata["ota-required-cache"] = str(script.required_cache)
- WriteMetadata(metadata, output_zip)
+ # We haven't written the metadata entry, which will be done in
+ # FinalizeMetadata.
+ common.ZipClose(output_zip)
-def WritePolicyConfig(file_name, output_zip):
- common.ZipWrite(output_zip, file_name, os.path.basename(file_name))
+ needed_property_files = (
+ NonAbOtaPropertyFiles(),
+ )
+ FinalizeMetadata(metadata, staging_file, output_file, needed_property_files)
def WriteMetadata(metadata, output_zip):
@@ -550,119 +892,504 @@
compress_type=zipfile.ZIP_STORED)
-def GetBuildProp(prop, info_dict):
- """Return the fingerprint of the build of a given target-files info_dict."""
- try:
- return info_dict.get("build.prop", {})[prop]
- except KeyError:
- raise common.ExternalError("couldn't find %s in build.prop" % (prop,))
-
-
-def HandleDowngradeMetadata(metadata):
+def HandleDowngradeMetadata(metadata, target_info, source_info):
# Only incremental OTAs are allowed to reach here.
assert OPTIONS.incremental_source is not None
- post_timestamp = GetBuildProp("ro.build.date.utc", OPTIONS.target_info_dict)
- pre_timestamp = GetBuildProp("ro.build.date.utc", OPTIONS.source_info_dict)
+ post_timestamp = target_info.GetBuildProp("ro.build.date.utc")
+ pre_timestamp = source_info.GetBuildProp("ro.build.date.utc")
is_downgrade = long(post_timestamp) < long(pre_timestamp)
if OPTIONS.downgrade:
if not is_downgrade:
- raise RuntimeError("--downgrade specified but no downgrade detected: "
- "pre: %s, post: %s" % (pre_timestamp, post_timestamp))
+ raise RuntimeError(
+ "--downgrade or --override_timestamp specified but no downgrade "
+ "detected: pre: %s, post: %s" % (pre_timestamp, post_timestamp))
metadata["ota-downgrade"] = "yes"
- elif OPTIONS.timestamp:
- if not is_downgrade:
- raise RuntimeError("--timestamp specified but no timestamp hack needed: "
- "pre: %s, post: %s" % (pre_timestamp, post_timestamp))
- metadata["post-timestamp"] = str(long(pre_timestamp) + 1)
else:
if is_downgrade:
- raise RuntimeError("Downgrade detected based on timestamp check: "
- "pre: %s, post: %s. Need to specify --timestamp OR "
- "--downgrade to allow building the incremental." % (
- pre_timestamp, post_timestamp))
- metadata["post-timestamp"] = post_timestamp
+ 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 WriteBlockIncrementalOTAPackage(target_zip, source_zip, output_zip):
- source_version = OPTIONS.source_info_dict["recovery_api_version"]
- target_version = OPTIONS.target_info_dict["recovery_api_version"]
+def GetPackageMetadata(target_info, source_info=None):
+ """Generates and returns the metadata dict.
- if source_version == 0:
- print("WARNING: generating edify script for a source that "
- "can't install it.")
- script = edify_generator.EdifyGenerator(
- source_version, OPTIONS.target_info_dict,
- fstab=OPTIONS.source_info_dict["fstab"])
+ 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.
- recovery_mount_options = OPTIONS.source_info_dict.get(
- "recovery_mount_options")
- source_oem_props = OPTIONS.source_info_dict.get("oem_fingerprint_properties")
- target_oem_props = OPTIONS.target_info_dict.get("oem_fingerprint_properties")
- oem_dicts = None
- if source_oem_props and target_oem_props:
- oem_dicts = _LoadOemDicts(script, recovery_mount_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, BuildInfo)
+ assert source_info is None or isinstance(source_info, BuildInfo)
metadata = {
- "pre-device": GetOemProperty("ro.product.device", source_oem_props,
- oem_dicts and oem_dicts[0],
- OPTIONS.source_info_dict),
- "ota-type": "BLOCK",
+ 'post-build' : target_info.fingerprint,
+ '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'),
}
- HandleDowngradeMetadata(metadata)
+ if target_info.is_ab:
+ metadata['ota-type'] = 'AB'
+ metadata['ota-required-cache'] = '0'
+ else:
+ metadata['ota-type'] = 'BLOCK'
+
+ if OPTIONS.wipe_user_data:
+ metadata['ota-wipe'] = 'yes'
+
+ is_incremental = source_info is not None
+ if is_incremental:
+ metadata['pre-build'] = source_info.fingerprint
+ metadata['pre-build-incremental'] = source_info.GetBuildProp(
+ 'ro.build.version.incremental')
+ metadata['pre-device'] = source_info.device
+ else:
+ metadata['pre-device'] = target_info.device
+
+ # 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."""
+
+ def ComputeEntryOffsetSize(name):
+ """Computes the zip entry offset and size."""
+ info = zip_file.getinfo(name)
+ offset = info.header_offset + len(info.FileHeader())
+ 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."""
+
+ def __init__(self):
+ super(StreamingPropertyFiles, self).__init__()
+ self.name = 'ota-streaming-property-files'
+ self.required = (
+ # payload.bin and payload_properties.txt must exist.
+ 'payload.bin',
+ 'payload_properties.txt',
+ )
+ self.optional = (
+ # care_map.txt is available only if dm-verity is enabled.
+ 'care_map.txt',
+ # compatibility.zip is available only if target supports Treble.
+ 'compatibility.zip',
+ )
+
+
+class AbOtaPropertyFiles(StreamingPropertyFiles):
+ """The property-files for A/B OTA that includes payload_metadata.bin info.
+
+ Since P, we expose one more token (aka property-file), in addition to the ones
+ for streaming A/B OTA, for a virtual entry of 'payload_metadata.bin'.
+ 'payload_metadata.bin' is the header part of a payload ('payload.bin'), which
+ doesn't exist as a separate ZIP entry, but can be used to verify if the
+ payload can be applied on the given device.
+
+ For backward compatibility, we keep both of the 'ota-streaming-property-files'
+ and the newly added 'ota-property-files' in P. The new token will only be
+ available in 'ota-property-files'.
+ """
+
+ def __init__(self):
+ super(AbOtaPropertyFiles, self).__init__()
+ self.name = 'ota-property-files'
+
+ def _GetPrecomputed(self, input_zip):
+ offset, size = self._GetPayloadMetadataOffsetAndSize(input_zip)
+ return ['payload_metadata.bin:{}:{}'.format(offset, size)]
+
+ @staticmethod
+ def _GetPayloadMetadataOffsetAndSize(input_zip):
+ """Computes the offset and size of the payload metadata for a given package.
+
+ (From system/update_engine/update_metadata.proto)
+ A delta update file contains all the deltas needed to update a system from
+ one specific version to another specific version. The update format is
+ represented by this struct pseudocode:
+
+ struct delta_update_file {
+ char magic[4] = "CrAU";
+ uint64 file_format_version;
+ uint64 manifest_size; // Size of protobuf DeltaArchiveManifest
+
+ // Only present if format_version > 1:
+ uint32 metadata_signature_size;
+
+ // The Bzip2 compressed DeltaArchiveManifest
+ char manifest[metadata_signature_size];
+
+ // The signature of the metadata (from the beginning of the payload up to
+ // this location, not including the signature itself). This is a
+ // serialized Signatures message.
+ char medatada_signature_message[metadata_signature_size];
+
+ // Data blobs for files, no specific format. The specific offset
+ // and length of each data blob is recorded in the DeltaArchiveManifest.
+ struct {
+ char data[];
+ } blobs[];
+
+ // These two are not signed:
+ uint64 payload_signatures_message_size;
+ char payload_signatures_message[];
+ };
+
+ 'payload-metadata.bin' contains all the bytes from the beginning of the
+ payload, till the end of 'medatada_signature_message'.
+ """
+ payload_info = input_zip.getinfo('payload.bin')
+ payload_offset = payload_info.header_offset + len(payload_info.FileHeader())
+ payload_size = payload_info.file_size
+
+ with input_zip.open('payload.bin', 'r') as payload_fp:
+ header_bin = payload_fp.read(24)
+
+ # network byte order (big-endian)
+ header = struct.unpack("!IQQL", header_bin)
+
+ # 'CrAU'
+ magic = header[0]
+ assert magic == 0x43724155, "Invalid magic: {:x}".format(magic)
+
+ manifest_size = header[2]
+ metadata_signature_size = header[3]
+ metadata_total = 24 + manifest_size + metadata_signature_size
+ assert metadata_total < payload_size
+
+ return (payload_offset, metadata_total)
+
+
+class NonAbOtaPropertyFiles(PropertyFiles):
+ """The property-files for non-A/B OTA.
+
+ For non-A/B OTA, the property-files string contains the info for METADATA
+ entry, with which a system updater can be fetched the package metadata prior
+ to downloading the entire package.
+ """
+
+ def __init__(self):
+ super(NonAbOtaPropertyFiles, self).__init__()
+ self.name = 'ota-property-files'
+
+
+def FinalizeMetadata(metadata, input_file, output_file, needed_property_files):
+ """Finalizes the metadata and signs an A/B OTA package.
+
+ In order to stream an A/B OTA package, we need 'ota-streaming-property-files'
+ that contains the offsets and sizes for the ZIP entries. An example
+ property-files string is as follows.
+
+ "payload.bin:679:343,payload_properties.txt:378:45,metadata:69:379"
+
+ OTA server can pass down this string, in addition to the package URL, to the
+ system update client. System update client can then fetch individual ZIP
+ entries (ZIP_STORED) directly at the given offset of the URL.
+
+ Args:
+ metadata: The metadata dict for the package.
+ input_file: The input ZIP filename that doesn't contain the package METADATA
+ entry yet.
+ output_file: The final output ZIP filename.
+ needed_property_files: The list of PropertyFiles' to be generated.
+ """
+
+ def ComputeAllPropertyFiles(input_file, needed_property_files):
+ # Write the current metadata entry with placeholders.
+ with zipfile.ZipFile(input_file) as input_zip:
+ for property_files in needed_property_files:
+ metadata[property_files.name] = property_files.Compute(input_zip)
+ namelist = input_zip.namelist()
+
+ if METADATA_NAME in namelist:
+ common.ZipDelete(input_file, METADATA_NAME)
+ output_zip = zipfile.ZipFile(input_file, 'a')
+ WriteMetadata(metadata, output_zip)
+ common.ZipClose(output_zip)
+
+ if OPTIONS.no_signing:
+ return input_file
+
+ prelim_signing = common.MakeTempFile(suffix='.zip')
+ SignOutput(input_file, prelim_signing)
+ return prelim_signing
+
+ def FinalizeAllPropertyFiles(prelim_signing, needed_property_files):
+ with zipfile.ZipFile(prelim_signing) as prelim_signing_zip:
+ for property_files in needed_property_files:
+ metadata[property_files.name] = property_files.Finalize(
+ prelim_signing_zip, len(metadata[property_files.name]))
+
+ # SignOutput(), which in turn calls signapk.jar, will possibly reorder the ZIP
+ # entries, as well as padding the entry headers. We do a preliminary signing
+ # (with an incomplete metadata entry) to allow that to happen. Then compute
+ # the ZIP entry offsets, write back the final metadata and do the final
+ # signing.
+ prelim_signing = ComputeAllPropertyFiles(input_file, needed_property_files)
+ try:
+ FinalizeAllPropertyFiles(prelim_signing, needed_property_files)
+ except PropertyFiles.InsufficientSpaceException:
+ # Even with the preliminary signing, the entry orders may change
+ # dramatically, which leads to insufficiently reserved space during the
+ # first call to ComputeAllPropertyFiles(). In that case, we redo all the
+ # preliminary signing works, based on the already ordered ZIP entries, to
+ # address the issue.
+ prelim_signing = ComputeAllPropertyFiles(
+ prelim_signing, needed_property_files)
+ FinalizeAllPropertyFiles(prelim_signing, needed_property_files)
+
+ # Replace the METADATA entry.
+ common.ZipDelete(prelim_signing, METADATA_NAME)
+ output_zip = zipfile.ZipFile(prelim_signing, 'a')
+ WriteMetadata(metadata, output_zip)
+ common.ZipClose(output_zip)
+
+ # Re-sign the package after updating the metadata entry.
+ if OPTIONS.no_signing:
+ output_file = prelim_signing
+ else:
+ SignOutput(prelim_signing, output_file)
+
+ # Reopen the final signed zip to double check the streaming metadata.
+ with zipfile.ZipFile(output_file) as output_zip:
+ for property_files in needed_property_files:
+ property_files.Verify(output_zip, metadata[property_files.name].strip())
+
+
+def WriteBlockIncrementalOTAPackage(target_zip, source_zip, output_file):
+ target_info = BuildInfo(OPTIONS.target_info_dict, OPTIONS.oem_dicts)
+ source_info = 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:
+ print("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_version,
+ source_version=source_api_version,
target_zip=target_zip,
- target_version=target_version,
+ target_version=target_api_version,
output_zip=output_zip,
script=script,
metadata=metadata,
- info_dict=OPTIONS.source_info_dict)
-
- source_fp = CalculateFingerprint(source_oem_props, oem_dicts and oem_dicts[0],
- OPTIONS.source_info_dict)
- target_fp = CalculateFingerprint(target_oem_props, oem_dicts and oem_dicts[0],
- OPTIONS.target_info_dict)
- metadata["pre-build"] = source_fp
- metadata["post-build"] = target_fp
- metadata["pre-build-incremental"] = GetBuildProp(
- "ro.build.version.incremental", OPTIONS.source_info_dict)
- metadata["post-build-incremental"] = GetBuildProp(
- "ro.build.version.incremental", OPTIONS.target_info_dict)
+ info_dict=source_info)
source_boot = common.GetBootableImage(
- "/tmp/boot.img", "boot.img", OPTIONS.source_tmp, "BOOT",
- OPTIONS.source_info_dict)
+ "/tmp/boot.img", "boot.img", OPTIONS.source_tmp, "BOOT", source_info)
target_boot = common.GetBootableImage(
- "/tmp/boot.img", "boot.img", OPTIONS.target_tmp, "BOOT")
+ "/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")
- system_src = GetImage("system", OPTIONS.source_tmp)
- system_tgt = GetImage("system", OPTIONS.target_tmp)
+ # When target uses 'BOARD_EXT4_SHARE_DUP_BLOCKS := true', images may contain
+ # shared blocks (i.e. some blocks will show up in multiple files' block
+ # list). We can only allocate such shared blocks to the first "owner", and
+ # disable imgdiff for all later occurrences.
+ allow_shared_blocks = (source_info.get('ext4_share_dup_blocks') == "true" or
+ target_info.get('ext4_share_dup_blocks') == "true")
+ system_src = common.GetSparseImage("system", OPTIONS.source_tmp, source_zip,
+ allow_shared_blocks)
+ system_tgt = common.GetSparseImage("system", OPTIONS.target_tmp, target_zip,
+ allow_shared_blocks)
- blockimgdiff_version = 1
- if OPTIONS.info_dict:
- blockimgdiff_version = max(
- int(i) for i in
- OPTIONS.info_dict.get("blockimgdiff_versions", "1").split(","))
+ blockimgdiff_version = max(
+ int(i) for i in target_info.get("blockimgdiff_versions", "1").split(","))
+ assert blockimgdiff_version >= 3
# Check the first block of the source system partition for remount R/W only
# if the filesystem is ext4.
- system_src_partition = OPTIONS.source_info_dict["fstab"]["/system"]
+ system_src_partition = source_info["fstab"]["/system"]
check_first_block = system_src_partition.fs_type == "ext4"
# Disable using imgdiff for squashfs. 'imgdiff -z' expects input files to be
# in zip formats. However with squashfs, a) all files are compressed in LZ4;
# b) the blocks listed in block map may not contain all the bytes for a given
# file (because they're rounded to be 4K-aligned).
- system_tgt_partition = OPTIONS.target_info_dict["fstab"]["/system"]
+ system_tgt_partition = target_info["fstab"]["/system"]
disable_imgdiff = (system_src_partition.fs_type == "squashfs" or
system_tgt_partition.fs_type == "squashfs")
system_diff = common.BlockDifference("system", system_tgt, system_src,
@@ -673,12 +1400,14 @@
if HasVendorPartition(target_zip):
if not HasVendorPartition(source_zip):
raise RuntimeError("can't generate incremental that adds /vendor")
- vendor_src = GetImage("vendor", OPTIONS.source_tmp)
- vendor_tgt = GetImage("vendor", OPTIONS.target_tmp)
+ vendor_src = common.GetSparseImage("vendor", OPTIONS.source_tmp, source_zip,
+ allow_shared_blocks)
+ vendor_tgt = common.GetSparseImage("vendor", OPTIONS.target_tmp, target_zip,
+ allow_shared_blocks)
# Check first block of vendor partition for remount R/W only if
# disk type is ext4
- vendor_partition = OPTIONS.source_info_dict["fstab"]["/vendor"]
+ vendor_partition = source_info["fstab"]["/vendor"]
check_first_block = vendor_partition.fs_type == "ext4"
disable_imgdiff = vendor_partition.fs_type == "squashfs"
vendor_diff = common.BlockDifference("vendor", vendor_tgt, vendor_src,
@@ -688,7 +1417,11 @@
else:
vendor_diff = None
- AppendAssertions(script, OPTIONS.target_info_dict, oem_dicts)
+ AddCompatibilityArchiveIfTrebleEnabled(
+ target_zip, output_zip, target_info, source_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,
@@ -714,12 +1447,12 @@
# (allow recovery to mark itself finished and reboot)
if OPTIONS.two_step:
- if not OPTIONS.source_info_dict.get("multistage_support", None):
+ if not source_info.get("multistage_support"):
assert False, "two-step packages not supported by this build"
- fs = OPTIONS.source_info_dict["fstab"]["/misc"]
+ 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}
+ 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
@@ -739,39 +1472,14 @@
script.Comment("Stage 1/3")
# Dump fingerprints
- script.Print("Source: %s" % (source_fp,))
- script.Print("Target: %s" % (target_fp,))
+ script.Print("Source: {}".format(source_info.fingerprint))
+ script.Print("Target: {}".format(target_info.fingerprint))
script.Print("Verifying current system...")
device_specific.IncrementalOTA_VerifyBegin()
- # When blockimgdiff version is less than 3 (non-resumable block-based OTA),
- # patching on a device that's already on the target build will damage the
- # system. Because operations like move don't check the block state, they
- # always apply the changes unconditionally.
- if blockimgdiff_version <= 2:
- if source_oem_props is None:
- script.AssertSomeFingerprint(source_fp)
- else:
- script.AssertSomeThumbprint(
- GetBuildProp("ro.build.thumbprint", OPTIONS.source_info_dict))
-
- else: # blockimgdiff_version > 2
- if source_oem_props is None and target_oem_props is None:
- script.AssertSomeFingerprint(source_fp, target_fp)
- elif source_oem_props is not None and target_oem_props is not None:
- script.AssertSomeThumbprint(
- GetBuildProp("ro.build.thumbprint", OPTIONS.target_info_dict),
- GetBuildProp("ro.build.thumbprint", OPTIONS.source_info_dict))
- elif source_oem_props is None and target_oem_props is not None:
- script.AssertFingerprintOrThumbprint(
- source_fp,
- GetBuildProp("ro.build.thumbprint", OPTIONS.target_info_dict))
- else:
- script.AssertFingerprintOrThumbprint(
- target_fp,
- GetBuildProp("ro.build.thumbprint", OPTIONS.source_info_dict))
+ WriteFingerprintAssertion(script, target_info, source_info)
# Check the required cache size (i.e. stashed blocks).
size = []
@@ -781,8 +1489,7 @@
size.append(vendor_diff.required_cache)
if updating_boot:
- boot_type, boot_device = common.GetTypeAndDevice(
- "/boot", OPTIONS.source_info_dict)
+ boot_type, boot_device = common.GetTypeAndDevice("/boot", source_info)
d = common.Difference(target_boot, source_boot)
_, _, d = d.ComputePatch()
if d is None:
@@ -872,7 +1579,6 @@
if OPTIONS.wipe_user_data:
script.Print("Erasing user data...")
script.FormatPartition("/data")
- metadata["ota-wipe"] = "yes"
if OPTIONS.two_step:
script.AppendExtra("""
@@ -889,386 +1595,187 @@
else:
script.AddToZip(target_zip, output_zip, input_path=OPTIONS.updater_binary)
metadata["ota-required-cache"] = str(script.required_cache)
- WriteMetadata(metadata, output_zip)
+
+ # 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 WriteVerifyPackage(input_zip, output_zip):
- script = edify_generator.EdifyGenerator(3, OPTIONS.info_dict)
+def GetTargetFilesZipForSecondaryImages(input_file, skip_postinstall=False):
+ """Returns a target-files.zip file for generating secondary payload.
- oem_props = OPTIONS.info_dict.get("oem_fingerprint_properties")
- recovery_mount_options = OPTIONS.info_dict.get(
- "recovery_mount_options")
- oem_dicts = None
- if oem_props:
- oem_dicts = _LoadOemDicts(script, recovery_mount_options)
+ Although the original target-files.zip already contains secondary slot
+ images (i.e. IMAGES/system_other.img), we need to rename the files to the
+ ones without _other suffix. Note that we cannot instead modify the names in
+ META/ab_partitions.txt, because there are no matching partitions on device.
- target_fp = CalculateFingerprint(oem_props, oem_dicts and oem_dicts[0],
- OPTIONS.info_dict)
- metadata = {
- "post-build": target_fp,
- "pre-device": GetOemProperty("ro.product.device", oem_props,
- oem_dicts and oem_dicts[0],
- OPTIONS.info_dict),
- "post-timestamp": GetBuildProp("ro.build.date.utc", OPTIONS.info_dict),
- }
+ For the partitions that don't have secondary images, the ones for primary
+ slot will be used. This is to ensure that we always have valid boot, vbmeta,
+ bootloader images in the inactive slot.
- device_specific = common.DeviceSpecificParams(
- input_zip=input_zip,
- input_version=OPTIONS.info_dict["recovery_api_version"],
- output_zip=output_zip,
- script=script,
- input_tmp=OPTIONS.input_tmp,
- metadata=metadata,
- info_dict=OPTIONS.info_dict)
+ Args:
+ input_file: The input target-files.zip file.
+ skip_postinstall: Whether to skip copying the postinstall config file.
- AppendAssertions(script, OPTIONS.info_dict, oem_dicts)
+ Returns:
+ The filename of the target-files.zip for generating secondary payload.
+ """
+ target_file = common.MakeTempFile(prefix="targetfiles-", suffix=".zip")
+ target_zip = zipfile.ZipFile(target_file, 'w', allowZip64=True)
- script.Print("Verifying device images against %s..." % target_fp)
- script.AppendExtra("")
+ input_tmp = common.UnzipTemp(input_file, UNZIP_PATTERN)
+ with zipfile.ZipFile(input_file, 'r') as input_zip:
+ infolist = input_zip.infolist()
- script.Print("Verifying boot...")
- boot_img = common.GetBootableImage(
- "boot.img", "boot.img", OPTIONS.input_tmp, "BOOT")
- boot_type, boot_device = common.GetTypeAndDevice(
- "/boot", OPTIONS.info_dict)
- script.Verify("%s:%s:%d:%s" % (
- boot_type, boot_device, boot_img.size, boot_img.sha1))
- script.AppendExtra("")
+ for info in infolist:
+ unzipped_file = os.path.join(input_tmp, *info.filename.split('/'))
+ if info.filename == 'IMAGES/system_other.img':
+ common.ZipWrite(target_zip, unzipped_file, arcname='IMAGES/system.img')
- script.Print("Verifying recovery...")
- recovery_img = common.GetBootableImage(
- "recovery.img", "recovery.img", OPTIONS.input_tmp, "RECOVERY")
- recovery_type, recovery_device = common.GetTypeAndDevice(
- "/recovery", OPTIONS.info_dict)
- script.Verify("%s:%s:%d:%s" % (
- recovery_type, recovery_device, recovery_img.size, recovery_img.sha1))
- script.AppendExtra("")
+ # Primary images and friends need to be skipped explicitly.
+ elif info.filename in ('IMAGES/system.img',
+ 'IMAGES/system.map'):
+ pass
- system_tgt = GetImage("system", OPTIONS.input_tmp)
- system_tgt.ResetFileMap()
- system_diff = common.BlockDifference("system", system_tgt, src=None)
- system_diff.WriteStrictVerifyScript(script)
+ # Skip copying the postinstall config if requested.
+ elif skip_postinstall and info.filename == POSTINSTALL_CONFIG:
+ pass
- if HasVendorPartition(input_zip):
- vendor_tgt = GetImage("vendor", OPTIONS.input_tmp)
- vendor_tgt.ResetFileMap()
- vendor_diff = common.BlockDifference("vendor", vendor_tgt, src=None)
- vendor_diff.WriteStrictVerifyScript(script)
+ elif info.filename.startswith(('META/', 'IMAGES/')):
+ common.ZipWrite(target_zip, unzipped_file, arcname=info.filename)
- # Device specific partitions, such as radio, bootloader and etc.
- device_specific.VerifyOTA_Assertions()
+ common.ZipClose(target_zip)
- script.SetProgress(1.0)
- script.AddToZip(input_zip, output_zip, input_path=OPTIONS.updater_binary)
- metadata["ota-required-cache"] = str(script.required_cache)
- WriteMetadata(metadata, output_zip)
+ return target_file
+
+
+def GetTargetFilesZipWithoutPostinstallConfig(input_file):
+ """Returns a target-files.zip that's not containing postinstall_config.txt.
+
+ This allows brillo_update_payload script to skip writing all the postinstall
+ hooks in the generated payload. The input target-files.zip file will be
+ duplicated, with 'META/postinstall_config.txt' skipped. If input_file doesn't
+ contain the postinstall_config.txt entry, the input file will be returned.
+
+ Args:
+ input_file: The input target-files.zip filename.
+
+ Returns:
+ 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:
+ if POSTINSTALL_CONFIG not in input_zip.namelist():
+ return input_file
+
+ target_file = common.MakeTempFile(prefix="targetfiles-", suffix=".zip")
+ shutil.copyfile(input_file, target_file)
+ common.ZipDelete(target_file, POSTINSTALL_CONFIG)
+ return target_file
def WriteABOTAPackageWithBrilloScript(target_file, output_file,
source_file=None):
- """Generate an Android OTA package that has A/B update payload."""
-
- def ComputeStreamingMetadata(zip_file, reserve_space=False,
- expected_length=None):
- """Compute the streaming metadata for a given zip.
-
- When 'reserve_space' is True, we reserve extra space for the offset and
- length of the metadata entry itself, although we don't know the final
- values until the package gets signed. This function will be called again
- after signing. We then write the actual values and pad the string to the
- length we set earlier. Note that we can't use the actual length of the
- metadata entry in the second run. Otherwise the offsets for other entries
- will be changing again.
- """
-
- def ComputeEntryOffsetSize(name):
- """Compute the zip entry offset and size."""
- info = zip_file.getinfo(name)
- offset = info.header_offset + len(info.FileHeader())
- size = info.file_size
- return '%s:%d:%d' % (os.path.basename(name), offset, size)
-
- # payload.bin and payload_properties.txt must exist.
- offsets = [ComputeEntryOffsetSize('payload.bin'),
- ComputeEntryOffsetSize('payload_properties.txt')]
-
- # care_map.txt is available only if dm-verity is enabled.
- if 'care_map.txt' in zip_file.namelist():
- offsets.append(ComputeEntryOffsetSize('care_map.txt'))
-
- if 'compatibility.zip' in zip_file.namelist():
- offsets.append(ComputeEntryOffsetSize('compatibility.zip'))
-
- # '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 10-byte as a placeholder, which is to cover the space for metadata
- # entry ('xx:xxx', since it's ZIP_STORED which should appear at the
- # beginning of the zip), as well as the possible value changes in other
- # entries.
- if reserve_space:
- offsets.append('metadata:' + ' ' * 10)
- else:
- offsets.append(ComputeEntryOffsetSize(METADATA_NAME))
-
- value = ','.join(offsets)
- if expected_length is not None:
- assert len(value) <= expected_length, \
- 'Insufficient reserved space: reserved=%d, actual=%d' % (
- expected_length, len(value))
- value += ' ' * (expected_length - len(value))
- return value
-
- # The place where the output from the subprocess should go.
- log_file = sys.stdout if OPTIONS.verbose else subprocess.PIPE
-
- # A/B updater expects a signing key in RSA format. Gets the key ready for
- # later use in step 3, unless a payload_signer has been specified.
- if OPTIONS.payload_signer is None:
- cmd = ["openssl", "pkcs8",
- "-in", OPTIONS.package_key + OPTIONS.private_key_suffix,
- "-inform", "DER"]
- pw = OPTIONS.key_passwords[OPTIONS.package_key]
- cmd.extend(["-passin", "pass:" + pw] if pw else ["-nocrypt"])
- rsa_key = common.MakeTempFile(prefix="key-", suffix=".key")
- cmd.extend(["-out", rsa_key])
- p1 = common.Run(cmd, verbose=False, stdout=log_file, stderr=subprocess.STDOUT)
- p1.communicate()
- assert p1.returncode == 0, "openssl pkcs8 failed"
-
+ """Generates an Android OTA package that has A/B update payload."""
# Stage the output zip package for package signing.
- temp_zip_file = tempfile.NamedTemporaryFile()
- output_zip = zipfile.ZipFile(temp_zip_file, "w",
+ 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)
- # Metadata to comply with Android OTA package format.
- oem_props = OPTIONS.info_dict.get("oem_fingerprint_properties", None)
- oem_dicts = None
- if oem_props:
- oem_dicts = _LoadOemDicts(None)
-
- metadata = {
- "post-build": CalculateFingerprint(oem_props, oem_dicts and oem_dicts[0],
- OPTIONS.info_dict),
- "post-build-incremental" : GetBuildProp("ro.build.version.incremental",
- OPTIONS.info_dict),
- "pre-device": GetOemProperty("ro.product.device", oem_props,
- oem_dicts and oem_dicts[0],
- OPTIONS.info_dict),
- "ota-required-cache": "0",
- "ota-type": "AB",
- }
-
if source_file is not None:
- metadata["pre-build"] = CalculateFingerprint(oem_props,
- oem_dicts and oem_dicts[0],
- OPTIONS.source_info_dict)
- metadata["pre-build-incremental"] = GetBuildProp(
- "ro.build.version.incremental", OPTIONS.source_info_dict)
-
- HandleDowngradeMetadata(metadata)
+ target_info = BuildInfo(OPTIONS.target_info_dict, OPTIONS.oem_dicts)
+ source_info = BuildInfo(OPTIONS.source_info_dict, OPTIONS.oem_dicts)
else:
- metadata["post-timestamp"] = GetBuildProp(
- "ro.build.date.utc", OPTIONS.info_dict)
+ target_info = BuildInfo(OPTIONS.info_dict, OPTIONS.oem_dicts)
+ source_info = None
- # 1. Generate payload.
- payload_file = common.MakeTempFile(prefix="payload-", suffix=".bin")
- cmd = ["brillo_update_payload", "generate",
- "--payload", payload_file,
- "--target_image", target_file]
- if source_file is not None:
- cmd.extend(["--source_image", source_file])
+ # Metadata to comply with Android OTA package format.
+ metadata = GetPackageMetadata(target_info, source_info)
+
+ if OPTIONS.skip_postinstall:
+ target_file = GetTargetFilesZipWithoutPostinstallConfig(target_file)
+
+ # Generate payload.
+ payload = Payload()
+
+ # Enforce a max timestamp this payload can be applied on top of.
if OPTIONS.downgrade:
- max_timestamp = GetBuildProp("ro.build.date.utc", OPTIONS.source_info_dict)
+ max_timestamp = source_info.GetBuildProp("ro.build.date.utc")
else:
max_timestamp = metadata["post-timestamp"]
- cmd.extend(["--max_timestamp", max_timestamp])
- p1 = common.Run(cmd, stdout=log_file, stderr=subprocess.STDOUT)
- p1.communicate()
- assert p1.returncode == 0, "brillo_update_payload generate failed"
+ additional_args = ["--max_timestamp", max_timestamp]
- # 2. Generate hashes of the payload and metadata files.
- payload_sig_file = common.MakeTempFile(prefix="sig-", suffix=".bin")
- metadata_sig_file = common.MakeTempFile(prefix="sig-", suffix=".bin")
- cmd = ["brillo_update_payload", "hash",
- "--unsigned_payload", payload_file,
- "--signature_size", "256",
- "--metadata_hash_file", metadata_sig_file,
- "--payload_hash_file", payload_sig_file]
- p1 = common.Run(cmd, stdout=log_file, stderr=subprocess.STDOUT)
- p1.communicate()
- assert p1.returncode == 0, "brillo_update_payload hash failed"
+ payload.Generate(target_file, source_file, additional_args)
- # 3. Sign the hashes and insert them back into the payload file.
- signed_payload_sig_file = common.MakeTempFile(prefix="signed-sig-",
- suffix=".bin")
- signed_metadata_sig_file = common.MakeTempFile(prefix="signed-sig-",
- suffix=".bin")
- # 3a. Sign the payload hash.
- if OPTIONS.payload_signer is not None:
- cmd = [OPTIONS.payload_signer]
- cmd.extend(OPTIONS.payload_signer_args)
- else:
- cmd = ["openssl", "pkeyutl", "-sign",
- "-inkey", rsa_key,
- "-pkeyopt", "digest:sha256"]
- cmd.extend(["-in", payload_sig_file,
- "-out", signed_payload_sig_file])
- p1 = common.Run(cmd, stdout=log_file, stderr=subprocess.STDOUT)
- p1.communicate()
- assert p1.returncode == 0, "openssl sign payload failed"
+ # Sign the payload.
+ payload_signer = PayloadSigner()
+ payload.Sign(payload_signer)
- # 3b. Sign the metadata hash.
- if OPTIONS.payload_signer is not None:
- cmd = [OPTIONS.payload_signer]
- cmd.extend(OPTIONS.payload_signer_args)
- else:
- cmd = ["openssl", "pkeyutl", "-sign",
- "-inkey", rsa_key,
- "-pkeyopt", "digest:sha256"]
- cmd.extend(["-in", metadata_sig_file,
- "-out", signed_metadata_sig_file])
- p1 = common.Run(cmd, stdout=log_file, stderr=subprocess.STDOUT)
- p1.communicate()
- assert p1.returncode == 0, "openssl sign metadata failed"
+ # Write the payload into output zip.
+ payload.WriteToZip(output_zip)
- # 3c. Insert the signatures back into the payload file.
- signed_payload_file = common.MakeTempFile(prefix="signed-payload-",
- suffix=".bin")
- cmd = ["brillo_update_payload", "sign",
- "--unsigned_payload", payload_file,
- "--payload", signed_payload_file,
- "--signature_size", "256",
- "--metadata_signature_file", signed_metadata_sig_file,
- "--payload_signature_file", signed_payload_sig_file]
- p1 = common.Run(cmd, stdout=log_file, stderr=subprocess.STDOUT)
- p1.communicate()
- assert p1.returncode == 0, "brillo_update_payload sign failed"
-
- # 4. Dump the signed payload properties.
- properties_file = common.MakeTempFile(prefix="payload-properties-",
- suffix=".txt")
- cmd = ["brillo_update_payload", "properties",
- "--payload", signed_payload_file,
- "--properties_file", properties_file]
- p1 = common.Run(cmd, stdout=log_file, stderr=subprocess.STDOUT)
- p1.communicate()
- assert p1.returncode == 0, "brillo_update_payload properties failed"
-
- if OPTIONS.wipe_user_data:
- with open(properties_file, "a") as f:
- f.write("POWERWASH=1\n")
- metadata["ota-wipe"] = "yes"
-
- # Add the signed payload file and properties into the zip. In order to
- # support streaming, we pack payload.bin, payload_properties.txt and
- # care_map.txt as ZIP_STORED. So these entries can be read directly with
- # the offset and length pairs.
- common.ZipWrite(output_zip, signed_payload_file, arcname="payload.bin",
- compress_type=zipfile.ZIP_STORED)
- common.ZipWrite(output_zip, properties_file,
- arcname="payload_properties.txt",
- compress_type=zipfile.ZIP_STORED)
+ # Generate and include the secondary payload that installs secondary images
+ # (e.g. system_other.img).
+ if OPTIONS.include_secondary:
+ # We always include a full payload for the secondary slot, even when
+ # building an incremental OTA. See the comments for "--include_secondary".
+ secondary_target_file = GetTargetFilesZipForSecondaryImages(
+ target_file, OPTIONS.skip_postinstall)
+ secondary_payload = Payload(secondary=True)
+ secondary_payload.Generate(secondary_target_file,
+ additional_args=additional_args)
+ 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")
- if (OPTIONS.info_dict.get("verity") == "true" or
- OPTIONS.info_dict.get("avb_enable") == "true"):
+ if (target_info.get("verity") == "true" or
+ target_info.get("avb_enable") == "true"):
care_map_path = "META/care_map.txt"
namelist = target_zip.namelist()
if care_map_path in namelist:
care_map_data = target_zip.read(care_map_path)
+ # In order to support streaming, care_map.txt needs to be packed as
+ # ZIP_STORED.
common.ZipWriteStr(output_zip, "care_map.txt", care_map_data,
- compress_type=zipfile.ZIP_STORED)
+ compress_type=zipfile.ZIP_STORED)
else:
print("Warning: cannot find care map file in target_file package")
- if HasVendorPartition(target_zip):
- update_vendor = True
- update_system = True
+ AddCompatibilityArchiveIfTrebleEnabled(
+ target_zip, output_zip, target_info, source_info)
- # If incremental then figure out what is being updated so metadata only for
- # the updated image is included.
- if source_file is not None:
- input_tmp, input_zip = common.UnzipTemp(
- target_file, UNZIP_PATTERN)
- source_tmp, source_zip = common.UnzipTemp(
- source_file, UNZIP_PATTERN)
-
- vendor_src = GetImage("vendor", source_tmp)
- vendor_tgt = GetImage("vendor", input_tmp)
- system_src = GetImage("system", source_tmp)
- system_tgt = GetImage("system", input_tmp)
-
- update_system = system_src.TotalSha1() != system_tgt.TotalSha1()
- update_vendor = vendor_src.TotalSha1() != vendor_tgt.TotalSha1()
-
- input_zip.close()
- source_zip.close()
-
- target_zip = zipfile.ZipFile(target_file, "r")
- AddCompatibilityArchive(target_zip, output_zip, update_system,
- update_vendor)
common.ZipClose(target_zip)
- # Write the current metadata entry with placeholders.
- metadata['ota-streaming-property-files'] = ComputeStreamingMetadata(
- output_zip, reserve_space=True)
- WriteMetadata(metadata, output_zip)
+ # We haven't written the metadata entry yet, which will be handled in
+ # FinalizeMetadata().
common.ZipClose(output_zip)
- # 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 = tempfile.NamedTemporaryFile()
- SignOutput(temp_zip_file.name, prelim_signing.name)
- common.ZipClose(temp_zip_file)
-
- # Open the signed zip. Compute the final metadata that's needed for streaming.
- prelim_zip = zipfile.ZipFile(prelim_signing, "r",
- compression=zipfile.ZIP_DEFLATED)
- expected_length = len(metadata['ota-streaming-property-files'])
- metadata['ota-streaming-property-files'] = ComputeStreamingMetadata(
- prelim_zip, reserve_space=False, expected_length=expected_length)
-
- # Copy the zip entries, as we cannot update / delete entries with zipfile.
- final_signing = tempfile.NamedTemporaryFile()
- output_zip = zipfile.ZipFile(final_signing, "w",
- compression=zipfile.ZIP_DEFLATED)
- for item in prelim_zip.infolist():
- if item.filename == METADATA_NAME:
- continue
-
- data = prelim_zip.read(item.filename)
- out_info = copy.copy(item)
- common.ZipWriteStr(output_zip, out_info, data)
-
- # Now write the final metadata entry.
- WriteMetadata(metadata, output_zip)
- common.ZipClose(prelim_zip)
- common.ZipClose(output_zip)
-
- # Re-sign the package after updating the metadata entry.
- SignOutput(final_signing.name, output_file)
- final_signing.close()
-
- # Reopen the final signed zip to double check the streaming metadata.
- output_zip = zipfile.ZipFile(output_file, "r")
- actual = metadata['ota-streaming-property-files'].strip()
- expected = ComputeStreamingMetadata(output_zip)
- assert actual == expected, \
- "Mismatching streaming metadata: %s vs %s." % (actual, expected)
- common.ZipClose(output_zip)
+ # AbOtaPropertyFiles intends to replace StreamingPropertyFiles, as it covers
+ # all the info of the latter. However, system updaters and OTA servers need to
+ # take time to switch to the new flag. We keep both of the flags for
+ # P-timeframe, and will remove StreamingPropertyFiles in later release.
+ needed_property_files = (
+ AbOtaPropertyFiles(),
+ StreamingPropertyFiles(),
+ )
+ FinalizeMetadata(metadata, staging_file, output_file, needed_property_files)
def main(argv):
def option_handler(o, a):
- if o == "--board_config":
- pass # deprecated
- elif o in ("-k", "--package_key"):
+ if o in ("-k", "--package_key"):
OPTIONS.package_key = a
elif o in ("-i", "--incremental_from"):
OPTIONS.incremental_source = a
@@ -1276,13 +1783,13 @@
OPTIONS.full_radio = True
elif o == "--full_bootloader":
OPTIONS.full_bootloader = True
- elif o in ("-w", "--wipe_user_data"):
+ elif o == "--wipe_user_data":
OPTIONS.wipe_user_data = True
elif o == "--downgrade":
OPTIONS.downgrade = True
OPTIONS.wipe_user_data = True
elif o == "--override_timestamp":
- OPTIONS.timestamp = True
+ OPTIONS.downgrade = True
elif o in ("-o", "--oem_settings"):
OPTIONS.oem_source = a.split(',')
elif o == "--oem_no_mount":
@@ -1297,6 +1804,8 @@
"integers are allowed." % (a, o))
elif o in ("-2", "--two_step"):
OPTIONS.two_step = True
+ elif o == "--include_secondary":
+ OPTIONS.include_secondary = True
elif o == "--no_signing":
OPTIONS.no_signing = True
elif o == "--verify":
@@ -1305,16 +1814,12 @@
OPTIONS.block_based = True
elif o in ("-b", "--binary"):
OPTIONS.updater_binary = a
- elif o in ("--no_fallback_to_full",):
- OPTIONS.fallback_to_full = False
elif o == "--stash_threshold":
try:
OPTIONS.stash_threshold = float(a)
except ValueError:
raise ValueError("Cannot parse value %r for option %r - expecting "
"a float" % (a, o))
- elif o == "--gen_verify":
- OPTIONS.gen_verify = True
elif o == "--log_diff":
OPTIONS.log_diff = a
elif o == "--payload_signer":
@@ -1323,14 +1828,15 @@
OPTIONS.payload_signer_args = shlex.split(a)
elif o == "--extracted_input_target_files":
OPTIONS.extracted_input = a
+ elif o == "--skip_postinstall":
+ OPTIONS.skip_postinstall = True
else:
return False
return True
args = common.ParseOptions(argv, __doc__,
- extra_opts="b:k:i:d:we:t:2o:",
+ extra_opts="b:k:i:d:e:t:2o:",
extra_long_opts=[
- "board_config=",
"package_key=",
"incremental_from=",
"full_radio",
@@ -1341,19 +1847,19 @@
"extra_script=",
"worker_threads=",
"two_step",
+ "include_secondary",
"no_signing",
"block",
"binary=",
"oem_settings=",
"oem_no_mount",
"verify",
- "no_fallback_to_full",
"stash_threshold=",
- "gen_verify",
"log_diff=",
"payload_signer=",
"payload_signer_args=",
"extracted_input_target_files=",
+ "skip_postinstall",
], extra_option_handler=option_handler)
if len(args) != 2:
@@ -1361,27 +1867,41 @@
sys.exit(1)
if OPTIONS.downgrade:
- # Sanity check to enforce a data wipe.
- if not OPTIONS.wipe_user_data:
- raise ValueError("Cannot downgrade without a data wipe")
-
# 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")
- assert not (OPTIONS.downgrade and OPTIONS.timestamp), \
- "Cannot have --downgrade AND --override_timestamp both"
-
- # Load the dict file from the zip directly to have a peek at the OTA type.
- # For packages using A/B update, unzipping is not needed.
+ # 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).
+ # When loading the info dicts, we don't need to provide the second parameter
+ # to common.LoadInfoDict(). Specifying the second parameter allows replacing
+ # some properties with their actual paths, such as 'selinux_fc',
+ # 'ramdisk_dir', which won't be used during OTA generation.
if OPTIONS.extracted_input is not None:
- OPTIONS.info_dict = common.LoadInfoDict(OPTIONS.extracted_input, OPTIONS.extracted_input)
+ OPTIONS.info_dict = common.LoadInfoDict(OPTIONS.extracted_input)
else:
- input_zip = zipfile.ZipFile(args[0], "r")
- OPTIONS.info_dict = common.LoadInfoDict(input_zip)
- common.ZipClose(input_zip)
+ with zipfile.ZipFile(args[0], 'r') as input_zip:
+ OPTIONS.info_dict = common.LoadInfoDict(input_zip)
+
+ if OPTIONS.verbose:
+ print("--- 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)
+
+ if OPTIONS.verbose:
+ print("--- source info ---")
+ common.DumpInfoDict(OPTIONS.source_info_dict)
+
+ # Load OEM dicts if provided.
+ OPTIONS.oem_dicts = _LoadOemDicts(OPTIONS.oem_source)
ab_update = OPTIONS.info_dict.get("ab_update") == "true"
@@ -1397,20 +1917,6 @@
OPTIONS.key_passwords = common.GetKeyPasswords([OPTIONS.package_key])
if ab_update:
- if OPTIONS.incremental_source is not None:
- OPTIONS.target_info_dict = OPTIONS.info_dict
- source_zip = zipfile.ZipFile(OPTIONS.incremental_source, "r")
- OPTIONS.source_info_dict = common.LoadInfoDict(source_zip)
- common.ZipClose(source_zip)
-
- if OPTIONS.verbose:
- print("--- target info ---")
- common.DumpInfoDict(OPTIONS.info_dict)
-
- if OPTIONS.incremental_source is not None:
- print("--- source info ---")
- common.DumpInfoDict(OPTIONS.source_info_dict)
-
WriteABOTAPackageWithBrilloScript(
target_file=args[0],
output_file=args[1],
@@ -1419,109 +1925,67 @@
print("done.")
return
+ # 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:
+ print("--- can't determine the cache partition size ---")
+ OPTIONS.cache_size = cache_size
+
if OPTIONS.extra_script is not None:
OPTIONS.extra_script = open(OPTIONS.extra_script).read()
if OPTIONS.extracted_input is not None:
OPTIONS.input_tmp = OPTIONS.extracted_input
- OPTIONS.target_tmp = OPTIONS.input_tmp
- OPTIONS.info_dict = common.LoadInfoDict(OPTIONS.input_tmp, OPTIONS.input_tmp)
- input_zip = zipfile.ZipFile(args[0], "r")
else:
print("unzipping target target-files...")
- OPTIONS.input_tmp, input_zip = common.UnzipTemp(
- args[0], UNZIP_PATTERN)
+ OPTIONS.input_tmp = common.UnzipTemp(args[0], UNZIP_PATTERN)
+ OPTIONS.target_tmp = OPTIONS.input_tmp
- OPTIONS.target_tmp = OPTIONS.input_tmp
- OPTIONS.info_dict = common.LoadInfoDict(input_zip, OPTIONS.target_tmp)
-
- if OPTIONS.verbose:
- print("--- target info ---")
- common.DumpInfoDict(OPTIONS.info_dict)
-
- # If the caller explicitly specified the device-specific extensions
- # path via -s/--device_specific, use that. Otherwise, use
- # META/releasetools.py if it is present in the target target_files.
- # Otherwise, take the path of the file from 'tool_extensions' in the
- # info dict and look for that in the local filesystem, relative to
- # the current directory.
-
+ # If 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):
print("(using device-specific extensions from target_files)")
OPTIONS.device_specific = from_input
else:
- OPTIONS.device_specific = OPTIONS.info_dict.get("tool_extensions", None)
+ 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)
- if OPTIONS.info_dict.get("no_recovery") == "true":
- raise common.ExternalError(
- "--- target build has specified no recovery ---")
-
- # Set up the output zip. Create a temporary zip file if signing is needed.
- if OPTIONS.no_signing:
- if os.path.exists(args[1]):
- os.unlink(args[1])
- output_zip = zipfile.ZipFile(args[1], "w",
- compression=zipfile.ZIP_DEFLATED)
- else:
- temp_zip_file = tempfile.NamedTemporaryFile()
- output_zip = zipfile.ZipFile(temp_zip_file, "w",
- compression=zipfile.ZIP_DEFLATED)
-
- # Non A/B OTAs rely on /cache partition to store temporary files.
- cache_size = OPTIONS.info_dict.get("cache_size", None)
- if cache_size is None:
- print("--- can't determine the cache partition size ---")
- OPTIONS.cache_size = cache_size
-
- # Generate a verify package.
- if OPTIONS.gen_verify:
- WriteVerifyPackage(input_zip, output_zip)
-
# Generate a full OTA.
- elif OPTIONS.incremental_source is None:
- WriteFullOTAPackage(input_zip, output_zip)
+ if OPTIONS.incremental_source is None:
+ with zipfile.ZipFile(args[0], 'r') as input_zip:
+ WriteFullOTAPackage(
+ input_zip,
+ output_file=args[1])
- # Generate an incremental OTA. It will fall back to generate a full OTA on
- # failure unless no_fallback_to_full is specified.
+ # Generate an incremental OTA.
else:
print("unzipping source target-files...")
- OPTIONS.source_tmp, source_zip = common.UnzipTemp(
- OPTIONS.incremental_source,
- UNZIP_PATTERN)
- OPTIONS.target_info_dict = OPTIONS.info_dict
- OPTIONS.source_info_dict = common.LoadInfoDict(source_zip,
- OPTIONS.source_tmp)
- if OPTIONS.verbose:
- print("--- source info ---")
- common.DumpInfoDict(OPTIONS.source_info_dict)
- try:
- WriteBlockIncrementalOTAPackage(input_zip, source_zip, output_zip)
- if OPTIONS.log_diff:
- out_file = open(OPTIONS.log_diff, 'w')
+ OPTIONS.source_tmp = common.UnzipTemp(
+ OPTIONS.incremental_source, UNZIP_PATTERN)
+ with zipfile.ZipFile(args[0], 'r') as input_zip, \
+ zipfile.ZipFile(OPTIONS.incremental_source, 'r') as source_zip:
+ WriteBlockIncrementalOTAPackage(
+ input_zip,
+ source_zip,
+ output_file=args[1])
+
+ if OPTIONS.log_diff:
+ with open(OPTIONS.log_diff, 'w') as out_file:
import target_files_diff
- target_files_diff.recursiveDiff('',
- OPTIONS.source_tmp,
- OPTIONS.input_tmp,
- out_file)
- out_file.close()
- except ValueError:
- if not OPTIONS.fallback_to_full:
- raise
- print("--- failed to build incremental; falling back to full ---")
- OPTIONS.incremental_source = None
- WriteFullOTAPackage(input_zip, output_zip)
-
- common.ZipClose(output_zip)
-
- # Sign the generated zip package unless no_signing is specified.
- if not OPTIONS.no_signing:
- SignOutput(temp_zip_file.name, args[1])
- temp_zip_file.close()
+ target_files_diff.recursiveDiff(
+ '', OPTIONS.source_tmp, OPTIONS.input_tmp, out_file)
print("done.")
diff --git a/tools/releasetools/pylintrc b/tools/releasetools/pylintrc
index 90de1af..7b3405c 100644
--- a/tools/releasetools/pylintrc
+++ b/tools/releasetools/pylintrc
@@ -144,9 +144,6 @@
[BASIC]
-# Required attributes for module, separated by a comma
-required-attributes=
-
# List of builtins function names that should not be used, separated by a comma
bad-functions=map,filter,input
@@ -357,10 +354,6 @@
[CLASSES]
-# List of interface methods to ignore, separated by a comma. This is used for
-# instance to not check methods defines in Zope's Interface base class.
-ignore-iface-methods=isImplementedBy,deferred,extends,names,namesAndDescriptions,queryDescriptionFor,getBases,getDescriptionFor,getDoc,getName,getTaggedValue,getTaggedValueTags,isEqualOrExtendedBy,setTaggedValue,isImplementedByInstancesOf,adaptWith,is_implemented_by
-
# List of method names used to declare (i.e. assign) instance attributes.
defining-attr-methods=__init__,__new__,setUp
diff --git a/tools/releasetools/rangelib.py b/tools/releasetools/rangelib.py
index fa6eec1..36becf4 100644
--- a/tools/releasetools/rangelib.py
+++ b/tools/releasetools/rangelib.py
@@ -13,18 +13,26 @@
# limitations under the License.
from __future__ import print_function
+
import heapq
import itertools
+
__all__ = ["RangeSet"]
+
class RangeSet(object):
- """A RangeSet represents a set of nonoverlapping ranges on the
- integers (ie, a set of integers, but efficient when the set contains
- lots of runs."""
+ """A RangeSet represents a set of non-overlapping ranges on integers.
+
+ Attributes:
+ monotonic: Whether the input has all its integers in increasing order.
+ extra: A dict that can be used by the caller, e.g. to store info that's
+ only meaningful to caller.
+ """
def __init__(self, data=None):
self.monotonic = False
+ self._extra = {}
if isinstance(data, str):
self._parse_internal(data)
elif data:
@@ -56,18 +64,24 @@
def __repr__(self):
return '<RangeSet("' + self.to_string() + '")>'
+ @property
+ def extra(self):
+ return self._extra
+
@classmethod
def parse(cls, text):
- """Parse a text string consisting of a space-separated list of
- blocks and ranges, eg "10-20 30 35-40". Ranges are interpreted to
- include both their ends (so the above example represents 18
- individual blocks. Returns a RangeSet object.
+ """Parses a text string into a RangeSet.
- If the input has all its blocks in increasing order, then returned
- RangeSet will have an extra attribute 'monotonic' that is set to
- True. For example the input "10-20 30" is monotonic, but the input
- "15-20 30 10-14" is not, even though they represent the same set
- of blocks (and the two RangeSets will compare equal with ==).
+ The input text string consists of a space-separated list of blocks and
+ ranges, e.g. "10-20 30 35-40". Ranges are interpreted to include both their
+ ends (so the above example represents 18 individual blocks). Returns a
+ RangeSet object.
+
+ If the input has all its blocks in increasing order, then the 'monotonic'
+ attribute of the returned RangeSet will be set to True. For example the
+ input "10-20 30" is monotonic, but the input "15-20 30 10-14" is not, even
+ though they represent the same set of blocks (and the two RangeSets will
+ compare equal with ==).
"""
return cls(text)
@@ -320,7 +334,7 @@
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> list(RangeSet("10-19 3-5").next_item())
[3, 4, 5, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
- >>> list(rangelib.RangeSet("10-19 3 5 7").next_item())
+ >>> list(RangeSet("10-19 3 5 7").next_item())
[3, 5, 7, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
"""
for s, e in self:
diff --git a/tools/releasetools/sign_target_files_apks.py b/tools/releasetools/sign_target_files_apks.py
index 83c2487..fa62c8f 100755
--- a/tools/releasetools/sign_target_files_apks.py
+++ b/tools/releasetools/sign_target_files_apks.py
@@ -90,14 +90,9 @@
the existing ones in info dict.
"""
-import sys
-
-if sys.hexversion < 0x02070000:
- print >> sys.stderr, "Python 2.7 or newer is required."
- sys.exit(1)
+from __future__ import print_function
import base64
-import cStringIO
import copy
import errno
import gzip
@@ -106,12 +101,20 @@
import shutil
import stat
import subprocess
+import sys
import tempfile
import zipfile
+from xml.etree import ElementTree
import add_img_to_target_files
import common
+
+if sys.hexversion < 0x02070000:
+ print("Python 2.7 or newer is required.", file=sys.stderr)
+ sys.exit(1)
+
+
OPTIONS = common.OPTIONS
OPTIONS.extra_apks = {}
@@ -126,6 +129,7 @@
OPTIONS.avb_algorithms = {}
OPTIONS.avb_extra_args = {}
+
def GetApkCerts(certmap):
# apply the key remapping to the contents of the file
for apk, cert in certmap.iteritems():
@@ -149,17 +153,18 @@
compressed_apk_extension = ".apk" + compressed_extension
for info in input_tf_zip.infolist():
if (info.filename.endswith(".apk") or
- (compressed_apk_extension and info.filename.endswith(compressed_apk_extension))):
+ (compressed_apk_extension and
+ info.filename.endswith(compressed_apk_extension))):
name = os.path.basename(info.filename)
if compressed_apk_extension and name.endswith(compressed_apk_extension):
name = name[:-len(compressed_extension)]
if name not in apk_key_map:
unknown_apks.append(name)
if unknown_apks:
- print "ERROR: no key specified for:\n\n ",
- print "\n ".join(unknown_apks)
- print "\nUse '-e <apkname>=' to specify a key (which may be an"
- print "empty string to not sign this apk)."
+ print("ERROR: no key specified for:\n")
+ print(" " + "\n ".join(unknown_apks))
+ print("\nUse '-e <apkname>=' to specify a key (which may be an empty "
+ "string to not sign this apk).")
sys.exit(1)
@@ -171,7 +176,8 @@
if is_compressed:
uncompressed = tempfile.NamedTemporaryFile()
- with gzip.open(unsigned.name, "rb") as in_file, open(uncompressed.name, "wb") as out_file:
+ with gzip.open(unsigned.name, "rb") as in_file, \
+ open(uncompressed.name, "wb") as out_file:
shutil.copyfileobj(in_file, out_file)
# Finally, close the "unsigned" file (which is gzip compressed), and then
@@ -203,14 +209,15 @@
min_api_level = 1
common.SignFile(unsigned.name, signed.name, keyname, pw,
- min_api_level=min_api_level,
- codename_to_api_level_map=codename_to_api_level_map)
+ min_api_level=min_api_level,
+ codename_to_api_level_map=codename_to_api_level_map)
- data = None;
+ data = None
if is_compressed:
# Recompress the file after it has been signed.
compressed = tempfile.NamedTemporaryFile()
- with open(signed.name, "rb") as in_file, gzip.open(compressed.name, "wb") as out_file:
+ with open(signed.name, "rb") as in_file, \
+ gzip.open(compressed.name, "wb") as out_file:
shutil.copyfileobj(in_file, out_file)
data = compressed.read()
@@ -233,10 +240,11 @@
if compressed_extension:
compressed_apk_extension = ".apk" + compressed_extension
- maxsize = max([len(os.path.basename(i.filename))
- for i in input_tf_zip.infolist()
- if i.filename.endswith('.apk') or
- (compressed_apk_extension and i.filename.endswith(compressed_apk_extension))])
+ maxsize = max(
+ [len(os.path.basename(i.filename)) for i in input_tf_zip.infolist()
+ if (i.filename.endswith('.apk') or
+ (compressed_apk_extension and
+ i.filename.endswith(compressed_apk_extension)))])
system_root_image = misc_info.get("system_root_image") == "true"
for info in input_tf_zip.infolist():
@@ -248,21 +256,23 @@
# Sign APKs.
if (info.filename.endswith(".apk") or
- (compressed_apk_extension and info.filename.endswith(compressed_apk_extension))):
- is_compressed = compressed_extension and info.filename.endswith(compressed_apk_extension)
+ (compressed_apk_extension and
+ info.filename.endswith(compressed_apk_extension))):
+ is_compressed = (compressed_extension and
+ info.filename.endswith(compressed_apk_extension))
name = os.path.basename(info.filename)
if is_compressed:
name = name[:-len(compressed_extension)]
key = apk_key_map[name]
if key not in common.SPECIAL_CERT_STRINGS:
- print " signing: %-*s (%s)" % (maxsize, name, key)
+ 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)
common.ZipWriteStr(output_tf_zip, out_info, signed_data)
else:
# an APK we're not supposed to sign.
- print "NOT signing: %s" % (name,)
+ print("NOT signing: %s" % (name,))
common.ZipWriteStr(output_tf_zip, out_info, data)
# System properties.
@@ -274,15 +284,17 @@
"ROOT/default.prop", # legacy
"RECOVERY/RAMDISK/prop.default",
"RECOVERY/RAMDISK/default.prop"): # legacy
- print "rewriting %s:" % (info.filename,)
+ print("Rewriting %s:" % (info.filename,))
if stat.S_ISLNK(info.external_attr >> 16):
new_data = data
else:
- new_data = RewriteProps(data, misc_info)
+ new_data = RewriteProps(data)
common.ZipWriteStr(output_tf_zip, out_info, new_data)
+ # Replace the certs in *mac_permissions.xml (there could be multiple, such
+ # as {system,vendor}/etc/selinux/{plat,nonplat}_mac_permissions.xml).
elif info.filename.endswith("mac_permissions.xml"):
- print "rewriting %s with new keys." % (info.filename,)
+ print("Rewriting %s with new keys." % (info.filename,))
new_data = ReplaceCerts(data)
common.ZipWriteStr(output_tf_zip, out_info, new_data)
@@ -333,10 +345,7 @@
ReplaceVerityPrivateKey(misc_info, OPTIONS.replace_verity_private_key[1])
if OPTIONS.replace_verity_public_key:
- if system_root_image:
- dest = "ROOT/verity_key"
- else:
- dest = "BOOT/RAMDISK/verity_key"
+ dest = "ROOT/verity_key" if system_root_image else "BOOT/RAMDISK/verity_key"
# We are replacing the one in boot image only, since the one under
# recovery won't ever be needed.
ReplaceVerityPublicKey(
@@ -355,38 +364,67 @@
def ReplaceCerts(data):
- """Given a string of data, replace all occurences of a set
- of X509 certs with a newer set of X509 certs and return
- the updated data string."""
- for old, new in OPTIONS.key_map.iteritems():
- try:
- if OPTIONS.verbose:
- print " Replacing %s.x509.pem with %s.x509.pem" % (old, new)
- f = open(old + ".x509.pem")
- old_cert16 = base64.b16encode(common.ParseCertificate(f.read())).lower()
- f.close()
- f = open(new + ".x509.pem")
- new_cert16 = base64.b16encode(common.ParseCertificate(f.read())).lower()
- f.close()
- # Only match entire certs.
- pattern = "\\b"+old_cert16+"\\b"
- (data, num) = re.subn(pattern, new_cert16, data, flags=re.IGNORECASE)
- if OPTIONS.verbose:
- print " Replaced %d occurence(s) of %s.x509.pem with " \
- "%s.x509.pem" % (num, old, new)
- except IOError as e:
- if e.errno == errno.ENOENT and not OPTIONS.verbose:
- continue
+ """Replaces all the occurences of X.509 certs with the new ones.
- print " Error accessing %s. %s. Skip replacing %s.x509.pem " \
- "with %s.x509.pem." % (e.filename, e.strerror, old, new)
+ The mapping info is read from OPTIONS.key_map. Non-existent certificate will
+ be skipped. After the replacement, it additionally checks for duplicate
+ entries, which would otherwise fail the policy loading code in
+ frameworks/base/services/core/java/com/android/server/pm/SELinuxMMAC.java.
+
+ Args:
+ data: Input string that contains a set of X.509 certs.
+
+ Returns:
+ A string after the replacement.
+
+ Raises:
+ AssertionError: On finding duplicate entries.
+ """
+ for old, new in OPTIONS.key_map.iteritems():
+ if OPTIONS.verbose:
+ print(" Replacing %s.x509.pem with %s.x509.pem" % (old, new))
+
+ try:
+ with open(old + ".x509.pem") as old_fp:
+ old_cert16 = base64.b16encode(
+ common.ParseCertificate(old_fp.read())).lower()
+ with open(new + ".x509.pem") as new_fp:
+ new_cert16 = base64.b16encode(
+ common.ParseCertificate(new_fp.read())).lower()
+ except IOError as e:
+ if OPTIONS.verbose or e.errno != errno.ENOENT:
+ print(" Error accessing %s: %s.\nSkip replacing %s.x509.pem with "
+ "%s.x509.pem." % (e.filename, e.strerror, old, new))
+ continue
+
+ # Only match entire certs.
+ pattern = "\\b" + old_cert16 + "\\b"
+ (data, num) = re.subn(pattern, new_cert16, data, flags=re.IGNORECASE)
+
+ if OPTIONS.verbose:
+ print(" Replaced %d occurence(s) of %s.x509.pem with %s.x509.pem" % (
+ num, old, new))
+
+ # Verify that there're no duplicate entries after the replacement. Note that
+ # it's only checking entries with global seinfo at the moment (i.e. ignoring
+ # the ones with inner packages). (Bug: 69479366)
+ root = ElementTree.fromstring(data)
+ signatures = [signer.attrib['signature'] for signer in root.findall('signer')]
+ assert len(signatures) == len(set(signatures)), \
+ "Found duplicate entries after cert replacement: {}".format(data)
return data
def EditTags(tags):
- """Given a string containing comma-separated tags, apply the edits
- specified in OPTIONS.tag_changes and return the updated string."""
+ """Applies the edits to the tag string as specified in OPTIONS.tag_changes.
+
+ Args:
+ tags: The input string that contains comma-separated tags.
+
+ Returns:
+ The updated tags (comma-separated and sorted).
+ """
tags = set(tags.split(","))
for ch in OPTIONS.tag_changes:
if ch[0] == "-":
@@ -396,20 +434,27 @@
return ",".join(sorted(tags))
-def RewriteProps(data, misc_info):
+def RewriteProps(data):
+ """Rewrites the system properties in the given string.
+
+ Each property is expected in 'key=value' format. The properties that contain
+ build tags (i.e. test-keys, dev-keys) will be updated accordingly by calling
+ EditTags().
+
+ Args:
+ data: Input string, separated by newlines.
+
+ Returns:
+ The string with modified properties.
+ """
output = []
for line in data.split("\n"):
line = line.strip()
original_line = line
if line and line[0] != '#' and "=" in line:
key, value = line.split("=", 1)
- if (key in ("ro.build.fingerprint", "ro.vendor.build.fingerprint")
- and misc_info.get("oem_fingerprint_properties") is None):
- pieces = value.split("/")
- pieces[-1] = EditTags(pieces[-1])
- value = "/".join(pieces)
- elif (key in ("ro.build.thumbprint", "ro.vendor.build.thumbprint")
- and misc_info.get("oem_fingerprint_properties") is not None):
+ if key in ("ro.build.fingerprint", "ro.build.thumbprint",
+ "ro.vendor.build.fingerprint", "ro.vendor.build.thumbprint"):
pieces = value.split("/")
pieces[-1] = EditTags(pieces[-1])
value = "/".join(pieces)
@@ -432,8 +477,8 @@
value = " ".join(value)
line = key + "=" + value
if line != original_line:
- print " replace: ", original_line
- print " with: ", line
+ print(" replace: ", original_line)
+ print(" with: ", line)
output.append(line)
return "\n".join(output) + "\n"
@@ -444,12 +489,12 @@
except KeyError:
raise common.ExternalError("can't read META/otakeys.txt from input")
- extra_recovery_keys = misc_info.get("extra_recovery_keys", None)
+ extra_recovery_keys = misc_info.get("extra_recovery_keys")
if extra_recovery_keys:
extra_recovery_keys = [OPTIONS.key_map.get(k, k) + ".x509.pem"
for k in extra_recovery_keys.split()]
if extra_recovery_keys:
- print "extra recovery-only key(s): " + ", ".join(extra_recovery_keys)
+ print("extra recovery-only key(s): " + ", ".join(extra_recovery_keys))
else:
extra_recovery_keys = []
@@ -463,13 +508,15 @@
mapped_keys.append(OPTIONS.key_map.get(k, k) + ".x509.pem")
if mapped_keys:
- print "using:\n ", "\n ".join(mapped_keys)
- print "for OTA package verification"
+ print("using:\n ", "\n ".join(mapped_keys))
+ print("for OTA package verification")
else:
devkey = misc_info.get("default_system_dev_certificate",
"build/target/product/security/testkey")
- mapped_keys.append(
- OPTIONS.key_map.get(devkey, devkey) + ".x509.pem")
+ mapped_devkey = OPTIONS.key_map.get(devkey, devkey)
+ if mapped_devkey != devkey:
+ misc_info["default_system_dev_certificate"] = mapped_devkey
+ mapped_keys.append(mapped_devkey + ".x509.pem")
print("META/otakeys.txt has no keys; using %s for OTA package"
" verification." % (mapped_keys[0],))
@@ -496,7 +543,11 @@
# put into a zipfile system/etc/security/otacerts.zip.
# We DO NOT include the extra_recovery_keys (if any) here.
- temp_file = cStringIO.StringIO()
+ try:
+ from StringIO import StringIO
+ except ImportError:
+ from io import StringIO
+ temp_file = StringIO()
certs_zip = zipfile.ZipFile(temp_file, "w")
for k in mapped_keys:
common.ZipWrite(certs_zip, k)
@@ -512,11 +563,8 @@
print("\n WARNING: Found more than one OTA keys; Using the first one"
" as payload verification key.\n\n")
- print "Using %s for payload verification." % (mapped_keys[0],)
- cmd = common.Run(
- ["openssl", "x509", "-pubkey", "-noout", "-in", mapped_keys[0]],
- stdout=subprocess.PIPE)
- pubkey, _ = cmd.communicate()
+ print("Using %s for payload verification." % (mapped_keys[0],))
+ pubkey = common.ExtractPublicKey(mapped_keys[0])
common.ZipWriteStr(
output_tf_zip,
"SYSTEM/etc/update_engine/update-payload-key.pub.pem",
@@ -529,41 +577,62 @@
return new_recovery_keys
-def ReplaceVerityPublicKey(targetfile_zip, filename, key_path):
- print "Replacing verity public key with %s" % (key_path,)
- common.ZipWrite(targetfile_zip, key_path, arcname=filename)
+def ReplaceVerityPublicKey(output_zip, filename, key_path):
+ """Replaces the verity public key at the given path in the given zip.
+
+ Args:
+ output_zip: The output target_files zip.
+ filename: The archive name in the output zip.
+ key_path: The path to the public key.
+ """
+ print("Replacing verity public key with %s" % (key_path,))
+ common.ZipWrite(output_zip, key_path, arcname=filename)
def ReplaceVerityPrivateKey(misc_info, key_path):
- print "Replacing verity private key with %s" % (key_path,)
+ """Replaces the verity private key in misc_info dict.
+
+ Args:
+ misc_info: The info dict.
+ key_path: The path to the private key in PKCS#8 format.
+ """
+ print("Replacing verity private key with %s" % (key_path,))
misc_info["verity_key"] = key_path
-def ReplaceVerityKeyId(targetfile_input_zip, targetfile_output_zip, keypath):
- in_cmdline = targetfile_input_zip.read("BOOT/cmdline")
- # copy in_cmdline to output_zip if veritykeyid is not present in in_cmdline
- if "veritykeyid" not in in_cmdline:
- common.ZipWriteStr(targetfile_output_zip, "BOOT/cmdline", in_cmdline)
- return in_cmdline
- out_cmdline = []
- for param in in_cmdline.split():
- if "veritykeyid" in param:
- # extract keyid using openssl command
- p = common.Run(
- ["openssl", "x509", "-in", keypath, "-text"],
- stdout=subprocess.PIPE)
- keyid, stderr = p.communicate()
- keyid = re.search(
- r'keyid:([0-9a-fA-F:]*)', keyid).group(1).replace(':', '').lower()
- print "Replacing verity keyid with %s error=%s" % (keyid, stderr)
- out_cmdline.append("veritykeyid=id:%s" % (keyid,))
- else:
- out_cmdline.append(param)
+def ReplaceVerityKeyId(input_zip, output_zip, key_path):
+ """Replaces the veritykeyid parameter in BOOT/cmdline.
- out_cmdline = ' '.join(out_cmdline)
- out_cmdline = out_cmdline.strip()
- print "out_cmdline %s" % (out_cmdline)
- common.ZipWriteStr(targetfile_output_zip, "BOOT/cmdline", out_cmdline)
+ Args:
+ input_zip: The input target_files zip, which should be already open.
+ output_zip: The output target_files zip, which should be already open and
+ writable.
+ key_path: The path to the PEM encoded X.509 certificate.
+ """
+ in_cmdline = input_zip.read("BOOT/cmdline")
+ # Copy in_cmdline to output_zip if veritykeyid is not present.
+ if "veritykeyid" not in in_cmdline:
+ common.ZipWriteStr(output_zip, "BOOT/cmdline", in_cmdline)
+ return
+
+ out_buffer = []
+ for param in in_cmdline.split():
+ if "veritykeyid" not in param:
+ out_buffer.append(param)
+ continue
+
+ # Extract keyid using openssl command.
+ p = common.Run(["openssl", "x509", "-in", key_path, "-text"],
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ keyid, stderr = p.communicate()
+ assert p.returncode == 0, "Failed to dump certificate: {}".format(stderr)
+ keyid = re.search(
+ r'keyid:([0-9a-fA-F:]*)', keyid).group(1).replace(':', '').lower()
+ print("Replacing verity keyid with {}".format(keyid))
+ out_buffer.append("veritykeyid=id:%s" % (keyid,))
+
+ out_cmdline = ' '.join(out_buffer).strip() + '\n'
+ common.ZipWriteStr(output_zip, "BOOT/cmdline", out_cmdline)
def ReplaceMiscInfoTxt(input_zip, output_zip, misc_info):
@@ -585,11 +654,12 @@
"""Replaces the AVB signing keys."""
AVB_FOOTER_ARGS_BY_PARTITION = {
- 'boot' : 'avb_boot_add_hash_footer_args',
- 'dtbo' : 'avb_dtbo_add_hash_footer_args',
- 'system' : 'avb_system_add_hashtree_footer_args',
- 'vendor' : 'avb_vendor_add_hashtree_footer_args',
- 'vbmeta' : 'avb_vbmeta_args',
+ 'boot' : 'avb_boot_add_hash_footer_args',
+ 'dtbo' : 'avb_dtbo_add_hash_footer_args',
+ 'recovery' : 'avb_recovery_add_hash_footer_args',
+ 'system' : 'avb_system_add_hashtree_footer_args',
+ 'vendor' : 'avb_vendor_add_hashtree_footer_args',
+ 'vbmeta' : 'avb_vbmeta_args',
}
def ReplaceAvbPartitionSigningKey(partition):
@@ -600,15 +670,15 @@
algorithm = OPTIONS.avb_algorithms.get(partition)
assert algorithm, 'Missing AVB signing algorithm for %s' % (partition,)
- print 'Replacing AVB signing key for %s with "%s" (%s)' % (
- partition, key, algorithm)
+ print('Replacing AVB signing key for %s with "%s" (%s)' % (
+ partition, key, algorithm))
misc_info['avb_' + partition + '_algorithm'] = algorithm
misc_info['avb_' + partition + '_key_path'] = key
extra_args = OPTIONS.avb_extra_args.get(partition)
if extra_args:
- print 'Setting extra AVB signing args for %s to "%s"' % (
- partition, extra_args)
+ print('Setting extra AVB signing args for %s to "%s"' % (
+ partition, extra_args))
args_key = AVB_FOOTER_ARGS_BY_PARTITION[partition]
misc_info[args_key] = (misc_info.get(args_key, '') + ' ' + extra_args)
@@ -751,29 +821,29 @@
argv, __doc__,
extra_opts="e:d:k:ot:",
extra_long_opts=[
- "extra_apks=",
- "default_key_mappings=",
- "key_mapping=",
- "replace_ota_keys",
- "tag_changes=",
- "replace_verity_public_key=",
- "replace_verity_private_key=",
- "replace_verity_keyid=",
- "avb_vbmeta_algorithm=",
- "avb_vbmeta_key=",
- "avb_vbmeta_extra_args=",
- "avb_boot_algorithm=",
- "avb_boot_key=",
- "avb_boot_extra_args=",
- "avb_dtbo_algorithm=",
- "avb_dtbo_key=",
- "avb_dtbo_extra_args=",
- "avb_system_algorithm=",
- "avb_system_key=",
- "avb_system_extra_args=",
- "avb_vendor_algorithm=",
- "avb_vendor_key=",
- "avb_vendor_extra_args=",
+ "extra_apks=",
+ "default_key_mappings=",
+ "key_mapping=",
+ "replace_ota_keys",
+ "tag_changes=",
+ "replace_verity_public_key=",
+ "replace_verity_private_key=",
+ "replace_verity_keyid=",
+ "avb_vbmeta_algorithm=",
+ "avb_vbmeta_key=",
+ "avb_vbmeta_extra_args=",
+ "avb_boot_algorithm=",
+ "avb_boot_key=",
+ "avb_boot_extra_args=",
+ "avb_dtbo_algorithm=",
+ "avb_dtbo_key=",
+ "avb_dtbo_extra_args=",
+ "avb_system_algorithm=",
+ "avb_system_key=",
+ "avb_system_extra_args=",
+ "avb_vendor_algorithm=",
+ "avb_vendor_key=",
+ "avb_vendor_extra_args=",
],
extra_option_handler=option_handler)
@@ -816,16 +886,14 @@
new_args.append(args[1])
add_img_to_target_files.main(new_args)
- print "done."
+ print("done.")
if __name__ == '__main__':
try:
main(sys.argv[1:])
- except common.ExternalError, e:
- print
- print " ERROR: %s" % (e,)
- print
+ except common.ExternalError as e:
+ print("\n ERROR: %s\n" % (e,))
sys.exit(1)
finally:
common.Cleanup()
diff --git a/tools/releasetools/sparse_img.py b/tools/releasetools/sparse_img.py
index 7eb60d9..083da7a 100644
--- a/tools/releasetools/sparse_img.py
+++ b/tools/releasetools/sparse_img.py
@@ -15,6 +15,7 @@
import bisect
import os
import struct
+import threading
from hashlib import sha1
import rangelib
@@ -32,7 +33,7 @@
"""
def __init__(self, simg_fn, file_map_fn=None, clobbered_blocks=None,
- mode="rb", build_map=True):
+ mode="rb", build_map=True, allow_shared_blocks=False):
self.simg_f = f = open(simg_fn, mode)
header_bin = f.read(28)
@@ -111,6 +112,8 @@
raise ValueError("Unknown chunk type 0x%04X not supported" %
(chunk_type,))
+ self.generator_lock = threading.Lock()
+
self.care_map = rangelib.RangeSet(care_data)
self.offset_index = [i[0] for i in offset_map]
@@ -126,7 +129,8 @@
self.extended = extended
if file_map_fn:
- self.LoadFileBlockMap(file_map_fn, self.clobbered_blocks)
+ self.LoadFileBlockMap(file_map_fn, self.clobbered_blocks,
+ allow_shared_blocks)
else:
self.file_map = {"__DATA": self.care_map}
@@ -173,40 +177,47 @@
particular is not necessarily equal to the number of ranges in
'ranges'.
- This generator is stateful -- it depends on the open file object
- contained in this SparseImage, so you should not try to run two
+ Use a lock to protect the generator so that we will not run two
instances of this generator on the same object simultaneously."""
f = self.simg_f
- for s, e in ranges:
- to_read = e-s
- idx = bisect.bisect_right(self.offset_index, s) - 1
- chunk_start, chunk_len, filepos, fill_data = self.offset_map[idx]
-
- # for the first chunk we may be starting partway through it.
- remain = chunk_len - (s - chunk_start)
- this_read = min(remain, to_read)
- if filepos is not None:
- p = filepos + ((s - chunk_start) * self.blocksize)
- f.seek(p, os.SEEK_SET)
- yield f.read(this_read * self.blocksize)
- else:
- yield fill_data * (this_read * (self.blocksize >> 2))
- to_read -= this_read
-
- while to_read > 0:
- # continue with following chunks if this range spans multiple chunks.
- idx += 1
+ with self.generator_lock:
+ for s, e in ranges:
+ to_read = e-s
+ idx = bisect.bisect_right(self.offset_index, s) - 1
chunk_start, chunk_len, filepos, fill_data = self.offset_map[idx]
- this_read = min(chunk_len, to_read)
+
+ # for the first chunk we may be starting partway through it.
+ remain = chunk_len - (s - chunk_start)
+ this_read = min(remain, to_read)
if filepos is not None:
- f.seek(filepos, os.SEEK_SET)
+ p = filepos + ((s - chunk_start) * self.blocksize)
+ f.seek(p, os.SEEK_SET)
yield f.read(this_read * self.blocksize)
else:
yield fill_data * (this_read * (self.blocksize >> 2))
to_read -= this_read
- def LoadFileBlockMap(self, fn, clobbered_blocks):
+ while to_read > 0:
+ # continue with following chunks if this range spans multiple chunks.
+ idx += 1
+ chunk_start, chunk_len, filepos, fill_data = self.offset_map[idx]
+ this_read = min(chunk_len, to_read)
+ if filepos is not None:
+ f.seek(filepos, os.SEEK_SET)
+ yield f.read(this_read * self.blocksize)
+ else:
+ yield fill_data * (this_read * (self.blocksize >> 2))
+ to_read -= this_read
+
+ def LoadFileBlockMap(self, fn, clobbered_blocks, allow_shared_blocks):
+ """Loads the given block map file.
+
+ Args:
+ fn: The filename of the block map file.
+ clobbered_blocks: A RangeSet instance for the clobbered blocks.
+ allow_shared_blocks: Whether having shared blocks is allowed.
+ """
remaining = self.care_map
self.file_map = out = {}
@@ -214,6 +225,18 @@
for line in f:
fn, ranges = line.split(None, 1)
ranges = rangelib.RangeSet.parse(ranges)
+
+ if allow_shared_blocks:
+ # Find the shared blocks that have been claimed by others.
+ shared_blocks = ranges.subtract(remaining)
+ if shared_blocks:
+ ranges = ranges.subtract(shared_blocks)
+ if not ranges:
+ continue
+
+ # Tag the entry so that we can skip applying imgdiff on this file.
+ ranges.extra['uses_shared_blocks'] = True
+
out[fn] = ranges
assert ranges.size() == ranges.intersect(remaining).size()
diff --git a/tools/releasetools/test_add_img_to_target_files.py b/tools/releasetools/test_add_img_to_target_files.py
new file mode 100644
index 0000000..9a0f78e
--- /dev/null
+++ b/tools/releasetools/test_add_img_to_target_files.py
@@ -0,0 +1,339 @@
+#
+# 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.
+#
+
+import os
+import os.path
+import unittest
+import zipfile
+
+import common
+import test_utils
+from add_img_to_target_files import (
+ AddCareMapTxtForAbOta, AddPackRadioImages, AddRadioImagesForAbOta,
+ GetCareMap)
+from rangelib import RangeSet
+
+
+OPTIONS = common.OPTIONS
+
+
+class AddImagesToTargetFilesTest(unittest.TestCase):
+
+ def setUp(self):
+ OPTIONS.input_tmp = common.MakeTempDir()
+
+ def tearDown(self):
+ common.Cleanup()
+
+ @staticmethod
+ def _create_images(images, prefix):
+ """Creates images under OPTIONS.input_tmp/prefix."""
+ path = os.path.join(OPTIONS.input_tmp, prefix)
+ if not os.path.exists(path):
+ os.mkdir(path)
+
+ for image in images:
+ image_path = os.path.join(path, image + '.img')
+ with open(image_path, 'wb') as image_fp:
+ image_fp.write(image.encode())
+
+ images_path = os.path.join(OPTIONS.input_tmp, 'IMAGES')
+ if not os.path.exists(images_path):
+ os.mkdir(images_path)
+ return images, images_path
+
+ def test_AddRadioImagesForAbOta_imageExists(self):
+ """Tests the case with existing images under IMAGES/."""
+ images, images_path = self._create_images(['aboot', 'xbl'], 'IMAGES')
+ AddRadioImagesForAbOta(None, images)
+
+ for image in images:
+ self.assertTrue(
+ os.path.exists(os.path.join(images_path, image + '.img')))
+
+ def test_AddRadioImagesForAbOta_copyFromRadio(self):
+ """Tests the case that copies images from RADIO/."""
+ images, images_path = self._create_images(['aboot', 'xbl'], 'RADIO')
+ AddRadioImagesForAbOta(None, images)
+
+ for image in images:
+ self.assertTrue(
+ os.path.exists(os.path.join(images_path, image + '.img')))
+
+ def test_AddRadioImagesForAbOta_copyFromRadio_zipOutput(self):
+ images, _ = self._create_images(['aboot', 'xbl'], 'RADIO')
+
+ # Set up the output zip.
+ output_file = common.MakeTempFile(suffix='.zip')
+ with zipfile.ZipFile(output_file, 'w') as output_zip:
+ AddRadioImagesForAbOta(output_zip, images)
+
+ with zipfile.ZipFile(output_file, 'r') as verify_zip:
+ for image in images:
+ self.assertIn('IMAGES/' + image + '.img', verify_zip.namelist())
+
+ def test_AddRadioImagesForAbOta_copyFromVendorImages(self):
+ """Tests the case that copies images from VENDOR_IMAGES/."""
+ vendor_images_path = os.path.join(OPTIONS.input_tmp, 'VENDOR_IMAGES')
+ os.mkdir(vendor_images_path)
+
+ partitions = ['aboot', 'xbl']
+ for index, partition in enumerate(partitions):
+ subdir = os.path.join(vendor_images_path, 'subdir-{}'.format(index))
+ os.mkdir(subdir)
+
+ partition_image_path = os.path.join(subdir, partition + '.img')
+ with open(partition_image_path, 'wb') as partition_fp:
+ partition_fp.write(partition.encode())
+
+ # Set up the output dir.
+ images_path = os.path.join(OPTIONS.input_tmp, 'IMAGES')
+ os.mkdir(images_path)
+
+ AddRadioImagesForAbOta(None, partitions)
+
+ for partition in partitions:
+ self.assertTrue(
+ os.path.exists(os.path.join(images_path, partition + '.img')))
+
+ def test_AddRadioImagesForAbOta_missingImages(self):
+ images, _ = self._create_images(['aboot', 'xbl'], 'RADIO')
+ self.assertRaises(AssertionError, AddRadioImagesForAbOta, None,
+ images + ['baz'])
+
+ def test_AddRadioImagesForAbOta_missingImages_zipOutput(self):
+ images, _ = self._create_images(['aboot', 'xbl'], 'RADIO')
+
+ # Set up the output zip.
+ output_file = common.MakeTempFile(suffix='.zip')
+ with zipfile.ZipFile(output_file, 'w') as output_zip:
+ self.assertRaises(AssertionError, AddRadioImagesForAbOta, output_zip,
+ images + ['baz'])
+
+ def test_AddPackRadioImages(self):
+ images, images_path = self._create_images(['foo', 'bar'], 'RADIO')
+ AddPackRadioImages(None, images)
+
+ for image in images:
+ self.assertTrue(
+ os.path.exists(os.path.join(images_path, image + '.img')))
+
+ def test_AddPackRadioImages_with_suffix(self):
+ images, images_path = self._create_images(['foo', 'bar'], 'RADIO')
+ images_with_suffix = [image + '.img' for image in images]
+ AddPackRadioImages(None, images_with_suffix)
+
+ for image in images:
+ self.assertTrue(
+ os.path.exists(os.path.join(images_path, image + '.img')))
+
+ def test_AddPackRadioImages_zipOutput(self):
+ images, _ = self._create_images(['foo', 'bar'], 'RADIO')
+
+ # Set up the output zip.
+ output_file = common.MakeTempFile(suffix='.zip')
+ with zipfile.ZipFile(output_file, 'w') as output_zip:
+ AddPackRadioImages(output_zip, images)
+
+ with zipfile.ZipFile(output_file, 'r') as verify_zip:
+ for image in images:
+ self.assertIn('IMAGES/' + image + '.img', verify_zip.namelist())
+
+ def test_AddPackRadioImages_imageExists(self):
+ images, images_path = self._create_images(['foo', 'bar'], 'RADIO')
+
+ # Additionally create images under IMAGES/ so that they should be skipped.
+ images, images_path = self._create_images(['foo', 'bar'], 'IMAGES')
+
+ AddPackRadioImages(None, images)
+
+ for image in images:
+ self.assertTrue(
+ os.path.exists(os.path.join(images_path, image + '.img')))
+
+ def test_AddPackRadioImages_missingImages(self):
+ images, _ = self._create_images(['foo', 'bar'], 'RADIO')
+ AddPackRadioImages(None, images)
+
+ self.assertRaises(AssertionError, AddPackRadioImages, None,
+ images + ['baz'])
+
+ @staticmethod
+ def _test_AddCareMapTxtForAbOta():
+ """Helper function to set up the test for test_AddCareMapTxtForAbOta()."""
+ OPTIONS.info_dict = {
+ 'system_verity_block_device' : '/dev/block/system',
+ 'vendor_verity_block_device' : '/dev/block/vendor',
+ }
+
+ # Prepare the META/ folder.
+ meta_path = os.path.join(OPTIONS.input_tmp, 'META')
+ if not os.path.exists(meta_path):
+ os.mkdir(meta_path)
+
+ system_image = test_utils.construct_sparse_image([
+ (0xCAC1, 6),
+ (0xCAC3, 4),
+ (0xCAC1, 6)])
+ vendor_image = test_utils.construct_sparse_image([
+ (0xCAC2, 10)])
+
+ image_paths = {
+ 'system' : system_image,
+ 'vendor' : vendor_image,
+ }
+ return image_paths
+
+ def test_AddCareMapTxtForAbOta(self):
+ image_paths = self._test_AddCareMapTxtForAbOta()
+
+ AddCareMapTxtForAbOta(None, ['system', 'vendor'], image_paths)
+
+ care_map_file = os.path.join(OPTIONS.input_tmp, 'META', 'care_map.txt')
+ with open(care_map_file, 'r') as verify_fp:
+ care_map = verify_fp.read()
+
+ lines = care_map.split('\n')
+ self.assertEqual(4, len(lines))
+ self.assertEqual('system', lines[0])
+ self.assertEqual(RangeSet("0-5 10-15").to_string_raw(), lines[1])
+ self.assertEqual('vendor', lines[2])
+ self.assertEqual(RangeSet("0-9").to_string_raw(), lines[3])
+
+ def test_AddCareMapTxtForAbOta_withNonCareMapPartitions(self):
+ """Partitions without care_map should be ignored."""
+ image_paths = self._test_AddCareMapTxtForAbOta()
+
+ AddCareMapTxtForAbOta(
+ None, ['boot', 'system', 'vendor', 'vbmeta'], image_paths)
+
+ care_map_file = os.path.join(OPTIONS.input_tmp, 'META', 'care_map.txt')
+ with open(care_map_file, 'r') as verify_fp:
+ care_map = verify_fp.read()
+
+ lines = care_map.split('\n')
+ self.assertEqual(4, len(lines))
+ self.assertEqual('system', lines[0])
+ self.assertEqual(RangeSet("0-5 10-15").to_string_raw(), lines[1])
+ self.assertEqual('vendor', lines[2])
+ self.assertEqual(RangeSet("0-9").to_string_raw(), lines[3])
+
+ def test_AddCareMapTxtForAbOta_withAvb(self):
+ """Tests the case for device using AVB."""
+ image_paths = self._test_AddCareMapTxtForAbOta()
+ OPTIONS.info_dict = {
+ 'avb_system_hashtree_enable' : 'true',
+ 'avb_vendor_hashtree_enable' : 'true',
+ }
+
+ AddCareMapTxtForAbOta(None, ['system', 'vendor'], image_paths)
+
+ care_map_file = os.path.join(OPTIONS.input_tmp, 'META', 'care_map.txt')
+ with open(care_map_file, 'r') as verify_fp:
+ care_map = verify_fp.read()
+
+ lines = care_map.split('\n')
+ self.assertEqual(4, len(lines))
+ self.assertEqual('system', lines[0])
+ self.assertEqual(RangeSet("0-5 10-15").to_string_raw(), lines[1])
+ self.assertEqual('vendor', lines[2])
+ self.assertEqual(RangeSet("0-9").to_string_raw(), lines[3])
+
+ def test_AddCareMapTxtForAbOta_verityNotEnabled(self):
+ """No care_map.txt should be generated if verity not enabled."""
+ image_paths = self._test_AddCareMapTxtForAbOta()
+ OPTIONS.info_dict = {}
+ AddCareMapTxtForAbOta(None, ['system', 'vendor'], image_paths)
+
+ care_map_file = os.path.join(OPTIONS.input_tmp, 'META', 'care_map.txt')
+ self.assertFalse(os.path.exists(care_map_file))
+
+ def test_AddCareMapTxtForAbOta_missingImageFile(self):
+ """Missing image file should be considered fatal."""
+ image_paths = self._test_AddCareMapTxtForAbOta()
+ image_paths['vendor'] = ''
+ self.assertRaises(AssertionError, AddCareMapTxtForAbOta, None,
+ ['system', 'vendor'], image_paths)
+
+ def test_AddCareMapTxtForAbOta_zipOutput(self):
+ """Tests the case with ZIP output."""
+ image_paths = self._test_AddCareMapTxtForAbOta()
+
+ output_file = common.MakeTempFile(suffix='.zip')
+ with zipfile.ZipFile(output_file, 'w') as output_zip:
+ AddCareMapTxtForAbOta(output_zip, ['system', 'vendor'], image_paths)
+
+ with zipfile.ZipFile(output_file, 'r') as verify_zip:
+ care_map = verify_zip.read('META/care_map.txt').decode('ascii')
+
+ lines = care_map.split('\n')
+ self.assertEqual(4, len(lines))
+ self.assertEqual('system', lines[0])
+ self.assertEqual(RangeSet("0-5 10-15").to_string_raw(), lines[1])
+ self.assertEqual('vendor', lines[2])
+ self.assertEqual(RangeSet("0-9").to_string_raw(), lines[3])
+
+ def test_AddCareMapTxtForAbOta_zipOutput_careMapEntryExists(self):
+ """Tests the case with ZIP output which already has care_map entry."""
+ image_paths = self._test_AddCareMapTxtForAbOta()
+
+ output_file = common.MakeTempFile(suffix='.zip')
+ with zipfile.ZipFile(output_file, 'w') as output_zip:
+ # Create an existing META/care_map.txt entry.
+ common.ZipWriteStr(output_zip, 'META/care_map.txt', 'dummy care_map.txt')
+
+ # Request to add META/care_map.txt again.
+ AddCareMapTxtForAbOta(output_zip, ['system', 'vendor'], image_paths)
+
+ # The one under OPTIONS.input_tmp must have been replaced.
+ care_map_file = os.path.join(OPTIONS.input_tmp, 'META', 'care_map.txt')
+ with open(care_map_file, 'r') as verify_fp:
+ care_map = verify_fp.read()
+
+ lines = care_map.split('\n')
+ self.assertEqual(4, len(lines))
+ self.assertEqual('system', lines[0])
+ self.assertEqual(RangeSet("0-5 10-15").to_string_raw(), lines[1])
+ self.assertEqual('vendor', lines[2])
+ self.assertEqual(RangeSet("0-9").to_string_raw(), lines[3])
+
+ # The existing entry should be scheduled to be replaced.
+ self.assertIn('META/care_map.txt', OPTIONS.replace_updated_files_list)
+
+ def test_GetCareMap(self):
+ sparse_image = test_utils.construct_sparse_image([
+ (0xCAC1, 6),
+ (0xCAC3, 4),
+ (0xCAC1, 6)])
+ OPTIONS.info_dict = {
+ 'system_adjusted_partition_size' : 12,
+ }
+ name, care_map = GetCareMap('system', sparse_image)
+ self.assertEqual('system', name)
+ self.assertEqual(RangeSet("0-5 10-12").to_string_raw(), care_map)
+
+ def test_GetCareMap_invalidPartition(self):
+ self.assertRaises(AssertionError, GetCareMap, 'oem', None)
+
+ def test_GetCareMap_invalidAdjustedPartitionSize(self):
+ sparse_image = test_utils.construct_sparse_image([
+ (0xCAC1, 6),
+ (0xCAC3, 4),
+ (0xCAC1, 6)])
+ OPTIONS.info_dict = {
+ 'system_adjusted_partition_size' : -12,
+ }
+ self.assertRaises(AssertionError, GetCareMap, 'system', sparse_image)
diff --git a/tools/releasetools/test_blockimgdiff.py b/tools/releasetools/test_blockimgdiff.py
index e5a3694..ceada18 100644
--- a/tools/releasetools/test_blockimgdiff.py
+++ b/tools/releasetools/test_blockimgdiff.py
@@ -16,12 +16,44 @@
from __future__ import print_function
-import common
import unittest
-from blockimgdiff import BlockImageDiff, EmptyImage, Transfer
+import common
+from blockimgdiff import (BlockImageDiff, EmptyImage, HeapItem, ImgdiffStats,
+ Transfer)
from rangelib import RangeSet
+
+class HealpItemTest(unittest.TestCase):
+
+ class Item(object):
+ def __init__(self, score):
+ self.score = score
+
+ def test_init(self):
+ item1 = HeapItem(self.Item(15))
+ item2 = HeapItem(self.Item(20))
+ item3 = HeapItem(self.Item(15))
+ self.assertTrue(item1)
+ self.assertTrue(item2)
+ self.assertTrue(item3)
+
+ self.assertNotEqual(item1, item2)
+ self.assertEqual(item1, item3)
+ # HeapItem uses negated scores.
+ self.assertGreater(item1, item2)
+ self.assertLessEqual(item1, item3)
+ self.assertTrue(item1 <= item3)
+ self.assertFalse(item2 >= item1)
+
+ def test_clear(self):
+ item = HeapItem(self.Item(15))
+ self.assertTrue(item)
+
+ item.clear()
+ self.assertFalse(item)
+
+
class BlockImageDiffTest(unittest.TestCase):
def test_GenerateDigraphOrder(self):
@@ -141,3 +173,102 @@
# Insufficient cache to stash 15 blocks (size * 0.8 < 15).
common.OPTIONS.cache_size = 15 * 4096
self.assertEqual(15, block_image_diff.ReviseStashSize())
+
+ def test_FileTypeSupportedByImgdiff(self):
+ self.assertTrue(
+ BlockImageDiff.FileTypeSupportedByImgdiff(
+ "/system/priv-app/Settings/Settings.apk"))
+ self.assertTrue(
+ BlockImageDiff.FileTypeSupportedByImgdiff(
+ "/system/framework/am.jar"))
+ self.assertTrue(
+ BlockImageDiff.FileTypeSupportedByImgdiff(
+ "/system/etc/security/otacerts.zip"))
+
+ self.assertFalse(
+ BlockImageDiff.FileTypeSupportedByImgdiff(
+ "/system/framework/arm/boot.oat"))
+ self.assertFalse(
+ BlockImageDiff.FileTypeSupportedByImgdiff(
+ "/system/priv-app/notanapk"))
+
+ def test_CanUseImgdiff(self):
+ block_image_diff = BlockImageDiff(EmptyImage(), EmptyImage())
+ self.assertTrue(
+ block_image_diff.CanUseImgdiff(
+ "/system/app/app1.apk", RangeSet("10-15"), RangeSet("0-5")))
+ self.assertTrue(
+ block_image_diff.CanUseImgdiff(
+ "/vendor/app/app2.apk", RangeSet("20 25"), RangeSet("30-31"), True))
+
+ self.assertDictEqual(
+ {
+ ImgdiffStats.USED_IMGDIFF : {"/system/app/app1.apk"},
+ ImgdiffStats.USED_IMGDIFF_LARGE_APK : {"/vendor/app/app2.apk"},
+ },
+ block_image_diff.imgdiff_stats.stats)
+
+
+ def test_CanUseImgdiff_ineligible(self):
+ # Disabled by caller.
+ block_image_diff = BlockImageDiff(EmptyImage(), EmptyImage(),
+ disable_imgdiff=True)
+ self.assertFalse(
+ block_image_diff.CanUseImgdiff(
+ "/system/app/app1.apk", RangeSet("10-15"), RangeSet("0-5")))
+
+ # Unsupported file type.
+ block_image_diff = BlockImageDiff(EmptyImage(), EmptyImage())
+ self.assertFalse(
+ block_image_diff.CanUseImgdiff(
+ "/system/bin/gzip", RangeSet("10-15"), RangeSet("0-5")))
+
+ # At least one of the ranges is in non-monotonic order.
+ self.assertFalse(
+ block_image_diff.CanUseImgdiff(
+ "/system/app/app2.apk", RangeSet("10-15"),
+ RangeSet("15-20 30 10-14")))
+
+ # At least one of the ranges has been modified.
+ src_ranges = RangeSet("0-5")
+ src_ranges.extra['trimmed'] = True
+ self.assertFalse(
+ block_image_diff.CanUseImgdiff(
+ "/vendor/app/app3.apk", RangeSet("10-15"), src_ranges))
+
+ # At least one of the ranges is incomplete.
+ src_ranges = RangeSet("0-5")
+ src_ranges.extra['incomplete'] = True
+ self.assertFalse(
+ block_image_diff.CanUseImgdiff(
+ "/vendor/app/app4.apk", RangeSet("10-15"), src_ranges))
+
+ # The stats are correctly logged.
+ self.assertDictEqual(
+ {
+ ImgdiffStats.SKIPPED_NONMONOTONIC : {'/system/app/app2.apk'},
+ ImgdiffStats.SKIPPED_TRIMMED : {'/vendor/app/app3.apk'},
+ ImgdiffStats.SKIPPED_INCOMPLETE: {'/vendor/app/app4.apk'},
+ },
+ block_image_diff.imgdiff_stats.stats)
+
+
+class ImgdiffStatsTest(unittest.TestCase):
+
+ def test_Log(self):
+ imgdiff_stats = ImgdiffStats()
+ imgdiff_stats.Log("/system/app/app2.apk", ImgdiffStats.USED_IMGDIFF)
+ self.assertDictEqual(
+ {
+ ImgdiffStats.USED_IMGDIFF: {'/system/app/app2.apk'},
+ },
+ imgdiff_stats.stats)
+
+ def test_Log_invalidInputs(self):
+ imgdiff_stats = ImgdiffStats()
+
+ self.assertRaises(AssertionError, imgdiff_stats.Log, "/system/bin/gzip",
+ ImgdiffStats.USED_IMGDIFF)
+
+ self.assertRaises(AssertionError, imgdiff_stats.Log, "/system/app/app1.apk",
+ "invalid reason")
diff --git a/tools/releasetools/test_build_image.py b/tools/releasetools/test_build_image.py
new file mode 100644
index 0000000..161faff
--- /dev/null
+++ b/tools/releasetools/test_build_image.py
@@ -0,0 +1,94 @@
+#
+# 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.
+#
+
+import unittest
+
+import common
+from build_image import CheckHeadroom, RunCommand
+
+
+class BuildImageTest(unittest.TestCase):
+
+ # Available: 1000 blocks.
+ EXT4FS_OUTPUT = (
+ "Created filesystem with 2777/129024 inodes and 515099/516099 blocks")
+
+ def test_CheckHeadroom_SizeUnderLimit(self):
+ # Required headroom: 1000 blocks.
+ prop_dict = {
+ 'fs_type' : 'ext4',
+ 'partition_headroom' : '4096000',
+ 'mount_point' : 'system',
+ }
+ self.assertTrue(CheckHeadroom(self.EXT4FS_OUTPUT, prop_dict))
+
+ def test_CheckHeadroom_InsufficientHeadroom(self):
+ # Required headroom: 1001 blocks.
+ prop_dict = {
+ 'fs_type' : 'ext4',
+ 'partition_headroom' : '4100096',
+ 'mount_point' : 'system',
+ }
+ self.assertFalse(CheckHeadroom(self.EXT4FS_OUTPUT, prop_dict))
+
+ def test_CheckHeadroom_WrongFsType(self):
+ prop_dict = {
+ 'fs_type' : 'f2fs',
+ 'partition_headroom' : '4100096',
+ 'mount_point' : 'system',
+ }
+ self.assertRaises(
+ AssertionError, CheckHeadroom, self.EXT4FS_OUTPUT, prop_dict)
+
+ def test_CheckHeadroom_MissingProperties(self):
+ prop_dict = {
+ 'fs_type' : 'ext4',
+ 'partition_headroom' : '4100096',
+ }
+ self.assertRaises(
+ AssertionError, CheckHeadroom, self.EXT4FS_OUTPUT, prop_dict)
+
+ prop_dict = {
+ 'fs_type' : 'ext4',
+ 'mount_point' : 'system',
+ }
+ self.assertRaises(
+ AssertionError, CheckHeadroom, self.EXT4FS_OUTPUT, prop_dict)
+
+ def test_CheckHeadroom_WithMke2fsOutput(self):
+ """Tests the result parsing from actual call to mke2fs."""
+ input_dir = common.MakeTempDir()
+ output_image = common.MakeTempFile(suffix='.img')
+ command = ['mkuserimg_mke2fs.sh', input_dir, output_image, 'ext4',
+ '/system', '409600', '-j', '0']
+ ext4fs_output, exit_code = RunCommand(command)
+ self.assertEqual(0, exit_code)
+
+ prop_dict = {
+ 'fs_type' : 'ext4',
+ 'partition_headroom' : '40960',
+ 'mount_point' : 'system',
+ }
+ self.assertTrue(CheckHeadroom(ext4fs_output, prop_dict))
+
+ prop_dict = {
+ 'fs_type' : 'ext4',
+ 'partition_headroom' : '413696',
+ 'mount_point' : 'system',
+ }
+ self.assertFalse(CheckHeadroom(ext4fs_output, prop_dict))
+
+ common.Cleanup()
diff --git a/tools/releasetools/test_common.py b/tools/releasetools/test_common.py
index 36f256d..fb26b66 100644
--- a/tools/releasetools/test_common.py
+++ b/tools/releasetools/test_common.py
@@ -13,39 +13,38 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
+
import os
-import shutil
+import subprocess
import tempfile
import time
import unittest
import zipfile
+from hashlib import sha1
import common
+import test_utils
import validate_target_files
+from rangelib import RangeSet
-def random_string_with_holes(size, block_size, step_size):
- data = ["\0"] * size
- for begin in range(0, size, step_size):
- end = begin + block_size
- data[begin:end] = os.urandom(block_size)
- return "".join(data)
+KiB = 1024
+MiB = 1024 * KiB
+GiB = 1024 * MiB
+
def get_2gb_string():
- kilobytes = 1024
- megabytes = 1024 * kilobytes
- gigabytes = 1024 * megabytes
-
- size = int(2 * gigabytes + 1)
- block_size = 4 * kilobytes
- step_size = 4 * megabytes
- two_gb_string = random_string_with_holes(
- size, block_size, step_size)
- return two_gb_string
+ size = int(2 * GiB + 1)
+ block_size = 4 * KiB
+ step_size = 4 * MiB
+ # Generate a long string with holes, e.g. 'xyz\x00abc\x00...'.
+ for _ in range(0, size, step_size):
+ yield os.urandom(block_size)
+ yield '\0' * (step_size - block_size)
class CommonZipTest(unittest.TestCase):
- def _verify(self, zip_file, zip_file_name, arcname, contents,
+ def _verify(self, zip_file, zip_file_name, arcname, expected_hash,
test_file_name=None, expected_stat=None, expected_mode=0o644,
expected_compress_type=zipfile.ZIP_STORED):
# Verify the stat if present.
@@ -69,7 +68,11 @@
self.assertEqual(info.compress_type, expected_compress_type)
# Verify the zip contents.
- self.assertEqual(zip_file.read(arcname), contents)
+ entry = zip_file.open(arcname)
+ sha1_hash = sha1()
+ for chunk in iter(lambda: entry.read(4 * MiB), ''):
+ sha1_hash.update(chunk)
+ self.assertEqual(expected_hash, sha1_hash.hexdigest())
self.assertIsNone(zip_file.testzip())
def _test_ZipWrite(self, contents, extra_zipwrite_args=None):
@@ -90,7 +93,10 @@
zip_file = zipfile.ZipFile(zip_file_name, "w")
try:
- test_file.write(contents)
+ sha1_hash = sha1()
+ for data in contents:
+ sha1_hash.update(data)
+ test_file.write(data)
test_file.close()
expected_stat = os.stat(test_file_name)
@@ -102,8 +108,9 @@
common.ZipWrite(zip_file, test_file_name, **extra_zipwrite_args)
common.ZipClose(zip_file)
- self._verify(zip_file, zip_file_name, arcname, contents, test_file_name,
- expected_stat, expected_mode, expected_compress_type)
+ self._verify(zip_file, zip_file_name, arcname, sha1_hash.hexdigest(),
+ test_file_name, expected_stat, expected_mode,
+ expected_compress_type)
finally:
os.remove(test_file_name)
os.remove(zip_file_name)
@@ -133,7 +140,7 @@
common.ZipWriteStr(zip_file, zinfo_or_arcname, contents, **extra_args)
common.ZipClose(zip_file)
- self._verify(zip_file, zip_file_name, arcname, contents,
+ self._verify(zip_file, zip_file_name, arcname, sha1(contents).hexdigest(),
expected_mode=expected_mode,
expected_compress_type=expected_compress_type)
finally:
@@ -159,7 +166,10 @@
zip_file = zipfile.ZipFile(zip_file_name, "w")
try:
- test_file.write(large)
+ sha1_hash = sha1()
+ for data in large:
+ sha1_hash.update(data)
+ test_file.write(data)
test_file.close()
expected_stat = os.stat(test_file_name)
@@ -173,12 +183,13 @@
common.ZipClose(zip_file)
# Verify the contents written by ZipWrite().
- self._verify(zip_file, zip_file_name, arcname_large, large,
- test_file_name, expected_stat, expected_mode,
- expected_compress_type)
+ self._verify(zip_file, zip_file_name, arcname_large,
+ sha1_hash.hexdigest(), test_file_name, expected_stat,
+ expected_mode, expected_compress_type)
# Verify the contents written by ZipWriteStr().
- self._verify(zip_file, zip_file_name, arcname_small, small,
+ self._verify(zip_file, zip_file_name, arcname_small,
+ sha1(small).hexdigest(),
expected_compress_type=expected_compress_type)
finally:
os.remove(zip_file_name)
@@ -287,31 +298,379 @@
common.ZipWriteStr(zip_file, zinfo, random_string, perms=0o400)
common.ZipClose(zip_file)
- self._verify(zip_file, zip_file_name, "foo", random_string,
+ self._verify(zip_file, zip_file_name, "foo",
+ sha1(random_string).hexdigest(),
expected_mode=0o644)
- self._verify(zip_file, zip_file_name, "bar", random_string,
+ self._verify(zip_file, zip_file_name, "bar",
+ sha1(random_string).hexdigest(),
expected_mode=0o755)
- self._verify(zip_file, zip_file_name, "baz", random_string,
+ self._verify(zip_file, zip_file_name, "baz",
+ sha1(random_string).hexdigest(),
expected_mode=0o740)
- self._verify(zip_file, zip_file_name, "qux", random_string,
+ self._verify(zip_file, zip_file_name, "qux",
+ sha1(random_string).hexdigest(),
expected_mode=0o400)
finally:
os.remove(zip_file_name)
-class InstallRecoveryScriptFormatTest(unittest.TestCase):
- """Check the format of install-recovery.sh
+ def test_ZipDelete(self):
+ zip_file = tempfile.NamedTemporaryFile(delete=False, suffix='.zip')
+ output_zip = zipfile.ZipFile(zip_file.name, 'w',
+ compression=zipfile.ZIP_DEFLATED)
+ with tempfile.NamedTemporaryFile() as entry_file:
+ entry_file.write(os.urandom(1024))
+ common.ZipWrite(output_zip, entry_file.name, arcname='Test1')
+ common.ZipWrite(output_zip, entry_file.name, arcname='Test2')
+ common.ZipWrite(output_zip, entry_file.name, arcname='Test3')
+ common.ZipClose(output_zip)
+ zip_file.close()
- Its format should match between common.py and validate_target_files.py."""
+ try:
+ common.ZipDelete(zip_file.name, 'Test2')
+ with zipfile.ZipFile(zip_file.name, 'r') as check_zip:
+ entries = check_zip.namelist()
+ self.assertTrue('Test1' in entries)
+ self.assertFalse('Test2' in entries)
+ self.assertTrue('Test3' in entries)
+
+ self.assertRaises(AssertionError, common.ZipDelete, zip_file.name,
+ 'Test2')
+ with zipfile.ZipFile(zip_file.name, 'r') 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:
+ 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:
+ entries = check_zip.namelist()
+ self.assertFalse('Test1' in entries)
+ self.assertFalse('Test2' in entries)
+ self.assertFalse('Test3' in entries)
+ finally:
+ os.remove(zip_file.name)
+
+
+class CommonApkUtilsTest(unittest.TestCase):
+ """Tests the APK utils related functions."""
+
+ APKCERTS_TXT1 = (
+ 'name="RecoveryLocalizer.apk" certificate="certs/devkey.x509.pem"'
+ ' private_key="certs/devkey.pk8"\n'
+ 'name="Settings.apk"'
+ ' certificate="build/target/product/security/platform.x509.pem"'
+ ' private_key="build/target/product/security/platform.pk8"\n'
+ 'name="TV.apk" certificate="PRESIGNED" private_key=""\n'
+ )
+
+ APKCERTS_CERTMAP1 = {
+ 'RecoveryLocalizer.apk' : 'certs/devkey',
+ 'Settings.apk' : 'build/target/product/security/platform',
+ 'TV.apk' : 'PRESIGNED',
+ }
+
+ APKCERTS_TXT2 = (
+ 'name="Compressed1.apk" certificate="certs/compressed1.x509.pem"'
+ ' private_key="certs/compressed1.pk8" compressed="gz"\n'
+ 'name="Compressed2a.apk" certificate="certs/compressed2.x509.pem"'
+ ' private_key="certs/compressed2.pk8" compressed="gz"\n'
+ 'name="Compressed2b.apk" certificate="certs/compressed2.x509.pem"'
+ ' private_key="certs/compressed2.pk8" compressed="gz"\n'
+ 'name="Compressed3.apk" certificate="certs/compressed3.x509.pem"'
+ ' private_key="certs/compressed3.pk8" compressed="gz"\n'
+ )
+
+ APKCERTS_CERTMAP2 = {
+ 'Compressed1.apk' : 'certs/compressed1',
+ 'Compressed2a.apk' : 'certs/compressed2',
+ 'Compressed2b.apk' : 'certs/compressed2',
+ 'Compressed3.apk' : 'certs/compressed3',
+ }
+
+ APKCERTS_TXT3 = (
+ 'name="Compressed4.apk" certificate="certs/compressed4.x509.pem"'
+ ' private_key="certs/compressed4.pk8" compressed="xz"\n'
+ )
+
+ APKCERTS_CERTMAP3 = {
+ 'Compressed4.apk' : 'certs/compressed4',
+ }
def setUp(self):
- self._tempdir = tempfile.mkdtemp()
+ self.testdata_dir = test_utils.get_testdata_dir()
+
+ def tearDown(self):
+ common.Cleanup()
+
+ @staticmethod
+ def _write_apkcerts_txt(apkcerts_txt, additional=None):
+ if additional is None:
+ additional = []
+ target_files = common.MakeTempFile(suffix='.zip')
+ with zipfile.ZipFile(target_files, 'w') as target_files_zip:
+ target_files_zip.writestr('META/apkcerts.txt', apkcerts_txt)
+ for entry in additional:
+ target_files_zip.writestr(entry, '')
+ return target_files
+
+ def test_ReadApkCerts_NoncompressedApks(self):
+ target_files = self._write_apkcerts_txt(self.APKCERTS_TXT1)
+ with zipfile.ZipFile(target_files, 'r') as input_zip:
+ certmap, ext = common.ReadApkCerts(input_zip)
+
+ self.assertDictEqual(self.APKCERTS_CERTMAP1, certmap)
+ self.assertIsNone(ext)
+
+ def test_ReadApkCerts_CompressedApks(self):
+ # We have "installed" Compressed1.apk.gz only. Note that Compressed3.apk is
+ # not stored in '.gz' format, so it shouldn't be considered as installed.
+ target_files = self._write_apkcerts_txt(
+ self.APKCERTS_TXT2,
+ ['Compressed1.apk.gz', 'Compressed3.apk'])
+
+ with zipfile.ZipFile(target_files, 'r') as input_zip:
+ certmap, ext = common.ReadApkCerts(input_zip)
+
+ self.assertDictEqual(self.APKCERTS_CERTMAP2, certmap)
+ self.assertEqual('.gz', ext)
+
+ # Alternative case with '.xz'.
+ target_files = self._write_apkcerts_txt(
+ self.APKCERTS_TXT3, ['Compressed4.apk.xz'])
+
+ with zipfile.ZipFile(target_files, 'r') as input_zip:
+ certmap, ext = common.ReadApkCerts(input_zip)
+
+ self.assertDictEqual(self.APKCERTS_CERTMAP3, certmap)
+ self.assertEqual('.xz', ext)
+
+ def test_ReadApkCerts_CompressedAndNoncompressedApks(self):
+ target_files = self._write_apkcerts_txt(
+ self.APKCERTS_TXT1 + self.APKCERTS_TXT2,
+ ['Compressed1.apk.gz', 'Compressed3.apk'])
+
+ with zipfile.ZipFile(target_files, 'r') as input_zip:
+ certmap, ext = common.ReadApkCerts(input_zip)
+
+ certmap_merged = self.APKCERTS_CERTMAP1.copy()
+ certmap_merged.update(self.APKCERTS_CERTMAP2)
+ self.assertDictEqual(certmap_merged, certmap)
+ self.assertEqual('.gz', ext)
+
+ def test_ReadApkCerts_MultipleCompressionMethods(self):
+ target_files = self._write_apkcerts_txt(
+ self.APKCERTS_TXT2 + self.APKCERTS_TXT3,
+ ['Compressed1.apk.gz', 'Compressed4.apk.xz'])
+
+ with zipfile.ZipFile(target_files, 'r') as input_zip:
+ self.assertRaises(ValueError, common.ReadApkCerts, input_zip)
+
+ def test_ReadApkCerts_MismatchingKeys(self):
+ malformed_apkcerts_txt = (
+ 'name="App1.apk" certificate="certs/cert1.x509.pem"'
+ ' private_key="certs/cert2.pk8"\n'
+ )
+ target_files = self._write_apkcerts_txt(malformed_apkcerts_txt)
+
+ with zipfile.ZipFile(target_files, 'r') as input_zip:
+ self.assertRaises(ValueError, common.ReadApkCerts, input_zip)
+
+ def test_ExtractPublicKey(self):
+ cert = os.path.join(self.testdata_dir, 'testkey.x509.pem')
+ pubkey = os.path.join(self.testdata_dir, 'testkey.pubkey.pem')
+ with open(pubkey, 'rb') as pubkey_fp:
+ self.assertEqual(pubkey_fp.read(), common.ExtractPublicKey(cert))
+
+ def test_ExtractPublicKey_invalidInput(self):
+ wrong_input = os.path.join(self.testdata_dir, 'testkey.pk8')
+ self.assertRaises(AssertionError, common.ExtractPublicKey, wrong_input)
+
+ def test_ParseCertificate(self):
+ cert = os.path.join(self.testdata_dir, 'testkey.x509.pem')
+
+ cmd = ['openssl', 'x509', '-in', cert, '-outform', 'DER']
+ proc = common.Run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ expected, _ = proc.communicate()
+ self.assertEqual(0, proc.returncode)
+
+ with open(cert) as cert_fp:
+ actual = common.ParseCertificate(cert_fp.read())
+ self.assertEqual(expected, actual)
+
+
+class CommonUtilsTest(unittest.TestCase):
+
+ def tearDown(self):
+ common.Cleanup()
+
+ def test_GetSparseImage_emptyBlockMapFile(self):
+ target_files = common.MakeTempFile(prefix='target_files-', suffix='.zip')
+ with zipfile.ZipFile(target_files, 'w') as target_files_zip:
+ target_files_zip.write(
+ test_utils.construct_sparse_image([
+ (0xCAC1, 6),
+ (0xCAC3, 3),
+ (0xCAC1, 4)]),
+ arcname='IMAGES/system.img')
+ target_files_zip.writestr('IMAGES/system.map', '')
+ target_files_zip.writestr('SYSTEM/file1', os.urandom(4096 * 8))
+ target_files_zip.writestr('SYSTEM/file2', os.urandom(4096 * 3))
+
+ tempdir = common.UnzipTemp(target_files)
+ with zipfile.ZipFile(target_files, 'r') as input_zip:
+ sparse_image = common.GetSparseImage('system', tempdir, input_zip, False)
+
+ self.assertDictEqual(
+ {
+ '__COPY': RangeSet("0"),
+ '__NONZERO-0': RangeSet("1-5 9-12"),
+ },
+ sparse_image.file_map)
+
+ def test_GetSparseImage_invalidImageName(self):
+ self.assertRaises(
+ AssertionError, common.GetSparseImage, 'system2', None, None, False)
+ self.assertRaises(
+ AssertionError, common.GetSparseImage, 'unknown', None, None, False)
+
+ def test_GetSparseImage_missingBlockMapFile(self):
+ target_files = common.MakeTempFile(prefix='target_files-', suffix='.zip')
+ with zipfile.ZipFile(target_files, 'w') as target_files_zip:
+ target_files_zip.write(
+ test_utils.construct_sparse_image([
+ (0xCAC1, 6),
+ (0xCAC3, 3),
+ (0xCAC1, 4)]),
+ arcname='IMAGES/system.img')
+ target_files_zip.writestr('SYSTEM/file1', os.urandom(4096 * 8))
+ target_files_zip.writestr('SYSTEM/file2', os.urandom(4096 * 3))
+
+ tempdir = common.UnzipTemp(target_files)
+ with zipfile.ZipFile(target_files, 'r') as input_zip:
+ self.assertRaises(
+ AssertionError, common.GetSparseImage, 'system', tempdir, input_zip,
+ False)
+
+ 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:
+ target_files_zip.write(
+ test_utils.construct_sparse_image([(0xCAC2, 16)]),
+ arcname='IMAGES/system.img')
+ # Block 10 is shared between two files.
+ target_files_zip.writestr(
+ 'IMAGES/system.map',
+ '\n'.join([
+ '/system/file1 1-5 9-10',
+ '/system/file2 10-12']))
+ target_files_zip.writestr('SYSTEM/file1', os.urandom(4096 * 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:
+ self.assertRaises(
+ AssertionError, common.GetSparseImage, 'system', tempdir, input_zip,
+ False)
+
+ 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:
+ # Construct an image with a care_map of "0-5 9-12".
+ target_files_zip.write(
+ test_utils.construct_sparse_image([(0xCAC2, 16)]),
+ arcname='IMAGES/system.img')
+ # Block 10 is shared between two files.
+ target_files_zip.writestr(
+ 'IMAGES/system.map',
+ '\n'.join([
+ '/system/file1 1-5 9-10',
+ '/system/file2 10-12']))
+ target_files_zip.writestr('SYSTEM/file1', os.urandom(4096 * 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:
+ sparse_image = common.GetSparseImage('system', tempdir, input_zip, True)
+
+ self.assertDictEqual(
+ {
+ '__COPY': RangeSet("0"),
+ '__NONZERO-0': RangeSet("6-8 13-15"),
+ '/system/file1': RangeSet("1-5 9-10"),
+ '/system/file2': RangeSet("11-12"),
+ },
+ sparse_image.file_map)
+
+ # '/system/file2' should be marked with 'uses_shared_blocks', but not with
+ # 'incomplete'.
+ self.assertTrue(
+ sparse_image.file_map['/system/file2'].extra['uses_shared_blocks'])
+ self.assertNotIn(
+ 'incomplete', sparse_image.file_map['/system/file2'].extra)
+
+ # All other entries should look normal without any tags.
+ self.assertFalse(sparse_image.file_map['__COPY'].extra)
+ self.assertFalse(sparse_image.file_map['__NONZERO-0'].extra)
+ self.assertFalse(sparse_image.file_map['/system/file1'].extra)
+
+ 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:
+ target_files_zip.write(
+ test_utils.construct_sparse_image([(0xCAC2, 16)]),
+ arcname='IMAGES/system.img')
+ target_files_zip.writestr(
+ 'IMAGES/system.map',
+ '\n'.join([
+ '/system/file1 1-5 9-10',
+ '/system/file2 11-12']))
+ target_files_zip.writestr('SYSTEM/file1', os.urandom(4096 * 7))
+ # '/system/file2' has less blocks listed (2) than actual (3).
+ target_files_zip.writestr('SYSTEM/file2', os.urandom(4096 * 3))
+
+ tempdir = common.UnzipTemp(target_files)
+ with zipfile.ZipFile(target_files, 'r') as input_zip:
+ sparse_image = common.GetSparseImage('system', tempdir, input_zip, False)
+
+ self.assertFalse(sparse_image.file_map['/system/file1'].extra)
+ self.assertTrue(sparse_image.file_map['/system/file2'].extra['incomplete'])
+
+
+class InstallRecoveryScriptFormatTest(unittest.TestCase):
+ """Checks the format of install-recovery.sh.
+
+ Its format should match between common.py and validate_target_files.py.
+ """
+
+ def setUp(self):
+ self._tempdir = common.MakeTempDir()
# Create a dummy dict that contains the fstab info for boot&recovery.
self._info = {"fstab" : {}}
- dummy_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(lambda x : "\n".join(x),
- 2, dummy_fstab)
+ dummy_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)
+ # Construct the gzipped recovery.img and boot.img
+ self.recovery_data = bytearray([
+ 0x1f, 0x8b, 0x08, 0x00, 0x81, 0x11, 0x02, 0x5a, 0x00, 0x03, 0x2b, 0x4a,
+ 0x4d, 0xce, 0x2f, 0x4b, 0x2d, 0xaa, 0x04, 0x00, 0xc9, 0x93, 0x43, 0xf3,
+ 0x08, 0x00, 0x00, 0x00
+ ])
+ # echo -n "boot" | gzip -f | hd
+ self.boot_data = bytearray([
+ 0x1f, 0x8b, 0x08, 0x00, 0x8c, 0x12, 0x02, 0x5a, 0x00, 0x03, 0x4b, 0xca,
+ 0xcf, 0x2f, 0x01, 0x00, 0xc4, 0xae, 0xed, 0x46, 0x04, 0x00, 0x00, 0x00
+ ])
def _out_tmp_sink(self, name, data, prefix="SYSTEM"):
loc = os.path.join(self._tempdir, prefix, name)
@@ -321,8 +680,8 @@
f.write(data)
def test_full_recovery(self):
- recovery_image = common.File("recovery.img", "recovery");
- boot_image = common.File("boot.img", "boot");
+ recovery_image = common.File("recovery.img", self.recovery_data)
+ boot_image = common.File("boot.img", self.boot_data)
self._info["full_recovery_image"] = "true"
common.MakeRecoveryPatch(self._tempdir, self._out_tmp_sink,
@@ -331,9 +690,9 @@
self._info)
def test_recovery_from_boot(self):
- recovery_image = common.File("recovery.img", "recovery");
+ recovery_image = common.File("recovery.img", self.recovery_data)
self._out_tmp_sink("recovery.img", recovery_image.data, "IMAGES")
- boot_image = common.File("boot.img", "boot");
+ boot_image = common.File("boot.img", self.boot_data)
self._out_tmp_sink("boot.img", boot_image.data, "IMAGES")
common.MakeRecoveryPatch(self._tempdir, self._out_tmp_sink,
@@ -348,4 +707,4 @@
self._info)
def tearDown(self):
- shutil.rmtree(self._tempdir)
+ common.Cleanup()
diff --git a/tools/releasetools/test_ota_from_target_files.py b/tools/releasetools/test_ota_from_target_files.py
new file mode 100644
index 0000000..262e701
--- /dev/null
+++ b/tools/releasetools/test_ota_from_target_files.py
@@ -0,0 +1,1336 @@
+#
+# 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.
+#
+
+import copy
+import os
+import os.path
+import subprocess
+import unittest
+import zipfile
+
+import common
+import test_utils
+from ota_from_target_files import (
+ _LoadOemDicts, AbOtaPropertyFiles, BuildInfo, FinalizeMetadata,
+ GetPackageMetadata, GetTargetFilesZipForSecondaryImages,
+ GetTargetFilesZipWithoutPostinstallConfig, NonAbOtaPropertyFiles,
+ Payload, PayloadSigner, POSTINSTALL_CONFIG, PropertyFiles,
+ StreamingPropertyFiles, WriteFingerprintAssertion)
+
+
+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:
+ # META/update_engine_config.txt
+ target_files_zip.writestr(
+ 'META/update_engine_config.txt',
+ "PAYLOAD_MAJOR_VERSION=2\nPAYLOAD_MINOR_VERSION=4\n")
+
+ # META/postinstall_config.txt
+ target_files_zip.writestr(
+ POSTINSTALL_CONFIG,
+ '\n'.join([
+ "RUN_POSTINSTALL_system=true",
+ "POSTINSTALL_PATH_system=system/bin/otapreopt_script",
+ "FILESYSTEM_TYPE_system=ext4",
+ "POSTINSTALL_OPTIONAL_system=true",
+ ]))
+
+ # META/ab_partitions.txt
+ ab_partitions = ['boot', 'system', 'vendor']
+ target_files_zip.writestr(
+ 'META/ab_partitions.txt',
+ '\n'.join(ab_partitions))
+
+ # Create dummy images for each of them.
+ for partition in ab_partitions:
+ target_files_zip.writestr('IMAGES/' + partition + '.img',
+ os.urandom(len(partition)))
+
+ if secondary:
+ target_files_zip.writestr('IMAGES/system_other.img',
+ os.urandom(len("system_other")))
+
+ return target_files
+
+
+class MockScriptWriter(object):
+ """A class that mocks edify_generator.EdifyGenerator.
+
+ It simply pushes the incoming arguments onto script stack, which is to assert
+ the calls to EdifyGenerator functions.
+ """
+
+ def __init__(self):
+ self.script = []
+
+ def Mount(self, *args):
+ self.script.append(('Mount',) + args)
+
+ def AssertDevice(self, *args):
+ self.script.append(('AssertDevice',) + args)
+
+ def AssertOemProperty(self, *args):
+ self.script.append(('AssertOemProperty',) + args)
+
+ def AssertFingerprintOrThumbprint(self, *args):
+ self.script.append(('AssertFingerprintOrThumbprint',) + args)
+
+ def AssertSomeFingerprint(self, *args):
+ self.script.append(('AssertSomeFingerprint',) + args)
+
+ def AssertSomeThumbprint(self, *args):
+ self.script.append(('AssertSomeThumbprint',) + args)
+
+
+class BuildInfoTest(unittest.TestCase):
+
+ TEST_INFO_DICT = {
+ 'build.prop' : {
+ 'ro.product.device' : 'product-device',
+ 'ro.product.name' : 'product-name',
+ 'ro.build.fingerprint' : 'build-fingerprint',
+ 'ro.build.foo' : 'build-foo',
+ },
+ 'vendor.build.prop' : {
+ 'ro.vendor.build.fingerprint' : 'vendor-build-fingerprint',
+ },
+ 'property1' : 'value1',
+ 'property2' : 4096,
+ }
+
+ TEST_INFO_DICT_USES_OEM_PROPS = {
+ 'build.prop' : {
+ 'ro.product.name' : 'product-name',
+ 'ro.build.thumbprint' : 'build-thumbprint',
+ 'ro.build.bar' : 'build-bar',
+ },
+ 'vendor.build.prop' : {
+ '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_init(self):
+ target_info = BuildInfo(self.TEST_INFO_DICT, None)
+ self.assertEqual('product-device', target_info.device)
+ self.assertEqual('build-fingerprint', target_info.fingerprint)
+ self.assertFalse(target_info.is_ab)
+ self.assertIsNone(target_info.oem_props)
+
+ def test_init_with_oem_props(self):
+ target_info = BuildInfo(self.TEST_INFO_DICT_USES_OEM_PROPS,
+ self.TEST_OEM_DICTS)
+ self.assertEqual('device1', target_info.device)
+ self.assertEqual('brand1/product-name/device1:build-thumbprint',
+ target_info.fingerprint)
+
+ # Swap the order in oem_dicts, which would lead to different BuildInfo.
+ oem_dicts = copy.copy(self.TEST_OEM_DICTS)
+ oem_dicts[0], oem_dicts[2] = oem_dicts[2], oem_dicts[0]
+ target_info = BuildInfo(self.TEST_INFO_DICT_USES_OEM_PROPS, oem_dicts)
+ self.assertEqual('device3', target_info.device)
+ self.assertEqual('brand3/product-name/device3:build-thumbprint',
+ target_info.fingerprint)
+
+ # Missing oem_dict should be rejected.
+ self.assertRaises(AssertionError, BuildInfo,
+ self.TEST_INFO_DICT_USES_OEM_PROPS, None)
+
+ def test___getitem__(self):
+ target_info = BuildInfo(self.TEST_INFO_DICT, None)
+ self.assertEqual('value1', target_info['property1'])
+ self.assertEqual(4096, target_info['property2'])
+ self.assertEqual('build-foo', target_info['build.prop']['ro.build.foo'])
+
+ def test___getitem__with_oem_props(self):
+ target_info = BuildInfo(self.TEST_INFO_DICT_USES_OEM_PROPS,
+ self.TEST_OEM_DICTS)
+ self.assertEqual('value1', target_info['property1'])
+ self.assertEqual(4096, target_info['property2'])
+ self.assertRaises(KeyError,
+ lambda: target_info['build.prop']['ro.build.foo'])
+
+ def test_get(self):
+ target_info = BuildInfo(self.TEST_INFO_DICT, None)
+ self.assertEqual('value1', target_info.get('property1'))
+ self.assertEqual(4096, target_info.get('property2'))
+ self.assertEqual(4096, target_info.get('property2', 1024))
+ self.assertEqual(1024, target_info.get('property-nonexistent', 1024))
+ self.assertEqual('build-foo', target_info.get('build.prop')['ro.build.foo'])
+
+ def test_get_with_oem_props(self):
+ target_info = BuildInfo(self.TEST_INFO_DICT_USES_OEM_PROPS,
+ self.TEST_OEM_DICTS)
+ self.assertEqual('value1', target_info.get('property1'))
+ self.assertEqual(4096, target_info.get('property2'))
+ self.assertEqual(4096, target_info.get('property2', 1024))
+ self.assertEqual(1024, target_info.get('property-nonexistent', 1024))
+ self.assertIsNone(target_info.get('build.prop').get('ro.build.foo'))
+ self.assertRaises(KeyError,
+ lambda: target_info.get('build.prop')['ro.build.foo'])
+
+ def test_GetBuildProp(self):
+ target_info = BuildInfo(self.TEST_INFO_DICT, None)
+ self.assertEqual('build-foo', target_info.GetBuildProp('ro.build.foo'))
+ self.assertRaises(common.ExternalError, target_info.GetBuildProp,
+ 'ro.build.nonexistent')
+
+ def test_GetBuildProp_with_oem_props(self):
+ target_info = BuildInfo(self.TEST_INFO_DICT_USES_OEM_PROPS,
+ self.TEST_OEM_DICTS)
+ self.assertEqual('build-bar', target_info.GetBuildProp('ro.build.bar'))
+ self.assertRaises(common.ExternalError, target_info.GetBuildProp,
+ 'ro.build.nonexistent')
+
+ def test_GetVendorBuildProp(self):
+ target_info = BuildInfo(self.TEST_INFO_DICT, None)
+ self.assertEqual('vendor-build-fingerprint',
+ target_info.GetVendorBuildProp(
+ 'ro.vendor.build.fingerprint'))
+ self.assertRaises(common.ExternalError, target_info.GetVendorBuildProp,
+ 'ro.build.nonexistent')
+
+ def test_GetVendorBuildProp_with_oem_props(self):
+ target_info = BuildInfo(self.TEST_INFO_DICT_USES_OEM_PROPS,
+ self.TEST_OEM_DICTS)
+ self.assertEqual('vendor-build-fingerprint',
+ target_info.GetVendorBuildProp(
+ 'ro.vendor.build.fingerprint'))
+ self.assertRaises(common.ExternalError, target_info.GetVendorBuildProp,
+ 'ro.build.nonexistent')
+
+ def test_WriteMountOemScript(self):
+ target_info = BuildInfo(self.TEST_INFO_DICT_USES_OEM_PROPS,
+ self.TEST_OEM_DICTS)
+ script_writer = MockScriptWriter()
+ target_info.WriteMountOemScript(script_writer)
+ self.assertEqual([('Mount', '/oem', None)], script_writer.script)
+
+ def test_WriteDeviceAssertions(self):
+ target_info = BuildInfo(self.TEST_INFO_DICT, None)
+ script_writer = MockScriptWriter()
+ target_info.WriteDeviceAssertions(script_writer, False)
+ self.assertEqual([('AssertDevice', 'product-device')], script_writer.script)
+
+ def test_WriteDeviceAssertions_with_oem_props(self):
+ target_info = BuildInfo(self.TEST_INFO_DICT_USES_OEM_PROPS,
+ self.TEST_OEM_DICTS)
+ script_writer = MockScriptWriter()
+ target_info.WriteDeviceAssertions(script_writer, False)
+ self.assertEqual(
+ [
+ ('AssertOemProperty', 'ro.product.device',
+ ['device1', 'device2', 'device3'], False),
+ ('AssertOemProperty', 'ro.product.brand',
+ ['brand1', 'brand2', 'brand3'], False),
+ ],
+ script_writer.script)
+
+ def test_WriteFingerprintAssertion_without_oem_props(self):
+ target_info = BuildInfo(self.TEST_INFO_DICT, None)
+ source_info_dict = copy.deepcopy(self.TEST_INFO_DICT)
+ source_info_dict['build.prop']['ro.build.fingerprint'] = (
+ 'source-build-fingerprint')
+ source_info = BuildInfo(source_info_dict, None)
+
+ script_writer = MockScriptWriter()
+ WriteFingerprintAssertion(script_writer, target_info, source_info)
+ self.assertEqual(
+ [('AssertSomeFingerprint', 'source-build-fingerprint',
+ 'build-fingerprint')],
+ script_writer.script)
+
+ def test_WriteFingerprintAssertion_with_source_oem_props(self):
+ target_info = BuildInfo(self.TEST_INFO_DICT, None)
+ source_info = BuildInfo(self.TEST_INFO_DICT_USES_OEM_PROPS,
+ self.TEST_OEM_DICTS)
+
+ script_writer = MockScriptWriter()
+ WriteFingerprintAssertion(script_writer, target_info, source_info)
+ self.assertEqual(
+ [('AssertFingerprintOrThumbprint', 'build-fingerprint',
+ 'build-thumbprint')],
+ script_writer.script)
+
+ def test_WriteFingerprintAssertion_with_target_oem_props(self):
+ target_info = BuildInfo(self.TEST_INFO_DICT_USES_OEM_PROPS,
+ self.TEST_OEM_DICTS)
+ source_info = BuildInfo(self.TEST_INFO_DICT, None)
+
+ script_writer = MockScriptWriter()
+ WriteFingerprintAssertion(script_writer, target_info, source_info)
+ self.assertEqual(
+ [('AssertFingerprintOrThumbprint', 'build-fingerprint',
+ 'build-thumbprint')],
+ script_writer.script)
+
+ def test_WriteFingerprintAssertion_with_both_oem_props(self):
+ target_info = 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']['ro.build.thumbprint'] = (
+ 'source-build-thumbprint')
+ source_info = BuildInfo(source_info_dict, self.TEST_OEM_DICTS)
+
+ script_writer = MockScriptWriter()
+ WriteFingerprintAssertion(script_writer, target_info, source_info)
+ self.assertEqual(
+ [('AssertSomeThumbprint', 'build-thumbprint',
+ 'source-build-thumbprint')],
+ script_writer.script)
+
+
+class LoadOemDictsTest(unittest.TestCase):
+
+ def tearDown(self):
+ common.Cleanup()
+
+ def test_NoneDict(self):
+ self.assertIsNone(_LoadOemDicts(None))
+
+ def test_SingleDict(self):
+ dict_file = common.MakeTempFile()
+ with open(dict_file, 'w') as dict_fp:
+ dict_fp.write('abc=1\ndef=2\nxyz=foo\na.b.c=bar\n')
+
+ oem_dicts = _LoadOemDicts([dict_file])
+ self.assertEqual(1, len(oem_dicts))
+ self.assertEqual('foo', oem_dicts[0]['xyz'])
+ self.assertEqual('bar', oem_dicts[0]['a.b.c'])
+
+ def test_MultipleDicts(self):
+ oem_source = []
+ for i in range(3):
+ dict_file = common.MakeTempFile()
+ with open(dict_file, 'w') as dict_fp:
+ dict_fp.write(
+ 'ro.build.index={}\ndef=2\nxyz=foo\na.b.c=bar\n'.format(i))
+ oem_source.append(dict_file)
+
+ oem_dicts = _LoadOemDicts(oem_source)
+ self.assertEqual(3, len(oem_dicts))
+ for i, oem_dict in enumerate(oem_dicts):
+ self.assertEqual('2', oem_dict['def'])
+ self.assertEqual('foo', oem_dict['xyz'])
+ self.assertEqual('bar', oem_dict['a.b.c'])
+ self.assertEqual('{}'.format(i), oem_dict['ro.build.index'])
+
+
+class OtaFromTargetFilesTest(unittest.TestCase):
+
+ TEST_TARGET_INFO_DICT = {
+ 'build.prop' : {
+ '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_SOURCE_INFO_DICT = {
+ 'build.prop' : {
+ 'ro.product.device' : 'product-device',
+ 'ro.build.fingerprint' : 'build-fingerprint-source',
+ 'ro.build.version.incremental' : 'build-version-incremental-source',
+ 'ro.build.version.sdk' : '25',
+ 'ro.build.version.security_patch' : '2016-12-01',
+ 'ro.build.date.utc' : '1400000000',
+ },
+ }
+
+ def setUp(self):
+ self.testdata_dir = test_utils.get_testdata_dir()
+ self.assertTrue(os.path.exists(self.testdata_dir))
+
+ # Reset the global options as in ota_from_target_files.py.
+ common.OPTIONS.incremental_source = None
+ common.OPTIONS.downgrade = False
+ common.OPTIONS.timestamp = False
+ common.OPTIONS.wipe_user_data = False
+ 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.search_path = test_utils.get_search_path()
+ self.assertIsNotNone(common.OPTIONS.search_path)
+
+ def tearDown(self):
+ common.Cleanup()
+
+ def test_GetPackageMetadata_abOta_full(self):
+ target_info_dict = copy.deepcopy(self.TEST_TARGET_INFO_DICT)
+ target_info_dict['ab_update'] = 'true'
+ target_info = BuildInfo(target_info_dict, None)
+ metadata = GetPackageMetadata(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',
+ },
+ 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 = BuildInfo(target_info_dict, None)
+ source_info = BuildInfo(self.TEST_SOURCE_INFO_DICT, None)
+ common.OPTIONS.incremental_source = ''
+ metadata = GetPackageMetadata(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',
+ },
+ metadata)
+
+ def test_GetPackageMetadata_nonAbOta_full(self):
+ target_info = BuildInfo(self.TEST_TARGET_INFO_DICT, None)
+ metadata = GetPackageMetadata(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',
+ },
+ metadata)
+
+ def test_GetPackageMetadata_nonAbOta_incremental(self):
+ target_info = BuildInfo(self.TEST_TARGET_INFO_DICT, None)
+ source_info = BuildInfo(self.TEST_SOURCE_INFO_DICT, None)
+ common.OPTIONS.incremental_source = ''
+ metadata = GetPackageMetadata(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',
+ },
+ metadata)
+
+ def test_GetPackageMetadata_wipe(self):
+ target_info = BuildInfo(self.TEST_TARGET_INFO_DICT, None)
+ common.OPTIONS.wipe_user_data = True
+ metadata = GetPackageMetadata(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',
+ },
+ metadata)
+
+ @staticmethod
+ def _test_GetPackageMetadata_swapBuildTimestamps(target_info, source_info):
+ (target_info['build.prop']['ro.build.date.utc'],
+ source_info['build.prop']['ro.build.date.utc']) = (
+ source_info['build.prop']['ro.build.date.utc'],
+ target_info['build.prop']['ro.build.date.utc'])
+
+ def test_GetPackageMetadata_unintentionalDowngradeDetected(self):
+ target_info_dict = copy.deepcopy(self.TEST_TARGET_INFO_DICT)
+ source_info_dict = copy.deepcopy(self.TEST_SOURCE_INFO_DICT)
+ self._test_GetPackageMetadata_swapBuildTimestamps(
+ target_info_dict, source_info_dict)
+
+ target_info = BuildInfo(target_info_dict, None)
+ source_info = BuildInfo(source_info_dict, None)
+ common.OPTIONS.incremental_source = ''
+ self.assertRaises(RuntimeError, GetPackageMetadata, target_info,
+ source_info)
+
+ def test_GetPackageMetadata_downgrade(self):
+ target_info_dict = copy.deepcopy(self.TEST_TARGET_INFO_DICT)
+ source_info_dict = copy.deepcopy(self.TEST_SOURCE_INFO_DICT)
+ self._test_GetPackageMetadata_swapBuildTimestamps(
+ target_info_dict, source_info_dict)
+
+ target_info = BuildInfo(target_info_dict, None)
+ source_info = BuildInfo(source_info_dict, None)
+ common.OPTIONS.incremental_source = ''
+ common.OPTIONS.downgrade = True
+ common.OPTIONS.wipe_user_data = True
+ metadata = GetPackageMetadata(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',
+ },
+ metadata)
+
+ def test_GetTargetFilesZipForSecondaryImages(self):
+ input_file = construct_target_files(secondary=True)
+ target_file = GetTargetFilesZipForSecondaryImages(input_file)
+
+ with zipfile.ZipFile(target_file) as verify_zip:
+ namelist = verify_zip.namelist()
+
+ self.assertIn('META/ab_partitions.txt', namelist)
+ self.assertIn('IMAGES/boot.img', namelist)
+ self.assertIn('IMAGES/system.img', namelist)
+ self.assertIn('IMAGES/vendor.img', namelist)
+ self.assertIn(POSTINSTALL_CONFIG, namelist)
+
+ self.assertNotIn('IMAGES/system_other.img', namelist)
+ self.assertNotIn('IMAGES/system.map', namelist)
+
+ def test_GetTargetFilesZipForSecondaryImages_skipPostinstall(self):
+ input_file = construct_target_files(secondary=True)
+ target_file = GetTargetFilesZipForSecondaryImages(
+ input_file, skip_postinstall=True)
+
+ with zipfile.ZipFile(target_file) as verify_zip:
+ namelist = verify_zip.namelist()
+
+ self.assertIn('META/ab_partitions.txt', namelist)
+ self.assertIn('IMAGES/boot.img', namelist)
+ self.assertIn('IMAGES/system.img', namelist)
+ self.assertIn('IMAGES/vendor.img', namelist)
+
+ self.assertNotIn('IMAGES/system_other.img', namelist)
+ self.assertNotIn('IMAGES/system.map', namelist)
+ self.assertNotIn(POSTINSTALL_CONFIG, namelist)
+
+ def test_GetTargetFilesZipWithoutPostinstallConfig(self):
+ input_file = construct_target_files()
+ target_file = GetTargetFilesZipWithoutPostinstallConfig(input_file)
+ with zipfile.ZipFile(target_file) as verify_zip:
+ self.assertNotIn(POSTINSTALL_CONFIG, verify_zip.namelist())
+
+ def test_GetTargetFilesZipWithoutPostinstallConfig_missingEntry(self):
+ input_file = construct_target_files()
+ common.ZipDelete(input_file, POSTINSTALL_CONFIG)
+ target_file = GetTargetFilesZipWithoutPostinstallConfig(input_file)
+ with zipfile.ZipFile(target_file) as verify_zip:
+ self.assertNotIn(POSTINSTALL_CONFIG, verify_zip.namelist())
+
+ def _test_FinalizeMetadata(self, large_entry=False):
+ entries = [
+ 'required-entry1',
+ 'required-entry2',
+ ]
+ 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:
+ zip_fp.writestr(
+ # Using 'zoo' so that the entry stays behind others after signing.
+ 'zoo',
+ 'A' * 1024 * 1024 * 1024,
+ zipfile.ZIP_STORED)
+
+ metadata = {}
+ 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)
+
+ def test_FinalizeMetadata(self):
+ self._test_FinalizeMetadata()
+
+ def test_FinalizeMetadata_withNoSigning(self):
+ common.OPTIONS.no_signing = True
+ self._test_FinalizeMetadata()
+
+ def test_FinalizeMetadata_largeEntry(self):
+ self._test_FinalizeMetadata(large_entry=True)
+
+ def test_FinalizeMetadata_largeEntry_withNoSigning(self):
+ common.OPTIONS.no_signing = True
+ self._test_FinalizeMetadata(large_entry=True)
+
+ def test_FinalizeMetadata_insufficientSpace(self):
+ entries = [
+ 'required-entry1',
+ 'required-entry2',
+ 'optional-entry1',
+ 'optional-entry2',
+ ]
+ zip_file = PropertyFilesTest.construct_zip_package(entries)
+ with zipfile.ZipFile(zip_file, 'a') 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
+ # InsufficientSpaceException and an automatic retry.
+ 'foo-entry1',
+ 'A' * 1024 * 1024,
+ zipfile.ZIP_STORED)
+
+ metadata = {}
+ 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)
+
+
+class TestPropertyFiles(PropertyFiles):
+ """A class that extends PropertyFiles for testing purpose."""
+
+ def __init__(self):
+ super(TestPropertyFiles, self).__init__()
+ self.name = 'ota-test-property-files'
+ self.required = (
+ 'required-entry1',
+ 'required-entry2',
+ )
+ self.optional = (
+ 'optional-entry1',
+ 'optional-entry2',
+ )
+
+
+class PropertyFilesTest(unittest.TestCase):
+
+ def setUp(self):
+ common.OPTIONS.no_signing = False
+
+ def tearDown(self):
+ common.Cleanup()
+
+ @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))
+
+ def test_Compute(self):
+ entries = (
+ 'required-entry1',
+ 'required-entry2',
+ )
+ zip_file = self.construct_zip_package(entries)
+ property_files = TestPropertyFiles()
+ with zipfile.ZipFile(zip_file, 'r') 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._verify_entries(zip_file, tokens, entries)
+
+ def test_Compute_withOptionalEntries(self):
+ entries = (
+ 'required-entry1',
+ 'required-entry2',
+ 'optional-entry1',
+ 'optional-entry2',
+ )
+ zip_file = self.construct_zip_package(entries)
+ property_files = TestPropertyFiles()
+ with zipfile.ZipFile(zip_file, 'r') 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._verify_entries(zip_file, tokens, entries)
+
+ def test_Compute_missingRequiredEntry(self):
+ entries = (
+ 'required-entry2',
+ )
+ zip_file = self.construct_zip_package(entries)
+ property_files = TestPropertyFiles()
+ with zipfile.ZipFile(zip_file, 'r') as zip_fp:
+ self.assertRaises(KeyError, property_files.Compute, zip_fp)
+
+ def test_Finalize(self):
+ entries = [
+ 'required-entry1',
+ 'required-entry2',
+ 'META-INF/com/android/metadata',
+ ]
+ zip_file = self.construct_zip_package(entries)
+ property_files = TestPropertyFiles()
+ with zipfile.ZipFile(zip_file, 'r') as zip_fp:
+ # pylint: disable=protected-access
+ 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))
+ # 'META-INF/com/android/metadata' will be key'd as 'metadata' in the
+ # streaming metadata.
+ entries[2] = 'metadata'
+ self._verify_entries(zip_file, tokens, entries)
+
+ def test_Finalize_assertReservedLength(self):
+ entries = (
+ 'required-entry1',
+ 'required-entry2',
+ 'optional-entry1',
+ 'optional-entry2',
+ 'META-INF/com/android/metadata',
+ )
+ zip_file = self.construct_zip_package(entries)
+ property_files = TestPropertyFiles()
+ with zipfile.ZipFile(zip_file, 'r') as zip_fp:
+ # First get the raw metadata string (i.e. without padding space).
+ # pylint: disable=protected-access
+ raw_metadata = property_files._GetPropertyFilesString(
+ zip_fp, reserve_space=False)
+ raw_length = len(raw_metadata)
+
+ # Now pass in the exact expected length.
+ streaming_metadata = property_files.Finalize(zip_fp, raw_length)
+ self.assertEqual(raw_length, len(streaming_metadata))
+
+ # Or pass in insufficient length.
+ self.assertRaises(
+ PropertyFiles.InsufficientSpaceException,
+ property_files.Finalize,
+ zip_fp,
+ raw_length - 1)
+
+ # Or pass in a much larger size.
+ streaming_metadata = property_files.Finalize(
+ zip_fp,
+ raw_length + 20)
+ self.assertEqual(raw_length + 20, len(streaming_metadata))
+ self.assertEqual(' ' * 20, streaming_metadata[raw_length:])
+
+ def test_Verify(self):
+ entries = (
+ 'required-entry1',
+ 'required-entry2',
+ 'optional-entry1',
+ 'optional-entry2',
+ 'META-INF/com/android/metadata',
+ )
+ zip_file = self.construct_zip_package(entries)
+ property_files = TestPropertyFiles()
+ with zipfile.ZipFile(zip_file, 'r') as zip_fp:
+ # First get the raw metadata string (i.e. without padding space).
+ # pylint: disable=protected-access
+ raw_metadata = property_files._GetPropertyFilesString(
+ zip_fp, reserve_space=False)
+
+ # Should pass the test if verification passes.
+ property_files.Verify(zip_fp, raw_metadata)
+
+ # Or raise on verification failure.
+ self.assertRaises(
+ AssertionError, property_files.Verify, zip_fp, raw_metadata + 'x')
+
+
+class StreamingPropertyFilesTest(PropertyFilesTest):
+ """Additional sanity checks specialized for StreamingPropertyFiles."""
+
+ def test_init(self):
+ property_files = StreamingPropertyFiles()
+ self.assertEqual('ota-streaming-property-files', property_files.name)
+ self.assertEqual(
+ (
+ 'payload.bin',
+ 'payload_properties.txt',
+ ),
+ property_files.required)
+ self.assertEqual(
+ (
+ 'care_map.txt',
+ 'compatibility.zip',
+ ),
+ property_files.optional)
+
+ def test_Compute(self):
+ entries = (
+ 'payload.bin',
+ 'payload_properties.txt',
+ 'care_map.txt',
+ 'compatibility.zip',
+ )
+ zip_file = self.construct_zip_package(entries)
+ property_files = StreamingPropertyFiles()
+ with zipfile.ZipFile(zip_file, 'r') 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._verify_entries(zip_file, tokens, entries)
+
+ def test_Finalize(self):
+ entries = [
+ 'payload.bin',
+ 'payload_properties.txt',
+ 'care_map.txt',
+ 'compatibility.zip',
+ 'META-INF/com/android/metadata',
+ ]
+ zip_file = self.construct_zip_package(entries)
+ property_files = StreamingPropertyFiles()
+ with zipfile.ZipFile(zip_file, 'r') as zip_fp:
+ # pylint: disable=protected-access
+ 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))
+ # 'META-INF/com/android/metadata' will be key'd as 'metadata' in the
+ # streaming metadata.
+ entries[4] = 'metadata'
+ self._verify_entries(zip_file, tokens, entries)
+
+ def test_Verify(self):
+ entries = (
+ 'payload.bin',
+ 'payload_properties.txt',
+ 'care_map.txt',
+ 'compatibility.zip',
+ 'META-INF/com/android/metadata',
+ )
+ zip_file = self.construct_zip_package(entries)
+ property_files = StreamingPropertyFiles()
+ with zipfile.ZipFile(zip_file, 'r') as zip_fp:
+ # First get the raw metadata string (i.e. without padding space).
+ # pylint: disable=protected-access
+ raw_metadata = property_files._GetPropertyFilesString(
+ zip_fp, reserve_space=False)
+
+ # Should pass the test if verification passes.
+ property_files.Verify(zip_fp, raw_metadata)
+
+ # Or raise on verification failure.
+ self.assertRaises(
+ AssertionError, property_files.Verify, zip_fp, raw_metadata + 'x')
+
+
+class AbOtaPropertyFilesTest(PropertyFilesTest):
+ """Additional sanity checks specialized for AbOtaPropertyFiles."""
+
+ # The size for payload and metadata signature size.
+ SIGNATURE_SIZE = 256
+
+ def setUp(self):
+ self.testdata_dir = test_utils.get_testdata_dir()
+ self.assertTrue(os.path.exists(self.testdata_dir))
+
+ common.OPTIONS.wipe_user_data = False
+ common.OPTIONS.payload_signer = None
+ 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,
+ }
+
+ def test_init(self):
+ property_files = AbOtaPropertyFiles()
+ self.assertEqual('ota-property-files', property_files.name)
+ self.assertEqual(
+ (
+ 'payload.bin',
+ 'payload_properties.txt',
+ ),
+ property_files.required)
+ self.assertEqual(
+ (
+ 'care_map.txt',
+ 'compatibility.zip',
+ ),
+ property_files.optional)
+
+ def test_GetPayloadMetadataOffsetAndSize(self):
+ target_file = construct_target_files()
+ payload = Payload()
+ payload.Generate(target_file)
+
+ payload_signer = PayloadSigner()
+ payload.Sign(payload_signer)
+
+ output_file = common.MakeTempFile(suffix='.zip')
+ with zipfile.ZipFile(output_file, 'w') as output_zip:
+ payload.WriteToZip(output_zip)
+
+ # Find out the payload metadata offset and size.
+ property_files = AbOtaPropertyFiles()
+ with zipfile.ZipFile(output_file) as input_zip:
+ # pylint: disable=protected-access
+ payload_offset, metadata_total = (
+ property_files._GetPayloadMetadataOffsetAndSize(input_zip))
+
+ # Read in the metadata signature directly.
+ with open(output_file, 'rb') as verify_fp:
+ verify_fp.seek(payload_offset + metadata_total - self.SIGNATURE_SIZE)
+ metadata_signature = verify_fp.read(self.SIGNATURE_SIZE)
+
+ # Now we extract the metadata hash via brillo_update_payload script, which
+ # will serve as the oracle result.
+ payload_sig_file = common.MakeTempFile(prefix="sig-", suffix=".bin")
+ metadata_sig_file = common.MakeTempFile(prefix="sig-", suffix=".bin")
+ cmd = ['brillo_update_payload', 'hash',
+ '--unsigned_payload', payload.payload_file,
+ '--signature_size', str(self.SIGNATURE_SIZE),
+ '--metadata_hash_file', metadata_sig_file,
+ '--payload_hash_file', payload_sig_file]
+ proc = common.Run(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+ stdoutdata, _ = proc.communicate()
+ self.assertEqual(
+ 0, proc.returncode,
+ 'Failed to run brillo_update_payload: {}'.format(stdoutdata))
+
+ signed_metadata_sig_file = payload_signer.Sign(metadata_sig_file)
+
+ # Finally we can compare the two signatures.
+ with open(signed_metadata_sig_file, 'rb') as verify_fp:
+ self.assertEqual(verify_fp.read(), metadata_signature)
+
+ @staticmethod
+ def construct_zip_package_withValidPayload(with_metadata=False):
+ # Cannot use construct_zip_package() since we need a "valid" payload.bin.
+ target_file = construct_target_files()
+ payload = Payload()
+ payload.Generate(target_file)
+
+ payload_signer = PayloadSigner()
+ payload.Sign(payload_signer)
+
+ zip_file = common.MakeTempFile(suffix='.zip')
+ with zipfile.ZipFile(zip_file, 'w') as zip_fp:
+ # 'payload.bin',
+ payload.WriteToZip(zip_fp)
+
+ # Other entries.
+ entries = ['care_map.txt', 'compatibility.zip']
+
+ # Put META-INF/com/android/metadata if needed.
+ if with_metadata:
+ entries.append('META-INF/com/android/metadata')
+
+ for entry in entries:
+ zip_fp.writestr(
+ entry, entry.replace('.', '-').upper(), zipfile.ZIP_STORED)
+
+ return zip_file
+
+ def test_Compute(self):
+ zip_file = self.construct_zip_package_withValidPayload()
+ property_files = AbOtaPropertyFiles()
+ with zipfile.ZipFile(zip_file, 'r') 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
+ # for payload-metadata.bin.
+ self.assertEqual(6, len(tokens))
+ self._verify_entries(
+ zip_file, tokens, ('care_map.txt', 'compatibility.zip'))
+
+ 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:
+ # pylint: disable=protected-access
+ 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)
+ # "6" indcludes the four entries above, one metadata entry, and one entry
+ # for payload-metadata.bin.
+ self.assertEqual(6, len(tokens))
+ self._verify_entries(
+ zip_file, tokens, ('care_map.txt', 'compatibility.zip'))
+
+ 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:
+ # pylint: disable=protected-access
+ 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:
+ # pylint: disable=protected-access
+ 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:
+ # pylint: disable=protected-access
+ raw_metadata = property_files._GetPropertyFilesString(
+ zip_fp, reserve_space=False)
+
+ property_files.Verify(zip_fp, raw_metadata)
+
+
+class PayloadSignerTest(unittest.TestCase):
+
+ SIGFILE = 'sigfile.bin'
+ SIGNED_SIGFILE = 'signed-sigfile.bin'
+
+ def setUp(self):
+ self.testdata_dir = test_utils.get_testdata_dir()
+ self.assertTrue(os.path.exists(self.testdata_dir))
+
+ common.OPTIONS.payload_signer = None
+ 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,
+ }
+
+ def tearDown(self):
+ common.Cleanup()
+
+ def _assertFilesEqual(self, file1, file2):
+ with open(file1, 'rb') as fp1, open(file2, 'rb') as fp2:
+ self.assertEqual(fp1.read(), fp2.read())
+
+ def test_init(self):
+ payload_signer = PayloadSigner()
+ self.assertEqual('openssl', payload_signer.signer)
+
+ def test_init_withPassword(self):
+ common.OPTIONS.package_key = os.path.join(
+ self.testdata_dir, 'testkey_with_passwd')
+ common.OPTIONS.key_passwords = {
+ common.OPTIONS.package_key : 'foo',
+ }
+ payload_signer = PayloadSigner()
+ self.assertEqual('openssl', payload_signer.signer)
+
+ def test_init_withExternalSigner(self):
+ common.OPTIONS.payload_signer = 'abc'
+ common.OPTIONS.payload_signer_args = ['arg1', 'arg2']
+ payload_signer = PayloadSigner()
+ self.assertEqual('abc', payload_signer.signer)
+ self.assertEqual(['arg1', 'arg2'], payload_signer.signer_args)
+
+ def test_Sign(self):
+ payload_signer = PayloadSigner()
+ input_file = os.path.join(self.testdata_dir, self.SIGFILE)
+ signed_file = payload_signer.Sign(input_file)
+
+ verify_file = os.path.join(self.testdata_dir, self.SIGNED_SIGFILE)
+ self._assertFilesEqual(verify_file, signed_file)
+
+ def test_Sign_withExternalSigner_openssl(self):
+ """Uses openssl as the external payload signer."""
+ common.OPTIONS.payload_signer = 'openssl'
+ common.OPTIONS.payload_signer_args = [
+ 'pkeyutl', '-sign', '-keyform', 'DER', '-inkey',
+ os.path.join(self.testdata_dir, 'testkey.pk8'),
+ '-pkeyopt', 'digest:sha256']
+ payload_signer = PayloadSigner()
+ input_file = os.path.join(self.testdata_dir, self.SIGFILE)
+ signed_file = payload_signer.Sign(input_file)
+
+ verify_file = os.path.join(self.testdata_dir, self.SIGNED_SIGFILE)
+ self._assertFilesEqual(verify_file, signed_file)
+
+ def test_Sign_withExternalSigner_script(self):
+ """Uses testdata/payload_signer.sh as the external payload signer."""
+ common.OPTIONS.payload_signer = os.path.join(
+ self.testdata_dir, 'payload_signer.sh')
+ common.OPTIONS.payload_signer_args = [
+ os.path.join(self.testdata_dir, 'testkey.pk8')]
+ payload_signer = PayloadSigner()
+ input_file = os.path.join(self.testdata_dir, self.SIGFILE)
+ signed_file = payload_signer.Sign(input_file)
+
+ verify_file = os.path.join(self.testdata_dir, self.SIGNED_SIGFILE)
+ self._assertFilesEqual(verify_file, signed_file)
+
+
+class PayloadTest(unittest.TestCase):
+
+ def setUp(self):
+ self.testdata_dir = test_utils.get_testdata_dir()
+ self.assertTrue(os.path.exists(self.testdata_dir))
+
+ common.OPTIONS.wipe_user_data = False
+ common.OPTIONS.payload_signer = None
+ 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,
+ }
+
+ def tearDown(self):
+ common.Cleanup()
+
+ @staticmethod
+ def _create_payload_full(secondary=False):
+ target_file = construct_target_files(secondary)
+ payload = Payload(secondary)
+ payload.Generate(target_file)
+ return payload
+
+ @staticmethod
+ def _create_payload_incremental():
+ target_file = construct_target_files()
+ source_file = construct_target_files()
+ payload = Payload()
+ payload.Generate(target_file, source_file)
+ return payload
+
+ def test_Generate_full(self):
+ payload = self._create_payload_full()
+ self.assertTrue(os.path.exists(payload.payload_file))
+
+ def test_Generate_incremental(self):
+ payload = self._create_payload_incremental()
+ self.assertTrue(os.path.exists(payload.payload_file))
+
+ def test_Generate_additionalArgs(self):
+ target_file = construct_target_files()
+ source_file = construct_target_files()
+ payload = Payload()
+ # This should work the same as calling payload.Generate(target_file,
+ # source_file).
+ payload.Generate(
+ target_file, additional_args=["--source_image", source_file])
+ self.assertTrue(os.path.exists(payload.payload_file))
+
+ def test_Generate_invalidInput(self):
+ target_file = construct_target_files()
+ common.ZipDelete(target_file, 'IMAGES/vendor.img')
+ payload = Payload()
+ self.assertRaises(AssertionError, payload.Generate, target_file)
+
+ def test_Sign_full(self):
+ payload = self._create_payload_full()
+ payload.Sign(PayloadSigner())
+
+ output_file = common.MakeTempFile(suffix='.zip')
+ with zipfile.ZipFile(output_file, 'w') as output_zip:
+ payload.WriteToZip(output_zip)
+
+ import check_ota_package_signature
+ check_ota_package_signature.VerifyAbOtaPayload(
+ os.path.join(self.testdata_dir, 'testkey.x509.pem'),
+ output_file)
+
+ def test_Sign_incremental(self):
+ payload = self._create_payload_incremental()
+ payload.Sign(PayloadSigner())
+
+ output_file = common.MakeTempFile(suffix='.zip')
+ with zipfile.ZipFile(output_file, 'w') as output_zip:
+ payload.WriteToZip(output_zip)
+
+ import check_ota_package_signature
+ check_ota_package_signature.VerifyAbOtaPayload(
+ os.path.join(self.testdata_dir, 'testkey.x509.pem'),
+ output_file)
+
+ def test_Sign_withDataWipe(self):
+ common.OPTIONS.wipe_user_data = True
+ payload = self._create_payload_full()
+ payload.Sign(PayloadSigner())
+
+ with open(payload.payload_properties) as properties_fp:
+ self.assertIn("POWERWASH=1", properties_fp.read())
+
+ def test_Sign_secondary(self):
+ payload = self._create_payload_full(secondary=True)
+ payload.Sign(PayloadSigner())
+
+ with open(payload.payload_properties) as properties_fp:
+ self.assertIn("SWITCH_SLOT_ON_REBOOT=0", properties_fp.read())
+
+ def test_Sign_badSigner(self):
+ """Tests that signing failure can be captured."""
+ payload = self._create_payload_full()
+ payload_signer = PayloadSigner()
+ payload_signer.signer_args.append('bad-option')
+ self.assertRaises(AssertionError, payload.Sign, payload_signer)
+
+ def test_WriteToZip(self):
+ payload = self._create_payload_full()
+ payload.Sign(PayloadSigner())
+
+ output_file = common.MakeTempFile(suffix='.zip')
+ with zipfile.ZipFile(output_file, 'w') as output_zip:
+ payload.WriteToZip(output_zip)
+
+ with zipfile.ZipFile(output_file) as verify_zip:
+ # First make sure we have the essential entries.
+ namelist = verify_zip.namelist()
+ self.assertIn(Payload.PAYLOAD_BIN, namelist)
+ self.assertIn(Payload.PAYLOAD_PROPERTIES_TXT, namelist)
+
+ # Then assert these entries are stored.
+ for entry_info in verify_zip.infolist():
+ if entry_info.filename not in (Payload.PAYLOAD_BIN,
+ Payload.PAYLOAD_PROPERTIES_TXT):
+ continue
+ self.assertEqual(zipfile.ZIP_STORED, entry_info.compress_type)
+
+ def test_WriteToZip_unsignedPayload(self):
+ """Unsigned payloads should not be allowed to be written to zip."""
+ payload = self._create_payload_full()
+
+ output_file = common.MakeTempFile(suffix='.zip')
+ with zipfile.ZipFile(output_file, 'w') 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:
+ self.assertRaises(AssertionError, payload.WriteToZip, output_zip)
+
+ def test_WriteToZip_secondary(self):
+ payload = self._create_payload_full(secondary=True)
+ payload.Sign(PayloadSigner())
+
+ output_file = common.MakeTempFile(suffix='.zip')
+ with zipfile.ZipFile(output_file, 'w') as output_zip:
+ payload.WriteToZip(output_zip)
+
+ with zipfile.ZipFile(output_file) as verify_zip:
+ # First make sure we have the essential entries.
+ namelist = verify_zip.namelist()
+ self.assertIn(Payload.SECONDARY_PAYLOAD_BIN, namelist)
+ self.assertIn(Payload.SECONDARY_PAYLOAD_PROPERTIES_TXT, namelist)
+
+ # 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):
+ continue
+ self.assertEqual(zipfile.ZIP_STORED, entry_info.compress_type)
diff --git a/tools/releasetools/test_sign_target_files_apks.py b/tools/releasetools/test_sign_target_files_apks.py
new file mode 100644
index 0000000..26f9e10
--- /dev/null
+++ b/tools/releasetools/test_sign_target_files_apks.py
@@ -0,0 +1,213 @@
+#
+# 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.
+#
+
+from __future__ import print_function
+
+import base64
+import os.path
+import unittest
+import zipfile
+
+import common
+import test_utils
+from sign_target_files_apks import (
+ EditTags, ReplaceCerts, ReplaceVerityKeyId, RewriteProps)
+
+
+class SignTargetFilesApksTest(unittest.TestCase):
+
+ MAC_PERMISSIONS_XML = """<?xml version="1.0" encoding="iso-8859-1"?>
+<policy>
+ <signer signature="{}"><seinfo value="platform"/></signer>
+ <signer signature="{}"><seinfo value="media"/></signer>
+</policy>"""
+
+ def setUp(self):
+ self.testdata_dir = test_utils.get_testdata_dir()
+
+ def tearDown(self):
+ common.Cleanup()
+
+ def test_EditTags(self):
+ self.assertEqual(EditTags('dev-keys'), ('release-keys'))
+ self.assertEqual(EditTags('test-keys'), ('release-keys'))
+
+ # Multiple tags.
+ self.assertEqual(EditTags('abc,dev-keys,xyz'), ('abc,release-keys,xyz'))
+
+ # Tags are sorted.
+ self.assertEqual(EditTags('xyz,abc,dev-keys,xyz'), ('abc,release-keys,xyz'))
+
+ def test_RewriteProps(self):
+ props = (
+ ('', '\n'),
+ ('ro.build.fingerprint=foo/bar/dev-keys',
+ 'ro.build.fingerprint=foo/bar/release-keys\n'),
+ ('ro.build.thumbprint=foo/bar/dev-keys',
+ 'ro.build.thumbprint=foo/bar/release-keys\n'),
+ ('ro.vendor.build.fingerprint=foo/bar/dev-keys',
+ 'ro.vendor.build.fingerprint=foo/bar/release-keys\n'),
+ ('ro.vendor.build.thumbprint=foo/bar/dev-keys',
+ 'ro.vendor.build.thumbprint=foo/bar/release-keys\n'),
+ ('# comment line 1', '# comment line 1\n'),
+ ('ro.bootimage.build.fingerprint=foo/bar/dev-keys',
+ 'ro.bootimage.build.fingerprint=foo/bar/release-keys\n'),
+ ('ro.build.description='
+ 'sailfish-user 8.0.0 OPR6.170623.012 4283428 dev-keys',
+ 'ro.build.description='
+ 'sailfish-user 8.0.0 OPR6.170623.012 4283428 release-keys\n'),
+ ('ro.build.tags=dev-keys', 'ro.build.tags=release-keys\n'),
+ ('# comment line 2', '# comment line 2\n'),
+ ('ro.build.display.id=OPR6.170623.012 dev-keys',
+ 'ro.build.display.id=OPR6.170623.012\n'),
+ ('# comment line 3', '# comment line 3\n'),
+ )
+
+ # Assert the case for each individual line.
+ for prop, output in props:
+ self.assertEqual(RewriteProps(prop), output)
+
+ # Concatenate all the input lines.
+ self.assertEqual(RewriteProps('\n'.join([prop[0] for prop in props])),
+ ''.join([prop[1] for prop in props]))
+
+ def test_ReplaceVerityKeyId(self):
+ BOOT_CMDLINE1 = (
+ "console=ttyHSL0,115200,n8 androidboot.console=ttyHSL0 "
+ "androidboot.hardware=marlin user_debug=31 ehci-hcd.park=3 "
+ "lpm_levels.sleep_disabled=1 cma=32M@0-0xffffffff loop.max_part=7 "
+ "buildvariant=userdebug "
+ "veritykeyid=id:7e4333f9bba00adfe0ede979e28ed1920492b40f\n")
+
+ BOOT_CMDLINE2 = (
+ "console=ttyHSL0,115200,n8 androidboot.console=ttyHSL0 "
+ "androidboot.hardware=marlin user_debug=31 ehci-hcd.park=3 "
+ "lpm_levels.sleep_disabled=1 cma=32M@0-0xffffffff loop.max_part=7 "
+ "buildvariant=userdebug "
+ "veritykeyid=id:d24f2590e9abab5cff5f59da4c4f0366e3f43e94\n")
+
+ input_file = common.MakeTempFile(suffix='.zip')
+ with zipfile.ZipFile(input_file, 'w') 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:
+ ReplaceVerityKeyId(input_zip, output_zip, cert_file)
+
+ with zipfile.ZipFile(output_file) as output_zip:
+ self.assertEqual(BOOT_CMDLINE1, output_zip.read('BOOT/cmdline'))
+
+ # 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:
+ ReplaceVerityKeyId(input_zip, output_zip, cert_file)
+
+ with zipfile.ZipFile(output_file) as output_zip:
+ self.assertEqual(BOOT_CMDLINE2, output_zip.read('BOOT/cmdline'))
+
+ def test_ReplaceVerityKeyId_no_veritykeyid(self):
+ BOOT_CMDLINE = (
+ "console=ttyHSL0,115200,n8 androidboot.hardware=bullhead boot_cpus=0-5 "
+ "lpm_levels.sleep_disabled=1 msm_poweroff.download_mode=0 "
+ "loop.max_part=7\n")
+
+ input_file = common.MakeTempFile(suffix='.zip')
+ with zipfile.ZipFile(input_file, 'w') 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:
+ ReplaceVerityKeyId(input_zip, output_zip, None)
+
+ with zipfile.ZipFile(output_file) as output_zip:
+ self.assertEqual(BOOT_CMDLINE, output_zip.read('BOOT/cmdline'))
+
+ def test_ReplaceCerts(self):
+ cert1_path = os.path.join(self.testdata_dir, 'platform.x509.pem')
+ with open(cert1_path) as cert1_fp:
+ cert1 = cert1_fp.read()
+ cert2_path = os.path.join(self.testdata_dir, 'media.x509.pem')
+ with open(cert2_path) as cert2_fp:
+ cert2 = cert2_fp.read()
+ cert3_path = os.path.join(self.testdata_dir, 'testkey.x509.pem')
+ with open(cert3_path) as cert3_fp:
+ cert3 = cert3_fp.read()
+
+ # Replace cert1 with cert3.
+ input_xml = self.MAC_PERMISSIONS_XML.format(
+ base64.b16encode(common.ParseCertificate(cert1)).lower(),
+ base64.b16encode(common.ParseCertificate(cert2)).lower())
+
+ output_xml = self.MAC_PERMISSIONS_XML.format(
+ base64.b16encode(common.ParseCertificate(cert3)).lower(),
+ base64.b16encode(common.ParseCertificate(cert2)).lower())
+
+ common.OPTIONS.key_map = {
+ cert1_path[:-9] : cert3_path[:-9],
+ }
+
+ self.assertEqual(output_xml, ReplaceCerts(input_xml))
+
+ def test_ReplaceCerts_duplicateEntries(self):
+ cert1_path = os.path.join(self.testdata_dir, 'platform.x509.pem')
+ with open(cert1_path) as cert1_fp:
+ cert1 = cert1_fp.read()
+ cert2_path = os.path.join(self.testdata_dir, 'media.x509.pem')
+ with open(cert2_path) as cert2_fp:
+ cert2 = cert2_fp.read()
+
+ # Replace cert1 with cert2, which leads to duplicate entries.
+ input_xml = self.MAC_PERMISSIONS_XML.format(
+ base64.b16encode(common.ParseCertificate(cert1)).lower(),
+ base64.b16encode(common.ParseCertificate(cert2)).lower())
+
+ common.OPTIONS.key_map = {
+ cert1_path[:-9] : cert2_path[:-9],
+ }
+ self.assertRaises(AssertionError, ReplaceCerts, input_xml)
+
+ def test_ReplaceCerts_skipNonExistentCerts(self):
+ cert1_path = os.path.join(self.testdata_dir, 'platform.x509.pem')
+ with open(cert1_path) as cert1_fp:
+ cert1 = cert1_fp.read()
+ cert2_path = os.path.join(self.testdata_dir, 'media.x509.pem')
+ with open(cert2_path) as cert2_fp:
+ cert2 = cert2_fp.read()
+ cert3_path = os.path.join(self.testdata_dir, 'testkey.x509.pem')
+ with open(cert3_path) as cert3_fp:
+ cert3 = cert3_fp.read()
+
+ input_xml = self.MAC_PERMISSIONS_XML.format(
+ base64.b16encode(common.ParseCertificate(cert1)).lower(),
+ base64.b16encode(common.ParseCertificate(cert2)).lower())
+
+ output_xml = self.MAC_PERMISSIONS_XML.format(
+ base64.b16encode(common.ParseCertificate(cert3)).lower(),
+ base64.b16encode(common.ParseCertificate(cert2)).lower())
+
+ common.OPTIONS.key_map = {
+ cert1_path[:-9] : cert3_path[:-9],
+ 'non-existent' : cert3_path[:-9],
+ cert2_path[:-9] : 'non-existent',
+ }
+ self.assertEqual(output_xml, ReplaceCerts(input_xml))
diff --git a/tools/releasetools/test_utils.py b/tools/releasetools/test_utils.py
new file mode 100644
index 0000000..a15ff5b
--- /dev/null
+++ b/tools/releasetools/test_utils.py
@@ -0,0 +1,112 @@
+#
+# 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.
+#
+
+"""
+Utils for running unittests.
+"""
+
+import os
+import os.path
+import struct
+
+import common
+
+
+def get_testdata_dir():
+ """Returns the testdata dir, in relative to the script dir."""
+ # The script dir is the one we want, which could be different from pwd.
+ current_dir = os.path.dirname(os.path.realpath(__file__))
+ return os.path.join(current_dir, 'testdata')
+
+
+def get_search_path():
+ """Returns the search path that has 'framework/signapk.jar' under."""
+ current_dir = os.path.dirname(os.path.realpath(__file__))
+ for path in (
+ # In relative to 'build/make/tools/releasetools' in the Android source.
+ ['..'] * 4 + ['out', 'host', 'linux-x86'],
+ # Or running the script unpacked from otatools.zip.
+ ['..']):
+ full_path = os.path.realpath(os.path.join(current_dir, *path))
+ signapk_path = os.path.realpath(
+ os.path.join(full_path, 'framework', 'signapk.jar'))
+ if os.path.exists(signapk_path):
+ return full_path
+ return None
+
+
+def construct_sparse_image(chunks):
+ """Returns a sparse image file constructed from the given chunks.
+
+ From system/core/libsparse/sparse_format.h.
+ typedef struct sparse_header {
+ __le32 magic; // 0xed26ff3a
+ __le16 major_version; // (0x1) - reject images with higher major versions
+ __le16 minor_version; // (0x0) - allow images with higer minor versions
+ __le16 file_hdr_sz; // 28 bytes for first revision of the file format
+ __le16 chunk_hdr_sz; // 12 bytes for first revision of the file format
+ __le32 blk_sz; // block size in bytes, must be a multiple of 4 (4096)
+ __le32 total_blks; // total blocks in the non-sparse output image
+ __le32 total_chunks; // total chunks in the sparse input image
+ __le32 image_checksum; // CRC32 checksum of the original data, counting
+ // "don't care" as 0. Standard 802.3 polynomial,
+ // use a Public Domain table implementation
+ } sparse_header_t;
+
+ typedef struct chunk_header {
+ __le16 chunk_type; // 0xCAC1 -> raw; 0xCAC2 -> fill;
+ // 0xCAC3 -> don't care
+ __le16 reserved1;
+ __le32 chunk_sz; // in blocks in output image
+ __le32 total_sz; // in bytes of chunk input file including chunk header
+ // and data
+ } chunk_header_t;
+
+ Args:
+ chunks: A list of chunks to be written. Each entry should be a tuple of
+ (chunk_type, block_number).
+
+ Returns:
+ Filename of the created sparse image.
+ """
+ SPARSE_HEADER_MAGIC = 0xED26FF3A
+ SPARSE_HEADER_FORMAT = "<I4H4I"
+ CHUNK_HEADER_FORMAT = "<2H2I"
+
+ sparse_image = common.MakeTempFile(prefix='sparse-', suffix='.img')
+ with open(sparse_image, 'wb') as fp:
+ fp.write(struct.pack(
+ SPARSE_HEADER_FORMAT, SPARSE_HEADER_MAGIC, 1, 0, 28, 12, 4096,
+ sum(chunk[1] for chunk in chunks),
+ len(chunks), 0))
+
+ for chunk in chunks:
+ data_size = 0
+ if chunk[0] == 0xCAC1:
+ data_size = 4096 * chunk[1]
+ elif chunk[0] == 0xCAC2:
+ data_size = 4
+ elif chunk[0] == 0xCAC3:
+ pass
+ else:
+ assert False, "Unsupported chunk type: {}".format(chunk[0])
+
+ fp.write(struct.pack(
+ CHUNK_HEADER_FORMAT, chunk[0], 0, chunk[1], data_size + 12))
+ if data_size != 0:
+ fp.write(os.urandom(data_size))
+
+ return sparse_image
diff --git a/tools/releasetools/testdata/media.x509.pem b/tools/releasetools/testdata/media.x509.pem
new file mode 100644
index 0000000..98cd443
--- /dev/null
+++ b/tools/releasetools/testdata/media.x509.pem
@@ -0,0 +1,27 @@
+-----BEGIN CERTIFICATE-----
+MIIEqDCCA5CgAwIBAgIJAPK5jmEjVyxOMA0GCSqGSIb3DQEBBAUAMIGUMQswCQYD
+VQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4g
+VmlldzEQMA4GA1UEChMHQW5kcm9pZDEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UE
+AxMHQW5kcm9pZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTAe
+Fw0wODA0MTUyMzQwNTdaFw0zNTA5MDEyMzQwNTdaMIGUMQswCQYDVQQGEwJVUzET
+MBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEQMA4G
+A1UEChMHQW5kcm9pZDEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9p
+ZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTCCASAwDQYJKoZI
+hvcNAQEBBQADggENADCCAQgCggEBAK4lDFoW75f8KGmsZRsyF8w2ug6GlkFo1YoE
+n0DOhYZxI6P/tPbZScM88to6BcI+rKpX2AOImxdZvPWefG8hiQriUIW37VaqYmwJ
+ie+czTY2LKDo0blgP9TYModnkmzMCQxot3Wuf/MJNMw2nvKFWiZn3wxmf9DHz12O
+umVYBnNzA7tiRybquu37cvB+16dqs8uaOBxLfc2AmxQNiR8AITvkAfWNagamHq3D
+qcLxxlZyhbCa4JNCpm+kIer5Ot91c6AowzHXBgGrOvfMhAM+znx3KjpbhrDb6dd3
+w6SKqYAe3O4ngVifRNnkETl5YAV2qZQQuoEJElna2YxsaP94S48CAQOjgfwwgfkw
+HQYDVR0OBBYEFMopPKqLwO0+VC7vQgWiv/K1fk11MIHJBgNVHSMEgcEwgb6AFMop
+PKqLwO0+VC7vQgWiv/K1fk11oYGapIGXMIGUMQswCQYDVQQGEwJVUzETMBEGA1UE
+CBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEQMA4GA1UEChMH
+QW5kcm9pZDEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9pZDEiMCAG
+CSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbYIJAPK5jmEjVyxOMAwGA1Ud
+EwQFMAMBAf8wDQYJKoZIhvcNAQEEBQADggEBAITelRbV5KhyF6c9qEhwSPUzc6X3
+M/OQ1hvfPMnlJRYlv8qnwxWcriddFyqa4eh21UWBJ6xUL2gpDdUQwAKdj1Hg7hVr
+e3tazbOUJBuOx4t05cQsXK+uFWyvW9GZojonUk2gct6743hGSlM2MLDk0P+34I7L
+cB+ttjecdEZ/bgDG7YiFlTgHkgOHVgB4csjjAHr0I6V6LKs6KChptkxLe9X8GH0K
+fiQVll1ark4Hpt91G0p16Xk8kYphK4HNC2KK7gFo3ETkexDTWTJghJ1q321yfcJE
+RMIh0/nsw2jK0HmZ8rgQW8HyDTjUEGbMFBHCV6lupDSfV0ZWVQfk6AIKGoE=
+-----END CERTIFICATE-----
diff --git a/tools/releasetools/testdata/payload_signer.sh b/tools/releasetools/testdata/payload_signer.sh
new file mode 100755
index 0000000..a44ef34
--- /dev/null
+++ b/tools/releasetools/testdata/payload_signer.sh
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+# The script will be called with 'payload_signer.sh <key> -in <input> -out <output>'.
+openssl pkeyutl -sign -keyform DER -inkey $1 -pkeyopt digest:sha256 -in $3 -out $5
diff --git a/tools/releasetools/testdata/platform.x509.pem b/tools/releasetools/testdata/platform.x509.pem
new file mode 100644
index 0000000..087f02e
--- /dev/null
+++ b/tools/releasetools/testdata/platform.x509.pem
@@ -0,0 +1,27 @@
+-----BEGIN CERTIFICATE-----
+MIIEqDCCA5CgAwIBAgIJALOZgIbQVs/6MA0GCSqGSIb3DQEBBAUAMIGUMQswCQYD
+VQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4g
+VmlldzEQMA4GA1UEChMHQW5kcm9pZDEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UE
+AxMHQW5kcm9pZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTAe
+Fw0wODA0MTUyMjQwNTBaFw0zNTA5MDEyMjQwNTBaMIGUMQswCQYDVQQGEwJVUzET
+MBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEQMA4G
+A1UEChMHQW5kcm9pZDEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9p
+ZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTCCASAwDQYJKoZI
+hvcNAQEBBQADggENADCCAQgCggEBAJx4BZKsDV04HN6qZezIpgBuNkgMbXIHsSAR
+vlCGOqvitV0Amt9xRtbyICKAx81Ne9smJDuKgGwms0sTdSOkkmgiSQTcAUk+fArP
+GgXIdPabA3tgMJ2QdNJCgOFrrSqHNDYZUer3KkgtCbIEsYdeEqyYwap3PWgAuer9
+5W1Yvtjo2hb5o2AJnDeoNKbf7be2tEoEngeiafzPLFSW8s821k35CjuNjzSjuqtM
+9TNxqydxmzulh1StDFP8FOHbRdUeI0+76TybpO35zlQmE1DsU1YHv2mi/0qgfbX3
+6iANCabBtJ4hQC+J7RGQiTqrWpGA8VLoL4WkV1PPX8GQccXuyCcCAQOjgfwwgfkw
+HQYDVR0OBBYEFE/koLPdnLop9x1yh8Tnw48ghsKZMIHJBgNVHSMEgcEwgb6AFE/k
+oLPdnLop9x1yh8Tnw48ghsKZoYGapIGXMIGUMQswCQYDVQQGEwJVUzETMBEGA1UE
+CBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEQMA4GA1UEChMH
+QW5kcm9pZDEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9pZDEiMCAG
+CSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbYIJALOZgIbQVs/6MAwGA1Ud
+EwQFMAMBAf8wDQYJKoZIhvcNAQEEBQADggEBAFclUbjZOh9z3g9tRp+G2tZwFAAp
+PIigzXzXeLc9r8wZf6t25iEuVsHHYc/EL9cz3lLFCuCIFM78CjtaGkNGBU2Cnx2C
+tCsgSL+ItdFJKe+F9g7dEtctVWV+IuPoXQTIMdYT0Zk4u4mCJH+jISVroS0dao+S
+6h2xw3Mxe6DAN/DRr/ZFrvIkl5+6bnoUvAJccbmBOM7z3fwFlhfPJIRc97QNY4L3
+J17XOElatuWTG5QhdlxJG3L7aOCA29tYwgKdNHyLMozkPvaosVUz7fvpib1qSN1L
+IC7alMarjdW4OZID2q4u1EYjLk/pvZYTlMYwDlE448/Shebk5INTjLixs1c=
+-----END CERTIFICATE-----
diff --git a/tools/releasetools/testdata/sigfile.bin b/tools/releasetools/testdata/sigfile.bin
new file mode 100644
index 0000000..8682216
--- /dev/null
+++ b/tools/releasetools/testdata/sigfile.bin
@@ -0,0 +1 @@
+ºQàÂÜ¢¡½¨Gpø£Õùù°ÔÖ'[4KéL¡c
\ No newline at end of file
diff --git a/tools/releasetools/testdata/signed-sigfile.bin b/tools/releasetools/testdata/signed-sigfile.bin
new file mode 100644
index 0000000..86d2f9e
--- /dev/null
+++ b/tools/releasetools/testdata/signed-sigfile.bin
@@ -0,0 +1,2 @@
+R¡&EÿsÁ%ø?¹|¤&ÍñzbSA[ßtqçWKÒl¦àÙÙås¥Ò~Fcæ `¯¾Í#
+T{Ý×Û½FÒÁxø16Ì=Q°Væ^Tß°ØxX£¶/þ#©êI'ÜîtcLp¬ëovzÑRá:õóWþ9(¹Á26Û̬ábÂBP1¸6ãnÒß±QÕC©gh;r²O}%Ľõáo6ãdê´Éãå2Y`¦ÕÛ¼ª¥_ROrCa,èI"n(`ínñÜÐbaiö¹Å¨ÔäS×Ê)kO[`6c¬e
\ No newline at end of file
diff --git a/tools/releasetools/testdata/testkey.pk8 b/tools/releasetools/testdata/testkey.pk8
new file mode 100644
index 0000000..99be291
--- /dev/null
+++ b/tools/releasetools/testdata/testkey.pk8
Binary files differ
diff --git a/tools/releasetools/testdata/testkey.pubkey.pem b/tools/releasetools/testdata/testkey.pubkey.pem
new file mode 100644
index 0000000..418ae60
--- /dev/null
+++ b/tools/releasetools/testdata/testkey.pubkey.pem
@@ -0,0 +1,9 @@
+-----BEGIN PUBLIC KEY-----
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvjvyO2LwWgmQNyq7z+xK
+04eg0t3AL4y2NhpAAOzVnFyCArFcFjLTGQDDvkbZP6N12O6+dwJoPLntnm9A+VnP
+IFFRHg0HUWSbHM+Qk8Jgv2/2AVkAUj5J1r9t4X+2WI0eRzJP15Zjn68pQKGmcyci
+ry0gbvmYvXL2ZUmTm56DmEfCUCRIY2IGJ/CcMnFeItVU0LxKsV5Mlt5BO0Vv/CV4
+EaiOLwyCnoZuUhYto7dHlO/47v/H9zhkJC54OA1dkD38EPgO5GnfhGFSNXQRmJDT
+XrFgd6O+QO4yUNX8lYP10MzimUpItZa05t68NADqwYl3T7nWzvuC9r4IqZDyPf21
+TQIDAQAB
+-----END PUBLIC KEY-----
diff --git a/tools/releasetools/testdata/testkey.x509.pem b/tools/releasetools/testdata/testkey.x509.pem
new file mode 100644
index 0000000..65c8085
--- /dev/null
+++ b/tools/releasetools/testdata/testkey.x509.pem
@@ -0,0 +1,24 @@
+-----BEGIN CERTIFICATE-----
+MIIEADCCAuigAwIBAgIJAN/FvjYzGNOKMA0GCSqGSIb3DQEBCwUAMIGUMQswCQYD
+VQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4g
+VmlldzEQMA4GA1UECgwHQW5kcm9pZDEQMA4GA1UECwwHQW5kcm9pZDEQMA4GA1UE
+AwwHQW5kcm9pZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTAe
+Fw0xODAxMTgwMDM0NTFaFw00NTA2MDUwMDM0NTFaMIGUMQswCQYDVQQGEwJVUzET
+MBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEQMA4G
+A1UECgwHQW5kcm9pZDEQMA4GA1UECwwHQW5kcm9pZDEQMA4GA1UEAwwHQW5kcm9p
+ZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBAL478jti8FoJkDcqu8/sStOHoNLdwC+MtjYa
+QADs1ZxcggKxXBYy0xkAw75G2T+jddjuvncCaDy57Z5vQPlZzyBRUR4NB1FkmxzP
+kJPCYL9v9gFZAFI+Sda/beF/tliNHkcyT9eWY5+vKUChpnMnIq8tIG75mL1y9mVJ
+k5ueg5hHwlAkSGNiBifwnDJxXiLVVNC8SrFeTJbeQTtFb/wleBGoji8Mgp6GblIW
+LaO3R5Tv+O7/x/c4ZCQueDgNXZA9/BD4DuRp34RhUjV0EZiQ016xYHejvkDuMlDV
+/JWD9dDM4plKSLWWtObevDQA6sGJd0+51s77gva+CKmQ8j39tU0CAwEAAaNTMFEw
+HQYDVR0OBBYEFNJPJZDpq6tc/19Z2kxPA2bj9D6UMB8GA1UdIwQYMBaAFNJPJZDp
+q6tc/19Z2kxPA2bj9D6UMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQAD
+ggEBABSUG9qrwV3WcClDJwqkNLN4yeVVYzkRMGA8/XqOiYrW4zh0mKDLfr6OeU1C
+AKwZBLhhql59Po25r4gcwPiTN2DkoCfb3T59XG8J54PAgTQjIAZ3J+mGZplnmuD3
+wj+UGUpPe0qTr33ZPoJfwxVo4RVnOt/UCsIGXch0HS/BIdpechqP0w4rOHUbq6EA
+8UEi5irKSDOU9b/5rD/tX2f4nGwJlKQEHWrsj9LLKlaL7fX36ghoSxN/pBJOhedg
+/VjT6xbaEwfyhC6Zj9av5Xl7UdpYt+rBMroAGenz0OSxKhIphdcx4ZMhvfkBoYG9
+Crupdqe+kUsfg2RlPb5grQ3klMo=
+-----END CERTIFICATE-----
diff --git a/tools/releasetools/testdata/testkey_with_passwd.pk8 b/tools/releasetools/testdata/testkey_with_passwd.pk8
new file mode 100644
index 0000000..3d567de
--- /dev/null
+++ b/tools/releasetools/testdata/testkey_with_passwd.pk8
Binary files differ
diff --git a/tools/releasetools/testdata/testkey_with_passwd.x509.pem b/tools/releasetools/testdata/testkey_with_passwd.x509.pem
new file mode 100644
index 0000000..449396e
--- /dev/null
+++ b/tools/releasetools/testdata/testkey_with_passwd.x509.pem
@@ -0,0 +1,24 @@
+-----BEGIN CERTIFICATE-----
+MIIEADCCAuigAwIBAgIJANefUd3Piu0yMA0GCSqGSIb3DQEBCwUAMIGUMQswCQYD
+VQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4g
+VmlldzEQMA4GA1UECgwHQW5kcm9pZDEQMA4GA1UECwwHQW5kcm9pZDEQMA4GA1UE
+AwwHQW5kcm9pZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTAe
+Fw0xODAxMTgwMDI3NDRaFw00NTA2MDUwMDI3NDRaMIGUMQswCQYDVQQGEwJVUzET
+MBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEQMA4G
+A1UECgwHQW5kcm9pZDEQMA4GA1UECwwHQW5kcm9pZDEQMA4GA1UEAwwHQW5kcm9p
+ZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBALBoA4c+qCQKapQAVGclbousC5J/L0TNZJEd
+KSW2nzXUHIwgTQ3r82227xkIvjnqXMCsc0q3/N2gGKR4sHqA30JO9Dyfgsx1ISaR
+GXe5cG048m5U5snplQgvPovtah9ZyvwNPzWPYC3uceJaDxKQKwVdsV+mOWM6WmpQ
+bdLO37jxfytyAbzaz3sG5HA3FSB8rX/xDM6If18NsxSHpcjaOjZXC4Fg6wlp0klY
+5/qhFEdmieu2zQVelXjoJfKSku8tPa7kZeDU/F3uLUq/U/xvFk7NVsRV+QvYOdQK
+1QECc/3yv1TKNAN3huWTgzCX6bMHmi09Npw3MQaGY0oS34cH9x0CAwEAAaNTMFEw
+HQYDVR0OBBYEFNsJZ0n9Opeea0rVAzL+1jwkDKzPMB8GA1UdIwQYMBaAFNsJZ0n9
+Opeea0rVAzL+1jwkDKzPMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQAD
+ggEBAJ/bzIzA+NrYwPEv56XKf6Vuj81+M1rTHAsH9PqbOvJT7iM7aU7wAl6vmXAo
+DQtvKoOBMdIXprapwe0quHCQm7PGxg+RRegr+dcTSVJFv1plnODOBOEAVlEfFwuW
+Cz0USF2jrNq+4ciH5zPL1a31ONb1rMkxJXQ/tAi0x8m6tZz+jsbE0wO6qB80UmkA
+4WY2Tu/gnAvFpD8plkiU0EKwedBHAcaFFZkQp23MKsVZ3UBqsqzzfXDYV1Oa6rIy
+XIZpI2Gx75pvAb57T2ap/yl0DBEAu7Nmpll0GCsgeJVdy7tS4LNj96Quya3CHWQw
+WNTVuan0KZqwDIm4Xn1oHUFQ9vc=
+-----END CERTIFICATE-----
diff --git a/tools/releasetools/testdata/verity.x509.pem b/tools/releasetools/testdata/verity.x509.pem
new file mode 100644
index 0000000..86399c3
--- /dev/null
+++ b/tools/releasetools/testdata/verity.x509.pem
@@ -0,0 +1,24 @@
+-----BEGIN CERTIFICATE-----
+MIID/TCCAuWgAwIBAgIJAJcPmDkJqolJMA0GCSqGSIb3DQEBBQUAMIGUMQswCQYD
+VQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4g
+VmlldzEQMA4GA1UECgwHQW5kcm9pZDEQMA4GA1UECwwHQW5kcm9pZDEQMA4GA1UE
+AwwHQW5kcm9pZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTAe
+Fw0xNDExMDYxOTA3NDBaFw00MjAzMjQxOTA3NDBaMIGUMQswCQYDVQQGEwJVUzET
+MBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEQMA4G
+A1UECgwHQW5kcm9pZDEQMA4GA1UECwwHQW5kcm9pZDEQMA4GA1UEAwwHQW5kcm9p
+ZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBAOjreE0vTVSRenuzO9vnaWfk0eQzYab0gqpi
+6xAzi6dmD+ugoEKJmbPiuE5Dwf21isZ9uhUUu0dQM46dK4ocKxMRrcnmGxydFn6o
+fs3ODJMXOkv2gKXL/FdbEPdDbxzdu8z3yk+W67udM/fW7WbaQ3DO0knu+izKak/3
+T41c5uoXmQ81UNtAzRGzGchNVXMmWuTGOkg6U+0I2Td7K8yvUMWhAWPPpKLtVH9r
+AL5TzjYNR92izdKcz3AjRsI3CTjtpiVABGeX0TcjRSuZB7K9EK56HV+OFNS6I1NP
+jdD7FIShyGlqqZdUOkAUZYanbpgeT5N7QL6uuqcGpoTOkalu6kkCAwEAAaNQME4w
+HQYDVR0OBBYEFH5DM/m7oArf4O3peeKO0ZIEkrQPMB8GA1UdIwQYMBaAFH5DM/m7
+oArf4O3peeKO0ZIEkrQPMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEB
+AHO3NSvDE5jFvMehGGtS8BnFYdFKRIglDMc4niWSzhzOVYRH4WajxdtBWc5fx0ix
+NF/+hVKVhP6AIOQa+++sk+HIi7RvioPPbhjcsVlZe7cUEGrLSSveGouQyc+j0+m6
+JF84kszIl5GGNMTnx0XRPO+g8t6h5LWfnVydgZfpGRRg+WHewk1U2HlvTjIceb0N
+dcoJ8WKJAFWdcuE7VIm4w+vF/DYX/A2Oyzr2+QRhmYSv1cusgAeC1tvH4ap+J1Lg
+UnOu5Kh/FqPLLSwNVQp4Bu7b9QFfqK8Moj84bj88NqRGZgDyqzuTrFxn6FW7dmyA
+yttuAJAEAymk1mipd9+zp38=
+-----END CERTIFICATE-----
diff --git a/tools/releasetools/validate_target_files.py b/tools/releasetools/validate_target_files.py
index b065a21..8c9e07c 100755
--- a/tools/releasetools/validate_target_files.py
+++ b/tools/releasetools/validate_target_files.py
@@ -23,40 +23,24 @@
same check also applies to the vendor image if present.
"""
-import common
import logging
import os.path
import re
-import sparse_img
import sys
+import zipfile
-
-def _GetImage(which, tmpdir):
- assert which in ('system', 'vendor')
-
- path = os.path.join(tmpdir, 'IMAGES', which + '.img')
- mappath = os.path.join(tmpdir, 'IMAGES', which + '.map')
-
- # Map file must exist (allowed to be empty).
- assert os.path.exists(path) and os.path.exists(mappath)
-
- clobbered_blocks = '0'
- return sparse_img.SparseImage(path, mappath, clobbered_blocks)
+import common
def _ReadFile(file_name, unpacked_name, round_up=False):
"""Constructs and returns a File object. Rounds up its size if needed."""
- def RoundUpTo4K(value):
- rounded_up = value + 4095
- return rounded_up - (rounded_up % 4096)
-
assert os.path.exists(unpacked_name)
with open(unpacked_name, 'r') as f:
file_data = f.read()
file_size = len(file_data)
if round_up:
- file_size_rounded_up = RoundUpTo4K(file_size)
+ file_size_rounded_up = common.RoundUpTo4K(file_size)
file_data += '\0' * (file_size_rounded_up - file_size)
return common.File(file_name, file_data)
@@ -64,23 +48,27 @@
def ValidateFileAgainstSha1(input_tmp, file_name, file_path, expected_sha1):
"""Check if the file has the expected SHA-1."""
- logging.info('Validating the SHA-1 of {}'.format(file_name))
+ logging.info('Validating the SHA-1 of %s', file_name)
unpacked_name = os.path.join(input_tmp, file_path)
assert os.path.exists(unpacked_name)
actual_sha1 = _ReadFile(file_name, unpacked_name, False).sha1
assert actual_sha1 == expected_sha1, \
'SHA-1 mismatches for {}. actual {}, expected {}'.format(
- file_name, actual_sha1, expected_sha1)
+ file_name, actual_sha1, expected_sha1)
-def ValidateFileConsistency(input_zip, input_tmp):
+def ValidateFileConsistency(input_zip, input_tmp, info_dict):
"""Compare the files from image files and unpacked folders."""
def CheckAllFiles(which):
logging.info('Checking %s image.', which)
- image = _GetImage(which, input_tmp)
+ # Allow having shared blocks when loading the sparse image, because allowing
+ # that doesn't affect the checks below (we will have all the blocks on file,
+ # unless it's skipped due to the holes).
+ image = common.GetSparseImage(which, input_tmp, input_zip, True)
prefix = '/' + which
for entry in image.file_map:
+ # Skip entries like '__NONZERO-0'.
if not entry.startswith(prefix):
continue
@@ -88,6 +76,11 @@
# bytes past the file length, which is expected to be padded with '\0's.
ranges = image.file_map[entry]
+ incomplete = ranges.extra.get('incomplete', False)
+ if incomplete:
+ logging.warning('Skipping %s that has incomplete block list', entry)
+ continue
+
# TODO(b/79951650): Handle files with non-monotonic ranges.
if not ranges.monotonic:
logging.warning(
@@ -100,18 +93,6 @@
unpacked_name = os.path.join(
input_tmp, which.upper(), entry[(len(prefix) + 1):])
unpacked_file = _ReadFile(entry, unpacked_name, True)
- file_size = unpacked_file.size
-
- # block.map may contain less blocks, because mke2fs may skip allocating
- # blocks if they contain all zeros. We can't reconstruct such a file from
- # its block list. (Bug: 65213616)
- if file_size > ranges.size() * 4096:
- logging.warning(
- 'Skipping %s that has less blocks: file size %d-byte,'
- ' ranges %s (%d-byte)', entry, file_size, ranges,
- ranges.size() * 4096)
- continue
-
file_sha1 = unpacked_file.sha1
assert blocks_sha1 == file_sha1, \
'file: %s, range: %s, blocks_sha1: %s, file_sha1: %s' % (
@@ -119,6 +100,11 @@
logging.info('Validating file consistency.')
+ # TODO(b/79617342): Validate non-sparse images.
+ if info_dict.get('extfs_sparse_flag') != '-s':
+ logging.warning('Skipped due to target using non-sparse images')
+ return
+
# Verify IMAGES/system.img.
CheckAllFiles('system')
@@ -154,10 +140,10 @@
script_path = 'SYSTEM/bin/install-recovery.sh'
if not os.path.exists(os.path.join(input_tmp, script_path)):
- logging.info('{} does not exist in input_tmp'.format(script_path))
+ logging.info('%s does not exist in input_tmp', script_path)
return
- logging.info('Checking {}'.format(script_path))
+ logging.info('Checking %s', script_path)
with open(os.path.join(input_tmp, script_path), 'r') as script:
lines = script.read().strip().split('\n')
assert len(lines) >= 6
@@ -175,7 +161,7 @@
expected_recovery_sha1 = applypatch_argv[3].strip()
assert expected_recovery_check_sha1 == expected_recovery_sha1
ValidateFileAgainstSha1(input_tmp, 'recovery.img',
- 'SYSTEM/etc/recovery.img', expected_recovery_sha1)
+ 'SYSTEM/etc/recovery.img', expected_recovery_sha1)
else:
# We're patching boot.img to get recovery.img where bonus_args is optional
if applypatch_argv[1] == "-b":
@@ -189,16 +175,17 @@
boot_info = applypatch_argv[boot_info_index].strip().split(':')
assert len(boot_info) == 4
ValidateFileAgainstSha1(input_tmp, file_name='boot.img',
- file_path='IMAGES/boot.img', expected_sha1=boot_info[3])
+ file_path='IMAGES/boot.img',
+ expected_sha1=boot_info[3])
recovery_sha1_index = boot_info_index + 2
expected_recovery_sha1 = applypatch_argv[recovery_sha1_index]
assert expected_recovery_check_sha1 == expected_recovery_sha1
ValidateFileAgainstSha1(input_tmp, file_name='recovery.img',
- file_path='IMAGES/recovery.img',
- expected_sha1=expected_recovery_sha1)
+ file_path='IMAGES/recovery.img',
+ expected_sha1=expected_recovery_sha1)
- logging.info('Done checking {}'.format(script_path))
+ logging.info('Done checking %s', script_path)
def main(argv):
@@ -220,11 +207,12 @@
datefmt=date_format)
logging.info("Unzipping the input target_files.zip: %s", args[0])
- input_tmp, input_zip = common.UnzipTemp(args[0])
-
- ValidateFileConsistency(input_zip, input_tmp)
+ input_tmp = common.UnzipTemp(args[0])
info_dict = common.LoadInfoDict(input_tmp)
+ with zipfile.ZipFile(args[0], 'r') as input_zip:
+ ValidateFileConsistency(input_zip, input_tmp, info_dict)
+
ValidateInstallRecoveryScript(input_tmp, info_dict)
# TODO: Check if the OTA keys have been properly updated (the ones on /system,
diff --git a/tools/signapk/Android.bp b/tools/signapk/Android.bp
new file mode 100644
index 0000000..4954cf5
--- /dev/null
+++ b/tools/signapk/Android.bp
@@ -0,0 +1,31 @@
+//
+// 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.
+//
+
+// the signapk tool (a .jar application used to sign packages)
+// ============================================================
+java_library_host {
+ name: "signapk",
+ srcs: ["src/**/*.java"],
+ manifest: "SignApk.mf",
+ static_libs: [
+ "apksig",
+ "bouncycastle",
+ "bouncycastle-bcpkix",
+ "conscrypt",
+ ],
+
+ required: ["libconscrypt_openjdk_jni"],
+}
diff --git a/tools/signapk/Android.mk b/tools/signapk/Android.mk
index 051a51d..ff54d6d 100644
--- a/tools/signapk/Android.mk
+++ b/tools/signapk/Android.mk
@@ -15,24 +15,10 @@
#
LOCAL_PATH := $(call my-dir)
-# the signapk tool (a .jar application used to sign packages)
-# ============================================================
-include $(CLEAR_VARS)
-LOCAL_MODULE := signapk
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_JAR_MANIFEST := SignApk.mf
-LOCAL_STATIC_JAVA_LIBRARIES := \
- apksig \
- bouncycastle-host \
- bouncycastle-bcpkix-host \
- conscrypt-host
-LOCAL_REQUIRED_MODULES := libconscrypt_openjdk_jni
-include $(BUILD_HOST_JAVA_LIBRARY)
-
ifeq ($(TARGET_BUILD_APPS),)
# The post-build signing tools need signapk.jar and its shared libraries,
# but we don't need this if we're just doing unbundled apps.
-my_dist_files := $(LOCAL_INSTALLED_MODULE) \
+my_dist_files := $(HOST_OUT_JAVA_LIBRARIES)/signapk.jar \
$(HOST_OUT_SHARED_LIBRARIES)/libconscrypt_openjdk_jni$(HOST_SHLIB_SUFFIX)
$(call dist-for-goals,droidcore,$(my_dist_files))
diff --git a/tools/signapk/OWNERS b/tools/signapk/OWNERS
new file mode 100644
index 0000000..0b8d398
--- /dev/null
+++ b/tools/signapk/OWNERS
@@ -0,0 +1,2 @@
+cbrubaker@google.com
+klyubin@google.com
diff --git a/tools/signapk/src/com/android/signapk/SignApk.java b/tools/signapk/src/com/android/signapk/SignApk.java
index 3b00599..fdf6283 100644
--- a/tools/signapk/src/com/android/signapk/SignApk.java
+++ b/tools/signapk/src/com/android/signapk/SignApk.java
@@ -1082,14 +1082,15 @@
ByteBuffer[] outputChunks = new ByteBuffer[] {v1SignedApk};
ZipSections zipSections = findMainZipSections(v1SignedApk);
- ApkSignerEngine.OutputApkSigningBlockRequest addV2SignatureRequest =
- apkSigner.outputZipSections(
+ ApkSignerEngine.OutputApkSigningBlockRequest2 addV2SignatureRequest =
+ apkSigner.outputZipSections2(
DataSources.asDataSource(zipSections.beforeCentralDir),
DataSources.asDataSource(zipSections.centralDir),
DataSources.asDataSource(zipSections.eocd));
if (addV2SignatureRequest != null) {
// Need to insert the returned APK Signing Block before ZIP Central
// Directory.
+ int padding = addV2SignatureRequest.getPaddingSizeBeforeApkSigningBlock();
byte[] apkSigningBlock = addV2SignatureRequest.getApkSigningBlock();
// Because the APK Signing Block is inserted before the Central Directory,
// we need to adjust accordingly the offset of Central Directory inside the
@@ -1100,10 +1101,12 @@
modifiedEocd.order(ByteOrder.LITTLE_ENDIAN);
ApkUtils.setZipEocdCentralDirectoryOffset(
modifiedEocd,
- zipSections.beforeCentralDir.remaining() + apkSigningBlock.length);
+ zipSections.beforeCentralDir.remaining() + padding +
+ apkSigningBlock.length);
outputChunks =
new ByteBuffer[] {
zipSections.beforeCentralDir,
+ ByteBuffer.allocate(padding),
ByteBuffer.wrap(apkSigningBlock),
zipSections.centralDir,
modifiedEocd};
diff --git a/tools/signtos/Android.bp b/tools/signtos/Android.bp
new file mode 100644
index 0000000..b26631f
--- /dev/null
+++ b/tools/signtos/Android.bp
@@ -0,0 +1,27 @@
+//
+// 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.
+//
+
+// the signtos tool - signs Trusty images
+// ============================================================
+java_library_host {
+ name: "signtos",
+ srcs: ["SignTos.java"],
+ manifest: "SignTos.mf",
+ static_libs: [
+ "bouncycastle",
+ "bouncycastle-bcpkix",
+ ],
+}
diff --git a/tools/signtos/Android.mk b/tools/signtos/Android.mk
deleted file mode 100644
index 94ab944..0000000
--- a/tools/signtos/Android.mk
+++ /dev/null
@@ -1,25 +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.
-#
-LOCAL_PATH := $(call my-dir)
-
-# the signtos tool - signs Trusty images
-# ============================================================
-include $(CLEAR_VARS)
-LOCAL_MODULE := signtos
-LOCAL_SRC_FILES := SignTos.java
-LOCAL_JAR_MANIFEST := SignTos.mf
-LOCAL_STATIC_JAVA_LIBRARIES := bouncycastle-host bouncycastle-bcpkix-host
-include $(BUILD_HOST_JAVA_LIBRARY)
diff --git a/tools/soong_to_convert.py b/tools/soong_to_convert.py
index 3d62d43..083f6f7 100755
--- a/tools/soong_to_convert.py
+++ b/tools/soong_to_convert.py
@@ -76,8 +76,10 @@
problems = dict()
deps = dict()
reverse_deps = dict()
+ module_types = dict()
- for (module, problem, dependencies) in reader:
+ for (module, module_type, problem, dependencies) in reader:
+ module_types[module] = module_type
problems[module] = problem
deps[module] = [d for d in dependencies.strip().split(' ') if d != ""]
for dep in deps[module]:
@@ -94,16 +96,19 @@
extra = ""
if len(problems[module]) > 0:
extra = " ({})".format(problems[module])
- results.append((count_deps(reverse_deps, module, []), module + extra))
+ results.append((count_deps(reverse_deps, module, []), module + extra, module_types[module]))
return sorted(results, key=lambda result: (-result[0], result[1]))
+def filter(results, module_type):
+ return [x for x in results if x[2] == module_type]
+
def display(results):
"""Displays the results"""
count_header = "# Blocked on"
count_width = len(count_header)
print("{} Module (potential problems)".format(count_header))
- for (count, module) in results:
+ for (count, module, module_type) in results:
print("{:>{}} {}".format(count, count_width, module))
def main(filename):
@@ -111,7 +116,15 @@
with open(filename, 'rb') as csvfile:
results = process(csv.reader(csvfile))
- display(results)
+ native_results = filter(results, "native")
+ java_results = filter(results, "java")
+
+ print("native modules ready to convert")
+ display(native_results)
+
+ print("")
+ print("java modules ready to convert")
+ display(java_results)
if __name__ == "__main__":
if len(sys.argv) != 2:
diff --git a/tools/vendor_buildinfo.sh b/tools/vendor_buildinfo.sh
index 485ada3..c12f7cb 100755
--- a/tools/vendor_buildinfo.sh
+++ b/tools/vendor_buildinfo.sh
@@ -6,10 +6,10 @@
echo "ro.product.board=$TARGET_BOOTLOADER_BOARD_NAME"
echo "ro.board.platform=$TARGET_BOARD_PLATFORM"
-echo "ro.vendor.product.manufacturer=$PRODUCT_MANUFACTURER"
-echo "ro.vendor.product.model=$PRODUCT_MODEL"
-echo "ro.vendor.product.brand=$PRODUCT_BRAND"
-echo "ro.vendor.product.name=$PRODUCT_NAME"
-echo "ro.vendor.product.device=$TARGET_DEVICE"
+echo "ro.product.vendor.manufacturer=$PRODUCT_MANUFACTURER"
+echo "ro.product.vendor.model=$PRODUCT_MODEL"
+echo "ro.product.vendor.brand=$PRODUCT_BRAND"
+echo "ro.product.vendor.name=$PRODUCT_NAME"
+echo "ro.product.vendor.device=$TARGET_DEVICE"
echo "# end build properties"
diff --git a/tools/warn.py b/tools/warn.py
index 44ad368..01398be 100755
--- a/tools/warn.py
+++ b/tools/warn.py
@@ -509,6 +509,26 @@
{'category': 'java',
'severity': Severity.LOW,
'description':
+ 'Java: Fields that can be null should be annotated @Nullable',
+ 'patterns': [r".*: warning: \[FieldMissingNullable\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.LOW,
+ 'description':
+ 'Java: Method parameters that aren\'t checked for null shouldn\'t be annotated @Nullable',
+ 'patterns': [r".*: warning: \[ParameterNotNullable\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.LOW,
+ 'description':
+ 'Java: Methods that can return null should be annotated @Nullable',
+ 'patterns': [r".*: warning: \[ReturnMissingNullable\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.LOW,
+ 'description':
+ 'Java: Use parameter comments to document ambiguous literals',
+ 'patterns': [r".*: warning: \[BooleanParameter\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.LOW,
+ 'description':
'Java: Field name is CONSTANT CASE, but field is not static and final',
'patterns': [r".*: warning: \[ConstantField\] .+"]},
{'category': 'java',
@@ -519,11 +539,21 @@
{'category': 'java',
'severity': Severity.LOW,
'description':
+ 'Java: Use Java\'s utility functional interfaces instead of Function\u003cA, B> for primitive types.',
+ 'patterns': [r".*: warning: \[LambdaFunctionalInterface\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.LOW,
+ 'description':
'Java: Prefer \'L\' to \'l\' for the suffix to long literals',
'patterns': [r".*: warning: \[LongLiteralLowerCaseSuffix\] .+"]},
{'category': 'java',
'severity': Severity.LOW,
'description':
+ 'Java: A private method that does not reference the enclosing instance can be static',
+ 'patterns': [r".*: warning: \[MethodCanBeStatic\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.LOW,
+ 'description':
'Java: C-style array declarations should not be used',
'patterns': [r".*: warning: \[MixedArrayDimensions\] .+"]},
{'category': 'java',
@@ -539,11 +569,21 @@
{'category': 'java',
'severity': Severity.LOW,
'description':
+ 'Java: Avoid having multiple unary operators acting on the same variable in a method call',
+ 'patterns': [r".*: warning: \[MultipleUnaryOperatorsInMethodCall\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.LOW,
+ 'description':
'Java: Package names should match the directory they are declared in',
'patterns': [r".*: warning: \[PackageLocation\] .+"]},
{'category': 'java',
'severity': Severity.LOW,
'description':
+ 'Java: Non-standard parameter comment; prefer `/*paramName=*/ arg`',
+ 'patterns': [r".*: warning: \[ParameterComment\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.LOW,
+ 'description':
'Java: Utility classes (only static members) are not designed to be instantiated and should be made noninstantiable with a default constructor.',
'patterns': [r".*: warning: \[PrivateConstructorForUtilityClass\] .+"]},
{'category': 'java',
@@ -554,11 +594,31 @@
{'category': 'java',
'severity': Severity.LOW,
'description':
+ 'Java: The default case of a switch should appear at the end of the last statement group',
+ 'patterns': [r".*: warning: \[SwitchDefault\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.LOW,
+ 'description':
'Java: Unchecked exceptions do not need to be declared in the method signature.',
'patterns': [r".*: warning: \[ThrowsUncheckedException\] .+"]},
{'category': 'java',
'severity': Severity.LOW,
'description':
+ 'Java: Type parameters must be a single letter with an optional numeric suffix, or an UpperCamelCase name followed by the letter \'T\'.',
+ 'patterns': [r".*: warning: \[TypeParameterNaming\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.LOW,
+ 'description':
+ 'Java: Constructors and methods with the same name should appear sequentially with no other code in between',
+ 'patterns': [r".*: warning: \[UngroupedOverloads\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.LOW,
+ 'description':
+ 'Java: Unnecessary call to NullPointerTester#setDefault',
+ 'patterns': [r".*: warning: \[UnnecessarySetDefault\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.LOW,
+ 'description':
'Java: Using static imports for types is unnecessary',
'patterns': [r".*: warning: \[UnnecessaryStaticImport\] .+"]},
{'category': 'java',
@@ -567,6 +627,61 @@
'Java: Wildcard imports, static or otherwise, should not be used',
'patterns': [r".*: warning: \[WildcardImport\] .+"]},
{'category': 'java',
+ 'severity': Severity.LOW,
+ 'description':
+ 'Java: ',
+ 'patterns': [r".*: warning: \[RemoveFieldPrefixes\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.LOW,
+ 'description':
+ 'Java: Prefer assertThrows to ExpectedException',
+ 'patterns': [r".*: warning: \[ExpectedExceptionMigration\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.LOW,
+ 'description':
+ 'Java: Logger instances are not constants -- they are mutable and have side effects -- and should not be named using CONSTANT CASE',
+ 'patterns': [r".*: warning: \[LoggerVariableCase\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.LOW,
+ 'description':
+ 'Java: Prefer assertThrows to @Test(expected=...)',
+ 'patterns': [r".*: warning: \[TestExceptionMigration\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.MEDIUM,
+ 'description':
+ 'Java: Public fields must be final.',
+ 'patterns': [r".*: warning: \[NonFinalPublicFields\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.MEDIUM,
+ 'description':
+ 'Java: Private fields that are only assigned in the initializer should be made final.',
+ 'patterns': [r".*: warning: \[PrivateFieldsNotAssigned\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.MEDIUM,
+ 'description':
+ 'Java: Lists returned by methods should be immutable.',
+ 'patterns': [r".*: warning: \[ReturnedListNotImmutable\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.MEDIUM,
+ 'description':
+ 'Java: Parameters to log methods should not be generated by a call to String.format() or MessageFormat.format().',
+ 'patterns': [r".*: warning: \[SaferLoggerFormat\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.MEDIUM,
+ 'description':
+ 'Java: Parameters to log methods should not be generated by a call to toString(); see b/22986665.',
+ 'patterns': [r".*: warning: \[SaferLoggerToString\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.MEDIUM,
+ 'description':
+ 'Java: A call to Binder.clearCallingIdentity() should be followed by Binder.restoreCallingIdentity() in a finally block. Otherwise the wrong Binder identity may be used by subsequent code.',
+ 'patterns': [r".*: warning: \[BinderIdentityRestoredDangerously\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.MEDIUM,
+ 'description':
+ 'Java: Classes extending PreferenceActivity must implement isValidFragment such that it does not unconditionally return true to prevent vulnerability to fragment injection attacks.',
+ 'patterns': [r".*: warning: \[FragmentInjection\] .+"]},
+ {'category': 'java',
'severity': Severity.MEDIUM,
'description':
'Java: Subclasses of Fragment must be instantiable via Class#newInstance(): the class must be public, static and have a public nullary constructor',
@@ -579,6 +694,26 @@
{'category': 'java',
'severity': Severity.MEDIUM,
'description':
+ 'Java: A wakelock acquired with a timeout may be released by the system before calling `release`, even after checking `isHeld()`. If so, it will throw a RuntimeException. Please wrap in a try/catch block.',
+ 'patterns': [r".*: warning: \[WakelockReleasedDangerously\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.MEDIUM,
+ 'description':
+ 'Java: Arguments are in the wrong order or could be commented for clarity.',
+ 'patterns': [r".*: warning: \[ArgumentSelectionDefectChecker\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.MEDIUM,
+ 'description':
+ 'Java: Arguments are swapped in assertEquals-like call',
+ 'patterns': [r".*: warning: \[AssertEqualsArgumentOrderChecker\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.MEDIUM,
+ 'description':
+ 'Java: An equality test between objects with incompatible types always returns false',
+ 'patterns': [r".*: warning: \[EqualsIncompatibleType\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.MEDIUM,
+ 'description':
'Java: @AssistedInject and @Inject should not be used on different constructors in the same class.',
'patterns': [r".*: warning: \[AssistedInjectAndInjectOnConstructors\] .+"]},
{'category': 'java',
@@ -604,11 +739,21 @@
{'category': 'java',
'severity': Severity.MEDIUM,
'description':
+ 'Java: The ordering of parameters in overloaded methods should be as consistent as possible (when viewed from left to right)',
+ 'patterns': [r".*: warning: \[InconsistentOverloads\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.MEDIUM,
+ 'description':
'Java: Double-checked locking on non-volatile fields is unsafe',
'patterns': [r".*: warning: \[DoubleCheckedLocking\] .+"]},
{'category': 'java',
'severity': Severity.MEDIUM,
'description':
+ 'Java: Annotations should always be immutable',
+ 'patterns': [r".*: warning: \[ImmutableAnnotationChecker\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.MEDIUM,
+ 'description':
'Java: Enums should always be immutable',
'patterns': [r".*: warning: \[ImmutableEnumChecker\] .+"]},
{'category': 'java',
@@ -629,13 +774,13 @@
{'category': 'java',
'severity': Severity.MEDIUM,
'description':
- 'Java: A different potential argument is more similar to the name of the parameter than the existing argument; this may be an error',
- 'patterns': [r".*: warning: \[ArgumentParameterMismatch\] .+"]},
+ 'Java: Assertions may be disabled at runtime and do not guarantee that execution will halt here; consider throwing an exception instead',
+ 'patterns': [r".*: warning: \[AssertFalse\] .+"]},
{'category': 'java',
'severity': Severity.MEDIUM,
'description':
- 'Java: Assertions may be disabled at runtime and do not guarantee that execution will halt here; consider throwing an exception instead',
- 'patterns': [r".*: warning: \[AssertFalse\] .+"]},
+ 'Java: This assertion throws an AssertionError if it fails, which will be caught by an enclosing try block.',
+ 'patterns': [r".*: warning: \[AssertionFailureIgnored\] .+"]},
{'category': 'java',
'severity': Severity.MEDIUM,
'description':
@@ -664,23 +809,63 @@
{'category': 'java',
'severity': Severity.MEDIUM,
'description':
+ 'Java: Duration can be expressed more clearly with different units',
+ 'patterns': [r".*: warning: \[CanonicalDuration\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.MEDIUM,
+ 'description':
+ 'Java: Logging or rethrowing exceptions should usually be preferred to catching and calling printStackTrace',
+ 'patterns': [r".*: warning: \[CatchAndPrintStackTrace\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.MEDIUM,
+ 'description':
+ 'Java: Ignoring exceptions and calling fail() is unnecessary, and makes test output less useful',
+ 'patterns': [r".*: warning: \[CatchFail\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.MEDIUM,
+ 'description':
'Java: Inner class is non-static but does not reference enclosing class',
'patterns': [r".*: warning: \[ClassCanBeStatic\] .+"]},
{'category': 'java',
'severity': Severity.MEDIUM,
'description':
- 'Java: Class.newInstance() bypasses exception checking; prefer getConstructor().newInstance()',
+ 'Java: Class.newInstance() bypasses exception checking; prefer getDeclaredConstructor().newInstance()',
'patterns': [r".*: warning: \[ClassNewInstance\] .+"]},
{'category': 'java',
'severity': Severity.MEDIUM,
'description':
- 'Java: Implicit use of the platform default charset, which can result in e.g. non-ASCII characters being silently replaced with \'?\' in many environments',
- 'patterns': [r".*: warning: \[DefaultCharset\] .+"]},
+ 'Java: The type of the array parameter of Collection.toArray needs to be compatible with the array type',
+ 'patterns': [r".*: warning: \[CollectionToArraySafeParameter\] .+"]},
{'category': 'java',
'severity': Severity.MEDIUM,
'description':
- 'Java: This code, which counts elements using a loop, can be replaced by a simpler library method',
- 'patterns': [r".*: warning: \[ElementsCountedInLoop\] .+"]},
+ 'Java: Collector.of() should not use state',
+ 'patterns': [r".*: warning: \[CollectorShouldNotUseState\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.MEDIUM,
+ 'description':
+ 'Java: Class should not implement both `Comparable` and `Comparator`',
+ 'patterns': [r".*: warning: \[ComparableAndComparator\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.MEDIUM,
+ 'description':
+ 'Java: Constructors should not invoke overridable methods.',
+ 'patterns': [r".*: warning: \[ConstructorInvokesOverridable\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.MEDIUM,
+ 'description':
+ 'Java: Constructors should not pass the \'this\' reference out in method invocations, since the object may not be fully constructed.',
+ 'patterns': [r".*: warning: \[ConstructorLeaksThis\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.MEDIUM,
+ 'description':
+ 'Java: DateFormat is not thread-safe, and should not be used as a constant field.',
+ 'patterns': [r".*: warning: \[DateFormatConstant\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.MEDIUM,
+ 'description':
+ 'Java: Implicit use of the platform default charset, which can result in differing behavior between JVM executions or incorrect behavior if the encoding of the data source doesn\'t match expectations.',
+ 'patterns': [r".*: warning: \[DefaultCharset\] .+"]},
{'category': 'java',
'severity': Severity.MEDIUM,
'description':
@@ -694,8 +879,13 @@
{'category': 'java',
'severity': Severity.MEDIUM,
'description':
- 'Java: An equality test between objects with incompatible types always returns false',
- 'patterns': [r".*: warning: \[EqualsIncompatibleType\] .+"]},
+ 'Java: Calls to ExpectedException#expect should always be followed by exactly one statement.',
+ 'patterns': [r".*: warning: \[ExpectedExceptionChecker\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.MEDIUM,
+ 'description':
+ 'Java: Switch case may fall through',
+ 'patterns': [r".*: warning: \[FallThrough\] .+"]},
{'category': 'java',
'severity': Severity.MEDIUM,
'description':
@@ -704,26 +894,61 @@
{'category': 'java',
'severity': Severity.MEDIUM,
'description':
+ 'Java: Use parentheses to make the precedence explicit',
+ 'patterns': [r".*: warning: \[FloatCast\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.MEDIUM,
+ 'description':
+ 'Java: Floating point literal loses precision',
+ 'patterns': [r".*: warning: \[FloatingPointLiteralPrecision\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.MEDIUM,
+ 'description':
'Java: Overloads will be ambiguous when passing lambda arguments',
'patterns': [r".*: warning: \[FunctionalInterfaceClash\] .+"]},
{'category': 'java',
'severity': Severity.MEDIUM,
'description':
+ 'Java: Return value of methods returning Future must be checked. Ignoring returned Futures suppresses exceptions thrown from the code that completes the Future.',
+ 'patterns': [r".*: warning: \[FutureReturnValueIgnored\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.MEDIUM,
+ 'description':
'Java: Calling getClass() on an enum may return a subclass of the enum type',
'patterns': [r".*: warning: \[GetClassOnEnum\] .+"]},
{'category': 'java',
'severity': Severity.MEDIUM,
'description':
+ 'Java: Hiding fields of superclasses may cause confusion and errors',
+ 'patterns': [r".*: warning: \[HidingField\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.MEDIUM,
+ 'description':
'Java: This annotation has incompatible modifiers as specified by its @IncompatibleModifiers annotation',
'patterns': [r".*: warning: \[IncompatibleModifiers\] .+"]},
{'category': 'java',
'severity': Severity.MEDIUM,
'description':
+ 'Java: This for loop increments the same variable in the header and in the body',
+ 'patterns': [r".*: warning: \[IncrementInForLoopAndHeader\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.MEDIUM,
+ 'description':
'Java: Please also override int read(byte[], int, int), otherwise multi-byte reads from this input stream are likely to be slow.',
'patterns': [r".*: warning: \[InputStreamSlowMultibyteRead\] .+"]},
{'category': 'java',
'severity': Severity.MEDIUM,
'description':
+ 'Java: Casting inside an if block should be plausibly consistent with the instanceof type',
+ 'patterns': [r".*: warning: \[InstanceOfAndCastMatchWrongType\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.MEDIUM,
+ 'description':
+ 'Java: Expression of type int may overflow before being assigned to a long',
+ 'patterns': [r".*: warning: \[IntLongMath\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.MEDIUM,
+ 'description':
'Java: Class should not implement both `Iterable` and `Iterator`',
'patterns': [r".*: warning: \[IterableAndIterator\] .+"]},
{'category': 'java',
@@ -734,16 +959,41 @@
{'category': 'java',
'severity': Severity.MEDIUM,
'description':
+ 'Java: Some JUnit4 construct cannot be used in a JUnit3 context. Convert your class to JUnit4 style to use them.',
+ 'patterns': [r".*: warning: \[JUnit4ClassUsedInJUnit3\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.MEDIUM,
+ 'description':
'Java: Test class inherits from JUnit 3\'s TestCase but has JUnit 4 @Test annotations.',
'patterns': [r".*: warning: \[JUnitAmbiguousTestClass\] .+"]},
{'category': 'java',
'severity': Severity.MEDIUM,
'description':
- 'Java: The Google Java Style Guide requires switch statements to have an explicit default',
+ 'Java: Never reuse class names from java.lang',
+ 'patterns': [r".*: warning: \[JavaLangClash\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.MEDIUM,
+ 'description':
+ 'Java: Suggests alternatives to obsolete JDK classes.',
+ 'patterns': [r".*: warning: \[JdkObsolete\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.MEDIUM,
+ 'description':
+ 'Java: Assignment where a boolean expression was expected; use == if this assignment wasn\'t expected or add parentheses for clarity.',
+ 'patterns': [r".*: warning: \[LogicalAssignment\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.MEDIUM,
+ 'description':
+ 'Java: Switches on enum types should either handle all values, or have a default case.',
'patterns': [r".*: warning: \[MissingCasesInEnumSwitch\] .+"]},
{'category': 'java',
'severity': Severity.MEDIUM,
'description':
+ 'Java: The Google Java Style Guide requires that each switch statement includes a default statement group, even if it contains no code. (This requirement is lifted for any switch statement that covers all values of an enum.)',
+ 'patterns': [r".*: warning: \[MissingDefault\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.MEDIUM,
+ 'description':
'Java: Not calling fail() when expecting an exception masks bugs',
'patterns': [r".*: warning: \[MissingFail\] .+"]},
{'category': 'java',
@@ -754,11 +1004,36 @@
{'category': 'java',
'severity': Severity.MEDIUM,
'description':
- 'Java: Compound assignments to bytes, shorts, chars, and floats hide dangerous casts',
+ 'Java: Modifying a collection while iterating over it in a loop may cause a ConcurrentModificationException to be thrown.',
+ 'patterns': [r".*: warning: \[ModifyCollectionInEnhancedForLoop\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.MEDIUM,
+ 'description':
+ 'Java: Multiple calls to either parallel or sequential are unnecessary and cause confusion.',
+ 'patterns': [r".*: warning: \[MultipleParallelOrSequentialCalls\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.MEDIUM,
+ 'description':
+ 'Java: Constant field declarations should use the immutable type (such as ImmutableList) instead of the general collection interface type (such as List)',
+ 'patterns': [r".*: warning: \[MutableConstantField\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.MEDIUM,
+ 'description':
+ 'Java: Method return type should use the immutable type (such as ImmutableList) instead of the general collection interface type (such as List)',
+ 'patterns': [r".*: warning: \[MutableMethodReturnType\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.MEDIUM,
+ 'description':
+ 'Java: Compound assignments may hide dangerous casts',
'patterns': [r".*: warning: \[NarrowingCompoundAssignment\] .+"]},
{'category': 'java',
'severity': Severity.MEDIUM,
'description':
+ 'Java: Nested instanceOf conditions of disjoint types create blocks of code that never execute',
+ 'patterns': [r".*: warning: \[NestedInstanceOfConditions\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.MEDIUM,
+ 'description':
'Java: This update of a volatile variable is non-atomic',
'patterns': [r".*: warning: \[NonAtomicVolatileUpdate\] .+"]},
{'category': 'java',
@@ -794,6 +1069,31 @@
{'category': 'java',
'severity': Severity.MEDIUM,
'description':
+ 'Java: One should not call optional.get() inside an if statement that checks !optional.isPresent',
+ 'patterns': [r".*: warning: \[OptionalNotPresent\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.MEDIUM,
+ 'description':
+ 'Java: String literal contains format specifiers, but is not passed to a format method',
+ 'patterns': [r".*: warning: \[OrphanedFormatString\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.MEDIUM,
+ 'description':
+ 'Java: To return a custom message with a Throwable class, one should override getMessage() instead of toString() for Throwable.',
+ 'patterns': [r".*: warning: \[OverrideThrowableToString\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.MEDIUM,
+ 'description':
+ 'Java: Varargs doesn\'t agree for overridden method',
+ 'patterns': [r".*: warning: \[Overrides\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.MEDIUM,
+ 'description':
+ 'Java: Detects `/* name= */`-style comments on actual parameters where the name doesn\'t match the formal parameter',
+ 'patterns': [r".*: warning: \[ParameterName\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.MEDIUM,
+ 'description':
'Java: Preconditions only accepts the %s placeholder in error message strings',
'patterns': [r".*: warning: \[PreconditionsInvalidPlaceholder\] .+"]},
{'category': 'java',
@@ -809,6 +1109,16 @@
{'category': 'java',
'severity': Severity.MEDIUM,
'description':
+ 'Java: BugChecker has incorrect ProvidesFix tag, please update',
+ 'patterns': [r".*: warning: \[ProvidesFix\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.MEDIUM,
+ 'description':
+ 'Java: reachabilityFence should always be called inside a finally block',
+ 'patterns': [r".*: warning: \[ReachabilityFenceUsage\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.MEDIUM,
+ 'description':
'Java: Thrown exception is a subtype of another',
'patterns': [r".*: warning: \[RedundantThrows\] .+"]},
{'category': 'java',
@@ -824,8 +1134,18 @@
{'category': 'java',
'severity': Severity.MEDIUM,
'description':
- 'Java: A static variable or method should not be accessed from an object instance',
- 'patterns': [r".*: warning: \[StaticAccessedFromInstance\] .+"]},
+ 'Java: Prefer the short-circuiting boolean operators \u0026\u0026 and || to \u0026 and |.',
+ 'patterns': [r".*: warning: \[ShortCircuitBoolean\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.MEDIUM,
+ 'description':
+ 'Java: A static variable or method should be qualified with a class name, not expression',
+ 'patterns': [r".*: warning: \[StaticQualifiedUsingExpression\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.MEDIUM,
+ 'description':
+ 'Java: Streams that encapsulate a closeable resource should be closed using try-with-resources',
+ 'patterns': [r".*: warning: \[StreamResourceLeak\] .+"]},
{'category': 'java',
'severity': Severity.MEDIUM,
'description':
@@ -834,13 +1154,43 @@
{'category': 'java',
'severity': Severity.MEDIUM,
'description':
+ 'Java: String.split should never take only a single argument; it has surprising behavior',
+ 'patterns': [r".*: warning: \[StringSplit\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.MEDIUM,
+ 'description':
+ 'Java: Prefer Splitter to String.split',
+ 'patterns': [r".*: warning: \[StringSplitter\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.MEDIUM,
+ 'description':
+ 'Java: Using @Test(expected=...) is discouraged, since the test will pass if *any* statement in the test method throws the expected exception',
+ 'patterns': [r".*: warning: \[TestExceptionChecker\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.MEDIUM,
+ 'description':
+ 'Java: Thread.join needs to be surrounded by a loop until it succeeds, as in Uninterruptibles.joinUninterruptibly.',
+ 'patterns': [r".*: warning: \[ThreadJoinLoop\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.MEDIUM,
+ 'description':
+ 'Java: ThreadLocals should be stored in static fields',
+ 'patterns': [r".*: warning: \[ThreadLocalUsage\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.MEDIUM,
+ 'description':
+ 'Java: Three-letter time zone identifiers are deprecated, may be ambiguous, and might not do what you intend; the full IANA time zone ID should be used instead.',
+ 'patterns': [r".*: warning: \[ThreeLetterTimeZoneID\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.MEDIUM,
+ 'description':
'Java: Truth Library assert is called on a constant.',
'patterns': [r".*: warning: \[TruthConstantAsserts\] .+"]},
{'category': 'java',
'severity': Severity.MEDIUM,
'description':
- 'Java: An object is tested for equality to itself using Truth Libraries.',
- 'patterns': [r".*: warning: \[TruthSelfEquals\] .+"]},
+ 'Java: Type parameter declaration overrides another type parameter already declared',
+ 'patterns': [r".*: warning: \[TypeParameterShadowing\] .+"]},
{'category': 'java',
'severity': Severity.MEDIUM,
'description':
@@ -849,11 +1199,31 @@
{'category': 'java',
'severity': Severity.MEDIUM,
'description':
+ 'Java: Creation of a Set/HashSet/HashMap of java.net.URL. equals() and hashCode() of java.net.URL class make blocking internet connections.',
+ 'patterns': [r".*: warning: \[URLEqualsHashCode\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.MEDIUM,
+ 'description':
+ 'Java: Switch handles all enum values; an explicit default case is unnecessary and defeats error checking for non-exhaustive switches.',
+ 'patterns': [r".*: warning: \[UnnecessaryDefaultInEnumSwitch\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.MEDIUM,
+ 'description':
+ 'Java: Finalizer may run before native code finishes execution',
+ 'patterns': [r".*: warning: \[UnsafeFinalization\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.MEDIUM,
+ 'description':
'Java: Unsynchronized method overrides a synchronized method.',
'patterns': [r".*: warning: \[UnsynchronizedOverridesSynchronized\] .+"]},
{'category': 'java',
'severity': Severity.MEDIUM,
'description':
+ 'Java: Java assert is used in test. For testing purposes Assert.* matchers should be used.',
+ 'patterns': [r".*: warning: \[UseCorrectAssertInTests\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.MEDIUM,
+ 'description':
'Java: Non-constant variable missing @Var annotation',
'patterns': [r".*: warning: \[Var\] .+"]},
{'category': 'java',
@@ -862,6 +1232,151 @@
'Java: Because of spurious wakeups, Object.wait() and Condition.await() must always be called in a loop',
'patterns': [r".*: warning: \[WaitNotInLoop\] .+"]},
{'category': 'java',
+ 'severity': Severity.MEDIUM,
+ 'description':
+ 'Java: Pluggable Type checker internal error',
+ 'patterns': [r".*: warning: \[PluggableTypeChecker\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.MEDIUM,
+ 'description':
+ 'Java: Invalid message format-style format specifier ({0}), expected printf-style (%s)',
+ 'patterns': [r".*: warning: \[FloggerMessageFormat\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.MEDIUM,
+ 'description':
+ 'Java: Logger level check is already implied in the log() call. An explicit at[Level]().isEnabled() check is redundant.',
+ 'patterns': [r".*: warning: \[FloggerRedundantIsEnabled\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.MEDIUM,
+ 'description':
+ 'Java: Calling withCause(Throwable) with an inline allocated Throwable is discouraged. Consider using withStackTrace(StackSize) instead, and specifying a reduced stack size (e.g. SMALL, MEDIUM or LARGE) instead of FULL, to improve performance.',
+ 'patterns': [r".*: warning: \[FloggerWithCause\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.MEDIUM,
+ 'description':
+ 'Java: Use withCause to associate Exceptions with log statements',
+ 'patterns': [r".*: warning: \[FloggerWithoutCause\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.MEDIUM,
+ 'description':
+ 'Java: No bug exists to track an ignored test',
+ 'patterns': [r".*: warning: \[IgnoredTestWithoutBug\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.MEDIUM,
+ 'description':
+ 'Java: @Ignore is preferred to @Suppress for JUnit4 tests. @Suppress may silently fail in JUnit4 (that is, tests may run anyway.)',
+ 'patterns': [r".*: warning: \[JUnit4SuppressWithoutIgnore\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.MEDIUM,
+ 'description':
+ 'Java: Medium and large test classes should document why they are medium or large',
+ 'patterns': [r".*: warning: \[JUnit4TestAttributeMissing\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.MEDIUM,
+ 'description':
+ 'Java: java.net.IDN implements the older IDNA2003 standard. Prefer com.google.i18n.Idn, which implements the newer UTS #46 standard',
+ 'patterns': [r".*: warning: \[JavaNetIdn\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.MEDIUM,
+ 'description':
+ 'Java: Consider requiring strict parsing on JodaDurationFlag instances. Before adjusting existing flags, check the documentation and your existing configuration to avoid crashes!',
+ 'patterns': [r".*: warning: \[JodaDurationFlagStrictParsing\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.MEDIUM,
+ 'description':
+ 'Java: Logging an exception and throwing it (or a new exception) for the same exceptional situation is an anti-pattern.',
+ 'patterns': [r".*: warning: \[LogAndThrow\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.MEDIUM,
+ 'description':
+ 'Java: FormattingLogger uses wrong or mismatched format string',
+ 'patterns': [r".*: warning: \[MisusedFormattingLogger\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.MEDIUM,
+ 'description':
+ 'Java: Flags should be final',
+ 'patterns': [r".*: warning: \[NonFinalFlag\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.MEDIUM,
+ 'description':
+ 'Java: Reading a flag from a static field or initializer block will cause it to always receive the default value and will cause an IllegalFlagStateException if the flag is ever set.',
+ 'patterns': [r".*: warning: \[StaticFlagUsage\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.MEDIUM,
+ 'description':
+ 'Java: Apps must use BuildCompat.isAtLeastO to check whether they\'re running on Android O',
+ 'patterns': [r".*: warning: \[UnsafeSdkVersionCheck\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
+ 'Java: Logging tag cannot be longer than 23 characters.',
+ 'patterns': [r".*: warning: \[LogTagLength\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
+ 'Java: Relative class name passed to ComponentName constructor',
+ 'patterns': [r".*: warning: \[RelativeComponentName\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
+ 'Java: Explicitly enumerate all cases in switch statements for certain enum types.',
+ 'patterns': [r".*: warning: \[EnumerateAllCasesInEnumSwitch\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
+ 'Java: Do not call assumeTrue(tester.getExperimentValueFor(...)). Use @RequireEndToEndTestExperiment instead.',
+ 'patterns': [r".*: warning: \[JUnitAssumeExperiment\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
+ 'Java: The accessed field or method is not visible here. Note that the default production visibility for @VisibleForTesting is Visibility.PRIVATE.',
+ 'patterns': [r".*: warning: \[VisibleForTestingChecker\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
+ 'Java: Detects errors encountered building Error Prone plugins',
+ 'patterns': [r".*: warning: \[ErrorPronePluginCorrectness\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
+ 'Java: Parcelable CREATOR fields should be Creator\u003cT>',
+ 'patterns': [r".*: warning: \[ParcelableCreatorType\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
+ 'Java: Enforce reflected Parcelables are kept by Proguard',
+ 'patterns': [r".*: warning: \[ReflectedParcelable\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
+ 'Java: Any class that extends IntentService should have @Nullable notation on method onHandleIntent(@Nullable Intent intent) and handle the case if intent is null.',
+ 'patterns': [r".*: warning: \[OnHandleIntentNullableChecker\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
+ 'Java: In many cases, randomUUID is not necessary, and it slows the performance, which can be quite severe especially when this operation happens at start up time. Consider replacing it with cheaper alternatives, like object.hashCode() or IdGenerator.INSTANCE.getRandomId()',
+ 'patterns': [r".*: warning: \[UUIDChecker\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
+ 'Java: DynamicActivity.findViewById(int) is slow and should not be used inside View.onDraw(Canvas)!',
+ 'patterns': [r".*: warning: \[NoFindViewByIdInOnDrawChecker\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
+ 'Java: Passing Throwable/Exception argument to the message format L.x(). Calling L.w(tag, message, ex) instead of L.w(tag, ex, message)',
+ 'patterns': [r".*: warning: \[WrongThrowableArgumentInLogChecker\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
+ 'Java: New splicers are disallowed on paths that are being Libsearched',
+ 'patterns': [r".*: warning: \[BlacklistedSplicerPathChecker\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
+ 'Java: Object serialized in Bundle may have been flattened to base type.',
+ 'patterns': [r".*: warning: \[BundleDeserializationCast\] .+"]},
+ {'category': 'java',
'severity': Severity.HIGH,
'description':
'Java: Log tag too long, cannot exceed 23 characters.',
@@ -879,11 +1394,6 @@
{'category': 'java',
'severity': Severity.HIGH,
'description':
- 'Java: Static and default methods in interfaces are not allowed in android builds.',
- 'patterns': [r".*: warning: \[StaticOrDefaultInterfaceMethod\] .+"]},
- {'category': 'java',
- 'severity': Severity.HIGH,
- 'description':
'Java: Incompatible type as argument to Object-accepting Java collections method',
'patterns': [r".*: warning: \[CollectionIncompatibleType\] .+"]},
{'category': 'java',
@@ -909,113 +1419,8 @@
{'category': 'java',
'severity': Severity.HIGH,
'description':
- 'Java: @AssistedInject and @Inject cannot be used on the same constructor.',
- 'patterns': [r".*: warning: \[AssistedInjectAndInjectOnSameConstructor\] .+"]},
- {'category': 'java',
- 'severity': Severity.HIGH,
- 'description':
- 'Java: @AutoFactory and @Inject should not be used in the same type.',
- 'patterns': [r".*: warning: \[AutoFactoryAtInject\] .+"]},
- {'category': 'java',
- 'severity': Severity.HIGH,
- 'description':
- 'Java: Injected constructors cannot be optional nor have binding annotations',
- 'patterns': [r".*: warning: \[InjectedConstructorAnnotations\] .+"]},
- {'category': 'java',
- 'severity': Severity.HIGH,
- 'description':
- 'Java: A scoping annotation\'s Target should include TYPE and METHOD.',
- 'patterns': [r".*: warning: \[InjectInvalidTargetingOnScopingAnnotation\] .+"]},
- {'category': 'java',
- 'severity': Severity.HIGH,
- 'description':
- 'Java: Abstract and default methods are not injectable with javax.inject.Inject',
- 'patterns': [r".*: warning: \[JavaxInjectOnAbstractMethod\] .+"]},
- {'category': 'java',
- 'severity': Severity.HIGH,
- 'description':
- 'Java: @javax.inject.Inject cannot be put on a final field.',
- 'patterns': [r".*: warning: \[JavaxInjectOnFinalField\] .+"]},
- {'category': 'java',
- 'severity': Severity.HIGH,
- 'description':
- 'Java: This class has more than one @Inject-annotated constructor. Please remove the @Inject annotation from all but one of them.',
- 'patterns': [r".*: warning: \[MoreThanOneInjectableConstructor\] .+"]},
- {'category': 'java',
- 'severity': Severity.HIGH,
- 'description':
- 'Java: Using more than one qualifier annotation on the same element is not allowed.',
- 'patterns': [r".*: warning: \[InjectMoreThanOneQualifier\] .+"]},
- {'category': 'java',
- 'severity': Severity.HIGH,
- 'description':
- 'Java: A class can be annotated with at most one scope annotation.',
- 'patterns': [r".*: warning: \[InjectMoreThanOneScopeAnnotationOnClass\] .+"]},
- {'category': 'java',
- 'severity': Severity.HIGH,
- 'description':
- 'Java: Annotations cannot be both Scope annotations and Qualifier annotations: this causes confusion when trying to use them.',
- 'patterns': [r".*: warning: \[OverlappingQualifierAndScopeAnnotation\] .+"]},
- {'category': 'java',
- 'severity': Severity.HIGH,
- 'description':
- 'Java: Qualifier applied to a method that isn\'t a @Provides method. This method won\'t be used for dependency injection',
- 'patterns': [r".*: warning: \[QualifierOnMethodWithoutProvides\] .+"]},
- {'category': 'java',
- 'severity': Severity.HIGH,
- 'description':
- 'Java: Scope annotation on an interface or abstact class is not allowed',
- 'patterns': [r".*: warning: \[InjectScopeAnnotationOnInterfaceOrAbstractClass\] .+"]},
- {'category': 'java',
- 'severity': Severity.HIGH,
- 'description':
- 'Java: Scoping and qualifier annotations must have runtime retention.',
- 'patterns': [r".*: warning: \[InjectScopeOrQualifierAnnotationRetention\] .+"]},
- {'category': 'java',
- 'severity': Severity.HIGH,
- 'description':
- 'Java: `@Multibinds` is the new way to declare multibindings.',
- 'patterns': [r".*: warning: \[MultibindsInsteadOfMultibindings\] .+"]},
- {'category': 'java',
- 'severity': Severity.HIGH,
- 'description':
- 'Java: Dagger @Provides methods may not return null unless annotated with @Nullable',
- 'patterns': [r".*: warning: \[DaggerProvidesNull\] .+"]},
- {'category': 'java',
- 'severity': Severity.HIGH,
- 'description':
- 'Java: Scope annotation on implementation class of AssistedInject factory is not allowed',
- 'patterns': [r".*: warning: \[GuiceAssistedInjectScoping\] .+"]},
- {'category': 'java',
- 'severity': Severity.HIGH,
- 'description':
- 'Java: A constructor cannot have two @Assisted parameters of the same type unless they are disambiguated with named @Assisted annotations.',
- 'patterns': [r".*: warning: \[GuiceAssistedParameters\] .+"]},
- {'category': 'java',
- 'severity': Severity.HIGH,
- 'description':
- 'Java: Although Guice allows injecting final fields, doing so is disallowed because the injected value may not be visible to other threads.',
- 'patterns': [r".*: warning: \[GuiceInjectOnFinalField\] .+"]},
- {'category': 'java',
- 'severity': Severity.HIGH,
- 'description':
- 'Java: This method is not annotated with @Inject, but it overrides a method that is annotated with @javax.inject.Inject. The method will not be Injected.',
- 'patterns': [r".*: warning: \[OverridesJavaxInjectableMethod\] .+"]},
- {'category': 'java',
- 'severity': Severity.HIGH,
- 'description':
- 'Java: @Provides methods need to be declared in a Module to have any effect.',
- 'patterns': [r".*: warning: \[ProvidesMethodOutsideOfModule\] .+"]},
- {'category': 'java',
- 'severity': Severity.HIGH,
- 'description':
'Java: Checks for unguarded accesses to fields and methods with @GuardedBy annotations',
- 'patterns': [r".*: warning: \[GuardedByChecker\] .+"]},
- {'category': 'java',
- 'severity': Severity.HIGH,
- 'description':
- 'Java: Invalid @GuardedBy expression',
- 'patterns': [r".*: warning: \[GuardedByValidator\] .+"]},
+ 'patterns': [r".*: warning: \[GuardedBy\] .+"]},
{'category': 'java',
'severity': Severity.HIGH,
'description':
@@ -1034,13 +1439,13 @@
{'category': 'java',
'severity': Severity.HIGH,
'description':
- 'Java: An argument is more similar to a different parameter; the arguments may have been swapped.',
- 'patterns': [r".*: warning: \[ArgumentParameterSwap\] .+"]},
+ 'Java: Reference equality used to compare arrays',
+ 'patterns': [r".*: warning: \[ArrayEquals\] .+"]},
{'category': 'java',
'severity': Severity.HIGH,
'description':
- 'Java: Reference equality used to compare arrays',
- 'patterns': [r".*: warning: \[ArrayEquals\] .+"]},
+ 'Java: Arrays.fill(Object[], Object) called with incompatible types.',
+ 'patterns': [r".*: warning: \[ArrayFillIncompatibleType\] .+"]},
{'category': 'java',
'severity': Severity.HIGH,
'description':
@@ -1089,6 +1494,11 @@
{'category': 'java',
'severity': Severity.HIGH,
'description':
+ 'Java: Implementing \'Comparable\u003cT>\' where T is not compatible with the implementing class.',
+ 'patterns': [r".*: warning: \[ComparableType\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
'Java: This comparison method violates the contract',
'patterns': [r".*: warning: \[ComparisonContractViolated\] .+"]},
{'category': 'java',
@@ -1104,6 +1514,16 @@
{'category': 'java',
'severity': Severity.HIGH,
'description':
+ 'Java: Non-trivial compile time constant boolean expressions shouldn\'t be used.',
+ 'patterns': [r".*: warning: \[ComplexBooleanConstant\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
+ 'Java: A conditional expression with numeric operands of differing types will perform binary numeric promotion of the operands; when these operands are of reference types, the expression\'s result may not be of the expected type.',
+ 'patterns': [r".*: warning: \[ConditionalExpressionNumericPromotion\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
'Java: Compile-time constant expression overflows',
'patterns': [r".*: warning: \[ConstantOverflow\] .+"]},
{'category': 'java',
@@ -1114,11 +1534,21 @@
{'category': 'java',
'severity': Severity.HIGH,
'description':
+ 'Java: Thread created but not started',
+ 'patterns': [r".*: warning: \[DeadThread\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
'Java: Division by integer literal zero',
'patterns': [r".*: warning: \[DivZero\] .+"]},
{'category': 'java',
'severity': Severity.HIGH,
'description':
+ 'Java: This method should not be called.',
+ 'patterns': [r".*: warning: \[DoNotCall\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
'Java: Empty statement after if',
'patterns': [r".*: warning: \[EmptyIf\] .+"]},
{'category': 'java',
@@ -1129,7 +1559,12 @@
{'category': 'java',
'severity': Severity.HIGH,
'description':
- 'Java: Method annotated @ForOverride must be protected or package-private and only invoked from declaring class',
+ 'Java: == must be used in equals method to check equality to itself or an infinite loop will occur.',
+ 'patterns': [r".*: warning: \[EqualsReference\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
+ 'Java: Method annotated @ForOverride must be protected or package-private and only invoked from declaring class, or from an override of the method',
'patterns': [r".*: warning: \[ForOverride\] .+"]},
{'category': 'java',
'severity': Severity.HIGH,
@@ -1144,6 +1579,11 @@
{'category': 'java',
'severity': Severity.HIGH,
'description':
+ 'Java: DoubleMath.fuzzyEquals should never be used in an Object.equals() method',
+ 'patterns': [r".*: warning: \[FuzzyEqualsShouldNotBeUsedInEqualsMethod\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
'Java: Calling getClass() on an annotation may return a proxy class',
'patterns': [r".*: warning: \[GetClassOnAnnotation\] .+"]},
{'category': 'java',
@@ -1154,17 +1594,12 @@
{'category': 'java',
'severity': Severity.HIGH,
'description':
- 'Java: An object is tested for equality to itself using Guava Libraries',
- 'patterns': [r".*: warning: \[GuavaSelfEquals\] .+"]},
- {'category': 'java',
- 'severity': Severity.HIGH,
- 'description':
'Java: contains() is a legacy method that is equivalent to containsValue()',
'patterns': [r".*: warning: \[HashtableContains\] .+"]},
{'category': 'java',
'severity': Severity.HIGH,
'description':
- 'Java: Writing "a && a", "a || a", "a & a", or "a | a" is equivalent to "a".',
+ 'Java: A binary expression where both operands are the same is usually incorrect.',
'patterns': [r".*: warning: \[IdentityBinaryExpression\] .+"]},
{'category': 'java',
'severity': Severity.HIGH,
@@ -1174,6 +1609,16 @@
{'category': 'java',
'severity': Severity.HIGH,
'description':
+ 'Java: The first argument to indexOf is a Unicode code point, and the second is the index to start the search from',
+ 'patterns': [r".*: warning: \[IndexOfChar\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
+ 'Java: Conditional expression in varargs call contains array and non-array arguments',
+ 'patterns': [r".*: warning: \[InexactVarargsConditional\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
'Java: This method always recurses, and will cause a StackOverflowError',
'patterns': [r".*: warning: \[InfiniteRecursion\] .+"]},
{'category': 'java',
@@ -1189,36 +1634,71 @@
{'category': 'java',
'severity': Severity.HIGH,
'description':
+ 'Java: Invalid time zone identifier. TimeZone.getTimeZone(String) will silently return GMT instead of the time zone you intended.',
+ 'patterns': [r".*: warning: \[InvalidTimeZoneID\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
'Java: The argument to Class#isInstance(Object) should not be a Class',
'patterns': [r".*: warning: \[IsInstanceOfClass\] .+"]},
{'category': 'java',
'severity': Severity.HIGH,
'description':
+ 'Java: Path implements Iterable\u003cPath>; prefer Collection\u003cPath> for clarity',
+ 'patterns': [r".*: warning: \[IterablePathParameter\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
'Java: jMock tests must have a @RunWith(JMock.class) annotation, or the Mockery field must have a @Rule JUnit annotation',
'patterns': [r".*: warning: \[JMockTestWithoutRunWithOrRuleAnnotation\] .+"]},
{'category': 'java',
'severity': Severity.HIGH,
'description':
- 'Java: Test method will not be run; please prefix name with "test"',
+ 'Java: Test method will not be run; please correct method signature (Should be public, non-static, and method name should begin with "test").',
'patterns': [r".*: warning: \[JUnit3TestNotRun\] .+"]},
{'category': 'java',
'severity': Severity.HIGH,
'description':
- 'Java: setUp() method will not be run; Please add a @Before annotation',
+ 'Java: This method should be static',
+ 'patterns': [r".*: warning: \[JUnit4ClassAnnotationNonStatic\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
+ 'Java: setUp() method will not be run; please add JUnit\'s @Before annotation',
'patterns': [r".*: warning: \[JUnit4SetUpNotRun\] .+"]},
{'category': 'java',
'severity': Severity.HIGH,
'description':
- 'Java: tearDown() method will not be run; Please add an @After annotation',
+ 'Java: tearDown() method will not be run; please add JUnit\'s @After annotation',
'patterns': [r".*: warning: \[JUnit4TearDownNotRun\] .+"]},
{'category': 'java',
'severity': Severity.HIGH,
'description':
- 'Java: Test method will not be run; please add @Test annotation',
+ 'Java: This looks like a test method but is not run; please add @Test or @Ignore, or, if this is a helper method, reduce its visibility.',
'patterns': [r".*: warning: \[JUnit4TestNotRun\] .+"]},
{'category': 'java',
'severity': Severity.HIGH,
'description':
+ 'Java: An object is tested for reference equality to itself using JUnit library.',
+ 'patterns': [r".*: warning: \[JUnitAssertSameCheck\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
+ 'Java: This pattern will silently corrupt certain byte sequences from the serialized protocol message. Use ByteString or byte[] directly',
+ 'patterns': [r".*: warning: \[LiteByteStringUtf8\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
+ 'Java: Loop condition is never modified in loop body.',
+ 'patterns': [r".*: warning: \[LoopConditionChecker\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
+ 'Java: Overriding method is missing a call to overridden super method',
+ 'patterns': [r".*: warning: \[MissingSuperCall\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
'Java: Use of "YYYY" (week year) in a date pattern without "ww" (week in year). You probably meant to use "yyyy" (year) instead.',
'patterns': [r".*: warning: \[MisusedWeekYear\] .+"]},
{'category': 'java',
@@ -1239,6 +1719,16 @@
{'category': 'java',
'severity': Severity.HIGH,
'description':
+ 'Java: The result of this method must be closed.',
+ 'patterns': [r".*: warning: \[MustBeClosedChecker\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
+ 'Java: The first argument to nCopies is the number of copies, and the second is the item to copy',
+ 'patterns': [r".*: warning: \[NCopiesOfChar\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
'Java: @NoAllocation was specified on this method, but something was found that would trigger an allocation',
'patterns': [r".*: warning: \[NoAllocation\] .+"]},
{'category': 'java',
@@ -1259,6 +1749,11 @@
{'category': 'java',
'severity': Severity.HIGH,
'description':
+ 'Java: This conditional expression may evaluate to null, which will result in an NPE when the result is unboxed.',
+ 'patterns': [r".*: warning: \[NullTernary\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
'Java: Numeric comparison using reference equality instead of value equality',
'patterns': [r".*: warning: \[NumericEquality\] .+"]},
{'category': 'java',
@@ -1269,11 +1764,6 @@
{'category': 'java',
'severity': Severity.HIGH,
'description':
- 'Java: Varargs doesn\'t agree for overridden method',
- 'patterns': [r".*: warning: \[Overrides\] .+"]},
- {'category': 'java',
- 'severity': Severity.HIGH,
- 'description':
'Java: Declaring types inside package-info.java files is very bad form',
'patterns': [r".*: warning: \[PackageInfo\] .+"]},
{'category': 'java',
@@ -1289,6 +1779,16 @@
{'category': 'java',
'severity': Severity.HIGH,
'description':
+ 'Java: Using ::equals as an incompatible Predicate; the predicate will always return false',
+ 'patterns': [r".*: warning: \[PredicateIncompatibleType\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
+ 'Java: Access to a private protocol buffer field is forbidden. This protocol buffer carries a security contract, and can only be created using an approved library. Direct access to the fields is forbidden.',
+ 'patterns': [r".*: warning: \[PrivateSecurityContractProtoAccess\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
'Java: Protobuf fields cannot be null',
'patterns': [r".*: warning: \[ProtoFieldNullComparison\] .+"]},
{'category': 'java',
@@ -1299,6 +1799,16 @@
{'category': 'java',
'severity': Severity.HIGH,
'description':
+ 'Java: To get the tag number of a protocol buffer enum, use getNumber() instead.',
+ 'patterns': [r".*: warning: \[ProtocolBufferOrdinal\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
+ 'Java: Casting a random number in the range [0.0, 1.0) to an integer or long always results in 0.',
+ 'patterns': [r".*: warning: \[RandomCast\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
'Java: Use Random.nextInt(int). Random.nextInt() % n can have negative results',
'patterns': [r".*: warning: \[RandomModInteger\] .+"]},
{'category': 'java',
@@ -1324,13 +1834,13 @@
{'category': 'java',
'severity': Severity.HIGH,
'description':
- 'Java: Variable compared to itself',
- 'patterns': [r".*: warning: \[SelfEquality\] .+"]},
+ 'Java: Testing an object for equality with itself will always be true.',
+ 'patterns': [r".*: warning: \[SelfEquals\] .+"]},
{'category': 'java',
'severity': Severity.HIGH,
'description':
- 'Java: An object is tested for equality to itself',
- 'patterns': [r".*: warning: \[SelfEquals\] .+"]},
+ 'Java: This method must be called with an even number of arguments.',
+ 'patterns': [r".*: warning: \[ShouldHaveEvenArgs\] .+"]},
{'category': 'java',
'severity': Severity.HIGH,
'description':
@@ -1359,6 +1869,16 @@
{'category': 'java',
'severity': Severity.HIGH,
'description':
+ 'Java: Throwing \'null\' always results in a NullPointerException being thrown.',
+ 'patterns': [r".*: warning: \[ThrowNull\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
+ 'Java: isEqualTo should not be used to test an object for equality with itself; the assertion will never fail.',
+ 'patterns': [r".*: warning: \[TruthSelfEquals\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
'Java: Catching Throwable/Error masks failures from fail() or assert*() in the try block',
'patterns': [r".*: warning: \[TryFailThrowable\] .+"]},
{'category': 'java',
@@ -1384,8 +1904,193 @@
{'category': 'java',
'severity': Severity.HIGH,
'description':
+ 'Java: `var` should not be used as a type name.',
+ 'patterns': [r".*: warning: \[VarTypeName\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
'Java: Method parameter has wrong package',
'patterns': [r".*: warning: \[ParameterPackage\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
+ 'Java: Type declaration annotated with @ThreadSafe is not thread safe',
+ 'patterns': [r".*: warning: \[ThreadSafe\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
+ 'Java: Use of class, field, or method that is not compatible with legacy Android devices',
+ 'patterns': [r".*: warning: \[AndroidApiChecker\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
+ 'Java: Invalid use of Flogger format string',
+ 'patterns': [r".*: warning: \[AndroidFloggerFormatString\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
+ 'Java: Use TunnelException.getCauseAs(Class) instead of casting the result of TunnelException.getCause().',
+ 'patterns': [r".*: warning: \[DoNotCastTunnelExceptionCause\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
+ 'Java: Identifies undesirable mocks.',
+ 'patterns': [r".*: warning: \[DoNotMock_ForJavaBuilder\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
+ 'Java: Duration Flag should NOT have units in the variable name or the @FlagSpec\'s name or altName field.',
+ 'patterns': [r".*: warning: \[DurationFlagWithUnits\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
+ 'Java: Duration.get() only works with SECONDS or NANOS.',
+ 'patterns': [r".*: warning: \[DurationGetTemporalUnit\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
+ 'Java: Invalid printf-style format string',
+ 'patterns': [r".*: warning: \[FloggerFormatString\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
+ 'Java: Test class may not be run because it is missing a @RunWith annotation',
+ 'patterns': [r".*: warning: \[JUnit4RunWithMissing\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
+ 'Java: Use of class, field, or method that is not compatible with JDK 7',
+ 'patterns': [r".*: warning: \[Java7ApiChecker\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
+ 'Java: Use of java.time.Duration.withNanos(int) is not allowed.',
+ 'patterns': [r".*: warning: \[JavaDurationWithNanos\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
+ 'Java: Use of java.time.Duration.withSeconds(long) is not allowed.',
+ 'patterns': [r".*: warning: \[JavaDurationWithSeconds\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
+ 'Java: java.time APIs that silently use the default system time-zone are not allowed.',
+ 'patterns': [r".*: warning: \[JavaTimeDefaultTimeZone\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
+ 'Java: Use of new Duration(long) is not allowed. Please use Duration.millis(long) instead.',
+ 'patterns': [r".*: warning: \[JodaDurationConstructor\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
+ 'Java: Use of duration.withMillis(long) is not allowed. Please use Duration.millis(long) instead.',
+ 'patterns': [r".*: warning: \[JodaDurationWithMillis\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
+ 'Java: Use of instant.withMillis(long) is not allowed. Please use new Instant(long) instead.',
+ 'patterns': [r".*: warning: \[JodaInstantWithMillis\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
+ 'Java: Use of JodaTime\'s type.plus(long) or type.minus(long) is not allowed (where \u003ctype> = {Duration,Instant,DateTime,DateMidnight}). Please use type.plus(Duration.millis(long)) or type.minus(Duration.millis(long)) instead.',
+ 'patterns': [r".*: warning: \[JodaPlusMinusLong\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
+ 'Java: Changing JodaTime\'s current time is not allowed in non-testonly code.',
+ 'patterns': [r".*: warning: \[JodaSetCurrentMillis\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
+ 'Java: Use of Joda-Time\'s DateTime.toDateTime(), Duration.toDuration(), Instant.toInstant(), Interval.toInterval(), and Period.toPeriod() are not allowed.',
+ 'patterns': [r".*: warning: \[JodaToSelf\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
+ 'Java: Use of JodaTime\'s type.withDurationAdded(long, int) (where \u003ctype> = {Duration,Instant,DateTime}). Please use type.withDurationAdded(Duration.millis(long), int) instead.',
+ 'patterns': [r".*: warning: \[JodaWithDurationAddedLong\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
+ 'Java: LanguageCode comparison using reference equality instead of value equality',
+ 'patterns': [r".*: warning: \[LanguageCodeEquality\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
+ 'Java: The zero argument toString is not part of the Localizable interface and likely is just the java Object toString. You probably want to call toString(Locale).',
+ 'patterns': [r".*: warning: \[LocalizableWrongToString\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
+ 'Java: Period.get() only works with YEARS, MONTHS, or DAYS.',
+ 'patterns': [r".*: warning: \[PeriodGetTemporalUnit\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
+ 'Java: Return value of methods returning Promise must be checked. Ignoring returned Promises suppresses exceptions thrown from the code that completes the Promises.',
+ 'patterns': [r".*: warning: \[PromiseReturnValueIgnored\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
+ 'Java: When returning a Promise, use thenChain() instead of then()',
+ 'patterns': [r".*: warning: \[PromiseThenReturningPromise\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
+ 'Java: Streams.iterating() is unsafe for use except in the header of a for-each loop; please see its Javadoc for details.',
+ 'patterns': [r".*: warning: \[StreamsIteratingNotInLoop\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
+ 'Java: TemporalAccessor.get() only works for certain values of ChronoField.',
+ 'patterns': [r".*: warning: \[TemporalAccessorGetChronoField\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
+ 'Java: Try-with-resources is not supported in this code, use try/finally instead',
+ 'patterns': [r".*: warning: \[TryWithResources\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
+ 'Java: Adds checkOrThrow calls where needed',
+ 'patterns': [r".*: warning: \[AddCheckOrThrow\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
+ 'Java: Equality on Nano protos (== or .equals) might not be the same in Lite',
+ 'patterns': [r".*: warning: \[ForbidNanoEquality\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
+ 'Java: Submessages of a proto cannot be mutated',
+ 'patterns': [r".*: warning: \[ForbidSubmessageMutation\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
+ 'Java: Repeated fields on proto messages cannot be directly referenced',
+ 'patterns': [r".*: warning: \[NanoUnsafeRepeatedFieldUsage\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
+ 'Java: Requires that non-@enum int assignments to @enum ints is wrapped in a checkOrThrow',
+ 'patterns': [r".*: warning: \[RequireCheckOrThrow\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
+ 'Java: Assignments into repeated field elements must be sequential',
+ 'patterns': [r".*: warning: \[RequireSequentialRepeatedFields\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
+ 'Java: Future.get in Google Now Producers code',
+ 'patterns': [r".*: warning: \[FutureGetInNowProducers\] .+"]},
+ {'category': 'java',
+ 'severity': Severity.HIGH,
+ 'description':
+ 'Java: @SimpleEnum applied to non-enum type',
+ 'patterns': [r".*: warning: \[SimpleEnumUsage\] .+"]},
# End warnings generated by Error Prone
@@ -1807,6 +2512,7 @@
'patterns': [r".*: warning: In file included from .+,"]},
# warnings from clang-tidy
+ group_tidy_warn_pattern('android'),
group_tidy_warn_pattern('cert'),
group_tidy_warn_pattern('clang-diagnostic'),
group_tidy_warn_pattern('cppcoreguidelines'),
@@ -2370,7 +3076,7 @@
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/tools/warn.py'):
+ if os.path.exists(root_path + '/build/make/tools/warn.py'):
android_root = root_path
return root_path
return ''
diff --git a/tools/zipalign/Android.bp b/tools/zipalign/Android.bp
new file mode 100644
index 0000000..8e6196d
--- /dev/null
+++ b/tools/zipalign/Android.bp
@@ -0,0 +1,36 @@
+//
+// Copyright 2008 The Android Open Source Project
+//
+// Zip alignment tool
+//
+
+cc_binary_host {
+ name: "zipalign",
+
+ srcs: [
+ "ZipAlign.cpp",
+ "ZipEntry.cpp",
+ "ZipFile.cpp",
+ ],
+
+ cflags: ["-Wall", "-Werror"],
+
+ // NOTE: Do not add any shared_libs dependencies because they will break the
+ // static_sdk_tools target.
+ static_libs: [
+ "libutils",
+ "libcutils",
+ "liblog",
+ "libziparchive",
+ "libz",
+ "libbase",
+ "libzopfli",
+ ],
+
+ target: {
+ windows: {
+ host_ldlibs: ["-lpthread"],
+ enabled: true,
+ },
+ },
+}
diff --git a/tools/zipalign/Android.mk b/tools/zipalign/Android.mk
deleted file mode 100644
index 8c0240a..0000000
--- a/tools/zipalign/Android.mk
+++ /dev/null
@@ -1,38 +0,0 @@
-#
-# Copyright 2008 The Android Open Source Project
-#
-# Zip alignment tool
-#
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
- ZipAlign.cpp \
- ZipEntry.cpp \
- ZipFile.cpp
-
-LOCAL_C_INCLUDES += external/zlib \
- external/zopfli/src
-
-LOCAL_STATIC_LIBRARIES := \
- libandroidfw \
- libutils \
- libcutils \
- liblog \
- libzopfli
-
-LOCAL_LDLIBS_linux += -lrt
-
-LOCAL_STATIC_LIBRARIES_windows += libz
-LOCAL_LDLIBS_linux += -lz
-LOCAL_LDLIBS_darwin += -lz
-
-ifneq ($(strip $(BUILD_HOST_static)),)
-LOCAL_LDLIBS += -lpthread
-endif # BUILD_HOST_static
-
-LOCAL_MODULE := zipalign
-LOCAL_MODULE_HOST_OS := darwin linux windows
-
-include $(BUILD_HOST_EXECUTABLE)
diff --git a/tools/zipalign/ZipFile.cpp b/tools/zipalign/ZipFile.cpp
index 1b39902..43bc9bf 100644
--- a/tools/zipalign/ZipFile.cpp
+++ b/tools/zipalign/ZipFile.cpp
@@ -20,13 +20,12 @@
#define LOG_TAG "zip"
-#include <androidfw/ZipUtils.h>
#include <utils/Log.h>
+#include <ziparchive/zip_archive.h>
#include "ZipFile.h"
#include <zlib.h>
-#define DEF_MEM_LEVEL 8 // normally in zutil.h?
#include "zopfli/deflate.h"
@@ -135,7 +134,7 @@
/*
* Return the Nth entry in the archive.
*/
-ZipEntry* ZipFile::getEntryByIndex(int idx) const
+android::ZipEntry* ZipFile::getEntryByIndex(int idx) const
{
if (idx < 0 || idx >= (int) mEntries.size())
return NULL;
@@ -146,7 +145,7 @@
/*
* Find an entry by name.
*/
-ZipEntry* ZipFile::getEntryByName(const char* fileName) const
+android::ZipEntry* ZipFile::getEntryByName(const char* fileName) const
{
/*
* Do a stupid linear string-compare search.
@@ -785,8 +784,6 @@
status_t ZipFile::copyDataToFp(FILE* dstFp,
const void* data, size_t size, uint32_t* pCRC32)
{
- size_t count;
-
*pCRC32 = crc32(0L, Z_NULL, 0);
if (size > 0) {
*pCRC32 = crc32(*pCRC32, (const unsigned char*)data, size);
@@ -1198,6 +1195,58 @@
}
#endif
+class BufferWriter : public zip_archive::Writer {
+ public:
+ BufferWriter(void* buf, size_t size) : Writer(),
+ buf_(reinterpret_cast<uint8_t*>(buf)), size_(size), bytes_written_(0) {}
+
+ bool Append(uint8_t* buf, size_t buf_size) override {
+ if (bytes_written_ + buf_size > size_) {
+ return false;
+ }
+
+ memcpy(buf_ + bytes_written_, buf, buf_size);
+ bytes_written_ += buf_size;
+ return true;
+ }
+
+ private:
+ uint8_t* const buf_;
+ const size_t size_;
+ size_t bytes_written_;
+};
+
+class FileReader : public zip_archive::Reader {
+ public:
+ FileReader(FILE* fp) : Reader(), fp_(fp), current_offset_(0) {
+ }
+
+ bool ReadAtOffset(uint8_t* buf, size_t len, uint32_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.
+ if (offset != current_offset_) {
+ if (fseek(fp_, offset, SEEK_SET) != 0) {
+ return false;
+ }
+
+ current_offset_ = offset;
+ }
+
+ size_t read = fread(buf, 1, len, fp_);
+ if (read != len) {
+ return false;
+ }
+
+ current_offset_ += read;
+ return true;
+ }
+
+ private:
+ FILE* fp_;
+ mutable uint32_t current_offset_;
+};
+
// free the memory when you're done
void* ZipFile::uncompress(const ZipEntry* entry) const
{
@@ -1240,11 +1289,13 @@
}
break;
case ZipEntry::kCompressDeflated: {
- if (!ZipUtils::inflateToBuffer(mZipFp, buf, unlen, clen)) {
+ const FileReader reader(mZipFp);
+ BufferWriter writer(buf, unlen);
+ if (zip_archive::Inflate(reader, clen, unlen, &writer, nullptr) != 0) {
goto bail;
}
- }
break;
+ }
default:
goto bail;
}
diff --git a/tools/ziptime/Android.bp b/tools/ziptime/Android.bp
index 874d346..5ef45ed 100644
--- a/tools/ziptime/Android.bp
+++ b/tools/ziptime/Android.bp
@@ -27,6 +27,7 @@
],
name: "ziptime",
+ cflags: ["-Wall", "-Werror"],
target: {
windows: {
enabled: true,
diff --git a/tools/ziptime/ZipEntry.cpp b/tools/ziptime/ZipEntry.cpp
index 51ce09f..e7b52ed 100644
--- a/tools/ziptime/ZipEntry.cpp
+++ b/tools/ziptime/ZipEntry.cpp
@@ -86,7 +86,6 @@
*/
status_t ZipEntry::LocalFileHeader::rewrite(FILE* fp)
{
- status_t result = 0;
uint8_t buf[kLFHLen];
if (fread(buf, 1, kLFHLen, fp) != kLFHLen)
@@ -124,7 +123,6 @@
*/
status_t ZipEntry::CentralDirEntry::rewrite(FILE* fp)
{
- status_t result = 0;
uint8_t buf[kCDELen];
uint16_t fileNameLength, extraFieldLength, fileCommentLength;