Merge "Added TARGET_IS_64_BIT flag for x86_64 and aarch64"
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 877c690..c912497 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -205,6 +205,9 @@
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app/*)
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/APPS/*)
 
+# 4.4.1
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/build.prop)
+
 # ************************************************
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
 # ************************************************
diff --git a/core/Makefile b/core/Makefile
index fca06fa..a8a7d97 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -1262,6 +1262,7 @@
 endif
 	$(hide) echo 'mkbootimg_args=$(BOARD_MKBOOTIMG_ARGS)' >> $(zip_root)/META/misc_info.txt
 	$(hide) echo "use_set_metadata=1" >> $(zip_root)/META/misc_info.txt
+	$(hide) echo "update_rename_support=1" >> $(zip_root)/META/misc_info.txt
 	$(call generate-userimage-prop-dictionary, $(zip_root)/META/misc_info.txt)
 	@# Zip everything up, preserving symlinks
 	$(hide) (cd $(zip_root) && zip -qry ../$(notdir $@) .)
diff --git a/core/combo/javac.mk b/core/combo/javac.mk
index 74490fd..2aea3e1 100644
--- a/core/combo/javac.mk
+++ b/core/combo/javac.mk
@@ -8,10 +8,10 @@
 #   COMMON_JAVAC -- Java compiler command with common arguments
 #
 
-ifeq ($(EXPERIMENTAL_USE_JAVA7_OPENJDK),)
+ifeq ($(EXPERIMENTAL_USE_JAVA7),)
 common_flags := -target 1.5 -Xmaxerrs 9999999
 else
-common_flags := -Xmaxerrs 9999999
+common_flags := -source 1.7 -target 1.7 -Xmaxerrs 9999999
 endif
 
 
diff --git a/core/config.mk b/core/config.mk
index b7c0e10..90fb43a 100644
--- a/core/config.mk
+++ b/core/config.mk
@@ -389,16 +389,20 @@
 OLD_FLEX := prebuilts/misc/$(HOST_PREBUILT_TAG)/flex/flex-2.5.4a$(HOST_EXECUTABLE_SUFFIX)
 
 ifeq ($(HOST_OS),darwin)
-# Mac OS' screwy version of java uses a non-standard directory layout
-# and doesn't even seem to have tools.jar.  On the other hand, javac seems
-# to be able to magically find the classes in there, wherever they are, so
-# leave this blank
+ifneq ($(EXPERIMENTAL_USE_JAVA7),)
+HOST_JDK_TOOLS_JAR:= $(shell $(BUILD_SYSTEM)/find-jdk-tools-jar.sh)
+else
+# Deliberately set to blank for Java 6 installations on MacOS. These
+# versions allegedly use a non-standard directory structure.
 HOST_JDK_TOOLS_JAR :=
+endif
 else
 HOST_JDK_TOOLS_JAR:= $(shell $(BUILD_SYSTEM)/find-jdk-tools-jar.sh)
+endif
+
+ifneq ($(HOST_JDK_TOOLS_JAR),)
 ifeq ($(wildcard $(HOST_JDK_TOOLS_JAR)),)
-$(error Error: could not find jdk tools.jar, please install JDK6, \
-    which you can download from java.sun.com)
+$(error Error: could not find jdk tools.jar, please install JDK6)
 endif
 endif
 
diff --git a/core/copy_headers.mk b/core/copy_headers.mk
index dac07d5..e16560f 100644
--- a/core/copy_headers.mk
+++ b/core/copy_headers.mk
@@ -15,7 +15,9 @@
 $(foreach header,$(LOCAL_COPY_HEADERS), \
   $(eval _chFrom := $(LOCAL_PATH)/$(header)) \
   $(eval _chTo := \
-      $($(my_prefix)OUT_HEADERS)/$(LOCAL_COPY_HEADERS_TO)/$(notdir $(header))) \
+      $(if $(LOCAL_COPY_HEADERS_TO),\
+        $($(my_prefix)OUT_HEADERS)/$(LOCAL_COPY_HEADERS_TO)/$(notdir $(header)),\
+        $($(my_prefix)OUT_HEADERS)/$(notdir $(header)))) \
   $(eval $(call copy-one-header,$(_chFrom),$(_chTo))) \
   $(eval all_copied_headers: $(_chTo)) \
  )
diff --git a/core/droiddoc.mk b/core/droiddoc.mk
index 0d3094d..f528ee0 100644
--- a/core/droiddoc.mk
+++ b/core/droiddoc.mk
@@ -162,6 +162,7 @@
 			$(PRIVATE_SOURCE_INTERMEDIATES_DIR) $(PRIVATE_ADDITIONAL_JAVA_DIR))
 	$(hide) ( \
 		javadoc \
+                -encoding UTF-8 \
                 \@$(PRIVATE_SRC_LIST_FILE) \
                 -J-Xmx1280m \
                 $(PRIVATE_PROFILING_OPTIONS) \
@@ -195,6 +196,7 @@
 			$(PRIVATE_SOURCE_INTERMEDIATES_DIR) $(PRIVATE_ADDITIONAL_JAVA_DIR))
 	$(hide) ( \
 		javadoc \
+                -encoding UTF-8 \
                 $(PRIVATE_DROIDDOC_OPTIONS) \
                 \@$(PRIVATE_SRC_LIST_FILE) \
                 -J-Xmx1024m \
diff --git a/core/main.mk b/core/main.mk
index 511d19e..5494a73 100644
--- a/core/main.mk
+++ b/core/main.mk
@@ -138,18 +138,30 @@
 $(error Directory names containing spaces not supported)
 endif
 
-# Check for the current jdk
-ifneq ($(EXPERIMENTAL_USE_JAVA7_OPENJDK),)
-# The user asked for java7 openjdk, so check that the host
-# java version is really openjdk
+# Check for the current JDK.
+#
+# For Java 1.7, we require OpenJDK on linux and Oracle JDK on Mac OS.
+# For Java 1.6, we require Oracle for all host OSes.
+requires_openjdk := false
+ifneq ($(EXPERIMENTAL_USE_JAVA7),)
+ifeq ($(HOST_OS), linux)
+requires_openjdk := true
+endif
+endif
+
+ifeq ($(requires_openjdk), true)
 ifeq ($(shell java -version 2>&1 | grep -i openjdk),)
 $(info ************************************************************)
-$(info You asked for an OpenJDK 7 build but your version is)
+$(info You are attempting to build with an unsupported JDK.)
+$(info $(space))
+$(info This build requires OpenJDK, but you are using:
 $(info $(shell java -version 2>&1 | head -n 2).)
+$(info Please follow the machine setup instructions at)
+$(info $(space)$(space)$(space)$(space)https://source.android.com/source/download.html)
 $(info ************************************************************)
 $(error stop)
 endif # java version is not OpenJdk
-else # if EXPERIMENTAL_USE_JAVA7_OPENJDK
+else # if requires_openjdk
 ifneq ($(shell java -version 2>&1 | grep -i openjdk),)
 $(info ************************************************************)
 $(info You are attempting to build with an unsupported JDK.)
@@ -160,21 +172,19 @@
 $(info ************************************************************)
 $(error stop)
 endif # java version is not Sun Oracle JDK
-endif # if EXPERIMENTAL_USE_JAVA7_OPENJDK
+endif # if requires_openjdk
 
 # Check for the correct version of java, should be 1.7 if
-# EXPERIMENTAL_USE_JAVA7_OPENJDK is set, 1.6 otherwise.
-ifneq ($(EXPERIMENTAL_USE_JAVA7_OPENJDK),)
-required_version := "OpenJDK 1.7"
-required_javac_version := "1.7"
+# EXPERIMENTAL_USE_JAVA7 is set, 1.6 otherwise.
+ifneq ($(EXPERIMENTAL_USE_JAVA7),)
+required_version := "1.7.x"
 java_version := $(shell java -version 2>&1 | head -n 1 | grep '^java .*[ "]1\.7[\. "$$]')
 javac_version := $(shell javac -version 2>&1 | head -n 1 | grep '[ "]1\.7[\. "$$]')
-else # if EXPERIMENTAL_USE_JAVA7_OPENJDK
-required_version := "JavaSE 1.6"
-required_javac_version := "1.6"
+else # if EXPERIMENTAL_USE_JAVA7
+required_version := "1.6.x"
 java_version := $(shell java -version 2>&1 | head -n 1 | grep '^java .*[ "]1\.6[\. "$$]')
 javac_version := $(shell javac -version 2>&1 | head -n 1 | grep '[ "]1\.6[\. "$$]')
-endif # if EXPERIMENTAL_USE_JAVA7_OPENJDK
+endif # if EXPERIMENTAL_USE_JAVA7
 
 ifeq ($(strip $(java_version)),)
 $(info ************************************************************)
@@ -197,7 +207,7 @@
 $(info of javac.)
 $(info $(space))
 $(info Your version is: $(shell javac -version 2>&1 | head -n 1).)
-$(info The required version is: $(required_javac_version))
+$(info The required version is: $(required_java_version))
 $(info $(space))
 $(info Please follow the machine setup instructions at)
 $(info $(space)$(space)$(space)$(space)https://source.android.com/source/download.html)
diff --git a/target/product/base.mk b/target/product/base.mk
index ec263e5..6725c0d 100644
--- a/target/product/base.mk
+++ b/target/product/base.mk
@@ -23,6 +23,7 @@
     android.test.runner \
     app_process \
     applypatch \
+    blkid \
     bmgr \
     bugreport \
     content \
diff --git a/target/product/core_minimal.mk b/target/product/core_minimal.mk
index fc2fc80..159e7b2 100644
--- a/target/product/core_minimal.mk
+++ b/target/product/core_minimal.mk
@@ -33,6 +33,8 @@
     bu \
     com.android.location.provider \
     com.android.location.provider.xml \
+    com.android.media.remotedisplay \
+    com.android.media.remotedisplay.xml \
     drmserver \
     framework-res \
     installd \
diff --git a/target/product/full_base.mk b/target/product/full_base.mk
index b2e3189..059697e 100644
--- a/target/product/full_base.mk
+++ b/target/product/full_base.mk
@@ -49,6 +49,9 @@
 # Put en_US first in the list, so make it default.
 PRODUCT_LOCALES := en_US
 
+# Include drawables for all densities
+PRODUCT_AAPT_CONFIG := normal hdpi xhdpi xxhdpi
+
 # Get some sounds
 $(call inherit-product-if-exists, frameworks/base/data/sounds/AllAudio.mk)
 
diff --git a/tools/droiddoc/templates-sdk/assets/css/default.css b/tools/droiddoc/templates-sdk/assets/css/default.css
index fa9dee3..c4b81d2 100644
--- a/tools/droiddoc/templates-sdk/assets/css/default.css
+++ b/tools/droiddoc/templates-sdk/assets/css/default.css
@@ -393,6 +393,17 @@
   #nav li ul.tree-list-children ul {
     display:block; }
 
+#nav.samples-nav li li li {
+  font-size:13px;
+}
+#nav.samples-nav li li li a {
+  padding-top:3px;
+  padding-bottom:3px;
+}
+#nav.samples-nav li li ul > li:last-child {
+  padding-bottom:3px;
+}
+
 .new,
 .new-child {
   font-size: .78em;
@@ -860,7 +871,40 @@
   .framed-nexus4-port-216 img {
     width: 216px;
     height: 360px; }
+    
+.framed-nexus5-port-span-5 {
+  background: transparent url(../images/styles/device_nexus5_blank_port_span5.png) no-repeat
+  scroll top left;
+  padding: 52px 33px 69px 31px;
+  overflow: hidden;
+}
 
+.framed-nexus5-port-span-5,
+.framed-nexus5-port-span-5 video,
+.framed-nexus5-port-span-5 img {
+  width: 216px;
+  height: 384px;
+}
+
+.framed-nexus5-land-span-13 {
+  background: transparent url(../images/styles/device_nexus5_blank_land_span13.png) no-repeat scroll top left;
+  padding: 36px 119px 54px 108px;
+  overflow: hidden;
+}
+
+.framed-nexus5-land-span-13,
+.framed-nexus5-land-span-13 video,
+.framed-nexus5-land-span-13 img {
+  width: 533px;
+  height: 300px;
+}
+
+.framed-nexus5-port-span-5,
+.framed-nexus5-port-span-5 video,
+.framed-nexus5-port-span-5 img {
+  width: 216px;
+  height: 384px;
+}
 
 /* landing page disclosures */
 .landing-page-link {
@@ -1123,6 +1167,9 @@
   margin-top:5px;
   margin-bottom:5px;
 }
