Allow building recovery as boot.

With BOARD_USES_RECOVERY_AS_BOOT = true, we skip building the
non-ramdisk boot.img but building the recovery image as boot.img. It
contains recovery's ramdisk (e.g. with /sbin/recovery). It depends on
the bootloader parameter (skip_initramfs) to determine the actual mode
to boot into.

Change-Id: Id6e2d0a2b94383944ca8f35bba688c6401745622
(cherry picked from commit d80bef2b9e7aa5f92ab017247442798f47736566)
diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py
index ee0cdf9..aaf51e9 100644
--- a/tools/releasetools/common.py
+++ b/tools/releasetools/common.py
@@ -494,8 +494,11 @@
     info_dict = OPTIONS.info_dict
 
   # With system_root_image == "true", we don't pack ramdisk into the boot image.
-  has_ramdisk = (info_dict.get("system_root_image", None) != "true" or
-                 prebuilt_name != "boot.img")
+  # Unless "recovery_as_boot" is specified, in which case we carry the ramdisk
+  # for recovery.
+  has_ramdisk = (info_dict.get("system_root_image") != "true" or
+                 prebuilt_name != "boot.img" or
+                 info_dict.get("recovery_as_boot") == "true")
 
   fs_config = "META/" + tree_subdir.lower() + "_filesystem_config.txt"
   data = _BuildBootableImage(os.path.join(unpack_dir, tree_subdir),
diff --git a/tools/releasetools/ota_from_target_files.py b/tools/releasetools/ota_from_target_files.py
index 5259ede..a76eaa9 100755
--- a/tools/releasetools/ota_from_target_files.py
+++ b/tools/releasetools/ota_from_target_files.py
@@ -1703,7 +1703,9 @@
   if OPTIONS.device_specific is not None:
     OPTIONS.device_specific = os.path.abspath(OPTIONS.device_specific)
 
-  if OPTIONS.info_dict.get("no_recovery") == "true":
+  ab_update = OPTIONS.info_dict.get("ab_update") == "true"
+
+  if OPTIONS.info_dict.get("no_recovery") == "true" and not ab_update:
     raise common.ExternalError(
         "--- target build has specified no recovery ---")
 
@@ -1725,8 +1727,9 @@
     output_zip = zipfile.ZipFile(temp_zip_file, "w",
                                  compression=zipfile.ZIP_DEFLATED)
 
+  # Non A/B OTAs rely on /cache partition to store temporary files.
   cache_size = OPTIONS.info_dict.get("cache_size", None)
-  if cache_size is None:
+  if cache_size is None and not ab_update:
     print "--- can't determine the cache partition size ---"
   OPTIONS.cache_size = cache_size
 
@@ -1736,7 +1739,11 @@
 
   # Generate a full OTA.
   elif OPTIONS.incremental_source is None:
-    WriteFullOTAPackage(input_zip, output_zip)
+    if ab_update:
+      # TODO: Pending for b/25715402.
+      pass
+    else:
+      WriteFullOTAPackage(input_zip, output_zip)
 
   # Generate an incremental OTA. It will fall back to generate a full OTA on
   # failure unless no_fallback_to_full is specified.