Build image for super partition

... for bootstrapping / initializing the device.
Image is built to $(PRODUCT_OUT)/super.img when running
`m dist`. For A/B devices, the image contains other
partitions in the _a slot.

Change-Id: I1459d62f02b95f142dfb3b7608f88ec6801dbf37
Fixes: 111758129
Test: m superimage -j
diff --git a/core/Makefile b/core/Makefile
index f4bd213..830c714 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -2557,6 +2557,62 @@
 endif # BOARD_AVB_ENABLE
 
 # -----------------------------------------------------------------
+# super partition image
+
+# (1): list of items like "system", "vendor", "product", "product_services"
+# return: map each item to the corresponding image target.
+# system => $(BUILT_SYSTEMIMAGE), vendor => $(INSTALLED_VENDORIMAGE_TARGET), etc.
+define image-for-partitions
+$(foreach item,$(1),$(or $(strip $(foreach mapping,
+            system:$(BUILT_SYSTEMIMAGE)
+            product_services:$(INSTALLED_PRODUCT_SERVICESIMAGE_TARGET),
+        $(if $(filter $(call word-colon,1,$(mapping)),$(item)),
+            $(patsubst $(call word-colon,1,$(mapping)),$(call word-colon,2,$(mapping)),$(item))))),
+    $(INSTALLED_$(call to-upper,$(item)IMAGE_TARGET))))
+endef
+
+# (1): list of items like "system", "vendor", "product", "product_services"
+# return: map each item into a command ( wrapped in $$() ) that reads the size
+define read-size-of-partitions
+$(foreach p,$(1),$(call read-image-prop-dictionary,$($(p)image_intermediates)/generated_$(p)_image_info.txt,$(p)_size))
+endef
+
+ifeq (true,$(USE_LOGICAL_PARTITIONS))
+
+# BOARD_SUPER_PARTITION_SIZE must be defined to build super image.
+ifdef BOARD_SUPER_PARTITION_SIZE
+
+INSTALLED_SUPERIMAGE_TARGET := $(PRODUCT_OUT)/super.img
+$(INSTALLED_SUPERIMAGE_TARGET): $(call image-for-partitions,$(BOARD_SUPER_PARTITION_PARTITION_LIST))
+
+# For A/B devices, super partition always contains sub-partitions in the _a slot, because this
+# image should only be used for bootstrapping / initializing the device. When flashing the image,
+# bootloader fastboot should always mark _a slot as bootable.
+ifeq ($(AB_OTA_UPDATER),true)
+$(INSTALLED_SUPERIMAGE_TARGET): PRIVATE_PARTITION_SUFFIX=_a
+$(INSTALLED_SUPERIMAGE_TARGET): PRIVATE_METADATA_SLOTS=2
+else
+$(INSTALLED_SUPERIMAGE_TARGET): PRIVATE_METADATA_SLOTS=1
+endif # AB_OTA_UPDATER
+
+
+$(INSTALLED_SUPERIMAGE_TARGET): $(HOST_OUT_EXECUTABLES)/lpmake
+	$< \
+		--sparse \
+		--metadata-size 65536 \
+		--metadata-slots $(PRIVATE_METADATA_SLOTS) \
+		--device-size $(BOARD_SUPER_PARTITION_SIZE) \
+		--output $@ \
+		$(foreach name,$(BOARD_SUPER_PARTITION_PARTITION_LIST), \
+			--partition $(name)$(PRIVATE_PARTITION_SUFFIX):$$($(UUIDGEN) $(name)$(PRIVATE_PARTITION_SUFFIX)):readonly:$(call read-size-of-partitions,$(name)) \
+			--image $(name)$(PRIVATE_PARTITION_SUFFIX)=$(call image-for-partitions,$(name)))
+
+$(call dist-for-goals,dist_files,$(INSTALLED_SUPERIMAGE_TARGET))
+
+endif # BOARD_SUPER_PARTITION_SIZE
+endif # USE_LOGICAL_PARTITIONS
+
+# -----------------------------------------------------------------
 # Check image sizes <= size of super partition
 
 ifeq (,$(TARGET_BUILD_APPS))