+dl dd dl:first-child {
+  margin-top:0;
+}
 pre strong, pre b, a strong, a b, a code {
     color: inherit;
 }
@@ -2105,16 +2152,15 @@
   border: solid 1px #ddd;
   background: #f7f7f7;
 }
-.str { color: #080; }
+.str { color: #800; } /* Code string */
 .kwd { color: #008; }
-.com { color: #800; }
 .typ { color: #606; }
 .lit { color: #066; }
 .pun { color: #660; }
 .pln { color: #000; }
 .tag { color: #008; }
 .atn { color: #828; }
-.atv { color: #080; }
+.atv { color: #800; } /* XML string */
 .dec { color: #606; }
 
 /* --------------------------------------------------------------------------
@@ -2450,13 +2496,12 @@
   background-position: -10px 0;
 }
 
-
 /* --------------------------------------------------------------------------
 Styles for samples project trees and code browsing in resources tab 
 */
 
 #codesample-wrapper {
-  width:1000px;
+  width:100000px; /* super wide to contain floats, but doesn't cause scroll */
   overflow:visible;
 }
 pre#codesample-block {
@@ -2465,6 +2510,9 @@
   background:transparent;
   border:none;
 }
+pre#codesample-block a.number {
+  display:none;
+}
 pre#codesample-block .code-line:hover {
   background:#e7e7e7;
 }
@@ -2823,7 +2871,9 @@
 }
 
 /* notice box for cross links between Design/Develop docs */
+a.notice-developers-video,
 a.notice-developers,
+a.notice-designers-video,
 a.notice-designers {
   float:right;
   clear:right;
@@ -2832,11 +2882,15 @@
   margin:0 0 20px 20px;
   border:1px solid #ddd;
 }
+a.notice-developers-video.wide,
 a.notice-developers.wide,
+a.notice-designers-video.wide,
 a.notice-designers.wide {
   width:278px;
 }
+a.notice-developers-video div,
 a.notice-developers div,
+a.notice-designers-video div,
 a.notice-designers div {
   min-height:40px;
   background:url('../images/styles/notice-developers@2x.png') no-repeat 10px 10px;
@@ -2847,24 +2901,41 @@
   background:url('../images/styles/notice-designers@2x.png') no-repeat 10px 10px;
   background-size:40px 40px;
 }
+a.notice-designers-video div {
+  background:url('../images/styles/notice-designers-video@2x.png') no-repeat 10px 10px;
+  background-size:40px 40px;
+}
+a.notice-developers-video div {
+  background:url('../images/styles/notice-developers-video@2x.png') no-repeat 10px 10px;
+  background-size:40px 40px;
+}
+a.notice-developers-video:hover,
 a.notice-developers:hover,
+a.notice-designers-video:hover,
 a.notice-designers:hover {
   background:#eee;
 }
+a.notice-developers-video h3,
 a.notice-developers h3,
+a.notice-designers-video h3,
 a.notice-designers h3 {
-  font-size:14px;
-  font-weight:normal;
+  font-size:13px;
+  line-height:18px;
+  font-weight:bold;
   text-transform:uppercase;
   color:#000 !important;
-  margin:0;
+  margin:0 0 1px;
 }
+a.notice-developers-video p,
 a.notice-developers p,
+a.notice-designers-video p,
 a.notice-designers p {
   margin:0;
-  line-height:16px;
+  line-height:14px;
 }
+a.notice-developers-video.left,
 a.notice-developers.left,
+a.notice-designers-video.left,
 a.notice-designers.left {
   margin-left:0;
   float:left;
diff --git a/tools/droiddoc/templates-sdk/assets/images/styles/device_nexus5_blank_land_span13.png b/tools/droiddoc/templates-sdk/assets/images/styles/device_nexus5_blank_land_span13.png
new file mode 100644
index 0000000..5d37121
--- /dev/null
+++ b/tools/droiddoc/templates-sdk/assets/images/styles/device_nexus5_blank_land_span13.png
Binary files differ
diff --git a/tools/droiddoc/templates-sdk/assets/images/styles/device_nexus5_blank_port_span5.png b/tools/droiddoc/templates-sdk/assets/images/styles/device_nexus5_blank_port_span5.png
new file mode 100644
index 0000000..df35117
--- /dev/null
+++ b/tools/droiddoc/templates-sdk/assets/images/styles/device_nexus5_blank_port_span5.png
Binary files differ
diff --git a/tools/droiddoc/templates-sdk/assets/images/styles/notice-designers-video.png b/tools/droiddoc/templates-sdk/assets/images/styles/notice-designers-video.png
new file mode 100644
index 0000000..eea3485
--- /dev/null
+++ b/tools/droiddoc/templates-sdk/assets/images/styles/notice-designers-video.png
Binary files differ
diff --git a/tools/droiddoc/templates-sdk/assets/images/styles/notice-designers-video@2x.png b/tools/droiddoc/templates-sdk/assets/images/styles/notice-designers-video@2x.png
new file mode 100644
index 0000000..a5fdae3
--- /dev/null
+++ b/tools/droiddoc/templates-sdk/assets/images/styles/notice-designers-video@2x.png
Binary files differ
diff --git a/tools/droiddoc/templates-sdk/assets/images/styles/notice-developers-video.png b/tools/droiddoc/templates-sdk/assets/images/styles/notice-developers-video.png
new file mode 100644
index 0000000..e9f8ed2
--- /dev/null
+++ b/tools/droiddoc/templates-sdk/assets/images/styles/notice-developers-video.png
Binary files differ
diff --git a/tools/droiddoc/templates-sdk/assets/images/styles/notice-developers-video@2x.png b/tools/droiddoc/templates-sdk/assets/images/styles/notice-developers-video@2x.png
new file mode 100644
index 0000000..c067ac1
--- /dev/null
+++ b/tools/droiddoc/templates-sdk/assets/images/styles/notice-developers-video@2x.png
Binary files differ
diff --git a/tools/droiddoc/templates-sdk/assets/js/docs.js b/tools/droiddoc/templates-sdk/assets/js/docs.js
index 1659cc6..1996dac 100644
--- a/tools/droiddoc/templates-sdk/assets/js/docs.js
+++ b/tools/droiddoc/templates-sdk/assets/js/docs.js
@@ -241,7 +241,7 @@
     var training = $(".next-class-link").length; // decides whether to provide "next class" link
     var isCrossingBoundary = false;
 
-    if ($selListItem.hasClass('nav-section')) {
+    if ($selListItem.hasClass('nav-section') && $selListItem.children('div.empty').length == 0) {
       // we're on an index page, jump to the first topic
       $nextLink = $selListItem.find('ul:eq(0)').find('a:eq(0)');
 
@@ -262,12 +262,17 @@
     } else {
       // jump to the next topic in this section (if it exists)
       $nextLink = $selListItem.next('li').find('a:eq(0)');
-      if (!$nextLink.length) {
+      if ($nextLink.length == 0) {
         isCrossingBoundary = true;
         // no more topics in this section, jump to the first topic in the next section
         $nextLink = $selListItem.parents('li:eq(0)').next('li.nav-section').find('a:eq(0)');
         if (!$nextLink.length) {  // Go up another layer to look for next page (lesson > class > course)
           $nextLink = $selListItem.parents('li:eq(1)').next('li.nav-section').find('a:eq(0)');
+          if ($nextLink.length == 0) {
+            // if that doesn't work, we're at the end of the list, so disable NEXT link
+            $('.next-page-link').attr('href','').addClass("disabled")
+                                .click(function() { return false; });
+          }
         }
       }
     }
@@ -285,10 +290,11 @@
       $('.next-page-link').attr('href','')
                           .removeClass("hide").addClass("disabled")
                           .click(function() { return false; });
-
-      $('.next-class-link').attr('href',$nextLink.attr('href'))
-                          .removeClass("hide").append($nextLink.html());
-      $('.next-class-link').find('.new').empty();
+      if ($nextLink.length) {
+        $('.next-class-link').attr('href',$nextLink.attr('href'))
+                             .removeClass("hide").append($nextLink.html());
+        $('.next-class-link').find('.new').empty();
+      }
     } else {
       $('.next-page-link').attr('href', $nextLink.attr('href')).removeClass("hide");
     }
@@ -567,7 +573,7 @@
     } else {
     /* show me */
       // first hide all other siblings
-      var $others = $('li.nav-section.expanded', $(this).closest('ul'));
+      var $others = $('li.nav-section.expanded', $(this).closest('ul')).not('.sticky');
       $others.removeClass('expanded').children('ul').slideUp(250);
 
       // now expand me
@@ -2156,12 +2162,6 @@
 
 // when an event on the browser history occurs (back, forward, load) requery hash and do search
 $(window).hashchange( function(){
-  // Handle hash changes in the samples browser
-  if ($("body").hasClass("samples") && location.href.indexOf("/samples/index.html") != -1) {
-    showSamples();
-    highlightSidenav();
-    resizeNav();
-  }
   // Exit if the hash isn't a search query or there's an error in the query
   if ((location.hash.indexOf("q=") == -1) || (query == "undefined")) {
     // If the results pane is open, close it.
@@ -2382,7 +2382,8 @@
     // Grey things out that aren't available and give a tooltip title
     if (apiLevelNum > selectedLevelNum) {
       obj.addClass("absent").attr("title","Requires API Level \""
-            + apiLevel + "\" or higher");
+            + apiLevel + "\" or higher. To reveal, change the target API level "
+              + "above the left navigation.");
     }
     else obj.removeClass("absent").removeAttr("title");
   });
@@ -2710,6 +2711,9 @@
     $containerUl.append(new_google_node2(node_data));
   }
 
+  // Make all third-generation list items 'sticky' to prevent them from collapsing
+  $containerUl.find('li li li.nav-section').addClass('sticky');
+
   initExpandableNavItems("#"+navtree_id);
 }
 
@@ -2722,9 +2726,11 @@
   var $li = $('<li>');
   var $a;
   if (node_data[NODE_HREF] != null) {
-    $a = $('<a href="' + toRoot + node_data[NODE_HREF] + '">' + linkText + '</a>');
+    $a = $('<a href="' + toRoot + node_data[NODE_HREF] + '" title="' + linkText + '" >'
+        + linkText + '</a>');
   } else {
-    $a = $('<a href="#" onclick="return false;">' + linkText + '/</a>');
+    $a = $('<a href="#" onclick="return false;" title="' + linkText + '" >'
+        + linkText + '/</a>');
   }
   var $childUl = $('<ul>');
   if (node_data[NODE_CHILDREN] != null) {
@@ -2791,9 +2797,18 @@
   $.getScript(toRoot + 'samples_navtree_data.js', function(data, textStatus, jqxhr) {
       // when the file is loaded, initialize the tree
       if(jqxhr.status === 200) {
+          // hack to remove the "about the samples" link then put it back in
+          // after we nuke the list to remove the dummy static list of samples
+          var $firstLi = $("#nav.samples-nav > li:first-child").clone();
+          $("#nav.samples-nav").empty();
+          $("#nav.samples-nav").append($firstLi);
+
           init_google_navtree2("nav.samples-nav", SAMPLES_NAVTREE_DATA);
           highlightSidenav();
           resizeNav();
+          if ($("#jd-content #samples").length) {
+            showSamples();
+          }
       }
   });
 }
@@ -2943,10 +2958,31 @@
         range.moveToElementText(element);
         range.select();
     } else if (window.getSelection) { //all others
-        selection = window.getSelection();        
+        selection = window.getSelection();
         range = doc.createRange();
         range.selectNodeContents(element);
         selection.removeAllRanges();
         selection.addRange(range);
     }
 }
+
+
+
+
+/** Display links and other information about samples that match the
+    group specified by the URL */
+function showSamples() {
+  var group = $("#samples").attr('class');
+  $("#samples").html("<p>Here are some samples for <b>" + group + "</b> apps:</p>");
+
+  var $ul = $("<ul>");
+  $selectedLi = $("#nav li.selected");
+
+  $selectedLi.children("ul").children("li").each(function() {
+      var $li = $("<li>").append($(this).find("a").first().clone());
+      $ul.append($li);
+  });
+
+  $("#samples").append($ul);
+
+}
diff --git a/tools/droiddoc/templates-sdk/customizations.cs b/tools/droiddoc/templates-sdk/customizations.cs
index 985f059..d54d371 100644
--- a/tools/droiddoc/templates-sdk/customizations.cs
+++ b/tools/droiddoc/templates-sdk/customizations.cs
@@ -214,7 +214,8 @@
 <a class="totop" href="#top" data-g-event="left-nav-top">to top</a>
       <div id="api-nav-header">
         <div id="api-level-toggle">
-          <label for="apiLevelCheckbox" class="disabled">API level: </label>
+          <label for="apiLevelCheckbox" class="disabled"
+            title="Select your target API level to dim unavailable APIs">API level: </label>
           <div class="select-wrapper">
             <select id="apiLevelSelector">
               <!-- option elements added by buildApiLevelSelector() -->
@@ -239,7 +240,7 @@
             <div id="packages-nav" class="scroll-pane">
 
               <ul>
-              	<?cs call:package_link_list(docs.packages) ?>
+                <?cs call:package_link_list(docs.packages) ?>
               </ul><br/>
 
             </div> <!-- end packages-nav -->
diff --git a/tools/droiddoc/templates-sdk/sample.cs b/tools/droiddoc/templates-sdk/sample.cs
index a8eaf8c..3fed799 100644
--- a/tools/droiddoc/templates-sdk/sample.cs
+++ b/tools/droiddoc/templates-sdk/sample.cs
@@ -19,11 +19,9 @@
   &#124; <a href="<?cs var:toroot ?>samples/<?cs var:projectDir ?>/project.html">Project</a>
   &#124; <a href="<?cs var:toroot ?>downloads/samples/<?cs var:projectDir ?>.zip">Download</a>
 
-  </div><!-- end sum-details-links -->
-  <div class="api-level">
-  Other info
-  </div>
-</div> <!-- end api-info-block -->
+</div><!-- end sum-details-links -->
+
+</div><!-- end breadcurmb block -->
 
 <div id="jd-header" style="border:0;">
 
@@ -57,11 +55,6 @@
 <pre id="codesample-block"><?cs var:fileContents ?></pre>
 </div>
 
-<h3 id="file-location" style="clear:left">Source file location</h3>
-<p>The file containing the source code shown below is located in the corresponding directory in 
-<code>&lt;sdk&gt;/samples/android-&lt;version&gt;/...</code></p>
-
-
 <!-- end file contents -->
 <script type="text/javascript">
   initCodeLineNumbers();
@@ -74,11 +67,6 @@
   # else, this means it's offline docs,
           so don't show src links (we dont have the pages!) ?>
 
-<p>You can find the source code for this sample in your SDK at:</p>
-<p style="margin-left:2em">
-<code><em>&lt;sdk&gt;</em>/samples/android-<em>&lt;version&gt;</em>/</code>
-</p>
-
 <?cs /if ?><?cs # end if/else online docs ?>
 
   </div> <!-- end jd-content -->
diff --git a/tools/droiddoc/templates-sdk/sampleindex.cs b/tools/droiddoc/templates-sdk/sampleindex.cs
index 077b3d5..8db15c4 100644
--- a/tools/droiddoc/templates-sdk/sampleindex.cs
+++ b/tools/droiddoc/templates-sdk/sampleindex.cs
@@ -23,9 +23,7 @@
 &#124; <a href="<?cs var:toroot ?>downloads/samples/<?cs var:projectDir ?>.zip">Download</a>
 
 </div><!-- end sum-details-links -->
-<div class="api-level">
-  Other info
-</div>
+
 </div><!-- end breadcurmb block -->
 
 <h1 itemprop="name"><?cs var:projectDir ?></h1>
@@ -79,11 +77,6 @@
   # else, this means it's offline docs,
           so don't show src links (we dont have the pages!) ?>
 
-<p>You can find the source code for this sample in your SDK at:</p>
-<p style="margin-left:2em">
-<code><em>&lt;sdk&gt;</em>/samples/android-<em>&lt;version&gt;</em>/</code>
-</p>
-
 <?cs /if ?><?cs # end if/else online docs ?>
 
   </div> <!-- end jd-content -->
diff --git a/tools/releasetools/edify_generator.py b/tools/releasetools/edify_generator.py
index 2c3b9e7..189672c 100644
--- a/tools/releasetools/edify_generator.py
+++ b/tools/releasetools/edify_generator.py
@@ -184,6 +184,11 @@
     cmd = "delete(" + ",\0".join(['"%s"' % (i,) for i in file_list]) + ");"
     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):
+      self.script.append('rename("%s", "%s");' % (srcfile, tgtfile))
+
   def ApplyPatch(self, srcfile, tgtfile, tgtsize, tgtsha1, *patchpairs):
     """Apply binary patches (in *patchpairs) to the given srcfile to
     produce tgtfile (which may be "-" to indicate overwriting the
diff --git a/tools/releasetools/ota_from_target_files b/tools/releasetools/ota_from_target_files
index a6b9b69..2ef896f 100755
--- a/tools/releasetools/ota_from_target_files
+++ b/tools/releasetools/ota_from_target_files
@@ -108,6 +108,31 @@
   symlink."""
   return (info.external_attr >> 28) == 010
 
+def ClosestFileMatch(src, tgtfiles, existing):
+  """Returns the closest file match between a source file and list
+     of potential matches.  The exact filename match is preferred,
+     then the sha1 is searched for, and finally a file with the same
+     basename is evaluated.  Rename support in the updater-binary is
+     required for the latter checks to be used."""
+
+  result = tgtfiles.get("path:" + src.name)
+  if result is not None:
+    return result
+
+  if not OPTIONS.target_info_dict.get("update_rename_support", False):
+    return None
+
+  if src.size < 1000:
+    return None
+
+  result = tgtfiles.get("sha1:" + src.sha1)
+  if result is not None and existing.get(result.name) is None:
+    return result
+  result = tgtfiles.get("file:" + src.name.split("/")[-1])
+  if result is not None and existing.get(result.name) is None:
+    return result
+  return None
+
 class Item:
   """Items represent the metadata (user, group, mode) of files and
   directories in the system image."""
@@ -514,11 +539,27 @@
   verbatim_targets = []
   patch_list = []
   diffs = []
+  renames = {}
   largest_source_size = 0
+
+  matching_file_cache = {}
+  for fn in source_data.keys():
+    sf = source_data[fn]
+    assert fn == sf.name
+    matching_file_cache["path:" + fn] = sf
+    # Only allow eligability for filename/sha matching
+    # if there isn't a perfect path match.
+    if target_data.get(sf.name) is None:
+      matching_file_cache["file:" + fn.split("/")[-1]] = sf
+      matching_file_cache["sha:" + sf.sha1] = sf
+
   for fn in sorted(target_data.keys()):
     tf = target_data[fn]
     assert fn == tf.name
-    sf = source_data.get(fn, None)
+    sf = ClosestFileMatch(tf, matching_file_cache, renames)
+    if sf is not None and sf.name != tf.name:
+      print "File has moved from " + sf.name + " to " + tf.name
+      renames[sf.name] = tf
 
     if sf is None or fn in OPTIONS.require_verbatim:
       # This file should be included verbatim
@@ -531,7 +572,7 @@
       # File is different; consider sending as a patch
       diffs.append(common.Difference(tf, sf))
     else:
-      # Target file identical to source.
+      # Target file data identical to source (may still be renamed)
       pass
 
   common.ComputeDifferences(diffs)
@@ -543,8 +584,8 @@
       tf.AddToZip(output_zip)
       verbatim_targets.append((tf.name, tf.size))
     else:
-      common.ZipWriteStr(output_zip, "patch/" + tf.name + ".p", d)
-      patch_list.append((tf.name, tf, sf, tf.size, common.sha1(d).hexdigest()))
+      common.ZipWriteStr(output_zip, "patch/" + sf.name + ".p", d)
+      patch_list.append((sf.name, tf, sf, tf.size, common.sha1(d).hexdigest()))
       largest_source_size = max(largest_source_size, sf.size)
 
   source_fp = GetBuildProp("ro.build.fingerprint", OPTIONS.source_info_dict)
@@ -626,7 +667,8 @@
   script.Print("Removing unneeded files...")
   script.DeleteFiles(["/"+i[0] for i in verbatim_targets] +
                      ["/"+i for i in sorted(source_data)
-                            if i not in target_data] +
+                            if i not in target_data and
+                            i not in renames] +
                      ["/system/recovery.img"])
 
   script.ShowProgress(0.8, 0)
@@ -713,6 +755,13 @@
     script.Print("Unpacking new recovery...")
     script.UnpackPackageDir("recovery", "/system")
 
+  if len(renames) > 0:
+    script.Print("Renaming files...")
+
+  for src in renames:
+    print "Renaming " + src + " to " + renames[src].name
+    script.RenameFile(src, renames[src].name)
+
   script.Print("Symlinks and permissions...")
 
   # Create all the symlinks that don't already exist, or point to