Generate extra userdata partition if needed

* To support variants of devices which may come in 16/32/64GB variants.

Change-Id: I74c32d8316f0450a1445fe95a95e5cabb7a9dd1b
(cherry picked from commit aae837f9cbcff739cb660016a6d1abd7ef4663db)
diff --git a/core/Makefile b/core/Makefile
index 753f4d5..7b8698c 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -777,6 +777,8 @@
 $(if $(BOARD_SYSTEMIMAGE_SQUASHFS_COMPRESSOR_OPT),$(hide) echo "system_squashfs_compressor_opt=$(BOARD_SYSTEMIMAGE_SQUASHFS_COMPRESSOR_OPT)" >> $(1))
 $(if $(BOARD_USERDATAIMAGE_FILE_SYSTEM_TYPE),$(hide) echo "userdata_fs_type=$(BOARD_USERDATAIMAGE_FILE_SYSTEM_TYPE)" >> $(1))
 $(if $(BOARD_USERDATAIMAGE_PARTITION_SIZE),$(hide) echo "userdata_size=$(BOARD_USERDATAIMAGE_PARTITION_SIZE)" >> $(1))
+$(if $(BOARD_USERDATAEXTRAIMAGE_PARTITION_SIZE),$(hide) echo "userdataextra_size=$(BOARD_USERDATAEXTRAIMAGE_PARTITION_SIZE)" >> $(1))
+$(if $(BOARD_USERDATAEXTRAIMAGE_PARTITION_NAME),$(hide) echo "userdataextra_name=$(BOARD_USERDATAEXTRAIMAGE_PARTITION_NAME)" >> $(1))
 $(if $(BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE),$(hide) echo "cache_fs_type=$(BOARD_CACHEIMAGE_FILE_SYSTEM_TYPE)" >> $(1))
 $(if $(BOARD_CACHEIMAGE_PARTITION_SIZE),$(hide) echo "cache_size=$(BOARD_CACHEIMAGE_PARTITION_SIZE)" >> $(1))
 $(if $(BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE),$(hide) echo "vendor_fs_type=$(BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE)" >> $(1))
diff --git a/core/generate_extra_images.mk b/core/generate_extra_images.mk
index 8cd18fd..c253668 100644
--- a/core/generate_extra_images.mk
+++ b/core/generate_extra_images.mk
@@ -140,6 +140,35 @@
 
 
 #----------------------------------------------------------------------
+# Generate extra userdata images (for variants with multiple mmc sizes)
+#----------------------------------------------------------------------
+ifneq ($(BOARD_USERDATAEXTRAIMAGE_PARTITION_SIZE),)
+
+ifndef BOARD_USERDATAEXTRAIMAGE_PARTITION_NAME
+  BOARD_USERDATAEXTRAIMAGE_PARTITION_NAME := extra
+endif
+
+BUILT_USERDATAEXTRAIMAGE_TARGET := $(PRODUCT_OUT)/userdata_$(BOARD_USERDATAEXTRAIMAGE_PARTITION_NAME).img
+
+define build-userdataextraimage-target
+    $(call pretty,"Target EXTRA userdata fs image: $(INSTALLED_USERDATAEXTRAIMAGE_TARGET)")
+    @mkdir -p $(TARGET_OUT_DATA)
+    $(hide) $(MKEXTUSERIMG) -s $(TARGET_OUT_DATA) $@ ext4 data $(BOARD_USERDATAEXTRAIMAGE_PARTITION_SIZE)
+    $(hide) chmod a+r $@
+    $(hide) $(call assert-max-image-size,$@,$(BOARD_USERDATAEXTRAIMAGE_PARTITION_SIZE),yaffs)
+endef
+
+INSTALLED_USERDATAEXTRAIMAGE_TARGET := $(BUILT_USERDATAEXTRAIMAGE_TARGET)
+$(INSTALLED_USERDATAEXTRAIMAGE_TARGET): $(INSTALLED_USERDATAIMAGE_TARGET)
+	$(build-userdataextraimage-target)
+
+ALL_DEFAULT_INSTALLED_MODULES += $(INSTALLED_USERDATAEXTRAIMAGE_TARGET)
+ALL_MODULES.$(LOCAL_MODULE).INSTALLED += $(INSTALLED_USERDATAEXTRAIMAGE_TARGET)
+
+endif
+
+
+#----------------------------------------------------------------------
 # Generate NAND images
 #----------------------------------------------------------------------
 ifeq ($(call is-board-platform-in-list,msm7x27a msm7x30),true)