@@ -2571,21 +2627,10 @@
 .PHONY: check_android_partition_sizes
 
 # Add image dependencies so that generated_*_image_info.txt are written before checking.
-ifneq (,$(filter system,$(BOARD_SUPER_PARTITION_PARTITION_LIST)))
-check_android_partition_sizes: $(BUILT_SYSTEMIMAGE)
-endif
-ifneq (,$(filter vendor,$(BOARD_SUPER_PARTITION_PARTITION_LIST)))
-check_android_partition_sizes: $(INSTALLED_VENDORIMAGE_TARGET)
-endif
-ifneq (,$(filter product,$(BOARD_SUPER_PARTITION_PARTITION_LIST)))
-check_android_partition_sizes: $(INSTALLED_PRODUCTIMAGE_TARGET)
-endif
-ifneq (,$(filter productservices,$(BOARD_SUPER_PARTITION_PARTITION_LIST)))
-check_android_partition_sizes: $(INSTALLED_PRODUCT_SERVICESIMAGE_TARGET)
-endif
+check_android_partition_sizes: $(call image-for-partitions,$(BOARD_SUPER_PARTITION_PARTITION_LIST))
 
 check_android_partition_sizes:
-	partition_size_list="$(foreach p,$(BOARD_SUPER_PARTITION_PARTITION_LIST),$(call read-image-prop-dictionary,$($(p)image_intermediates)/generated_$(p)_image_info.txt,$(p)_size))"; \
+	partition_size_list="$(call read-size-of-partitions,$(BOARD_SUPER_PARTITION_PARTITION_LIST))"; \
 	sum_sizes_expr=$$(sed -e 's/ /+/g' <<< "$${partition_size_list}"); \
 	if [ $$(( $${sum_sizes_expr} )) -gt $(BOARD_SUPER_PARTITION_SIZE) ]; then \
 		echo 'The sum of sizes of all logical partitions is larger than BOARD_SUPER_PARTITION_SIZE.'; \
diff --git a/core/config.mk b/core/config.mk
index 9b9f042..5c6b271 100644
--- a/core/config.mk
+++ b/core/config.mk
@@ -701,6 +701,7 @@
 DATA_BINDING_COMPILER := $(HOST_OUT_JAVA_LIBRARIES)/databinding-compiler.jar
 FAT16COPY := build/make/tools/fat16copy.py
 CHECK_LINK_TYPE := build/make/tools/check_link_type.py
+UUIDGEN := build/make/tools/uuidgen.py
 
 PROGUARD := external/proguard/bin/proguard.sh
 JAVATAGS := build/make/tools/java-event-log-tags.py
diff --git a/core/main.mk b/core/main.mk
index a991d88..de23e49 100644
--- a/core/main.mk
+++ b/core/main.mk
@@ -1190,6 +1190,9 @@
 .PHONY: systemotherimage
 systemotherimage: $(INSTALLED_SYSTEMOTHERIMAGE_TARGET)
 
+.PHONY: superimage
+superimage: $(INSTALLED_SUPERIMAGE_TARGET)
+
 .PHONY: bootimage
 bootimage: $(INSTALLED_BOOTIMAGE_TARGET)
 
diff --git a/tools/uuidgen.py b/tools/uuidgen.py
new file mode 100755
index 0000000..d3091a7
--- /dev/null
+++ b/tools/uuidgen.py
@@ -0,0 +1,29 @@
+#!/usr/bin/env python
+#
+# Copyright 2018 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from __future__ import print_function
+import sys
+import uuid
+
+def uuidgen(name):
+    return uuid.uuid5(uuid.uuid5(uuid.NAMESPACE_URL, "android.com"), name)
+
+if __name__ == "__main__":
+    if len(sys.argv) < 2:
+        print("Usage: uuidgen.py <name>")
+        sys.exit(1)
+    name = sys.argv[1]
+    print(uuidgen(name))