new search results layout. no more custom suggestions; just API matches and organic results. am: 38b0e22
am: 4f9a67d
* commit '4f9a67dbb37abda3d6ccea540c4fa827141ca2dc':
Change-Id: I9225b324395c0ecf0de29a5b955cf2f335615105
diff --git a/core/Makefile b/core/Makefile
index 22dcee1..07d1c94 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -523,14 +523,14 @@
$(INSTALLED_BOOTIMAGE_TARGET): $(MKBOOTIMG) $(INTERNAL_BOOTIMAGE_FILES) $(VBOOT_SIGNER)
$(call pretty,"Target boot image: $@")
$(hide) $(MKBOOTIMG) $(INTERNAL_BOOTIMAGE_ARGS) $(BOARD_MKBOOTIMG_ARGS) --output $@.unsigned
- $(VBOOT_SIGNER) $(FUTILITY) $@.unsigned $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VBOOT_SIGNING_KEY).vbpubk $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VBOOT_SIGNING_KEY).vbprivk $@.keyblock $@
+ $(VBOOT_SIGNER) $(FUTILITY) $@.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 $@.keyblock $@
$(hide) $(call assert-max-image-size,$@,$(BOARD_BOOTIMAGE_PARTITION_SIZE))
.PHONY: bootimage-nodeps
bootimage-nodeps: $(MKBOOTIMG) $(VBOOT_SIGNER)
@echo "make $@: ignoring dependencies"
$(hide) $(MKBOOTIMG) $(INTERNAL_BOOTIMAGE_ARGS) $(BOARD_MKBOOTIMG_ARGS) --output $(INSTALLED_BOOTIMAGE_TARGET).unsigned
- $(VBOOT_SIGNER) $(FUTILITY) $(INSTALLED_BOOTIMAGE_TARGET).unsigned $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VBOOT_SIGNING_KEY).vbpubk $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VBOOT_SIGNING_KEY).vbprivk $(INSTALLED_BOOTIMAGE_TARGET).keyblock $(INSTALLED_BOOTIMAGE_TARGET)
+ $(VBOOT_SIGNER) $(FUTILITY) $(INSTALLED_BOOTIMAGE_TARGET).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 $(INSTALLED_BOOTIMAGE_TARGET).keyblock $(INSTALLED_BOOTIMAGE_TARGET)
$(hide) $(call assert-max-image-size,$(INSTALLED_BOOTIMAGE_TARGET),$(BOARD_BOOTIMAGE_PARTITION_SIZE))
else # PRODUCT_SUPPORTS_VBOOT != true
@@ -757,6 +757,7 @@
$(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_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))
$(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VBOOT),$(hide) echo "futility=$(FUTILITY)" >> $(1))
$(if $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_VBOOT),$(hide) echo "vboot_signer_cmd=$(VBOOT_SIGNER)" >> $(1))
$(if $(filter true,$(BOARD_BUILD_SYSTEM_ROOT_IMAGE)),\
@@ -893,7 +894,7 @@
$(if $(filter true,$(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_SUPPORTS_BOOT_SIGNER)),\
$(BOOT_SIGNER) /recovery $(1) $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VERITY_SIGNING_KEY).pk8 $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_VERITY_SIGNING_KEY).x509.pem $(1))
$(if $(filter true,$(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 $(1).keyblock $(1))
+ $(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))
$(hide) $(call assert-max-image-size,$(1),$(BOARD_RECOVERYIMAGE_PARTITION_SIZE))
@echo ----- Made recovery image: $(1) --------
endef
diff --git a/core/definitions.mk b/core/definitions.mk
index 78b0a39..9dea18c 100644
--- a/core/definitions.mk
+++ b/core/definitions.mk
@@ -175,16 +175,53 @@
endef
###########################################################
+## Find all of the directories under the named directories with
+## the specified name.
+## Meant to be used like:
+## INC_DIRS := $(call all-named-dirs-under,inc,.)
+###########################################################
+
+define all-named-dirs-under
+$(call find-subdir-files,$(2) -type d -name "$(1)")
+endef
+
+###########################################################
+## Find all the directories under the current directory that
+## haves name that match $(1)
+###########################################################
+
+define all-subdir-named-dirs
+$(call all-named-dirs-under,$(1),.)
+endef
+
+###########################################################
+## Find all of the files under the named directories with
+## the specified name.
+## Meant to be used like:
+## SRC_FILES := $(call all-named-files-under,*.h,src tests)
+###########################################################
+
+define all-named-files-under
+$(call find-files-in-subdirs,$(LOCAL_PATH),"$(1)",$(2))
+endef
+
+###########################################################
+## Find all of the files under the current directory with
+## the specified name.
+###########################################################
+
+define all-subdir-named-files
+$(call all-named-files-under,$(1),.)
+endef
+
+###########################################################
## Find all of the java files under the named directories.
## Meant to be used like:
## SRC_FILES := $(call all-java-files-under,src tests)
###########################################################
define all-java-files-under
-$(patsubst ./%,%, \
- $(shell cd $(LOCAL_PATH) ; \
- find -L $(1) -name "*.java" -and -not -name ".*") \
- )
+$(call all-named-files-under,*.java,$(1))
endef
###########################################################
@@ -203,10 +240,7 @@
###########################################################
define all-c-files-under
-$(patsubst ./%,%, \
- $(shell cd $(LOCAL_PATH) ; \
- find -L $(1) -name "*.c" -and -not -name ".*") \
- )
+$(call all-named-files-under,*.c,$(1))
endef
###########################################################
@@ -219,16 +253,36 @@
endef
###########################################################
+## Find all of the cpp files under the named directories.
+## LOCAL_CPP_EXTENSION is respected if set.
+## Meant to be used like:
+## SRC_FILES := $(call all-cpp-files-under,src tests)
+###########################################################
+
+define all-cpp-files-under
+$(sort $(patsubst ./%,%, \
+ $(shell cd $(LOCAL_PATH) ; \
+ find -L $(1) -name "*$(or $(LOCAL_CPP_EXTENSION),.cpp)" -and -not -name ".*") \
+ ))
+endef
+
+###########################################################
+## Find all of the cpp files from here. Meant to be used like:
+## SRC_FILES := $(call all-subdir-cpp-files)
+###########################################################
+
+define all-subdir-cpp-files
+$(call all-cpp-files-under,.)
+endef
+
+###########################################################
## Find all files named "I*.aidl" under the named directories,
## which must be relative to $(LOCAL_PATH). The returned list
## is relative to $(LOCAL_PATH).
###########################################################
define all-Iaidl-files-under
-$(patsubst ./%,%, \
- $(shell cd $(LOCAL_PATH) ; \
- find -L $(1) -name "I*.aidl" -and -not -name ".*") \
- )
+$(call all-named-files-under,I*.aidl,$(1))
endef
###########################################################
@@ -246,10 +300,7 @@
###########################################################
define all-logtags-files-under
-$(patsubst ./%,%, \
- $(shell cd $(LOCAL_PATH) ; \
- find -L $(1) -name "*.logtags" -and -not -name ".*") \
- )
+$(call all-named-files-under,*.logtags,$(1))
endef
###########################################################
@@ -259,10 +310,7 @@
###########################################################
define all-proto-files-under
-$(patsubst ./%,%, \
- $(shell cd $(LOCAL_PATH) ; \
- find -L $(1) -name "*.proto" -and -not -name ".*") \
- )
+$(call all-named-files-under,*.proto,$(1))
endef
###########################################################
@@ -272,10 +320,7 @@
###########################################################
define all-renderscript-files-under
-$(patsubst ./%,%, \
- $(shell cd $(LOCAL_PATH) ; \
- find -L $(1) \( -name "*.rs" -or -name "*.fs" \) -and -not -name ".*") \
- )
+$(call find-subdir-files,$(1) \( -name "*.rs" -or -name "*.fs" \) -and -not -name ".*")
endef
###########################################################
@@ -285,10 +330,7 @@
###########################################################
define all-S-files-under
-$(patsubst ./%,%, \
- $(shell cd $(LOCAL_PATH) ; \
- find -L $(1) -name "*.S" -and -not -name ".*") \
- )
+$(call all-named-files-under,*.S,$(1))
endef
###########################################################
@@ -298,10 +340,7 @@
###########################################################
define all-html-files-under
-$(patsubst ./%,%, \
- $(shell cd $(LOCAL_PATH) ; \
- find -L $(1) -name "*.html" -and -not -name ".*") \
- )
+$(call all-named-files-under,*.html,$(1))
endef
###########################################################
@@ -319,7 +358,7 @@
###########################################################
define find-subdir-files
-$(patsubst ./%,%,$(shell cd $(LOCAL_PATH) ; find -L $(1)))
+$(sort $(patsubst ./%,%,$(shell cd $(LOCAL_PATH) ; find -L $(1))))
endef
###########################################################
@@ -331,8 +370,8 @@
###########################################################
define find-subdir-subdir-files
-$(filter-out $(patsubst %,$(1)/%,$(3)),$(patsubst ./%,%,$(shell cd \
- $(LOCAL_PATH) ; find -L $(1) -maxdepth 1 -name $(2))))
+$(sort $(filter-out $(patsubst %,$(1)/%,$(3)),$(patsubst ./%,%,$(shell cd \
+ $(LOCAL_PATH) ; find -L $(1) -maxdepth 1 -name $(2)))))
endef
###########################################################
@@ -341,10 +380,10 @@
###########################################################
define find-subdir-assets
-$(if $(1),$(patsubst ./%,%, \
+$(sort $(if $(1),$(patsubst ./%,%, \
$(shell if [ -d $(1) ] ; then cd $(1) ; find ./ -not -name '.*' -and -type f -and -not -type l ; fi)), \
$(warning Empty argument supplied to find-subdir-assets) \
-)
+))
endef
###########################################################
@@ -352,11 +391,11 @@
###########################################################
define find-other-java-files
- $(call find-subdir-files,$(1) -name "*.java" -and -not -name ".*")
+$(call all-java-files-under,$(1))
endef
define find-other-html-files
- $(call find-subdir-files,$(1) -name "*.html" -and -not -name ".*")
+$(call all-html-files-under,$(1))
endef
###########################################################
@@ -369,10 +408,10 @@
###########################################################
define find-files-in-subdirs
-$(patsubst ./%,%, \
+$(sort $(patsubst ./%,%, \
$(shell cd $(1) ; \
find -L $(3) -name $(2) -and -not -name ".*") \
- )
+ ))
endef
###########################################################
@@ -1633,8 +1672,12 @@
## Commands for running javac to make .class files
###########################################################
-#@echo "Source intermediates dir: $(PRIVATE_SOURCE_INTERMEDIATES_DIR)"
-#@echo "Source intermediates: $$(find $(PRIVATE_SOURCE_INTERMEDIATES_DIR) -name '*.java')"
+# Add BUILD_NUMBER to apps default version name if it's unbundled build.
+ifdef TARGET_BUILD_APPS
+APPS_DEFAULT_VERSION_NAME := $(PLATFORM_VERSION)-$(BUILD_NUMBER)
+else
+APPS_DEFAULT_VERSION_NAME := $(PLATFORM_VERSION)
+endif
# TODO: Right now we generate the asset resources twice, first as part
# of generating the Java classes, then at the end when packaging the final
@@ -1661,8 +1704,8 @@
$(addprefix -G , $(PRIVATE_PROGUARD_OPTIONS_FILE)) \
$(addprefix --min-sdk-version , $(PRIVATE_DEFAULT_APP_TARGET_SDK)) \
$(addprefix --target-sdk-version , $(PRIVATE_DEFAULT_APP_TARGET_SDK)) \
- $(if $(filter --version-code,$(PRIVATE_AAPT_FLAGS)),,$(addprefix --version-code , $(PLATFORM_SDK_VERSION))) \
- $(if $(filter --version-name,$(PRIVATE_AAPT_FLAGS)),,$(addprefix --version-name , $(PLATFORM_VERSION)-$(BUILD_NUMBER))) \
+ $(if $(filter --version-code,$(PRIVATE_AAPT_FLAGS)),,--version-code $(PLATFORM_SDK_VERSION)) \
+ $(if $(filter --version-name,$(PRIVATE_AAPT_FLAGS)),,--version-name $(APPS_DEFAULT_VERSION_NAME)) \
$(addprefix --rename-manifest-package , $(PRIVATE_MANIFEST_PACKAGE_NAME)) \
$(addprefix --rename-instrumentation-target-package , $(PRIVATE_MANIFEST_INSTRUMENTATION_FOR)) \
--skip-symbols-without-default-localization
@@ -2010,8 +2053,8 @@
$(addprefix --min-sdk-version , $(PRIVATE_DEFAULT_APP_TARGET_SDK)) \
$(addprefix --target-sdk-version , $(PRIVATE_DEFAULT_APP_TARGET_SDK)) \
$(if $(filter --product,$(PRIVATE_AAPT_FLAGS)),,$(addprefix --product , $(TARGET_AAPT_CHARACTERISTICS))) \
- $(if $(filter --version-code,$(PRIVATE_AAPT_FLAGS)),,$(addprefix --version-code , $(PLATFORM_SDK_VERSION))) \
- $(if $(filter --version-name,$(PRIVATE_AAPT_FLAGS)),,$(addprefix --version-name , $(PLATFORM_VERSION)-$(BUILD_NUMBER))) \
+ $(if $(filter --version-code,$(PRIVATE_AAPT_FLAGS)),,--version-code $(PLATFORM_SDK_VERSION)) \
+ $(if $(filter --version-name,$(PRIVATE_AAPT_FLAGS)),,--version-name $(APPS_DEFAULT_VERSION_NAME)) \
$(addprefix --rename-manifest-package , $(PRIVATE_MANIFEST_PACKAGE_NAME)) \
$(addprefix --rename-instrumentation-target-package , $(PRIVATE_MANIFEST_INSTRUMENTATION_FOR)) \
--skip-symbols-without-default-localization \
diff --git a/core/main.mk b/core/main.mk
index 4f22b93..5b6e1e9 100644
--- a/core/main.mk
+++ b/core/main.mk
@@ -939,6 +939,7 @@
$(call dist-for-goals, droidcore, \
$(INTERNAL_UPDATE_PACKAGE_TARGET) \
$(INTERNAL_OTA_PACKAGE_TARGET) \
+ $(BUILT_OTATOOLS_PACKAGE) \
$(SYMBOLS_ZIP) \
$(INSTALLED_FILES_FILE) \
$(INSTALLED_BUILD_PROP_TARGET) \
diff --git a/core/product.mk b/core/product.mk
index 4e8bff1..e97cba4 100644
--- a/core/product.mk
+++ b/core/product.mk
@@ -104,6 +104,7 @@
PRODUCT_SYSTEM_PROPERTY_BLACKLIST \
PRODUCT_SYSTEM_SERVER_JARS \
PRODUCT_VBOOT_SIGNING_KEY \
+ PRODUCT_VBOOT_SIGNING_SUBKEY \
PRODUCT_VERITY_SIGNING_KEY \
PRODUCT_SYSTEM_VERITY_PARTITION \
PRODUCT_VENDOR_VERITY_PARTITION \
diff --git a/core/product_config.mk b/core/product_config.mk
index 5240ae7..94449c2 100644
--- a/core/product_config.mk
+++ b/core/product_config.mk
@@ -117,7 +117,7 @@
# which really means TARGET_PRODUCT=dream make installclean.
ifneq ($(filter-out $(INTERNAL_VALID_VARIANTS),$(TARGET_BUILD_VARIANT)),)
MAKECMDGOALS := $(MAKECMDGOALS) $(TARGET_BUILD_VARIANT)
- TARGET_BUILD_VARIANT := eng
+ TARGET_BUILD_VARIANT := userdebug
default_goal_substitution :=
else
default_goal_substitution := $(DEFAULT_GOAL)
diff --git a/core/version_defaults.mk b/core/version_defaults.mk
index 483c8f2..a67a82e 100644
--- a/core/version_defaults.mk
+++ b/core/version_defaults.mk
@@ -42,7 +42,7 @@
# which is the version that we reveal to the end user.
# Update this value when the platform version changes (rather
# than overriding it somewhere else). Can be an arbitrary string.
- PLATFORM_VERSION := 6.0
+ PLATFORM_VERSION := 6.0.1
endif
ifeq "" "$(PLATFORM_SDK_VERSION)"
@@ -103,7 +103,7 @@
# Can be an arbitrary string, but must be a single word.
#
# If there is no $PLATFORM_SECURITY_PATCH set, keep it empty.
- PLATFORM_SECURITY_PATCH :=
+ PLATFORM_SECURITY_PATCH := 2015-12-01
endif
ifeq "" "$(PLATFORM_BASE_OS)"
diff --git a/envsetup.sh b/envsetup.sh
index dba64ee..6ad3a9e 100644
--- a/envsetup.sh
+++ b/envsetup.sh
@@ -1355,14 +1355,20 @@
return
fi
T=$(gettop)
- if [[ ! -f $T/filelist ]]; then
+ if [ ! "$OUT_DIR" = "" ]; then
+ mkdir -p $OUT_DIR
+ FILELIST=$OUT_DIR/filelist
+ else
+ FILELIST=$T/filelist
+ fi
+ if [[ ! -f $FILELIST ]]; then
echo -n "Creating index..."
- (\cd $T; find . -wholename ./out -prune -o -wholename ./.repo -prune -o -type f > filelist)
+ (\cd $T; find . -wholename ./out -prune -o -wholename ./.repo -prune -o -type f > $FILELIST)
echo " Done"
echo ""
fi
local lines
- lines=($(\grep "$1" $T/filelist | sed -e 's/\/[^/]*$//' | sort | uniq))
+ lines=($(\grep "$1" $FILELIST | sed -e 's/\/[^/]*$//' | sort | uniq))
if [[ ${#lines[@]} = 0 ]]; then
echo "Not found"
return
diff --git a/target/board/generic/sepolicy/property_contexts b/target/board/generic/sepolicy/property_contexts
index 09b9b06..a0a4020 100644
--- a/target/board/generic/sepolicy/property_contexts
+++ b/target/board/generic/sepolicy/property_contexts
@@ -1,2 +1,4 @@
qemu. u:object_r:qemu_prop:s0
+emu. u:object_r:qemu_prop:s0
+emulator. u:object_r:qemu_prop:s0
radio.noril u:object_r:radio_noril_prop:s0
diff --git a/target/product/base.mk b/target/product/base.mk
index 1699156..4c49e86 100644
--- a/target/product/base.mk
+++ b/target/product/base.mk
@@ -111,6 +111,7 @@
run-as \
schedtest \
sdcard \
+ secdiscard \
services \
settings \
sgdisk \
diff --git a/target/product/core.mk b/target/product/core.mk
index 519dbb8..d453303 100644
--- a/target/product/core.mk
+++ b/target/product/core.mk
@@ -23,7 +23,6 @@
PRODUCT_PACKAGES += \
BasicDreams \
Browser \
- Calculator \
Calendar \
CalendarProvider \
CaptivePortalLogin \
@@ -33,6 +32,7 @@
DocumentsUI \
DownloadProviderUi \
Email \
+ ExactCalculator \
Exchange2 \
ExternalStorageProvider \
FusedLocation \
diff --git a/target/product/core_tiny.mk b/target/product/core_tiny.mk
index 0a92275..2be0507 100644
--- a/target/product/core_tiny.mk
+++ b/target/product/core_tiny.mk
@@ -57,6 +57,7 @@
gatekeeperd \
keystore \
keystore.default \
+ ld.mc \
libOpenMAXAL \
libOpenSLES \
libdownmix \
diff --git a/target/product/embedded.mk b/target/product/embedded.mk
index c40de4f..25a8975 100644
--- a/target/product/embedded.mk
+++ b/target/product/embedded.mk
@@ -89,6 +89,7 @@
PRODUCT_COPY_FILES += \
system/core/rootdir/init.usb.rc:root/init.usb.rc \
+ system/core/rootdir/init.usb.configfs.rc:root/init.usb.configfs.rc \
system/core/rootdir/init.trace.rc:root/init.trace.rc \
system/core/rootdir/ueventd.rc:root/ueventd.rc \
system/core/rootdir/etc/hosts:system/etc/hosts
diff --git a/target/product/emulator.mk b/target/product/emulator.mk
index 982f7da..7394d4f 100644
--- a/target/product/emulator.mk
+++ b/target/product/emulator.mk
@@ -50,6 +50,7 @@
sensors.ranchu
PRODUCT_COPY_FILES += \
+ frameworks/native/data/etc/android.hardware.ethernet.xml:system/etc/permissions/android.hardware.ethernet.xml \
device/generic/goldfish/fstab.goldfish:root/fstab.goldfish \
device/generic/goldfish/init.goldfish.rc:root/init.goldfish.rc \
device/generic/goldfish/init.goldfish.sh:system/etc/init.goldfish.sh \
diff --git a/target/product/full_base.mk b/target/product/full_base.mk
index 3b547c8..65bdf0f 100644
--- a/target/product/full_base.mk
+++ b/target/product/full_base.mk
@@ -45,9 +45,6 @@
# Put en_US first in the list, so make it default.
PRODUCT_LOCALES := en_US
-# Include drawables for all densities
-PRODUCT_AAPT_CONFIG := normal
-
# Get some sounds
$(call inherit-product-if-exists, frameworks/base/data/sounds/AllAudio.mk)
diff --git a/target/product/vboot.mk b/target/product/vboot.mk
index e4b1144..48a4883 100644
--- a/target/product/vboot.mk
+++ b/target/product/vboot.mk
@@ -22,3 +22,4 @@
# We expect this file to exist with the suffixes ".vbprivk" and ".vbpupk".
# TODO: find a proper location for this
PRODUCT_VBOOT_SIGNING_KEY := external/vboot_reference/tests/devkeys/kernel_data_key
+PRODUCT_VBOOT_SIGNING_SUBKEY := external/vboot_reference/tests/devkeys/kernel_subkey
diff --git a/tools/droiddoc/templates-sdk-dev/assets/css/default.css b/tools/droiddoc/templates-sdk-dev/assets/css/default.css
index 04f4b90..6fef241 100644
--- a/tools/droiddoc/templates-sdk-dev/assets/css/default.css
+++ b/tools/droiddoc/templates-sdk-dev/assets/css/default.css
@@ -6573,6 +6573,10 @@
background: #00bcd4;
}
+.dac-studio {
+ background: #424242;
+}
+
.dac-search-mode .dac-header {
background: #b0bec5;
-webkit-transition: background 200ms;
@@ -6712,6 +6716,18 @@
outline: 0;
}
+.dac-studio .dac-header-console-btn {
+ color:#fff;
+ background:rgba(255, 255, 255, 0.3);
+}
+.dac-studio .dac-header-console-btn:hover {
+ background:rgba(255, 255, 255, 0.5);
+}
+.dac-studio .dac-header-console-btn:focus {
+ background:rgba(255, 255, 255, 0.7);
+ color:#000;
+}
+
@media (max-width: 719px) {
.dac-header {
text-align: center;
@@ -6823,6 +6839,10 @@
transform-origin: right center;
width: 64px;
}
+ .dac-studio .dac-header-search-inner::after {
+ background: -webkit-linear-gradient(right, #424242, rgba(66, 66, 66, 0));
+ background: linear-gradient(to left, #424242, rgba(66, 66, 66, 0));
+ }
.dac-search-mode .dac-header-search-inner::after {
opacity: 0;
@@ -6854,6 +6874,13 @@
width: 100%;
}
+.dac-studio .dac-header-search {
+ right:150px;
+}
+.dac-studio .dac-header-search-input {
+ background: rgba(255, 255, 255, 0.3);
+}
+
.dac-header-search-close, .dac-header-search-clear {
background: none;
border: none;
@@ -7267,6 +7294,12 @@
width: 100%;
}
+.dac-studio .dac-nav-hamburger-top,
+.dac-studio .dac-nav-hamburger-mid,
+.dac-studio .dac-nav-hamburger-bot {
+ background: rgba(256, 256, 256, 0.4);
+}
+
.dac-nav-animating .dac-nav-hamburger-top, .dac-nav-animating .dac-nav-hamburger-mid, .dac-nav-animating .dac-nav-hamburger-bot {
-webkit-transition: opacity .3s;
transition: opacity .3s;
@@ -7793,6 +7826,20 @@
text-align: center;
}
+/* Android Studio download page */
+section#features {
+ padding-top:0;
+}
+.wrap.feature {
+ margin:80px auto;
+}
+.dac-section-links.feature-more {
+ margin-top:-20px;
+}
+.dac-toggle-content .wrap.feature {
+ margin-top:0;
+}
+
@media (max-width: 719px) {
.dac-hero-figure {
height: 150px;
@@ -7802,6 +7849,17 @@
.dac-hero-figure img {
max-height: 150px;
}
+
+ /* Android Studio download page */
+ .feature .dac-hero-figure,
+ .feature .dac-hero-figure img {
+ height:auto;
+ max-height:none;
+ }
+ .feature .dac-hero-figure img {
+ width:90%;
+ margin:0 auto;
+ }
}
.dac-hero-carousel {
@@ -9829,3 +9887,33 @@
position: absolute;
top: -4px;
}
+
+/** CSS Fixes for DevSite (akassay@) */
+.dac-button-social,
+.dac-fab:not('.dac-scroll-button') {
+ position: relative;
+}
+
+.dac-button-social .dac-sprite,
+.dac-fab .dac-sprite,
+.play-button .dac-sprite {
+ margin-top: -7px;
+ position: relative;
+ top: 50%;
+}
+
+.dac-fab .dac-sprite.dac-arrow-down-gray {
+ margin-top: -3px;
+}
+
+.dac-button-social .dac-sprite.dac-gplus {
+ margin-top: -17px;
+}
+
+.play-button .dac-sprite {
+ margin-top: -10px;
+}
+
+.dac-nav-link-forward {
+ padding: 9px 0;
+}
diff --git a/tools/droiddoc/templates-sdk-dev/assets/js/docs.js b/tools/droiddoc/templates-sdk-dev/assets/js/docs.js
index f64b41e..9afed71 100644
--- a/tools/droiddoc/templates-sdk-dev/assets/js/docs.js
+++ b/tools/droiddoc/templates-sdk-dev/assets/js/docs.js
@@ -15,7 +15,8 @@
$(document).ready(function() {
// prep nav expandos
- var pagePath = document.location.pathname;
+ var pagePath = devsite ?
+ location.href.replace(location.hash, '') : 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 /
@@ -3378,12 +3379,22 @@
})();
var localeTarget = (function() {
var localeTarget = locale;
- if (location.pathname.substring(0,6) == "/intl/") {
- var target = location.pathname.split('/')[2];
- if (!(target === 0) || (LANGUAGES.indexOf(target) === -1)) {
- localeTarget = target;
+ if (window.devsite) {
+ if (getQueryVariable('hl')) {
+ var target = getQueryVariable('hl');
+ if (!(target === 0) || (LANGUAGES.indexOf(target) === -1)) {
+ localeTarget = target;
+ }
+ }
+ } else {
+ if (location.pathname.substring(0,6) == "/intl/") {
+ var target = location.pathname.split('/')[2];
+ if (!(target === 0) || (LANGUAGES.indexOf(target) === -1)) {
+ localeTarget = target;
+ }
}
}
+
return localeTarget;
})();
@@ -3891,6 +3902,11 @@
this.el.removeClass('dac-active');
$('body').removeClass('dac-modal-open');
this.isOpen = false;
+ // When closing the modal for Android Studio downloads, reload the page
+ // because otherwise we might get stuck with post-download dialog state
+ if ($("[data-modal='studio_tos']").length) {
+ location.reload();
+ }
};
Modal.prototype.open_ = function() {
@@ -4383,6 +4399,14 @@
} else if (body.hasClass('downloads')) {
selected = navEl.find('> li.downloads > a').addClass('selected');
}
+ } else if (body.hasClass('studio')) {
+ if (body.hasClass('features')) {
+ selected = navEl.find('> li.features > a').addClass('selected');
+ } else if (body.hasClass('guide')) {
+ selected = navEl.find('> li.guide > a').addClass('selected');
+ } else if (body.hasClass('preview')) {
+ selected = navEl.find('> li.preview > a').addClass('selected');
+ }
} else if (body.hasClass('design')) {
selected = navEl.find('> li.design > a').addClass('selected');
// highlight Home nav
@@ -5344,7 +5368,8 @@
return $.get('https://content.googleapis.com/customsearch/v1?' + $.param(searchParams));
}
- function renderResults(el, results) {
+ function renderResults(el, results, searchAppliance) {
+ var referenceResults = searchAppliance.getReferenceResults();
if (!results.items) {
el.append($('<div>').text('No results'));
return;
@@ -5352,27 +5377,37 @@
for (var i = 0; i < results.items.length; i++) {
var item = results.items[i];
- var hasImage = item.pagemap && item.pagemap.cse_thumbnail;
- var sectionMatch = item.link.match(/developer\.android\.com\/(\w*)/);
- var section = (sectionMatch && sectionMatch[1]) || 'blog';
+ var isDuplicate = false;
+ $(referenceResults.android).each(function(index, result) {
+ if (item.link.indexOf(result.link) > -1) {
+ isDuplicate = true;
+ return false;
+ }
+ });
- var entry = $('<div>').addClass('dac-custom-search-entry cols');
+ if (!isDuplicate) {
+ var hasImage = item.pagemap && item.pagemap.cse_thumbnail;
+ var sectionMatch = item.link.match(/developer\.android\.com\/(\w*)/);
+ var section = (sectionMatch && sectionMatch[1]) || 'blog';
- if (hasImage) {
- var image = item.pagemap.cse_thumbnail[0];
- entry.append($('<div>').addClass('dac-custom-search-image-wrapper')
- .append($('<div>').addClass('dac-custom-search-image').css('background-image', 'url(' + image.src + ')')));
+ var entry = $('<div>').addClass('dac-custom-search-entry cols');
+
+ if (hasImage) {
+ var image = item.pagemap.cse_thumbnail[0];
+ entry.append($('<div>').addClass('dac-custom-search-image-wrapper')
+ .append($('<div>').addClass('dac-custom-search-image').css('background-image', 'url(' + image.src + ')')));
+ }
+
+ entry.append($('<div>').addClass('dac-custom-search-text-wrapper')
+ .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);
}
-
- entry.append($('<div>').addClass('dac-custom-search-text-wrapper')
- .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) {
@@ -5380,32 +5415,32 @@
.addClass('dac-custom-search-load-more')
.text('Load more')
.click(function() {
- loadMoreResults(el, results);
+ loadMoreResults(el, results, searchAppliance);
});
el.append(loadMoreButton);
}
- }
+ };
- function loadMoreResults(el, results) {
- var query = results.queries.request.searchTerms;
- var start = results.queries.nextPage.startIndex;
+ function loadMoreResults(el, results, searchAppliance) {
+ var query = results.queries.request[0].searchTerms;
+ var start = results.queries.nextPage[0].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);
+ renderResults(el, results, searchAppliance);
});
}
- $.fn.customSearch = function(query) {
+ $.fn.customSearch = function(query, searchAppliance) {
var el = $(this);
customSearch(query).then(function(results) {
el.empty();
- renderResults(el, results);
+ renderResults(el, results, searchAppliance);
});
};
})(jQuery);
@@ -5612,10 +5647,11 @@
this.searchResultsHero = $('#dac-search-results-hero');
this.searchResultsReference = $('#dac-search-results-reference');
this.searchHeader = $('[data-search]').data('search-input.dac');
+ this.currQueryReferenceResults = {};
}
Search.prototype.init = function() {
- if (this.checkRedirectToIndex()) { return; }
+ if (!devsite && this.checkRedirectToIndex()) { return; }
this.searchHistory = window.dacStore('search-history');
@@ -5626,9 +5662,8 @@
this.searchClose.click(this.close.bind(this));
this.customSearch = $.fn.debounce(function(query) {
- $('#dac-custom-search-results').customSearch(query);
- }, 1000);
-
+ $('#dac-custom-search-results').customSearch(query, this);
+ }.bind(this), 1000);
// Start search shortcut (/)
$('body').keyup(function(event) {
if (event.which === 191 && $(event.target).is(':not(:input)')) {
@@ -5751,6 +5786,10 @@
return this.searchInput.val().replace(/(^ +)|( +$)/g, '');
};
+ Search.prototype.getReferenceResults = function() {
+ return this.currQueryReferenceResults;
+ };
+
Search.prototype.onSearchChanged = function() {
var query = this.getQuery();
@@ -5767,10 +5806,19 @@
this.lastQuery = query;
this.searchResultsFor.text(query);
+
+ // CSE results lag behind the metadata/reference results. We need to empty
+ // the CSE results and add 'Loading' text so user's aren't looking at two
+ // different sets of search results at one time.
+ var $loadingEl =
+ $('<div class="loadingCustomSearchResults">Loading Results...</div>');
+ $('#dac-custom-search-results').empty().prepend($loadingEl);
+
this.customSearch(query);
var metadataResults = metadata.search(query);
this.searchResultsResources.dacSearchRenderResources(metadataResults.resources, query);
this.searchResultsReference.dacSearchRenderReferences(metadataResults, query);
+ this.currQueryReferenceResults = metadataResults;
var hasHero = this.searchResultsHero.dacSearchRenderHero(metadataResults.resources, query);
var hasQuery = !!query;
@@ -6489,3 +6537,22 @@
initWideTable();
});
})(jQuery);
+
+/** Utilities */
+
+/* returns the given string with all HTML brackets converted to entities
+ TODO: move this to the site's JS library */
+function escapeHTML(string) {
+ return string.replace(/</g,"<")
+ .replace(/>/g,">");
+};
+
+function getQueryVariable(variable) {
+ var query = window.location.search.substring(1);
+ var vars = query.split("&");
+ for (var i=0;i<vars.length;i++) {
+ var pair = vars[i].split("=");
+ if(pair[0] == variable){return pair[1];}
+ }
+ return(false);
+};
diff --git a/tools/droiddoc/templates-sdk-dev/sdkpage.cs b/tools/droiddoc/templates-sdk-dev/sdkpage.cs
index 94b6276..30d6d04 100644
--- a/tools/droiddoc/templates-sdk-dev/sdkpage.cs
+++ b/tools/droiddoc/templates-sdk-dev/sdkpage.cs
@@ -12,16 +12,19 @@
<?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
- elif:ndk ?> ndk<?cs
- if:downloads ?> downloads<?cs /if ?><?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/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">
@@ -41,15 +44,7 @@
# The following is for SDK/NDK pages
#
#
-?><?cs
-if:ndk ?>
- <ul class="dac-header-crumbs">
- <?cs # More <li> elements added here with javascript ?>
- </ul>
-
- <!-- Breadcrumb Setup -->
- <p><script>$('.dac-nav-list').dacCurrentPage().dacCrumbs();</script></p><?cs
-/if ?>
+?>
<?cs if:header.hide ?><?cs else ?>
<h1 itemprop="name"><?cs var:page.title ?></h1>
@@ -86,20 +81,20 @@
<th>Platform</th>
<th>Package</th>
<th style="white-space:nowrap">Size (Bytes)</th>
- <th>MD5 Checksum</th>
+ <th>SHA1 Checksum</th>
</tr>
<tr>
<td>Windows 32-bit</td>
<td>
- <a onClick="return onDownload(this)"
- href="http://dl.google.com/android/ndk/<?cs var:ndk.win32_download ?>"><?cs var:ndk.win32_download ?></a>
+ <a onClick="return onDownload(this)" data-modal-toggle="ndk_tos"
+ href="http://dl.google.com/android/repository/<?cs var:ndk.win32_download ?>"><?cs var:ndk.win32_download ?></a>
</td>
<td><?cs var:ndk.win32_bytes ?></td>
<td><?cs var:ndk.win32_checksum ?></td>
</tr>
<!-- <tr>
<td>
- <a onClick="return onDownload(this)"
+ <a onClick="return onDownload(this)" data-modal-toggle="ndk_tos"
href="http://dl.google.com/android/ndk/<?cs var:ndk.win32.legacy_download ?>"><?cs var:ndk.win32.legacy_download ?></a>
</td>
<td><?cs var:ndk.win32.legacy_bytes ?></td>
@@ -108,16 +103,16 @@
<tr>
<td>Windows 64-bit</td>
<td>
- <a onClick="return onDownload(this)"
- href="http://dl.google.com/android/ndk/<?cs var:ndk.win64_download ?>"><?cs var:ndk.win64_download ?></a>
+ <a onClick="return onDownload(this)" data-modal-toggle="ndk_tos"
+ href="http://dl.google.com/android/repository/<?cs var:ndk.win64_download ?>"><?cs var:ndk.win64_download ?></a>
</td>
<td><?cs var:ndk.win64_bytes ?></td>
<td><?cs var:ndk.win64_checksum ?></td>
</tr>
<!-- <tr>
<td>
- <a onClick="return onDownload(this)"
- href="http://dl.google.com/android/ndk/<?cs var:ndk.win64.legacy_download ?>"><?cs var:ndk.win64.legacy_download ?></a>
+ <a onClick="return onDownload(this)" data-modal-toggle="ndk_tos"
+ href="http://dl.google.com/android/repository/<?cs var:ndk.win64.legacy_download ?>"><?cs var:ndk.win64.legacy_download ?></a>
</td>
<td><?cs var:ndk.win64.legacy_bytes ?></td>
<td><?cs var:ndk.win64.legacy_checksum ?></td>
@@ -126,8 +121,8 @@
<tr>
<td>Mac OS X 32-bit</td>
<td>
- <a onClick="return onDownload(this)"
- href="http://dl.google.com/android/ndk/<?cs var:ndk.mac32_download ?>"><?cs var:ndk.mac32_download ?></a>
+ <a onClick="return onDownload(this)" data-modal-toggle="ndk_tos"
+ href="http://dl.google.com/android/repository/<?cs var:ndk.mac32_download ?>"><?cs var:ndk.mac32_download ?></a>
</td>
<td><?cs var:ndk.mac32_bytes ?></td>
<td><?cs var:ndk.mac32_checksum ?></td>
@@ -135,41 +130,32 @@
<!-- (this item is deprecated)
<tr>
<td>
- <a onClick="return onDownload(this)"
- href="http://dl.google.com/android/ndk/<?cs var:ndk.mac32.legacy_download ?>"><?cs var:ndk.mac32.legacy_download ?></a>
+ <a onClick="return onDownload(this)" data-modal-toggle="ndk_tos"
+ href="http://dl.google.com/android/repository/<?cs var:ndk.mac32.legacy_download ?>"><?cs var:ndk.mac32.legacy_download ?></a>
</td>
<td><?cs var:ndk.mac32.legacy_bytes ?></td>
<td><?cs var:ndk.mac32.legacy_checksum ?></td>
</tr> -->
<td>Mac OS X 64-bit</td>
<td>
- <a onClick="return onDownload(this)"
- href="http://dl.google.com/android/ndk/<?cs var:ndk.mac64_download ?>"><?cs var:ndk.mac64_download ?></a>
+ <a onClick="return onDownload(this)" data-modal-toggle="ndk_tos"
+ href="http://dl.google.com/android/repository/<?cs var:ndk.mac64_download ?>"><?cs var:ndk.mac64_download ?></a>
</td>
<td><?cs var:ndk.mac64_bytes ?></td>
<td><?cs var:ndk.mac64_checksum ?></td>
</tr>
<!-- <tr>
<td>
- <a onClick="return onDownload(this)"
- href="http://dl.google.com/android/ndk/<?cs var:ndk.mac64.legacy_download ?>"><?cs var:ndk.mac64.legacy_download ?></a>
+ <a onClick="return onDownload(this)" data-modal-toggle="ndk_tos"
+ href="http://dl.google.com/android/repository/<?cs var:ndk.mac64.legacy_download ?>"><?cs var:ndk.mac64.legacy_download ?></a>
</td>
<td><?cs var:ndk.mac64.legacy_bytes ?></td>
<td><?cs var:ndk.mac64.legacy_checksum ?></td>
</tr> -->
- <tr>
- <td>Linux 32-bit (x86)</td>
- <td>
- <a onClick="return onDownload(this)"
- href="http://dl.google.com/android/ndk/<?cs var:ndk.linux32_download ?>"><?cs var:ndk.linux32_download ?></a>
- </td>
- <td><?cs var:ndk.linux32_bytes ?></td>
- <td><?cs var:ndk.linux32_checksum ?></td>
- </tr>
<!-- <tr>
<td>
- <a onClick="return onDownload(this)"
- href="http://dl.google.com/android/ndk/<?cs var:ndk.linux32.legacy_download ?>"><?cs var:ndk.linux32.legacy_download ?></a>
+ <a onClick="return onDownload(this)" data-modal-toggle="ndk_tos"
+ href="http://dl.google.com/android/repository/<?cs var:ndk.linux32.legacy_download ?>"><?cs var:ndk.linux32.legacy_download ?></a>
</td>
<td><?cs var:ndk.linux32.legacy_bytes ?></td>
<td><?cs var:ndk.linux32.legacy_checksum ?></td>
@@ -177,16 +163,16 @@
<tr>
<td>Linux 64-bit (x86)</td>
<td>
- <a onClick="return onDownload(this)"
- href="http://dl.google.com/android/ndk/<?cs var:ndk.linux64_download ?>"><?cs var:ndk.linux64_download ?></a>
+ <a onClick="return onDownload(this)" data-modal-toggle="ndk_tos"
+ href="http://dl.google.com/android/repository/<?cs var:ndk.linux64_download ?>"><?cs var:ndk.linux64_download ?></a>
</td>
<td><?cs var:ndk.linux64_bytes ?></td>
<td><?cs var:ndk.linux64_checksum ?></td>
</tr>
<!-- <tr>
<td>
- <a onClick="return onDownload(this)"
- href="http://dl.google.com/android/ndk/<?cs var:ndk.linux64.legacy_download ?>"><?cs var:ndk.linux64.legacy_download ?></a>
+ <a onClick="return onDownload(this)" data-modal-toggle="ndk_tos"
+ href="http://dl.google.com/android/repository/<?cs var:ndk.linux64.legacy_download ?>"><?cs var:ndk.linux64.legacy_download ?></a>
</td>
<td><?cs var:ndk.linux64.legacy_bytes ?></td>
<td><?cs var:ndk.linux64.legacy_checksum ?></td>
@@ -198,16 +184,13 @@
<?cs call:tag_list(root.descr) ?>
-
+<?cs ######## The NDK version of the download script ######### ?>
<script>
function onDownload(link) {
$("#downloadForRealz").html("Download " + $(link).text());
$("#downloadForRealz").attr('href',$(link).attr('href'));
- $("#tos").fadeIn('slow');
-
- location.hash = "download";
return false;
}
@@ -220,25 +203,28 @@
}
}
- function onDownloadNdkForRealz(link) {
+
+ function onDownloadForRealz(link) {
if ($("input#agree").is(':checked')) {
- $("#tos").fadeOut('slow');
-
- $('html, body').animate({
- scrollTop: $("#Installing").offset().top
- }, 800, function() {
- $("#Installing").click();
+ $("div.sdk-terms").slideUp();
+ $("h2#tos-header").text('Now downloading...');
+ $(".sdk-terms-intro").text('Your download is in progress.');
+ $("#sdk-terms-form").fadeOut('slow', function() {
+ setTimeout(function() {
+ // close the dialog
+ $('#ndk_tos').trigger('modal-close');
+ // reload to refresh the tos or optionally forward the user
+ location.reload();
+ }, 3000);
});
-
+ ga('send', 'event', 'SDK', 'NDK tools', $("#downloadForRealz").html());
return true;
} else {
- $("label#agreeLabel").parent().stop().animate({color: "#258AAF"}, 200,
- function() {$("label#agreeLabel").parent().stop().animate({color: "#222"}, 200)}
- );
return false;
}
}
+
$(window).hashchange( function(){
if (location.hash == "") {
location.reload();
@@ -270,153 +256,173 @@
<?cs call:tag_list(root.descr) ?>
+<section id="downloads" class="dac-section dac-small">
+<div class="wrap">
+
+<h2 class="norule">Start using Android Studio today</h2>
+
+<p>Android Studio includes all the tools you need to build apps for Android.</p>
+
+<div style="float:left;margin-right:40px;width:auto;">
+<p>
+ <a class="landing-button green download-bundle-button"
+ data-modal-toggle="studio_tos">Download Android Studio 2.0<br>
+ <span class="small"></span></a>
+</p>
+</div>
+
+<div style="float:left;width:auto;margin-bottom:40px">
+<ul class="nolist" style="text-transform: uppercase;margin:8px 0">
+<li>Version: <?cs var:studio.version ?></li>
+<li>Release date: <?cs var:studio.release.date ?></li>
+</ul>
+</div>
-<div class="pax col-13 online" style="margin:0;">
-
-<h3>SDK Tools Only</h3>
-
-<p>If you prefer to use a different IDE or run the tools from the
-command line or with build scripts, you can instead download the stand-alone Android SDK Tools.
-These packages provide the basic SDK tools for app development, without an IDE.
-Also see the <a href="<?cs var:toroot ?>tools/sdk/tools-notes.html">SDK tools release notes</a>.</p>
+<h4 style="clear:left;margin-top:40px">Select a different platform</h4>
<table class="download">
<tr>
<th>Platform</th>
- <th>Package</th>
+ <th>Android Studio package</th>
<th>Size</th>
- <th>SHA-1 Checksum</th>
+ <th>SHA-1 checksum</th>
</tr>
<tr>
- <td rowspan="2">Windows</td>
- <td>
- <a onclick="return onDownload(this)" id="win-tools" href="http://dl.google.com/android/<?cs
-var:sdk.win_installer
-?>"><?cs var:sdk.win_installer ?></a> (Recommended)
- </td>
- <td><?cs var:sdk.win_installer_bytes ?> bytes</td>
- <td><?cs var:sdk.win_installer_checksum ?></td>
- </tr>
- <tr>
- <!-- blank TD from Windows rowspan -->
- <td>
- <a onclick="return onDownload(this)" href="http://dl.google.com/android/<?cs var:sdk.win_download
-?>"><?cs var:sdk.win_download ?></a>
- </td>
- <td><?cs var:sdk.win_bytes ?> bytes</td>
- <td><?cs var:sdk.win_checksum ?></td>
- </tr>
- <tr>
- <td><nobr>Mac OS X</nobr></td>
- <td>
- <a onclick="return onDownload(this)" id="mac-tools" href="http://dl.google.com/android/<?cs
-var:sdk.mac_download
-?>"><?cs var:sdk.mac_download ?></a>
- </td>
- <td><?cs var:sdk.mac_bytes ?> bytes</td>
- <td><?cs var:sdk.mac_checksum ?></td>
- </tr>
- <tr>
- <td>Linux</td>
- <td>
- <a onclick="return onDownload(this)" id="linux-tools" href="http://dl.google.com/android/<?cs
-var:sdk.linux_download
-?>"><?cs var:sdk.linux_download ?></a>
- </td>
- <td><?cs var:sdk.linux_bytes ?> bytes</td>
- <td><?cs var:sdk.linux_checksum ?></td>
- </tr>
- </table>
-
-
-
-<h3>All Android Studio Packages</h3>
-
-<p>Select a specific Android Studio package for your platform. Also see the
-<a href="<?cs var:toroot ?>tools/revisions/studio.html">Android Studio release notes</a>.</p>
-
- <table class="download">
- <tr>
- <th>Platform</th>
- <th>Package</th>
- <th>Size</th>
- <th>SHA-1 Checksum</th>
- </tr>
-
- <tr>
<td rowspan="3">Windows</td>
<td>
- <a onclick="return onDownload(this,false,true)" id="win-bundle"
+ <a onclick="return onDownload(this,false,true)" id="win-bundle" data-modal-toggle="studio_tos"
href="https://dl.google.com/dl/android/studio/install/<?cs var:studio.version ?>/<?cs var:studio.win_bundle_exe_download ?>"
- ><?cs var:studio.win_bundle_exe_download ?></a><br>(Recommended)
+ ><?cs var:studio.win_bundle_exe_download ?></a><br>
+ Includes Windows installer (recommended)
</td>
- <td><?cs var:studio.win_bundle_exe_bytes ?> bytes</td>
+ <td id="win-bundle-size"><?cs call:size_in_mb(studio.win_bundle_exe_bytes) ?> MB
+ <br>(<?cs var:studio.win_bundle_exe_bytes ?> bytes)</td>
<td><?cs var:studio.win_bundle_exe_checksum ?></td>
</tr>
-
<tr>
<!-- blank TD from Windows rowspan -->
<td>
- <a onclick="return onDownload(this,false,true)" id="win-bundle-notools"
- href="https://dl.google.com/dl/android/studio/install/<?cs var:studio.version ?>/<?cs var:studio.win_notools_exe_download ?>"
- ><?cs var:studio.win_notools_exe_download ?></a><br>(No SDK tools included)
- </td>
- <td><?cs var:studio.win_notools_exe_bytes ?> bytes</td>
- <td><?cs var:studio.win_notools_exe_checksum ?></td>
- </tr>
-
- <tr>
- <!-- blank TD from Windows rowspan -->
- <td>
- <a onclick="return onDownload(this,false,true)" id="win-bundle-zip"
+ <a onclick="return onDownload(this,false,true)" id="win-bundle-zip" data-modal-toggle="studio_tos"
href="https://dl.google.com/dl/android/studio/ide-zips/<?cs var:studio.version ?>/<?cs var:studio.win_bundle_download ?>"
- ><?cs var:studio.win_bundle_download ?></a>
+ ><?cs var:studio.win_bundle_download ?></a><br>
+ No Windows installer
</td>
- <td><?cs var:studio.win_bundle_bytes ?> bytes</td>
+ <td><?cs call:size_in_mb(studio.win_bundle_bytes) ?> MB
+ <br>(<?cs var:studio.win_bundle_bytes ?> bytes)</td>
<td><?cs var:studio.win_bundle_checksum ?></td>
</tr>
-
+ <tr>
+ <!-- blank TD from Windows rowspan -->
+ <td>
+ <a onclick="return onDownload(this,false,true)" id="win-bundle-notools" data-modal-toggle="studio_tos"
+ href="https://dl.google.com/dl/android/studio/install/<?cs var:studio.version ?>/<?cs var:studio.win_notools_exe_download ?>"
+ ><?cs var:studio.win_notools_exe_download ?></a><br>
+ Includes Windows installer but no SDK tools
+ </td>
+ <td><?cs call:size_in_mb(studio.win_notools_exe_bytes) ?> MB
+ <br>(<?cs var:studio.win_notools_exe_bytes ?> bytes)</td>
+ <td><?cs var:studio.win_notools_exe_checksum ?></td>
+ </tr>
<tr>
<td><nobr>Mac OS X</nobr></td>
<td>
- <a onclick="return onDownload(this,false,true)" id="mac-bundle"
+ <a onclick="return onDownload(this,false,true)" id="mac-bundle" data-modal-toggle="studio_tos"
href="https://dl.google.com/dl/android/studio/install/<?cs var:studio.version ?>/<?cs var:studio.mac_bundle_download ?>"
><?cs var:studio.mac_bundle_download ?></a>
</td>
- <td><?cs var:studio.mac_bundle_bytes ?> bytes</td>
+ <td id="mac-bundle-size"><?cs call:size_in_mb(studio.mac_bundle_bytes) ?> MB
+ <br>(<?cs var:studio.mac_bundle_bytes ?> bytes)</td>
<td><?cs var:studio.mac_bundle_checksum ?></td>
</tr>
-
<tr>
<td>Linux</td>
<td>
- <a onclick="return onDownload(this,false,true)" id="linux-bundle"
+ <a onclick="return onDownload(this,false,true)" id="linux-bundle" data-modal-toggle="studio_tos"
href="https://dl.google.com/dl/android/studio/ide-zips/<?cs var:studio.version ?>/<?cs var:studio.linux_bundle_download ?>"
><?cs var:studio.linux_bundle_download ?></a>
</td>
- <td><?cs var:studio.linux_bundle_bytes ?> bytes</td>
+ <td id="linux-bundle-size"><?cs call:size_in_mb(studio.linux_bundle_bytes) ?> MB
+ <br>(<?cs var:studio.linux_bundle_bytes ?> bytes)</td>
<td><?cs var:studio.linux_bundle_checksum ?></td>
</tr>
</table>
-</div><!-- end pax -->
+<h4 class="norule" style="margin-top:40px">Get just the SDK tools</h4>
+
+<p>If you do not need Android Studio, you can download the basic
+Android SDK tools below.</p>
+
+ <table class="download">
+ <tr>
+ <th>Platform</th>
+ <th>SDK tools package</th>
+ <th>Size</th>
+ <th>SHA-1 checksum</th>
+ </tr>
+ <tr>
+ <td rowspan="2">Windows</td>
+ <td>
+ <a onclick="return onDownload(this)" id="win-tools" data-modal-toggle="studio_tos"
+ href="//dl.google.com/android/<?cs
+var:sdk.win_installer
+?>"><?cs var:sdk.win_installer ?></a><br>
+ Includes Windows installer
+ </td>
+ <td><?cs call:size_in_mb(sdk.win_installer_bytes) ?> MB
+ <br>(<?cs var:sdk.win_installer_bytes ?> bytes)</td>
+ <td><?cs var:sdk.win_installer_checksum ?></td>
+ </tr>
+ <tr>
+ <!-- blank TD from Windows rowspan -->
+ <td>
+ <a onclick="return onDownload(this)" id="win-tools2" data-modal-toggle="studio_tos"
+ href="//dl.google.com/android/<?cs var:sdk.win_download
+?>"><?cs var:sdk.win_download ?></a><br>
+ No Windows installer
+ </td>
+ <td><?cs call:size_in_mb(sdk.win_bytes) ?> MB
+ <br>(<?cs var:sdk.win_bytes ?> bytes)</td>
+ <td><?cs var:sdk.win_checksum ?></td>
+ </tr>
+ <tr>
+ <td><nobr>Mac OS X</nobr></td>
+ <td>
+ <a onclick="return onDownload(this)" id="mac-tools" data-modal-toggle="studio_tos"
+ href="//dl.google.com/android/<?cs
+var:sdk.mac_download
+?>"><?cs var:sdk.mac_download ?></a>
+ </td>
+ <td><?cs call:size_in_mb(sdk.mac_bytes) ?> MB
+ <br>(<?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" data-modal-toggle="studio_tos"
+ href="//dl.google.com/android/<?cs
+var:sdk.linux_download
+?>"><?cs var:sdk.linux_download ?></a>
+ </td>
+ <td><?cs call:size_in_mb(sdk.linux_bytes) ?> MB
+ <br>(<?cs var:sdk.linux_bytes ?> bytes)</td>
+ <td><?cs var:sdk.linux_checksum ?></td>
+ </tr>
+ </table>
+ <p>
+Also see the <a href="<?cs var:toroot ?>tools/sdk/tools-notes.html">SDK
+tools release notes</a>.</p>
+
+ </div><!-- end wrap -->
+ </section>
-
-
-
+<?cs ######## The Android Studio version of the download script ######### ?>
<script>
-
- if (location.hash == "#Requirements") {
- $('.reqs').show();
- } else if (location.hash == "#ExistingIDE") {
- $('.ide').show();
- }
-
var os;
var bundlename;
var $toolslink;
@@ -441,7 +447,9 @@
$('#not-supported').hide();
/* set up primary Android Studio download button */
- $('.download-bundle-button > .small').html(" for " + os);
+ idname = bundlename + "-size";
+ sizeMB = $(idname).text().split(' MB')[0];
+ $('.download-bundle-button > .small').html(" for " + os + " <em>(" + sizeMB + " MB)</em>");
$('.download-bundle-button').click(function() {return onDownload(this,true,true);}).attr('href', bundlename);
}
@@ -459,13 +467,10 @@
if (bundle && !button) {
$("a#downloadForRealz").attr("name", "#" + $(link).attr('id'));
} else {
+ $("h2#tos-header").text('Download the Android SDK Tools');
$("a#downloadForRealz").attr("name", $(link).attr('href'));
}
- $("#tos").show();
- $("#landing").hide();
-
- location.hash = "top";
return false;
}
@@ -493,22 +498,24 @@
function onDownloadForRealz(link) {
if ($("input#agree").is(':checked')) {
- location.hash = "";
- location.hash = "top";
$("div.sdk-terms").slideUp();
- $("h1#tos-header").text('Now downloading...');
- $(".sdk-terms-intro").text('You\'ll be redirected to the install instructions in a moment.');
- $("#sdk-terms-form").fadeOut('slow', function() {
- setTimeout(function() {
- if ($("#downloadForRealz").attr('bundle') == 'true') {
- // User downloaded the studio Bundle
- window.location = "/sdk/installing/index.html?pkg=studio";
- } else {
- // User downloaded the SDK Tools
- window.location = "/sdk/installing/index.html?pkg=tools";
- }
- }, 3000);
- });
+ if ($("#downloadForRealz").attr('bundle') == 'true') {
+ $("h2#tos-header").text('Now downloading Android Studio!');
+ $(".sdk-terms-intro").text('Redirecting to the install instructions...');
+ $("#sdk-terms-form").slideUp(function() {
+ setTimeout(function() {
+ window.location = "/sdk/installing/index.html";
+ }, 2000);
+ });
+ } else {
+ $("h2#tos-header").text('Now downloading the Android SDK Tools!');
+ $(".sdk-terms-intro").html("<p>Because you've chosen to download " +
+ "only the Android SDK tools (and not Android Studio), there are no " +
+ "setup procedures to follow.</p><p>For information about how to " +
+ "keep your SDK tools up to date, refer to the " +
+ "<a href='/tools/help/sdk-manager.html'>SDK Manager</a> guide.</p>");
+ $("#sdk-terms-form").slideUp();
+ }
ga('send', 'event', 'SDK', 'IDE and Tools', $("#downloadForRealz").html());
return true;
} else {
@@ -526,7 +533,7 @@
-</div><!-- end the wrapper used for relative/absolute positions -->
+
<?cs # THIS DIV WAS OPENED IN INDEX.JD ?>
@@ -573,9 +580,14 @@
<?cs /if ?>
</div><!-- end g-unit -->
-<?cs if:!devsite ?>
+
<?cs include:"trailer.cs" ?>
-<?cs /if ?>
+<script src="https://developer.android.com/ytblogger_lists_unified.js?v=17" type="text/javascript"></script>
+<script src="/jd_lists_unified.js?v=17" type="text/javascript"></script>
+<script src="/jd_extras.js?v=17" type="text/javascript"></script>
+<script src="/jd_collections.js?v=17" type="text/javascript"></script>
+<script src="/jd_tag_helpers.js?v=17" type="text/javascript"></script>
+
<!-- Start of Tag -->
<script type="text/javascript">
var axel = Math.random() + "";
diff --git a/tools/droiddoc/templates-sdk/assets/css/default.css b/tools/droiddoc/templates-sdk/assets/css/default.css
index 106ab2f..accf7bf 100644
--- a/tools/droiddoc/templates-sdk/assets/css/default.css
+++ b/tools/droiddoc/templates-sdk/assets/css/default.css
@@ -732,7 +732,7 @@
text-align:center;
width: 50%;
}
-
+
.training-nav-top a.prev-page-link {
padding-left: 15px;
text-align: left;
@@ -840,7 +840,7 @@
margin: 0 0 6px;
line-height: 16px;
}
-
+
/* Class colors */
ol.class-list li:nth-child(10n+1) .title {
background: #00bcd4;
@@ -872,7 +872,7 @@
ol.class-list li:nth-child(10n+10) .title {
background: #7e57c2;
}
-
+
@media (max-width: 719px) {
ol.class-list ol,
ol.class-list .description {
@@ -6376,7 +6376,7 @@
.dac-button.dac-raised.dac-primary, .landing-secondary, .button {
background-color: #039bef; }
.dac-button.dac-raised.dac-primary:hover, .landing-secondary:hover, .button:hover {
- background-color: #0288d1;
+ background-color: #0288d1;
color:#fff; }
.dac-button.dac-raised.dac-primary:active, .landing-secondary:active, .button:active {
background-color: #0277bd;
@@ -7787,6 +7787,20 @@
text-align: center;
}
+/* Android Studio download page */
+section#features {
+ padding-top:0;
+}
+.wrap.feature {
+ margin:80px auto;
+}
+.dac-section-links.feature-more {
+ margin-top:-20px;
+}
+.dac-toggle-content .wrap.feature {
+ margin-top:0;
+}
+
@media (max-width: 719px) {
.dac-hero-figure {
height: 150px;
@@ -7796,6 +7810,17 @@
.dac-hero-figure img {
max-height: 150px;
}
+
+ /* Android Studio download page */
+ .feature .dac-hero-figure,
+ .feature .dac-hero-figure img {
+ height:auto;
+ max-height:none;
+ }
+ .feature .dac-hero-figure img {
+ width:90%;
+ margin:0 auto;
+ }
}
.dac-hero-carousel {
@@ -8874,4 +8899,85 @@
.dac-hero-cta.mprev {
white-space:nowrap;
}
-}
\ No newline at end of file
+}
+
+/** Custom search API styles */
+.dac-custom-search {
+ background: #fff;
+ margin: 0 -10px;
+ padding: 20px 10px;
+ z-index: 1;
+}
+
+.dac-custom-search-section-title {
+ color: #505050;
+}
+
+.dac-custom-search-entry {
+ margin-bottom: 36px;
+ margin-top: 24px;
+}
+
+.dac-custom-search-image {
+ background-size: cover;
+ height: 112px;
+}
+
+@media (max-width: 719px) {
+ .dac-custom-search-image {
+ display: none;
+ }
+}
+
+.dac-custom-search-title {
+ color: #333;
+ font-size: 14px;
+ font-weight: 700;
+ line-height: 24px;
+ margin: 0;
+ padding: 0;
+}
+
+.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: 0;
+}
+
+.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-sdk/assets/js/docs.js b/tools/droiddoc/templates-sdk/assets/js/docs.js
index da6695d..c4a8150 100644
--- a/tools/droiddoc/templates-sdk/assets/js/docs.js
+++ b/tools/droiddoc/templates-sdk/assets/js/docs.js
@@ -2548,12 +2548,13 @@
function submit_search() {
var query = document.getElementById('search_autocomplete').value;
location.hash = 'q=' + query;
- loadSearchResults();
+ searchControl.query = query;
+ searchControl.init();
+ searchControl.trackSearchRequest(query);
$("#searchResults").slideDown('slow', setStickyTop);
return false;
}
-
function hideResults() {
$("#searchResults").slideUp('fast', setStickyTop);
$("#search-close").addClass("hide");
@@ -2562,119 +2563,248 @@
$("#search_autocomplete").val("").blur();
// reset the ajax search callback to nothing, so results don't appear unless ENTER
- searchControl.setSearchStartingCallback(this, function(control, searcher, query) {});
-
- // forcefully regain key-up event control (previously jacked by search api)
- $("#search_autocomplete").keyup(function(event) {
- return search_changed(event, false, toRoot);
- });
+ searchControl.reset();
return false;
}
-
-
/* ########################################################## */
/* ################ CUSTOM SEARCH ENGINE ################## */
/* ########################################################## */
+var searchControl = null;
+var dacsearch = dacsearch || {};
-var searchControl;
-google.load('search', '1', {"callback" : function() {
- searchControl = new google.search.SearchControl();
- } });
+/**
+ * The custom search engine API.
+ * @constructor
+ */
+dacsearch.CustomSearchEngine = function() {
+ /**
+ * The last response from Google CSE.
+ * @private {Object}
+ */
+ this.resultQuery_ = {};
-function loadSearchResults() {
- document.getElementById("search_autocomplete").style.color = "#000";
+ /** @private {?Element} */
+ this.searchResultEl_ = null;
- searchControl = new google.search.SearchControl();
+ /** @private {?Element} */
+ this.searchInputEl_ = null;
- // use our existing search form and use tabs when multiple searchers are used
- drawOptions = new google.search.DrawOptions();
- drawOptions.setDrawMode(google.search.SearchControl.DRAW_MODE_TABBED);
- drawOptions.setInput(document.getElementById("search_autocomplete"));
+ /** @private {string} */
+ this.query = '';
+};
- // configure search result options
- searchOptions = new google.search.SearcherOptions();
- searchOptions.setExpandMode(GSearchControl.EXPAND_MODE_OPEN);
+/**
+ * Initializes DAC's Google custom search engine.
+ * @export
+ */
+dacsearch.CustomSearchEngine.prototype.init = function() {
+ this.searchResultEl_ = $('#leftSearchControl');
+ this.searchResultEl_.empty();
+ this.searchInputEl_ = $('#search_autocomplete');
+ this.searchInputEl_.focus().val(this.query);
+ this.getResults_();
+ this.bindEvents_();
+};
- // configure each of the searchers, for each tab
- devSiteSearcher = new google.search.WebSearch();
- devSiteSearcher.setUserDefinedLabel("All");
- devSiteSearcher.setSiteRestriction("001482626316274216503:zu90b7s047u");
- designSearcher = new google.search.WebSearch();
- designSearcher.setUserDefinedLabel("Design");
- designSearcher.setSiteRestriction("http://developer.android.com/design/");
+/**
+ * Binds the keyup event to the search input.
+ * @private
+ */
+dacsearch.CustomSearchEngine.prototype.bindEvents_ = function() {
+ this.searchInputEl_.keyup(this.debounce_(function(e) {
+ var code = e.which;
+ if (code != 13) {
+ this.query = this.searchInputEl_.val();
+ location.hash = 'q=' + encodeURI(this.query);
+ this.searchResultEl_.empty();
+ this.getResults_();
+ }
+ }.bind(this), 250));
+};
- trainingSearcher = new google.search.WebSearch();
- trainingSearcher.setUserDefinedLabel("Training");
- trainingSearcher.setSiteRestriction("http://developer.android.com/training/");
- guidesSearcher = new google.search.WebSearch();
- guidesSearcher.setUserDefinedLabel("Guides");
- guidesSearcher.setSiteRestriction("http://developer.android.com/guide/");
+/**
+ * Resets the search control.
+ */
+dacsearch.CustomSearchEngine.prototype.reset = function() {
+ this.query = '';
+ this.searchInputEl_.off('keyup');
+ this.searchResultEl_.empty();
+ this.updateResultTitle_();
+};
- referenceSearcher = new google.search.WebSearch();
- referenceSearcher.setUserDefinedLabel("Reference");
- referenceSearcher.setSiteRestriction("http://developer.android.com/reference/");
- googleSearcher = new google.search.WebSearch();
- googleSearcher.setUserDefinedLabel("Google Services");
- googleSearcher.setSiteRestriction("http://developer.android.com/google/");
+/**
+ * Updates the search query text at the top of the results.
+ * @private
+ */
+dacsearch.CustomSearchEngine.prototype.updateResultTitle_ = function() {
+ $("#searchTitle").html("Results for <em>" + this.query + "</em>");
+};
- blogSearcher = new google.search.WebSearch();
- blogSearcher.setUserDefinedLabel("Blog");
- blogSearcher.setSiteRestriction("http://android-developers.blogspot.com");
- // add each searcher to the search control
- searchControl.addSearcher(devSiteSearcher, searchOptions);
- searchControl.addSearcher(designSearcher, searchOptions);
- searchControl.addSearcher(trainingSearcher, searchOptions);
- searchControl.addSearcher(guidesSearcher, searchOptions);
- searchControl.addSearcher(referenceSearcher, searchOptions);
- searchControl.addSearcher(googleSearcher, searchOptions);
- searchControl.addSearcher(blogSearcher, searchOptions);
+/**
+ * Makes the CSE api call and gets the results.
+ * @param {number=} opt_start The optional start index.
+ * @private
+ */
+dacsearch.CustomSearchEngine.prototype.getResults_ = function(opt_start) {
+ var lang = getLangPref();
+ // Fix zh-cn to be zh-CN.
+ lang = lang.replace(/-\w+/, function(m) { return m.toUpperCase(); });
+ var cseUrl = 'https://content.googleapis.com/customsearch/v1?';
+ var searchParams = {
+ cx: '000521750095050289010:zpcpi1ea4s8',
+ key: 'AIzaSyCFhbGnjW06dYwvRCU8h_zjdpS4PYYbEe8',
+ q: this.query,
+ start: opt_start || 1,
+ num: 6,
+ hl: lang,
+ fields: 'queries,items(pagemap,link,title,htmlSnippet,formattedUrl)'
+ };
- // configure result options
- searchControl.setResultSetSize(google.search.Search.LARGE_RESULTSET);
- searchControl.setLinkTarget(google.search.Search.LINK_TARGET_SELF);
- searchControl.setTimeoutInterval(google.search.SearchControl.TIMEOUT_SHORT);
- searchControl.setNoResultsString(google.search.SearchControl.NO_RESULTS_DEFAULT_STRING);
+ $.get(cseUrl + $.param(searchParams), function(data) {
+ this.resultQuery_ = data;
+ this.renderResults_(data);
+ this.updateResultTitle_(this.query);
+ }.bind(this));
+};
- // upon ajax search, refresh the url and search title
- searchControl.setSearchStartingCallback(this, function(control, searcher, query) {
- updateResultTitle(query);
- var query = document.getElementById('search_autocomplete').value;
- location.hash = 'q=' + query;
- });
- // once search results load, set up click listeners
- searchControl.setSearchCompleteCallback(this, function(control, searcher, query) {
- addResultClickListeners();
- });
+/**
+ * Renders the results.
+ * @private
+ */
+dacsearch.CustomSearchEngine.prototype.renderResults_ = function(results) {
+ var el = this.searchResultEl_;
- // draw the search results box
- searchControl.draw(document.getElementById("leftSearchControl"), drawOptions);
+ if (!results.items) {
+ el.append($('<div>').text('No results'));
+ return;
+ }
- // get query and execute the search
- searchControl.execute(decodeURI(getQuery(location.hash)));
+ for (var i = 0; i < results.items.length; i++) {
+ var item = results.items[i];
+ var hasImage = item.pagemap && item.pagemap.cse_thumbnail;
+ var sectionMatch = item.link.match(/developer\.android\.com\/(\w*)/);
+ var section = (sectionMatch && sectionMatch[1]) || 'blog';
- document.getElementById("search_autocomplete").focus();
- addTabListeners();
-}
-// End of loadSearchResults
+ var entry = $('<div>').addClass('dac-custom-search-entry cols');
+
+ 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 + ')')));
+ }
+
+ var linkTitleEl = $('<a>').text(item.title).attr('href', item.link);
+ linkTitleEl.click(function(e) {
+ ga('send', 'event', 'Google Custom Search',
+ 'clicked: ' + linkTitleEl.attr('href'),
+ 'query: ' + $("#search_autocomplete").val().toLowerCase());
+ });
+
+ var linkUrlEl = $('<a>').addClass('dac-custom-search-link').text(
+ item.formattedUrl).attr('href', item.link);
+ linkUrlEl.click(function(e) {
+ ga('send', 'event', 'Google Custom Search',
+ 'clicked: ' + linkUrlEl.attr('href'),
+ 'query: ' + $("#search_autocomplete").val().toLowerCase());
+ });
+
+
+ entry.append($('<div>').addClass(hasImage ? 'col-5of6' : 'col-6of6')
+ .append($('<p>').addClass('dac-custom-search-section').text(section))
+ .append(
+ linkTitleEl.wrap('<h2>').parent().addClass('dac-custom-search-title'))
+ .append($('<p>').addClass('dac-custom-search-snippet')
+ .html(item.htmlSnippet.replace(/<br>/g, ''))).append(linkUrlEl));
+
+ el.append(entry);
+ }
+
+ if ($('#dac-custom-search-load-more')) {
+ $('#dac-custom-search-load-more').remove();
+ }
+
+ if (results.queries.nextPage) {
+ var loadMoreButton = $('<button id="dac-custom-search-load-more">')
+ .addClass('dac-custom-search-load-more')
+ .text('Load more')
+ .click(function() {
+ this.loadMoreResults_();
+ }.bind(this));
+
+ el.append(loadMoreButton);
+ }
+};
+
+
+/**
+ * Loads more results.
+ * @private
+ */
+dacsearch.CustomSearchEngine.prototype.loadMoreResults_ = function() {
+ this.query = this.resultQuery_.queries.request[0].searchTerms;
+ var start = this.resultQuery_.queries.nextPage[0].startIndex;
+ var loadMoreButton = this.searchResultEl_.find(
+ '#dac-custom-search-load-more');
+ loadMoreButton.text('Loading more...');
+ this.getResults_(start);
+ this.trackSearchRequest(this.query + ' startIndex = ' + start);
+};
+
+
+/**
+ * Tracks a search request.
+ * @param {string} query The query for the request,
+ * includes start index if loading more results.
+ */
+dacsearch.CustomSearchEngine.prototype.trackSearchRequest = function(query) {
+ ga('send', 'event', 'Google Custom Search Submit', 'submit search query',
+ 'query: ' + query);
+};
+
+
+/**
+ * Returns a function, that, as long as it continues to be invoked, will not
+ * be triggered. The function will be called after it stops being called for
+ * N milliseconds.
+ * @param {Function} func The function to debounce.
+ * @param {number} wait The number of milliseconds to wait before calling the function.
+ * @private
+ */
+dacsearch.CustomSearchEngine.prototype.debounce_ = function(func, wait) {
+ var timeout;
+ return function() {
+ var context = this, args = arguments;
+ var later = function() {
+ timeout = null;
+ func.apply(context, args);
+ };
+ clearTimeout(timeout);
+ timeout = setTimeout(later, wait);
+ };
+};
google.setOnLoadCallback(function(){
+ searchControl = new dacsearch.CustomSearchEngine();
if (location.hash.indexOf("q=") == -1) {
// if there's no query in the url, don't search and make sure results are hidden
$('#searchResults').hide();
return;
} else {
// first time loading search results for this page
+ searchControl.query = decodeURI(location.hash.split('q=')[1]);
+ searchControl.init();
+ searchControl.trackSearchRequest(searchControl.query);
$('#searchResults').slideDown('slow', setStickyTop);
$("#search-close").removeClass("hide");
- loadSearchResults();
}
}, true);
@@ -2703,7 +2833,7 @@
// If the hash isn't a search query or there's an error in the query,
// then adjust the scroll position to account for sticky header, then exit.
- if ((location.hash.indexOf("q=") == -1) || (query == "undefined")) {
+ if ((location.hash.indexOf("q=") == -1) || (searchControl.query == "undefined")) {
// If the results pane is open, close it.
if (!$("#searchResults").is(":hidden")) {
hideResults();
@@ -2712,65 +2842,11 @@
return;
}
- // Otherwise, we have a search to do
- var query = decodeURI(getQuery(location.hash));
- searchControl.execute(query);
$('#searchResults').slideDown('slow', setStickyTop);
$("#search_autocomplete").focus();
$("#search-close").removeClass("hide");
-
- updateResultTitle(query);
});
-function updateResultTitle(query) {
- $("#searchTitle").html("Results for <em>" + escapeHTML(query) + "</em>");
-}
-
-// forcefully regain key-up event control (previously jacked by search api)
-$("#search_autocomplete").keyup(function(event) {
- return search_changed(event, false, toRoot);
-});
-
-// add event listeners to each tab so we can track the browser history
-function addTabListeners() {
- var tabHeaders = $(".gsc-tabHeader");
- for (var i = 0; i < tabHeaders.length; i++) {
- $(tabHeaders[i]).attr("id",i).click(function() {
- /*
- // make a copy of the page numbers for the search left pane
- setTimeout(function() {
- // remove any residual page numbers
- $('#searchResults .gsc-tabsArea .gsc-cursor-box.gs-bidi-start-align').remove();
- // move the page numbers to the left position; make a clone,
- // because the element is drawn to the DOM only once
- // and because we're going to remove it (previous line),
- // we need it to be available to move again as the user navigates
- $('#searchResults .gsc-webResult .gsc-cursor-box.gs-bidi-start-align:visible')
- .clone().appendTo('#searchResults .gsc-tabsArea');
- }, 200);
- */
- });
- }
- setTimeout(function(){$(tabHeaders[0]).click()},200);
-}
-
-// add analytics tracking events to each result link
-function addResultClickListeners() {
- $("#searchResults a.gs-title").each(function(index, link) {
- // When user clicks enter for Google search results, track it
- $(link).click(function() {
- ga('send', 'event', 'Google Click', 'clicked: ' + $(this).attr('href'),
- 'query: ' + $("#search_autocomplete").val().toLowerCase());
- });
- });
-}
-
-
-function getQuery(hash) {
- var queryParts = hash.split('=');
- return queryParts[1];
-}
-
/* returns the given string with all HTML brackets converted to entities
TODO: move this to the site's JS library */
function escapeHTML(string) {
@@ -4868,6 +4944,11 @@
this.el.removeClass('dac-active');
$('body').removeClass('dac-modal-open');
this.isOpen = false;
+ // When closing the modal for Android Studio downloads, reload the page
+ // because otherwise we might get stuck with post-download dialog state
+ if ($("[data-modal='studio_tos']").length) {
+ location.reload();
+ }
};
Modal.prototype.open_ = function() {
diff --git a/tools/droiddoc/templates-sdk/designpage.cs b/tools/droiddoc/templates-sdk/designpage.cs
index b945a1c..9393b64 100644
--- a/tools/droiddoc/templates-sdk/designpage.cs
+++ b/tools/droiddoc/templates-sdk/designpage.cs
@@ -9,10 +9,10 @@
<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">
+ <link rel="stylesheet" href="<?cs var:toroot ?>assets/design/default.css?v=19">
<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>
+ <script src="<?cs var:toroot ?>assets/design/default.js?v=19"></script>
</head>
<body class="gc-documentation
<?cs if:(guide||develop||training||reference||tools||sdk) ?>develop<?cs
diff --git a/tools/droiddoc/templates-sdk/docpage.cs b/tools/droiddoc/templates-sdk/docpage.cs
index 809409e..d41adaa 100644
--- a/tools/droiddoc/templates-sdk/docpage.cs
+++ b/tools/droiddoc/templates-sdk/docpage.cs
@@ -193,11 +193,11 @@
</div><!-- end doc-content -->
<?cs include:"trailer.cs" ?>
- <script src="https://developer.android.com/ytblogger_lists_unified.js?v=18" type="text/javascript"></script>
- <script src="<?cs var:toroot ?>jd_lists_unified.js?v=18" type="text/javascript"></script>
- <script src="<?cs var:toroot ?>jd_extras.js?v=18" type="text/javascript"></script>
- <script src="<?cs var:toroot ?>jd_collections.js?v=18" type="text/javascript"></script>
- <script src="<?cs var:toroot ?>jd_tag_helpers.js?v=18" type="text/javascript"></script>
+ <script src="https://developer.android.com/ytblogger_lists_unified.js?v=19" type="text/javascript"></script>
+ <script src="<?cs var:toroot ?>jd_lists_unified.js?v=19" type="text/javascript"></script>
+ <script src="<?cs var:toroot ?>jd_extras.js?v=19" type="text/javascript"></script>
+ <script src="<?cs var:toroot ?>jd_collections.js?v=19" type="text/javascript"></script>
+ <script src="<?cs var:toroot ?>jd_tag_helpers.js?v=19" type="text/javascript"></script>
</body>
</html>
diff --git a/tools/droiddoc/templates-sdk/head_tag.cs b/tools/droiddoc/templates-sdk/head_tag.cs
index fad25ed..27a66cb 100644
--- a/tools/droiddoc/templates-sdk/head_tag.cs
+++ b/tools/droiddoc/templates-sdk/head_tag.cs
@@ -52,7 +52,7 @@
if:android.whichdoc != 'online' ?>http:<?cs
/if ?>//fonts.googleapis.com/css?family=Roboto+Mono:400,500,700" title="roboto-mono" type="text/css"><?cs
/if ?>
-<link href="<?cs var:toroot ?>assets/css/default.css?v=18" rel="stylesheet" type="text/css">
+<link href="<?cs var:toroot ?>assets/css/default.css?v=19" rel="stylesheet" type="text/css">
<?cs if:reference && !(reference.gms || reference.gcm || preview) ?>
<!-- FULLSCREEN STYLESHEET -->
diff --git a/tools/droiddoc/templates-sdk/sdkpage.cs b/tools/droiddoc/templates-sdk/sdkpage.cs
index 01b4ae2..30d6d04 100644
--- a/tools/droiddoc/templates-sdk/sdkpage.cs
+++ b/tools/droiddoc/templates-sdk/sdkpage.cs
@@ -86,7 +86,7 @@
<tr>
<td>Windows 32-bit</td>
<td>
- <a onClick="return onDownload(this)"
+ <a onClick="return onDownload(this)" data-modal-toggle="ndk_tos"
href="http://dl.google.com/android/repository/<?cs var:ndk.win32_download ?>"><?cs var:ndk.win32_download ?></a>
</td>
<td><?cs var:ndk.win32_bytes ?></td>
@@ -94,7 +94,7 @@
</tr>
<!-- <tr>
<td>
- <a onClick="return onDownload(this)"
+ <a onClick="return onDownload(this)" data-modal-toggle="ndk_tos"
href="http://dl.google.com/android/ndk/<?cs var:ndk.win32.legacy_download ?>"><?cs var:ndk.win32.legacy_download ?></a>
</td>
<td><?cs var:ndk.win32.legacy_bytes ?></td>
@@ -103,7 +103,7 @@
<tr>
<td>Windows 64-bit</td>
<td>
- <a onClick="return onDownload(this)"
+ <a onClick="return onDownload(this)" data-modal-toggle="ndk_tos"
href="http://dl.google.com/android/repository/<?cs var:ndk.win64_download ?>"><?cs var:ndk.win64_download ?></a>
</td>
<td><?cs var:ndk.win64_bytes ?></td>
@@ -111,7 +111,7 @@
</tr>
<!-- <tr>
<td>
- <a onClick="return onDownload(this)"
+ <a onClick="return onDownload(this)" data-modal-toggle="ndk_tos"
href="http://dl.google.com/android/repository/<?cs var:ndk.win64.legacy_download ?>"><?cs var:ndk.win64.legacy_download ?></a>
</td>
<td><?cs var:ndk.win64.legacy_bytes ?></td>
@@ -121,7 +121,7 @@
<tr>
<td>Mac OS X 32-bit</td>
<td>
- <a onClick="return onDownload(this)"
+ <a onClick="return onDownload(this)" data-modal-toggle="ndk_tos"
href="http://dl.google.com/android/repository/<?cs var:ndk.mac32_download ?>"><?cs var:ndk.mac32_download ?></a>
</td>
<td><?cs var:ndk.mac32_bytes ?></td>
@@ -130,7 +130,7 @@
<!-- (this item is deprecated)
<tr>
<td>
- <a onClick="return onDownload(this)"
+ <a onClick="return onDownload(this)" data-modal-toggle="ndk_tos"
href="http://dl.google.com/android/repository/<?cs var:ndk.mac32.legacy_download ?>"><?cs var:ndk.mac32.legacy_download ?></a>
</td>
<td><?cs var:ndk.mac32.legacy_bytes ?></td>
@@ -138,7 +138,7 @@
</tr> -->
<td>Mac OS X 64-bit</td>
<td>
- <a onClick="return onDownload(this)"
+ <a onClick="return onDownload(this)" data-modal-toggle="ndk_tos"
href="http://dl.google.com/android/repository/<?cs var:ndk.mac64_download ?>"><?cs var:ndk.mac64_download ?></a>
</td>
<td><?cs var:ndk.mac64_bytes ?></td>
@@ -146,7 +146,7 @@
</tr>
<!-- <tr>
<td>
- <a onClick="return onDownload(this)"
+ <a onClick="return onDownload(this)" data-modal-toggle="ndk_tos"
href="http://dl.google.com/android/repository/<?cs var:ndk.mac64.legacy_download ?>"><?cs var:ndk.mac64.legacy_download ?></a>
</td>
<td><?cs var:ndk.mac64.legacy_bytes ?></td>
@@ -154,7 +154,7 @@
</tr> -->
<!-- <tr>
<td>
- <a onClick="return onDownload(this)"
+ <a onClick="return onDownload(this)" data-modal-toggle="ndk_tos"
href="http://dl.google.com/android/repository/<?cs var:ndk.linux32.legacy_download ?>"><?cs var:ndk.linux32.legacy_download ?></a>
</td>
<td><?cs var:ndk.linux32.legacy_bytes ?></td>
@@ -163,7 +163,7 @@
<tr>
<td>Linux 64-bit (x86)</td>
<td>
- <a onClick="return onDownload(this)"
+ <a onClick="return onDownload(this)" data-modal-toggle="ndk_tos"
href="http://dl.google.com/android/repository/<?cs var:ndk.linux64_download ?>"><?cs var:ndk.linux64_download ?></a>
</td>
<td><?cs var:ndk.linux64_bytes ?></td>
@@ -171,7 +171,7 @@
</tr>
<!-- <tr>
<td>
- <a onClick="return onDownload(this)"
+ <a onClick="return onDownload(this)" data-modal-toggle="ndk_tos"
href="http://dl.google.com/android/repository/<?cs var:ndk.linux64.legacy_download ?>"><?cs var:ndk.linux64.legacy_download ?></a>
</td>
<td><?cs var:ndk.linux64.legacy_bytes ?></td>
@@ -184,16 +184,13 @@
<?cs call:tag_list(root.descr) ?>
-
+<?cs ######## The NDK version of the download script ######### ?>
<script>
function onDownload(link) {
$("#downloadForRealz").html("Download " + $(link).text());
$("#downloadForRealz").attr('href',$(link).attr('href'));
- $("#tos").fadeIn('slow');
-
- location.hash = "download";
return false;
}
@@ -206,25 +203,28 @@
}
}
- function onDownloadNdkForRealz(link) {
+
+ function onDownloadForRealz(link) {
if ($("input#agree").is(':checked')) {
- $("#tos").fadeOut('slow');
-
- $('html, body').animate({
- scrollTop: $("#Installing").offset().top
- }, 800, function() {
- $("#Installing").click();
+ $("div.sdk-terms").slideUp();
+ $("h2#tos-header").text('Now downloading...');
+ $(".sdk-terms-intro").text('Your download is in progress.');
+ $("#sdk-terms-form").fadeOut('slow', function() {
+ setTimeout(function() {
+ // close the dialog
+ $('#ndk_tos').trigger('modal-close');
+ // reload to refresh the tos or optionally forward the user
+ location.reload();
+ }, 3000);
});
-
+ ga('send', 'event', 'SDK', 'NDK tools', $("#downloadForRealz").html());
return true;
} else {
- $("label#agreeLabel").parent().stop().animate({color: "#258AAF"}, 200,
- function() {$("label#agreeLabel").parent().stop().animate({color: "#222"}, 200)}
- );
return false;
}
}
+
$(window).hashchange( function(){
if (location.hash == "") {
location.reload();
@@ -256,153 +256,173 @@
<?cs call:tag_list(root.descr) ?>
+<section id="downloads" class="dac-section dac-small">
+<div class="wrap">
+
+<h2 class="norule">Start using Android Studio today</h2>
+
+<p>Android Studio includes all the tools you need to build apps for Android.</p>
+
+<div style="float:left;margin-right:40px;width:auto;">
+<p>
+ <a class="landing-button green download-bundle-button"
+ data-modal-toggle="studio_tos">Download Android Studio 2.0<br>
+ <span class="small"></span></a>
+</p>
+</div>
+
+<div style="float:left;width:auto;margin-bottom:40px">
+<ul class="nolist" style="text-transform: uppercase;margin:8px 0">
+<li>Version: <?cs var:studio.version ?></li>
+<li>Release date: <?cs var:studio.release.date ?></li>
+</ul>
+</div>
-<div class="pax col-13 online" style="margin:0;">
-
-<h3>SDK Tools Only</h3>
-
-<p>If you prefer to use a different IDE or run the tools from the
-command line or with build scripts, you can instead download the stand-alone Android SDK Tools.
-These packages provide the basic SDK tools for app development, without an IDE.
-Also see the <a href="<?cs var:toroot ?>tools/sdk/tools-notes.html">SDK tools release notes</a>.</p>
+<h4 style="clear:left;margin-top:40px">Select a different platform</h4>
<table class="download">
<tr>
<th>Platform</th>
- <th>Package</th>
+ <th>Android Studio package</th>
<th>Size</th>
- <th>SHA-1 Checksum</th>
+ <th>SHA-1 checksum</th>
</tr>
<tr>
- <td rowspan="2">Windows</td>
- <td>
- <a onclick="return onDownload(this)" id="win-tools" href="http://dl.google.com/android/<?cs
-var:sdk.win_installer
-?>"><?cs var:sdk.win_installer ?></a> (Recommended)
- </td>
- <td><?cs var:sdk.win_installer_bytes ?> bytes</td>
- <td><?cs var:sdk.win_installer_checksum ?></td>
- </tr>
- <tr>
- <!-- blank TD from Windows rowspan -->
- <td>
- <a onclick="return onDownload(this)" href="http://dl.google.com/android/<?cs var:sdk.win_download
-?>"><?cs var:sdk.win_download ?></a>
- </td>
- <td><?cs var:sdk.win_bytes ?> bytes</td>
- <td><?cs var:sdk.win_checksum ?></td>
- </tr>
- <tr>
- <td><nobr>Mac OS X</nobr></td>
- <td>
- <a onclick="return onDownload(this)" id="mac-tools" href="http://dl.google.com/android/<?cs
-var:sdk.mac_download
-?>"><?cs var:sdk.mac_download ?></a>
- </td>
- <td><?cs var:sdk.mac_bytes ?> bytes</td>
- <td><?cs var:sdk.mac_checksum ?></td>
- </tr>
- <tr>
- <td>Linux</td>
- <td>
- <a onclick="return onDownload(this)" id="linux-tools" href="http://dl.google.com/android/<?cs
-var:sdk.linux_download
-?>"><?cs var:sdk.linux_download ?></a>
- </td>
- <td><?cs var:sdk.linux_bytes ?> bytes</td>
- <td><?cs var:sdk.linux_checksum ?></td>
- </tr>
- </table>
-
-
-
-<h3>All Android Studio Packages</h3>
-
-<p>Select a specific Android Studio package for your platform. Also see the
-<a href="<?cs var:toroot ?>tools/revisions/studio.html">Android Studio release notes</a>.</p>
-
- <table class="download">
- <tr>
- <th>Platform</th>
- <th>Package</th>
- <th>Size</th>
- <th>SHA-1 Checksum</th>
- </tr>
-
- <tr>
<td rowspan="3">Windows</td>
<td>
- <a onclick="return onDownload(this,false,true)" id="win-bundle"
+ <a onclick="return onDownload(this,false,true)" id="win-bundle" data-modal-toggle="studio_tos"
href="https://dl.google.com/dl/android/studio/install/<?cs var:studio.version ?>/<?cs var:studio.win_bundle_exe_download ?>"
- ><?cs var:studio.win_bundle_exe_download ?></a><br>(Recommended)
+ ><?cs var:studio.win_bundle_exe_download ?></a><br>
+ Includes Windows installer (recommended)
</td>
- <td><?cs var:studio.win_bundle_exe_bytes ?> bytes</td>
+ <td id="win-bundle-size"><?cs call:size_in_mb(studio.win_bundle_exe_bytes) ?> MB
+ <br>(<?cs var:studio.win_bundle_exe_bytes ?> bytes)</td>
<td><?cs var:studio.win_bundle_exe_checksum ?></td>
</tr>
-
<tr>
<!-- blank TD from Windows rowspan -->
<td>
- <a onclick="return onDownload(this,false,true)" id="win-bundle-notools"
- href="https://dl.google.com/dl/android/studio/install/<?cs var:studio.version ?>/<?cs var:studio.win_notools_exe_download ?>"
- ><?cs var:studio.win_notools_exe_download ?></a><br>(No SDK tools included)
- </td>
- <td><?cs var:studio.win_notools_exe_bytes ?> bytes</td>
- <td><?cs var:studio.win_notools_exe_checksum ?></td>
- </tr>
-
- <tr>
- <!-- blank TD from Windows rowspan -->
- <td>
- <a onclick="return onDownload(this,false,true)" id="win-bundle-zip"
+ <a onclick="return onDownload(this,false,true)" id="win-bundle-zip" data-modal-toggle="studio_tos"
href="https://dl.google.com/dl/android/studio/ide-zips/<?cs var:studio.version ?>/<?cs var:studio.win_bundle_download ?>"
- ><?cs var:studio.win_bundle_download ?></a>
+ ><?cs var:studio.win_bundle_download ?></a><br>
+ No Windows installer
</td>
- <td><?cs var:studio.win_bundle_bytes ?> bytes</td>
+ <td><?cs call:size_in_mb(studio.win_bundle_bytes) ?> MB
+ <br>(<?cs var:studio.win_bundle_bytes ?> bytes)</td>
<td><?cs var:studio.win_bundle_checksum ?></td>
</tr>
-
+ <tr>
+ <!-- blank TD from Windows rowspan -->
+ <td>
+ <a onclick="return onDownload(this,false,true)" id="win-bundle-notools" data-modal-toggle="studio_tos"
+ href="https://dl.google.com/dl/android/studio/install/<?cs var:studio.version ?>/<?cs var:studio.win_notools_exe_download ?>"
+ ><?cs var:studio.win_notools_exe_download ?></a><br>
+ Includes Windows installer but no SDK tools
+ </td>
+ <td><?cs call:size_in_mb(studio.win_notools_exe_bytes) ?> MB
+ <br>(<?cs var:studio.win_notools_exe_bytes ?> bytes)</td>
+ <td><?cs var:studio.win_notools_exe_checksum ?></td>
+ </tr>
<tr>
<td><nobr>Mac OS X</nobr></td>
<td>
- <a onclick="return onDownload(this,false,true)" id="mac-bundle"
+ <a onclick="return onDownload(this,false,true)" id="mac-bundle" data-modal-toggle="studio_tos"
href="https://dl.google.com/dl/android/studio/install/<?cs var:studio.version ?>/<?cs var:studio.mac_bundle_download ?>"
><?cs var:studio.mac_bundle_download ?></a>
</td>
- <td><?cs var:studio.mac_bundle_bytes ?> bytes</td>
+ <td id="mac-bundle-size"><?cs call:size_in_mb(studio.mac_bundle_bytes) ?> MB
+ <br>(<?cs var:studio.mac_bundle_bytes ?> bytes)</td>
<td><?cs var:studio.mac_bundle_checksum ?></td>
</tr>
-
<tr>
<td>Linux</td>
<td>
- <a onclick="return onDownload(this,false,true)" id="linux-bundle"
+ <a onclick="return onDownload(this,false,true)" id="linux-bundle" data-modal-toggle="studio_tos"
href="https://dl.google.com/dl/android/studio/ide-zips/<?cs var:studio.version ?>/<?cs var:studio.linux_bundle_download ?>"
><?cs var:studio.linux_bundle_download ?></a>
</td>
- <td><?cs var:studio.linux_bundle_bytes ?> bytes</td>
+ <td id="linux-bundle-size"><?cs call:size_in_mb(studio.linux_bundle_bytes) ?> MB
+ <br>(<?cs var:studio.linux_bundle_bytes ?> bytes)</td>
<td><?cs var:studio.linux_bundle_checksum ?></td>
</tr>
</table>
-</div><!-- end pax -->
+<h4 class="norule" style="margin-top:40px">Get just the SDK tools</h4>
+
+<p>If you do not need Android Studio, you can download the basic
+Android SDK tools below.</p>
+
+ <table class="download">
+ <tr>
+ <th>Platform</th>
+ <th>SDK tools package</th>
+ <th>Size</th>
+ <th>SHA-1 checksum</th>
+ </tr>
+ <tr>
+ <td rowspan="2">Windows</td>
+ <td>
+ <a onclick="return onDownload(this)" id="win-tools" data-modal-toggle="studio_tos"
+ href="//dl.google.com/android/<?cs
+var:sdk.win_installer
+?>"><?cs var:sdk.win_installer ?></a><br>
+ Includes Windows installer
+ </td>
+ <td><?cs call:size_in_mb(sdk.win_installer_bytes) ?> MB
+ <br>(<?cs var:sdk.win_installer_bytes ?> bytes)</td>
+ <td><?cs var:sdk.win_installer_checksum ?></td>
+ </tr>
+ <tr>
+ <!-- blank TD from Windows rowspan -->
+ <td>
+ <a onclick="return onDownload(this)" id="win-tools2" data-modal-toggle="studio_tos"
+ href="//dl.google.com/android/<?cs var:sdk.win_download
+?>"><?cs var:sdk.win_download ?></a><br>
+ No Windows installer
+ </td>
+ <td><?cs call:size_in_mb(sdk.win_bytes) ?> MB
+ <br>(<?cs var:sdk.win_bytes ?> bytes)</td>
+ <td><?cs var:sdk.win_checksum ?></td>
+ </tr>
+ <tr>
+ <td><nobr>Mac OS X</nobr></td>
+ <td>
+ <a onclick="return onDownload(this)" id="mac-tools" data-modal-toggle="studio_tos"
+ href="//dl.google.com/android/<?cs
+var:sdk.mac_download
+?>"><?cs var:sdk.mac_download ?></a>
+ </td>
+ <td><?cs call:size_in_mb(sdk.mac_bytes) ?> MB
+ <br>(<?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" data-modal-toggle="studio_tos"
+ href="//dl.google.com/android/<?cs
+var:sdk.linux_download
+?>"><?cs var:sdk.linux_download ?></a>
+ </td>
+ <td><?cs call:size_in_mb(sdk.linux_bytes) ?> MB
+ <br>(<?cs var:sdk.linux_bytes ?> bytes)</td>
+ <td><?cs var:sdk.linux_checksum ?></td>
+ </tr>
+ </table>
+ <p>
+Also see the <a href="<?cs var:toroot ?>tools/sdk/tools-notes.html">SDK
+tools release notes</a>.</p>
+
+ </div><!-- end wrap -->
+ </section>
-
-
-
+<?cs ######## The Android Studio version of the download script ######### ?>
<script>
-
- if (location.hash == "#Requirements") {
- $('.reqs').show();
- } else if (location.hash == "#ExistingIDE") {
- $('.ide').show();
- }
-
var os;
var bundlename;
var $toolslink;
@@ -427,7 +447,9 @@
$('#not-supported').hide();
/* set up primary Android Studio download button */
- $('.download-bundle-button > .small').html(" for " + os);
+ idname = bundlename + "-size";
+ sizeMB = $(idname).text().split(' MB')[0];
+ $('.download-bundle-button > .small').html(" for " + os + " <em>(" + sizeMB + " MB)</em>");
$('.download-bundle-button').click(function() {return onDownload(this,true,true);}).attr('href', bundlename);
}
@@ -445,13 +467,10 @@
if (bundle && !button) {
$("a#downloadForRealz").attr("name", "#" + $(link).attr('id'));
} else {
+ $("h2#tos-header").text('Download the Android SDK Tools');
$("a#downloadForRealz").attr("name", $(link).attr('href'));
}
- $("#tos").show();
- $("#landing").hide();
-
- location.hash = "top";
return false;
}
@@ -479,22 +498,24 @@
function onDownloadForRealz(link) {
if ($("input#agree").is(':checked')) {
- location.hash = "";
- location.hash = "top";
$("div.sdk-terms").slideUp();
- $("h1#tos-header").text('Now downloading...');
- $(".sdk-terms-intro").text('You\'ll be redirected to the install instructions in a moment.');
- $("#sdk-terms-form").fadeOut('slow', function() {
- setTimeout(function() {
- if ($("#downloadForRealz").attr('bundle') == 'true') {
- // User downloaded the studio Bundle
- window.location = "/sdk/installing/index.html?pkg=studio";
- } else {
- // User downloaded the SDK Tools
- window.location = "/sdk/installing/index.html?pkg=tools";
- }
- }, 3000);
- });
+ if ($("#downloadForRealz").attr('bundle') == 'true') {
+ $("h2#tos-header").text('Now downloading Android Studio!');
+ $(".sdk-terms-intro").text('Redirecting to the install instructions...');
+ $("#sdk-terms-form").slideUp(function() {
+ setTimeout(function() {
+ window.location = "/sdk/installing/index.html";
+ }, 2000);
+ });
+ } else {
+ $("h2#tos-header").text('Now downloading the Android SDK Tools!');
+ $(".sdk-terms-intro").html("<p>Because you've chosen to download " +
+ "only the Android SDK tools (and not Android Studio), there are no " +
+ "setup procedures to follow.</p><p>For information about how to " +
+ "keep your SDK tools up to date, refer to the " +
+ "<a href='/tools/help/sdk-manager.html'>SDK Manager</a> guide.</p>");
+ $("#sdk-terms-form").slideUp();
+ }
ga('send', 'event', 'SDK', 'IDE and Tools', $("#downloadForRealz").html());
return true;
} else {
@@ -512,7 +533,7 @@
-</div><!-- end the wrapper used for relative/absolute positions -->
+
<?cs # THIS DIV WAS OPENED IN INDEX.JD ?>
@@ -561,6 +582,11 @@
</div><!-- end g-unit -->
<?cs include:"trailer.cs" ?>
+<script src="https://developer.android.com/ytblogger_lists_unified.js?v=17" type="text/javascript"></script>
+<script src="/jd_lists_unified.js?v=17" type="text/javascript"></script>
+<script src="/jd_extras.js?v=17" type="text/javascript"></script>
+<script src="/jd_collections.js?v=17" type="text/javascript"></script>
+<script src="/jd_tag_helpers.js?v=17" type="text/javascript"></script>
<!-- Start of Tag -->
<script type="text/javascript">
diff --git a/tools/releasetools/add_img_to_target_files.py b/tools/releasetools/add_img_to_target_files.py
index eab8113..f2bf1e1 100755
--- a/tools/releasetools/add_img_to_target_files.py
+++ b/tools/releasetools/add_img_to_target_files.py
@@ -28,6 +28,7 @@
print >> sys.stderr, "Python 2.7 or newer is required."
sys.exit(1)
+import datetime
import errno
import os
import tempfile
@@ -40,6 +41,9 @@
OPTIONS.add_missing = False
OPTIONS.rebuild_recovery = False
+OPTIONS.replace_verity_public_key = False
+OPTIONS.replace_verity_private_key = False
+OPTIONS.verity_signer_path = None
def AddSystem(output_zip, prefix="IMAGES/", recovery_img=None, boot_img=None):
"""Turn the contents of SYSTEM into a system image and store it in
@@ -119,6 +123,12 @@
if fstab:
image_props["fs_type"] = fstab["/" + what].fs_type
+ # Use a fixed timestamp (01/01/2009) when packaging the image.
+ # Bug: 24377993
+ epoch = datetime.datetime.fromtimestamp(0)
+ timestamp = (datetime.datetime(2009, 1, 1) - epoch).total_seconds()
+ image_props["timestamp"] = int(timestamp)
+
if what == "system":
fs_config_prefix = ""
else:
@@ -170,6 +180,12 @@
print "creating userdata.img..."
+ # Use a fixed timestamp (01/01/2009) when packaging the image.
+ # Bug: 24377993
+ epoch = datetime.datetime.fromtimestamp(0)
+ 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", and build the image from that.
@@ -207,6 +223,12 @@
print "creating cache.img..."
+ # Use a fixed timestamp (01/01/2009) when packaging the image.
+ # Bug: 24377993
+ epoch = datetime.datetime.fromtimestamp(0)
+ 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.
@@ -296,18 +318,27 @@
common.ZipClose(output_zip)
def main(argv):
- def option_handler(o, _):
+ def option_handler(o, a):
if o in ("-a", "--add_missing"):
OPTIONS.add_missing = True
elif o in ("-r", "--rebuild_recovery",):
OPTIONS.rebuild_recovery = True
+ elif o == "--replace_verity_private_key":
+ OPTIONS.replace_verity_private_key = (True, a)
+ elif o == "--replace_verity_public_key":
+ OPTIONS.replace_verity_public_key = (True, a)
+ elif o == "--verity_signer_path":
+ OPTIONS.verity_signer_path = a
else:
return False
return True
args = common.ParseOptions(
argv, __doc__, extra_opts="ar",
- extra_long_opts=["add_missing", "rebuild_recovery"],
+ extra_long_opts=["add_missing", "rebuild_recovery",
+ "replace_verity_public_key=",
+ "replace_verity_private_key=",
+ "verity_signer_path="],
extra_option_handler=option_handler)
diff --git a/tools/releasetools/blockimgdiff.py b/tools/releasetools/blockimgdiff.py
index 6ed9ca2..cb6fc85 100644
--- a/tools/releasetools/blockimgdiff.py
+++ b/tools/releasetools/blockimgdiff.py
@@ -16,6 +16,7 @@
from collections import deque, OrderedDict
from hashlib import sha1
+import common
import heapq
import itertools
import multiprocessing
@@ -105,11 +106,13 @@
assert not (trim and pad)
partial = len(self.data) % self.blocksize
+ padded = False
if partial > 0:
if trim:
self.data = self.data[:-partial]
elif pad:
self.data += '\0' * (self.blocksize - partial)
+ padded = True
else:
raise ValueError(("data for DataImage must be multiple of %d bytes "
"unless trim or pad is specified") %
@@ -119,14 +122,23 @@
self.total_blocks = len(self.data) / self.blocksize
self.care_map = RangeSet(data=(0, self.total_blocks))
- self.clobbered_blocks = RangeSet()
+ # When the last block is padded, we always write the whole block even for
+ # incremental OTAs. Because otherwise the last block may get skipped if
+ # unchanged for an incremental, but would fail the post-install
+ # verification if it has non-zero contents in the padding bytes.
+ # Bug: 23828506
+ if padded:
+ self.clobbered_blocks = RangeSet(
+ data=(self.total_blocks-1, self.total_blocks))
+ else:
+ self.clobbered_blocks = RangeSet()
self.extended = RangeSet()
zero_blocks = []
nonzero_blocks = []
reference = '\0' * self.blocksize
- for i in range(self.total_blocks):
+ for i in range(self.total_blocks-1 if padded else self.total_blocks):
d = self.data[i*self.blocksize : (i+1)*self.blocksize]
if d == reference:
zero_blocks.append(i)
@@ -138,14 +150,18 @@
self.file_map = {"__ZERO": RangeSet(zero_blocks),
"__NONZERO": RangeSet(nonzero_blocks)}
+ if self.clobbered_blocks:
+ self.file_map["__COPY"] = self.clobbered_blocks
+
def ReadRangeSet(self, ranges):
return [self.data[s*self.blocksize:e*self.blocksize] for (s, e) in ranges]
def TotalSha1(self, include_clobbered_blocks=False):
- # DataImage always carries empty clobbered_blocks, so
- # include_clobbered_blocks can be ignored.
- assert self.clobbered_blocks.size() == 0
- return sha1(self.data).hexdigest()
+ if not include_clobbered_blocks:
+ ranges = self.care_map.subtract(self.clobbered_blocks)
+ return sha1(self.ReadRangeSet(ranges)).hexdigest()
+ else:
+ return sha1(self.data).hexdigest()
class Transfer(object):
@@ -173,6 +189,12 @@
return (sum(sr.size() for (_, sr) in self.stash_before) -
sum(sr.size() for (_, sr) in self.use_stash))
+ def ConvertToNew(self):
+ assert self.style != "new"
+ self.use_stash = []
+ self.style = "new"
+ self.src_ranges = RangeSet()
+
def __str__(self):
return (str(self.id) + ": <" + str(self.src_ranges) + " " + self.style +
" to " + str(self.tgt_ranges) + ">")
@@ -267,6 +289,10 @@
self.ReverseBackwardEdges()
self.ImproveVertexSequence()
+ # Ensure the runtime stash size is under the limit.
+ if self.version >= 2 and common.OPTIONS.cache_size is not None:
+ self.ReviseStashSize()
+
# Double-check our work.
self.AssertSequenceGood()
@@ -286,7 +312,6 @@
out = []
total = 0
- performs_read = False
stashes = {}
stashed_blocks = 0
@@ -398,7 +423,6 @@
out.append("%s %s\n" % (xf.style, xf.tgt_ranges.to_string_raw()))
total += tgt_size
elif xf.style == "move":
- performs_read = True
assert xf.tgt_ranges
assert xf.src_ranges.size() == tgt_size
if xf.src_ranges != xf.tgt_ranges:
@@ -423,7 +447,6 @@
xf.tgt_ranges.to_string_raw(), src_str))
total += tgt_size
elif xf.style in ("bsdiff", "imgdiff"):
- performs_read = True
assert xf.tgt_ranges
assert xf.src_ranges
if self.version == 1:
@@ -460,9 +483,20 @@
if free_string:
out.append("".join(free_string))
- # sanity check: abort if we're going to need more than 512 MB if
- # stash space
- assert max_stashed_blocks * self.tgt.blocksize < (512 << 20)
+ if self.version >= 2:
+ # Sanity check: abort if we're going to need more stash space than
+ # the allowed size (cache_size * threshold). There are two purposes
+ # of having a threshold here. a) Part of the cache may have been
+ # occupied by some recovery logs. b) It will buy us some time to deal
+ # with the oversize issue.
+ cache_size = common.OPTIONS.cache_size
+ stash_threshold = common.OPTIONS.stash_threshold
+ max_allowed = cache_size * stash_threshold
+ assert max_stashed_blocks * self.tgt.blocksize < max_allowed, \
+ 'Stash size %d (%d * %d) exceeds the limit %d (%d * %.2f)' % (
+ max_stashed_blocks * self.tgt.blocksize, max_stashed_blocks,
+ self.tgt.blocksize, max_allowed, cache_size,
+ stash_threshold)
# Zero out extended blocks as a workaround for bug 20881595.
if self.tgt.extended:
@@ -489,8 +523,81 @@
f.write(i)
if self.version >= 2:
- print("max stashed blocks: %d (%d bytes)\n" % (
- max_stashed_blocks, max_stashed_blocks * self.tgt.blocksize))
+ max_stashed_size = max_stashed_blocks * self.tgt.blocksize
+ max_allowed = common.OPTIONS.cache_size * common.OPTIONS.stash_threshold
+ print("max stashed blocks: %d (%d bytes), limit: %d bytes (%.2f%%)\n" % (
+ max_stashed_blocks, max_stashed_size, max_allowed,
+ max_stashed_size * 100.0 / max_allowed))
+
+ def ReviseStashSize(self):
+ print("Revising stash size...")
+ stashes = {}
+
+ # Create the map between a stash and its def/use points. For example, for a
+ # given stash of (idx, sr), stashes[idx] = (sr, def_cmd, use_cmd).
+ for xf in self.transfers:
+ # Command xf defines (stores) all the stashes in stash_before.
+ for idx, sr in xf.stash_before:
+ stashes[idx] = (sr, xf)
+
+ # Record all the stashes command xf uses.
+ for idx, _ in xf.use_stash:
+ stashes[idx] += (xf,)
+
+ # Compute the maximum blocks available for stash based on /cache size and
+ # the threshold.
+ cache_size = common.OPTIONS.cache_size
+ stash_threshold = common.OPTIONS.stash_threshold
+ max_allowed = cache_size * stash_threshold / self.tgt.blocksize
+
+ stashed_blocks = 0
+ new_blocks = 0
+
+ # Now go through all the commands. Compute the required stash size on the
+ # fly. If a command requires excess stash than available, it deletes the
+ # stash by replacing the command that uses the stash with a "new" command
+ # instead.
+ for xf in self.transfers:
+ replaced_cmds = []
+
+ # xf.stash_before generates explicit stash commands.
+ for idx, sr in xf.stash_before:
+ if stashed_blocks + sr.size() > max_allowed:
+ # We cannot stash this one for a later command. Find out the command
+ # that will use this stash and replace the command with "new".
+ use_cmd = stashes[idx][2]
+ replaced_cmds.append(use_cmd)
+ print("%10d %9s %s" % (sr.size(), "explicit", use_cmd))
+ else:
+ stashed_blocks += sr.size()
+
+ # xf.use_stash generates free commands.
+ for _, sr in xf.use_stash:
+ stashed_blocks -= sr.size()
+
+ # "move" and "diff" may introduce implicit stashes in BBOTA v3. Prior to
+ # ComputePatches(), they both have the style of "diff".
+ if xf.style == "diff" and self.version >= 3:
+ assert xf.tgt_ranges and xf.src_ranges
+ if xf.src_ranges.overlaps(xf.tgt_ranges):
+ if stashed_blocks + xf.src_ranges.size() > max_allowed:
+ replaced_cmds.append(xf)
+ print("%10d %9s %s" % (xf.src_ranges.size(), "implicit", xf))
+
+ # Replace the commands in replaced_cmds with "new"s.
+ for cmd in replaced_cmds:
+ # It no longer uses any commands in "use_stash". Remove the def points
+ # for all those stashes.
+ for idx, sr in cmd.use_stash:
+ def_cmd = stashes[idx][1]
+ assert (idx, sr) in def_cmd.stash_before
+ def_cmd.stash_before.remove((idx, sr))
+ new_blocks += sr.size()
+
+ cmd.ConvertToNew()
+
+ print(" Total %d blocks are packed as new blocks due to insufficient "
+ "cache size." % (new_blocks,))
def ComputePatches(self, prefix):
print("Reticulating splines...")
@@ -847,6 +954,57 @@
a.goes_after[b] = size
def FindTransfers(self):
+ """Parse the file_map to generate all the transfers."""
+
+ def AddTransfer(tgt_name, src_name, tgt_ranges, src_ranges, style, by_id,
+ split=False):
+ """Wrapper function for adding a Transfer().
+
+ For BBOTA v3, we need to stash source blocks for resumable feature.
+ However, with the growth of file size and the shrink of the cache
+ partition source blocks are too large to be stashed. If a file occupies
+ too many blocks (greater than MAX_BLOCKS_PER_DIFF_TRANSFER), we split it
+ into smaller pieces by getting multiple Transfer()s.
+
+ The downside is that after splitting, we can no longer use imgdiff but
+ only bsdiff."""
+
+ MAX_BLOCKS_PER_DIFF_TRANSFER = 1024
+
+ # We care about diff transfers only.
+ if style != "diff" or not split:
+ Transfer(tgt_name, src_name, tgt_ranges, src_ranges, style, by_id)
+ return
+
+ # Change nothing for small files.
+ if (tgt_ranges.size() <= MAX_BLOCKS_PER_DIFF_TRANSFER and
+ src_ranges.size() <= MAX_BLOCKS_PER_DIFF_TRANSFER):
+ Transfer(tgt_name, src_name, tgt_ranges, src_ranges, style, by_id)
+ return
+
+ pieces = 0
+ while (tgt_ranges.size() > MAX_BLOCKS_PER_DIFF_TRANSFER and
+ src_ranges.size() > MAX_BLOCKS_PER_DIFF_TRANSFER):
+ tgt_split_name = "%s-%d" % (tgt_name, pieces)
+ src_split_name = "%s-%d" % (src_name, pieces)
+ tgt_first = tgt_ranges.first(MAX_BLOCKS_PER_DIFF_TRANSFER)
+ src_first = src_ranges.first(MAX_BLOCKS_PER_DIFF_TRANSFER)
+ Transfer(tgt_split_name, src_split_name, tgt_first, src_first, style,
+ by_id)
+
+ tgt_ranges = tgt_ranges.subtract(tgt_first)
+ src_ranges = src_ranges.subtract(src_first)
+ pieces += 1
+
+ # Handle remaining blocks.
+ if tgt_ranges.size() or src_ranges.size():
+ # Must be both non-empty.
+ assert tgt_ranges.size() and src_ranges.size()
+ tgt_split_name = "%s-%d" % (tgt_name, pieces)
+ src_split_name = "%s-%d" % (src_name, pieces)
+ Transfer(tgt_split_name, src_split_name, tgt_ranges, src_ranges, style,
+ by_id)
+
empty = RangeSet()
for tgt_fn, tgt_ranges in self.tgt.file_map.items():
if tgt_fn == "__ZERO":
@@ -854,28 +1012,28 @@
# in any file and that are filled with zeros. We have a
# special transfer style for zero blocks.
src_ranges = self.src.file_map.get("__ZERO", empty)
- Transfer(tgt_fn, "__ZERO", tgt_ranges, src_ranges,
- "zero", self.transfers)
+ AddTransfer(tgt_fn, "__ZERO", tgt_ranges, src_ranges,
+ "zero", self.transfers)
continue
elif tgt_fn == "__COPY":
# "__COPY" domain includes all the blocks not contained in any
# file and that need to be copied unconditionally to the target.
- Transfer(tgt_fn, None, tgt_ranges, empty, "new", self.transfers)
+ AddTransfer(tgt_fn, None, tgt_ranges, empty, "new", self.transfers)
continue
elif tgt_fn in self.src.file_map:
# Look for an exact pathname match in the source.
- Transfer(tgt_fn, tgt_fn, tgt_ranges, self.src.file_map[tgt_fn],
- "diff", self.transfers)
+ AddTransfer(tgt_fn, tgt_fn, tgt_ranges, self.src.file_map[tgt_fn],
+ "diff", self.transfers, self.version >= 3)
continue
b = os.path.basename(tgt_fn)
if b in self.src_basenames:
# Look for an exact basename match in the source.
src_fn = self.src_basenames[b]
- Transfer(tgt_fn, src_fn, tgt_ranges, self.src.file_map[src_fn],
- "diff", self.transfers)
+ AddTransfer(tgt_fn, src_fn, tgt_ranges, self.src.file_map[src_fn],
+ "diff", self.transfers, self.version >= 3)
continue
b = re.sub("[0-9]+", "#", b)
@@ -885,11 +1043,11 @@
# for .so files that contain version numbers in the filename
# that get bumped.)
src_fn = self.src_numpatterns[b]
- Transfer(tgt_fn, src_fn, tgt_ranges, self.src.file_map[src_fn],
- "diff", self.transfers)
+ AddTransfer(tgt_fn, src_fn, tgt_ranges, self.src.file_map[src_fn],
+ "diff", self.transfers, self.version >= 3)
continue
- Transfer(tgt_fn, None, tgt_ranges, empty, "new", self.transfers)
+ AddTransfer(tgt_fn, None, tgt_ranges, empty, "new", self.transfers)
def AbbreviateSourceNames(self):
for k in self.src.file_map.keys():
diff --git a/tools/releasetools/build_image.py b/tools/releasetools/build_image.py
index 4b43c0c..357a666 100755
--- a/tools/releasetools/build_image.py
+++ b/tools/releasetools/build_image.py
@@ -399,6 +399,7 @@
mount_point: such as "system", "data" etc.
"""
d = {}
+
if "build.prop" in glob_dict:
bp = glob_dict["build.prop"]
if "ro.build.date.utc" in bp:
diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py
index 99b319d..2965fa8 100644
--- a/tools/releasetools/common.py
+++ b/tools/releasetools/common.py
@@ -59,6 +59,8 @@
self.device_specific = None
self.extras = {}
self.info_dict = None
+ self.source_info_dict = None
+ self.target_info_dict = None
self.worker_threads = None
@@ -390,7 +392,9 @@
img_keyblock = tempfile.NamedTemporaryFile()
cmd = [info_dict["vboot_signer_cmd"], info_dict["futility"],
img_unsigned.name, info_dict["vboot_key"] + ".vbpubk",
- info_dict["vboot_key"] + ".vbprivk", img_keyblock.name,
+ info_dict["vboot_key"] + ".vbprivk",
+ info_dict["vboot_subkey"] + ".vbprivk",
+ img_keyblock.name,
img.name]
p = Run(cmd, stdout=subprocess.PIPE)
p.communicate()
@@ -1193,7 +1197,11 @@
self.path = os.path.join(tmpdir, partition)
b.Compute(self.path)
- _, self.device = GetTypeAndDevice("/" + partition, OPTIONS.info_dict)
+ if src is None:
+ _, self.device = GetTypeAndDevice("/" + partition, OPTIONS.info_dict)
+ else:
+ _, self.device = GetTypeAndDevice("/" + partition,
+ OPTIONS.source_info_dict)
def WriteScript(self, script, output_zip, progress=None):
if not self.src:
@@ -1391,6 +1399,8 @@
output_sink("recovery-from-boot.p", patch)
try:
+ # The following GetTypeAndDevice()s need to use the path in the target
+ # info_dict instead of source_info_dict.
boot_type, boot_device = GetTypeAndDevice("/boot", info_dict)
recovery_type, recovery_device = GetTypeAndDevice("/recovery", info_dict)
except KeyError:
@@ -1413,18 +1423,28 @@
'bonus_args': bonus_args}
# The install script location moved from /system/etc to /system/bin
- # in the L release. Parse the init.rc file to find out where the
+ # in the L release. Parse init.*.rc files to find out where the
# target-files expects it to be, and put it there.
sh_location = "etc/install-recovery.sh"
- try:
- with open(os.path.join(input_dir, "BOOT", "RAMDISK", "init.rc")) as f:
+ found = False
+ init_rc_dir = os.path.join(input_dir, "BOOT", "RAMDISK")
+ init_rc_files = os.listdir(init_rc_dir)
+ for init_rc_file in init_rc_files:
+ if (not init_rc_file.startswith('init.') or
+ not init_rc_file.endswith('.rc')):
+ continue
+
+ with open(os.path.join(init_rc_dir, init_rc_file)) as f:
for line in f:
m = re.match(r"^service flash_recovery /system/(\S+)\s*$", line)
if m:
sh_location = m.group(1)
- print "putting script in", sh_location
+ found = True
break
- except (OSError, IOError) as e:
- print "failed to read init.rc: %s" % (e,)
+
+ if found:
+ break
+
+ print "putting script in", sh_location
output_sink(sh_location, sh)
diff --git a/tools/releasetools/edify_generator.py b/tools/releasetools/edify_generator.py
index 566e687..a52e328 100644
--- a/tools/releasetools/edify_generator.py
+++ b/tools/releasetools/edify_generator.py
@@ -243,6 +243,15 @@
cmd = "delete(" + ",\0".join(['"%s"' % (i,) for i in file_list]) + ");"
self.script.append(self.WordWrap(cmd))
+ def DeleteFilesIfNotMatching(self, file_list):
+ """Delete the file in file_list if not matching the checksum."""
+ if not file_list:
+ return
+ for name, sha1 in file_list:
+ cmd = ('sha1_check(read_file("{name}"), "{sha1}") || '
+ 'delete("{name}");'.format(name=name, sha1=sha1))
+ self.script.append(self.WordWrap(cmd))
+
def RenameFile(self, srcfile, tgtfile):
"""Moves a file from one location to another."""
if self.info.get("update_rename_support", False):
@@ -254,7 +263,7 @@
"""Prepend an action with an apply_patch_check in order to
skip the action if the file exists. Used when a patch
is later renamed."""
- cmd = ('sha1_check(read_file("%s"), %s) || ' % (tgtfile, tgtsha1))
+ cmd = ('sha1_check(read_file("%s"), %s) ||' % (tgtfile, tgtsha1))
self.script.append(self.WordWrap(cmd))
def ApplyPatch(self, srcfile, tgtfile, tgtsize, tgtsha1, *patchpairs):
diff --git a/tools/releasetools/ota_from_target_files.py b/tools/releasetools/ota_from_target_files.py
index 531a728..c5c16b4 100755
--- a/tools/releasetools/ota_from_target_files.py
+++ b/tools/releasetools/ota_from_target_files.py
@@ -42,6 +42,11 @@
radio image. This option is only meaningful when -i is specified,
because a full radio is always included in a full OTA if applicable.
+ --full_bootloader
+ When generating an incremental OTA, always include a full copy of
+ bootloader image. This option is only meaningful when -i is specified,
+ because a full bootloader is always included in a full OTA if applicable.
+
-v (--verify)
Remount and verify the checksums of the files written to the
system and vendor (if used) partitions. Incremental builds only.
@@ -84,6 +89,9 @@
Specifies the number of worker-threads that will be used when
generating patches for incremental updates (defaults to 3).
+ --stash_threshold <float>
+ Specifies the threshold that will be used to compute the maximum
+ allowed stash size (defaults to 0.8).
"""
import sys
@@ -122,6 +130,10 @@
OPTIONS.oem_source = None
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
def MostPopularKey(d, default):
"""Given a dict, return the key corresponding to the largest
@@ -747,7 +759,7 @@
output_zip=output_zip,
script=script,
metadata=metadata,
- info_dict=OPTIONS.info_dict)
+ info_dict=OPTIONS.source_info_dict)
# TODO: Currently this works differently from WriteIncrementalOTAPackage().
# This function doesn't consider thumbprints when writing
@@ -1147,7 +1159,7 @@
output_zip=output_zip,
script=script,
metadata=metadata,
- info_dict=OPTIONS.info_dict)
+ info_dict=OPTIONS.source_info_dict)
system_diff = FileDifference("system", source_zip, target_zip, output_zip)
script.Mount("/system", recovery_mount_options)
@@ -1384,11 +1396,36 @@
# Delete all the symlinks in source that aren't in target. This
# needs to happen before verbatim files are unpacked, in case a
# symlink in the source is replaced by a real file in the target.
- to_delete = []
+
+ # If a symlink in the source will be replaced by a regular file, we cannot
+ # delete the symlink/file in case the package gets applied again. For such
+ # a symlink, we prepend a sha1_check() to detect if it has been updated.
+ # (Bug: 23646151)
+ replaced_symlinks = dict()
+ if system_diff:
+ for i in system_diff.verbatim_targets:
+ replaced_symlinks["/%s" % (i[0],)] = i[2]
+ if vendor_diff:
+ for i in vendor_diff.verbatim_targets:
+ replaced_symlinks["/%s" % (i[0],)] = i[2]
+
+ if system_diff:
+ for tf in system_diff.renames.values():
+ replaced_symlinks["/%s" % (tf.name,)] = tf.sha1
+ if vendor_diff:
+ for tf in vendor_diff.renames.values():
+ replaced_symlinks["/%s" % (tf.name,)] = tf.sha1
+
+ always_delete = []
+ may_delete = []
for dest, link in source_symlinks:
if link not in target_symlinks_d:
- to_delete.append(link)
- script.DeleteFiles(to_delete)
+ if link in replaced_symlinks:
+ may_delete.append((link, replaced_symlinks[link]))
+ else:
+ always_delete.append(link)
+ script.DeleteFiles(always_delete)
+ script.DeleteFilesIfNotMatching(may_delete)
if system_diff.verbatim_targets:
script.Print("Unpacking new system files...")
@@ -1474,6 +1511,8 @@
OPTIONS.incremental_source = a
elif o == "--full_radio":
OPTIONS.full_radio = True
+ elif o == "--full_bootloader":
+ OPTIONS.full_bootloader = True
elif o in ("-w", "--wipe_user_data"):
OPTIONS.wipe_user_data = True
elif o in ("-n", "--no_prereq"):
@@ -1505,6 +1544,12 @@
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))
else:
return False
return True
@@ -1516,6 +1561,7 @@
"package_key=",
"incremental_from=",
"full_radio",
+ "full_bootloader",
"wipe_user_data",
"no_prereq",
"extra_script=",
@@ -1528,6 +1574,7 @@
"oem_settings=",
"verify",
"no_fallback_to_full",
+ "stash_threshold=",
], extra_option_handler=option_handler)
if len(args) != 2:
@@ -1585,6 +1632,11 @@
output_zip = zipfile.ZipFile(temp_zip_file, "w",
compression=zipfile.ZIP_DEFLATED)
+ cache_size = OPTIONS.info_dict.get("cache_size", None)
+ if cache_size is None:
+ raise RuntimeError("can't determine the cache partition size")
+ OPTIONS.cache_size = cache_size
+
if OPTIONS.incremental_source is None:
WriteFullOTAPackage(input_zip, output_zip)
if OPTIONS.package_key is None:
diff --git a/tools/releasetools/rangelib.py b/tools/releasetools/rangelib.py
index 1506658..373bbed 100644
--- a/tools/releasetools/rangelib.py
+++ b/tools/releasetools/rangelib.py
@@ -24,6 +24,7 @@
lots of runs."""
def __init__(self, data=None):
+ # TODO(tbao): monotonic is broken when passing in a tuple.
self.monotonic = False
if isinstance(data, str):
self._parse_internal(data)
@@ -260,6 +261,38 @@
out = out.union(RangeSet(str(s1) + "-" + str(e1-1)))
return out
+ def first(self, n):
+ """Return the RangeSet that contains at most the first 'n' integers.
+
+ >>> RangeSet("0-9").first(1)
+ <RangeSet("0")>
+ >>> RangeSet("10-19").first(5)
+ <RangeSet("10-14")>
+ >>> RangeSet("10-19").first(15)
+ <RangeSet("10-19")>
+ >>> RangeSet("10-19 30-39").first(3)
+ <RangeSet("10-12")>
+ >>> RangeSet("10-19 30-39").first(15)
+ <RangeSet("10-19 30-34")>
+ >>> RangeSet("10-19 30-39").first(30)
+ <RangeSet("10-19 30-39")>
+ >>> RangeSet("0-9").first(0)
+ <RangeSet("")>
+ """
+
+ if self.size() <= n:
+ return self
+
+ out = []
+ for s, e in self:
+ if e - s >= n:
+ out += (s, s+n)
+ break
+ else:
+ out += (s, e)
+ n -= e - s
+ return RangeSet(data=out)
+
if __name__ == "__main__":
import doctest
diff --git a/tools/releasetools/sign_target_files_apks.py b/tools/releasetools/sign_target_files_apks.py
index ec49112..60d62c2 100755
--- a/tools/releasetools/sign_target_files_apks.py
+++ b/tools/releasetools/sign_target_files_apks.py
@@ -203,11 +203,13 @@
common.ZipWriteStr(output_tf_zip, out_info, data)
elif info.filename in ("SYSTEM/build.prop",
"VENDOR/build.prop",
+ "BOOT/RAMDISK/default.prop",
"RECOVERY/RAMDISK/default.prop"):
print "rewriting %s:" % (info.filename,)
new_data = RewriteProps(data, misc_info)
common.ZipWriteStr(output_tf_zip, out_info, new_data)
- if info.filename == "RECOVERY/RAMDISK/default.prop":
+ if info.filename in ("BOOT/RAMDISK/default.prop",
+ "RECOVERY/RAMDISK/default.prop"):
write_to_temp(info.filename, info.external_attr, new_data)
elif info.filename.endswith("mac_permissions.xml"):
print "rewriting %s with new keys." % (info.filename,)
@@ -310,6 +312,10 @@
pieces = value.split("/")
pieces[-1] = EditTags(pieces[-1])
value = "/".join(pieces)
+ elif key == "ro.bootimage.build.fingerprint":
+ pieces = value.split("/")
+ pieces[-1] = EditTags(pieces[-1])
+ value = "/".join(pieces)
elif key == "ro.build.description":
pieces = value.split(" ")
assert len(pieces) == 5
diff --git a/tools/releasetools/sparse_img.py b/tools/releasetools/sparse_img.py
index 07f3c1c..013044f 100644
--- a/tools/releasetools/sparse_img.py
+++ b/tools/releasetools/sparse_img.py
@@ -210,6 +210,16 @@
nonzero_blocks = []
reference = '\0' * self.blocksize
+ # Workaround for bug 23227672. For squashfs, we don't have a system.map. So
+ # the whole system image will be treated as a single file. But for some
+ # unknown bug, the updater will be killed due to OOM when writing back the
+ # patched image to flash (observed on lenok-userdebug MEA49). Prior to
+ # getting a real fix, we evenly divide the non-zero blocks into smaller
+ # groups (currently 1024 blocks or 4MB per group).
+ # Bug: 23227672
+ MAX_BLOCKS_PER_GROUP = 1024
+ nonzero_groups = []
+
f = self.simg_f
for s, e in remaining:
for b in range(s, e):
@@ -232,12 +242,22 @@
nonzero_blocks.append(b)
nonzero_blocks.append(b+1)
- assert zero_blocks or nonzero_blocks or clobbered_blocks
+ if len(nonzero_blocks) >= MAX_BLOCKS_PER_GROUP:
+ nonzero_groups.append(nonzero_blocks)
+ # Clear the list.
+ nonzero_blocks = []
+
+ if nonzero_blocks:
+ nonzero_groups.append(nonzero_blocks)
+ nonzero_blocks = []
+
+ assert zero_blocks or nonzero_groups or clobbered_blocks
if zero_blocks:
out["__ZERO"] = rangelib.RangeSet(data=zero_blocks)
- if nonzero_blocks:
- out["__NONZERO"] = rangelib.RangeSet(data=nonzero_blocks)
+ if nonzero_groups:
+ for i, blocks in enumerate(nonzero_groups):
+ out["__NONZERO-%d" % i] = rangelib.RangeSet(data=blocks)
if clobbered_blocks:
out["__COPY"] = clobbered_blocks