diff --git a/tools/releasetools/add_img_to_target_files.py b/tools/releasetools/add_img_to_target_files.py
index eab8113..ce474f7 100755
--- a/tools/releasetools/add_img_to_target_files.py
+++ b/tools/releasetools/add_img_to_target_files.py
@@ -191,6 +191,42 @@
   os.rmdir(temp_dir)
 
 
+def AddUserdataExtra(output_zip):
+  """Create extra userdata image and store it in output_zip."""
+
+  image_props = build_image.ImagePropFromGlobalDict(OPTIONS.info_dict,
+                                                  "data_extra")
+  # If no userdataextra_size is provided for extfs, skip userdata_extra.img.
+  if (image_props.get("fs_type", "").startswith("ext") and
+      not image_props.get("partition_size")):
+    return
+
+  extra_name = image_props.get("partition_name", "extra")
+
+  print "creating userdata_%s.img..." % extra_name
+
+  # 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.
+  temp_dir = tempfile.mkdtemp()
+  user_dir = os.path.join(temp_dir, "data")
+  os.mkdir(user_dir)
+  img = tempfile.NamedTemporaryFile()
+
+  fstab = OPTIONS.info_dict["fstab"]
+  if fstab:
+    image_props["fs_type" ] = fstab["/data"].fs_type
+  succ = build_image.BuildImage(user_dir, image_props, img.name)
+  assert succ, "build userdata_%s.img image failed" % extra_name
+
+  # Disable size check since this fetches original data partition size
+  #common.CheckSize(img.name, "userdata_extra.img", OPTIONS.info_dict)
+  output_zip.write(img.name, "userdata_%s.img" % extra_name)
+  img.close()
+  os.rmdir(user_dir)
+  os.rmdir(temp_dir)
+
+
 def AddCache(output_zip, prefix="IMAGES/"):
   """Create an empty cache image and store it in output_zip."""
 
@@ -290,6 +326,8 @@
     AddVendor(output_zip)
   banner("userdata")
   AddUserdata(output_zip)
+  banner("extrauserdata")
+  AddUserdataExtra(output_zip)
   banner("cache")
   AddCache(output_zip)
 
diff --git a/tools/releasetools/build_image.py b/tools/releasetools/build_image.py
index 79ef8da..91fe54b 100755
--- a/tools/releasetools/build_image.py
+++ b/tools/releasetools/build_image.py
@@ -264,8 +264,12 @@
     if "extfs_sparse_flag" in prop_dict:
       build_command.append(prop_dict["extfs_sparse_flag"])
       #run_fsck = True
-    build_command.extend([in_dir, out_file, fs_type,
-                          prop_dict["mount_point"]])
+    if "is_userdataextra" in prop_dict:
+      build_command.extend([in_dir, out_file, fs_type,
+                           "data"])
+    else:
+      build_command.extend([in_dir, out_file, fs_type,
+                            prop_dict["mount_point"]])
     build_command.append(prop_dict["partition_size"])
     if "journal_size" in prop_dict:
       build_command.extend(["-j", prop_dict["journal_size"]])
@@ -439,6 +443,11 @@
     copy_prop("fs_type", "fs_type")
     copy_prop("userdata_fs_type", "fs_type")
     copy_prop("userdata_size", "partition_size")
+  elif mount_point == "data_extra":
+    copy_prop("fs_type", "fs_type")
+    copy_prop("userdataextra_size", "partition_size")
+    copy_prop("userdataextra_name", "partition_name")
+    d["is_userdataextra"] = True
   elif mount_point == "cache":
     copy_prop("cache_fs_type", "fs_type")
     copy_prop("cache_size", "partition_size")
diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py
index 3b523a5..36f3305 100644
--- a/tools/releasetools/common.py
+++ b/tools/releasetools/common.py
@@ -612,8 +612,8 @@
   fs_type = None
   limit = None
   if info_dict["fstab"]:
-    if mount_point == "/userdata":
-      mount_point = "/data"
+    if mount_point == "/userdata_extra": mount_point = "/data"
+    if mount_point == "/userdata": mount_point = "/data"
     p = info_dict["fstab"][mount_point]
     fs_type = p.fs_type
     device = p.device