Merge "Do not disable prebuilts for sdk builds"
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 639c4ef..fff49b3 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -760,6 +760,9 @@
 # Common R directory has been removed.
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/R)
 
+# Most of SOONG_HOST_OUT_EXECUTABLES has been moved to HOST_OUT_EXECUTABLES
+$(call add-clean-step, rm -rf $(SOONG_HOST_OUT))
+
 # ************************************************
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
 # ************************************************
diff --git a/core/board_config.mk b/core/board_config.mk
index 40b6b3f..b3e6957 100644
--- a/core/board_config.mk
+++ b/core/board_config.mk
@@ -185,19 +185,44 @@
   .KATI_READONLY := TARGET_DEVICE_DIR
 endif
 
+# Dumps all variables that match [A-Z][A-Z0-9_]* to the file at $(1)
+# It is used to print only the variables that are likely to be relevant to the
+# board configuration.
+define dump-public-variables
+$(file >$(OUT_DIR)/dump-public-variables-temp.txt,$(subst $(space),$(newline),$(.VARIABLES)))\
+$(file >$(1),\
+$(foreach v, $(shell grep -he "^[A-Z][A-Z0-9_]*$$" $(OUT_DIR)/dump-public-variables-temp.txt | grep -vhe "^SOONG_"),\
+$(v) := $(strip $($(v)))$(newline)))
+endef
+
 # TODO(colefaust) change this if to RBC_PRODUCT_CONFIG when
 # the board configuration is known to work on everything
 # the product config works on.
 ifndef RBC_BOARD_CONFIG
 include $(board_config_mk)
 else
-  rc := $(shell build/soong/scripts/rbc-run $(board_config_mk) \
-      BUILDING_GSI=$(BUILDING_GSI) >$(OUT_DIR)/rbcboardtemp.mk || echo $$?)
-  ifneq (,$(rc))
-    $(error board configuration converter failed: $(rc))
+  $(shell mkdir -p $(OUT_DIR)/rbc)
+
+  $(call dump-public-variables, $(OUT_DIR)/rbc/make_vars_pre_board_config.mk)
+
+  $(shell $(OUT_DIR)/soong/mk2rbc \
+    --mode=write -r --outdir $(OUT_DIR)/rbc \
+    --boardlauncher=$(OUT_DIR)/rbc/boardlauncher.rbc \
+    --input_variables=$(OUT_DIR)/rbc/make_vars_pre_board_config.mk \
+    $(board_config_mk))
+  ifneq ($(.SHELLSTATUS),0)
+    $(error board configuration converter failed: $(.SHELLSTATUS))
   endif
 
-  include $(OUT_DIR)/rbcboardtemp.mk
+  $(shell $(OUT_DIR)/soong/rbcrun \
+    RBC_OUT="make,global" \
+    $(OUT_DIR)/rbc/boardlauncher.rbc \
+    >$(OUT_DIR)/rbc/rbc_board_config_results.mk)
+  ifneq ($(.SHELLSTATUS),0)
+    $(error board configuration runner failed: $(.SHELLSTATUS))
+  endif
+
+  include $(OUT_DIR)/rbc/rbc_board_config_results.mk
 endif
 
 ifneq (,$(and $(TARGET_ARCH),$(TARGET_ARCH_SUITE)))
diff --git a/core/config.mk b/core/config.mk
index 8f47ab5..e24e957 100644
--- a/core/config.mk
+++ b/core/config.mk
@@ -539,14 +539,14 @@
 ACP := $(prebuilt_build_tools_bin)/acp
 CKATI := $(prebuilt_build_tools_bin)/ckati
 DEPMOD := $(HOST_OUT_EXECUTABLES)/depmod
-FILESLIST := $(SOONG_HOST_OUT_EXECUTABLES)/fileslist
+FILESLIST := $(HOST_OUT_EXECUTABLES)/fileslist
 FILESLIST_UTIL :=$= build/make/tools/fileslist_util.py
 HOST_INIT_VERIFIER := $(HOST_OUT_EXECUTABLES)/host_init_verifier
-XMLLINT := $(SOONG_HOST_OUT_EXECUTABLES)/xmllint
+XMLLINT := $(HOST_OUT_EXECUTABLES)/xmllint
 
 # SOONG_ZIP is exported by Soong, but needs to be defined early for
 # $OUT/dexpreopt.global.  It will be verified against the Soong version.
-SOONG_ZIP := $(SOONG_HOST_OUT_EXECUTABLES)/soong_zip
+SOONG_ZIP := $(HOST_OUT_EXECUTABLES)/soong_zip
 
 # ---------------------------------------------------------------
 # Generic tools.
diff --git a/core/main.mk b/core/main.mk
index c57f7c9..f7cf8de 100644
--- a/core/main.mk
+++ b/core/main.mk
@@ -1379,7 +1379,7 @@
 
   # Verify the artifact path requirements made by included products.
   is_asan := $(if $(filter address,$(SANITIZE_TARGET)),true)
-  ifeq (,$(or $(is_asan),$(DISABLE_ARTIFACT_PATH_REQUIREMENTS),$(RBC_PRODUCT_CONFIG)))
+  ifeq (,$(or $(is_asan),$(DISABLE_ARTIFACT_PATH_REQUIREMENTS),$(RBC_PRODUCT_CONFIG),$(RBC_BOARD_CONFIG)))
     include $(BUILD_SYSTEM)/artifact_path_requirements.mk
   endif
 else
diff --git a/core/product-graph.mk b/core/product-graph.mk
index de4e581..f28ea3d 100644
--- a/core/product-graph.mk
+++ b/core/product-graph.mk
@@ -81,7 +81,7 @@
 $(products_graph): PRIVATE_PRODUCTS_FILTER := $(products_list)
 
 $(products_graph): $(this_makefile)
-ifeq (,$(RBC_PRODUCT_CONFIG)$(RBC_NO_PRODUCT_GRAPH))
+ifeq (,$(RBC_PRODUCT_CONFIG)$(RBC_NO_PRODUCT_GRAPH)$(RBC_BOARD_CONFIG))
 	@echo Product graph DOT: $@ for $(PRIVATE_PRODUCTS_FILTER)
 	$(hide) echo 'digraph {' > $@.in
 	$(hide) echo 'graph [ ratio=.5 ];' >> $@.in
@@ -148,7 +148,7 @@
 	$(hide) cat $$< | build/make/tools/product_debug.py > $$@
 endef
 
-ifeq (,$(RBC_PRODUCT_CONFIG)$(RBC_NO_PRODUCT_GRAPH))
+ifeq (,$(RBC_PRODUCT_CONFIG)$(RBC_NO_PRODUCT_GRAPH)$(RBC_BOARD_CONFIG))
 product_debug_files:=
 $(foreach p,$(all_products), \
 			$(eval $(call transform-product-debug, $(p))) \
@@ -164,4 +164,4 @@
 .PHONY: product-graph
 	@echo RBC_PRODUCT_CONFIG and RBC_NO_PRODUCT_GRAPH should be unset to generate product graph
 	false
-endif
\ No newline at end of file
+endif
diff --git a/core/product_config.mk b/core/product_config.mk
index 33b15d3..6588b8e 100644
--- a/core/product_config.mk
+++ b/core/product_config.mk
@@ -206,10 +206,10 @@
 ifndef RBC_PRODUCT_CONFIG
 $(call import-products, $(current_product_makefile))
 else
-  rc := $(shell build/soong/scripts/rbc-run $(current_product_makefile) \
-      >$(OUT_DIR)/rbctemp.mk || echo $$?)
-  ifneq (,$(rc))
-    $(error product configuration converter failed: $(rc))
+  $(shell build/soong/scripts/rbc-run $(current_product_makefile) \
+      >$(OUT_DIR)/rbctemp.mk)
+  ifneq ($(.SHELLSTATUS),0)
+    $(error product configuration converter failed: $(.SHELLSTATUS))
   endif
   include $(OUT_DIR)/rbctemp.mk
   PRODUCTS += $(current_product_makefile)
diff --git a/core/product_config.rbc b/core/product_config.rbc
index 9876d56..fe6ba7c 100644
--- a/core/product_config.rbc
+++ b/core/product_config.rbc
@@ -17,7 +17,7 @@
 """Runtime functions."""
 
 _soong_config_namespaces_key = "$SOONG_CONFIG_NAMESPACES"
-def _global_init(version_info):
+def _init_globals(version_info):
     """Returns dict created from the runtime environment."""
     globals = dict()
 
@@ -50,7 +50,8 @@
 
 
 def __print_attr(attr, value):
-    if not value:
+    # Allow using empty strings to clear variables, but not None values
+    if value == None:
         return
     if type(value) == "list":
         if _options.rearrange:
@@ -74,21 +75,24 @@
         __print_attr(attr, val)
     if _options.print_globals:
         print()
-        for attr, val in sorted(globals.items()):
-            if attr == _soong_config_namespaces_key:
-                __print_attr("SOONG_CONFIG_NAMESPACES", val.keys())
-                for nsname, nsvars in sorted(val.items()):
-                    # Define SOONG_CONFIG_<ns> for Make, othewise
-                    # it cannot be added to .KATI_READONLY list
-                    if _options.format == "make":
-                        print("SOONG_CONFIG_" + nsname, ":=", " ".join(nsvars.keys()))
-                    for var, val in sorted(nsvars.items()):
-                        if val:
-                            __print_attr("SOONG_CONFIG_%s_%s" % (nsname, var), val)
-                        else:
-                            print("SOONG_CONFIG_%s_%s :=" % (nsname, var))
-            elif attr not in globals_base or globals_base[attr] != val:
-                __print_attr(attr, val)
+        _printglobals(globals, globals_base)
+
+def _printglobals(globals, globals_base):
+    for attr, val in sorted(globals.items()):
+        if attr == _soong_config_namespaces_key:
+            __print_attr("SOONG_CONFIG_NAMESPACES", val.keys())
+            for nsname, nsvars in sorted(val.items()):
+                # Define SOONG_CONFIG_<ns> for Make, othewise
+                # it cannot be added to .KATI_READONLY list
+                if _options.format == "make":
+                    print("SOONG_CONFIG_" + nsname, ":=", " ".join(nsvars.keys()))
+                for var, val in sorted(nsvars.items()):
+                    if val:
+                        __print_attr("SOONG_CONFIG_%s_%s" % (nsname, var), val)
+                    else:
+                        print("SOONG_CONFIG_%s_%s :=" % (nsname, var))
+        elif attr not in globals_base or globals_base[attr] != val:
+            __print_attr(attr, val)
 
 def __printvars_rearrange_list(value_list):
     """Rearrange value list: return only distinct elements, maybe sorted."""
@@ -109,7 +113,7 @@
     # PCM means "Product Configuration Module", i.e., a Starlark file
     # whose body consists of a single init function.
 
-    globals_base = _global_init(version_info)
+    globals_base = _init_globals(version_info)
     globals = dict(**globals_base)
 
     config_postfix = []  # Configs in postfix order
@@ -203,6 +207,16 @@
 
     return (globals, configs[top_pcm_name][1], globals_base)
 
+
+def _board_configuration(board_config_init, input_variables_init):
+    globals = {}
+    h = __h_new()
+    input_variables_init(globals, h)
+    globals_base = dict(**globals)
+    board_config_init(globals, h)
+    return (globals, h[1], globals_base)
+
+
 def _substitute_inherited(configs, pcm_name, cfg):
     """Substitutes inherited values in all the attributes.
 
@@ -645,7 +659,7 @@
     filter = _filter,
     filter_out = _filter_out,
     find_and_copy = _find_and_copy,
-    global_init = _global_init,
+    init_globals = _init_globals,
     inherit = _inherit,
     indirect = _indirect,
     mkinfo = _mkinfo,
@@ -655,7 +669,9 @@
     mkstrip = _mkstrip,
     mksubst = _mksubst,
     printvars = _printvars,
+    printglobals = _printglobals,
     product_configuration = _product_configuration,
+    board_configuration = _board_configuration,
     product_copy_files_by_pattern = _product_copy_files_by_pattern,
     require_artifacts_in_path = _require_artifacts_in_path,
     require_artifacts_in_path_relaxed = _require_artifacts_in_path_relaxed,
diff --git a/tools/releasetools/check_target_files_vintf.py b/tools/releasetools/check_target_files_vintf.py
index a2ddfe7..213ae21 100755
--- a/tools/releasetools/check_target_files_vintf.py
+++ b/tools/releasetools/check_target_files_vintf.py
@@ -132,7 +132,7 @@
       'checkvintf',
       '--check-compat',
   ]
-  for device_path, real_path in dirmap.items():
+  for device_path, real_path in sorted(dirmap.items()):
     common_command += ['--dirmap', '{}:{}'.format(device_path, real_path)]
   common_command += kernel_args
   common_command += shipping_api_level_args
@@ -165,7 +165,15 @@
   def PathToPatterns(path):
     if path[-1] == '/':
       path += '*'
-    for device_path, target_files_rel_paths in DIR_SEARCH_PATHS.items():
+
+    # Loop over all the entries in DIR_SEARCH_PATHS and find one where the key
+    # is a prefix of path. In order to get find the correct prefix, sort the
+    # entries by decreasing length of their keys, so that we check if longer
+    # strings are prefixes before shorter strings. This is so that keys that
+    # are substrings of other keys (like /system vs /system_ext) are checked
+    # later, and we don't mistakenly mark a path that starts with /system_ext
+    # as starting with only /system.
+    for device_path, target_files_rel_paths in sorted(DIR_SEARCH_PATHS.items(), key=lambda i: len(i[0]), reverse=True):
       if path.startswith(device_path):
         suffix = path[len(device_path):]
         return [rel_path + suffix for rel_path in target_files_rel_paths]
diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py
index 1937f29..1533030 100644
--- a/tools/releasetools/common.py
+++ b/tools/releasetools/common.py
@@ -2105,7 +2105,9 @@
   need_passwords = []
   key_passwords = {}
   devnull = open("/dev/null", "w+b")
-  for k in sorted(keylist):
+
+  # sorted() can't compare strings to None, so convert Nones to strings
+  for k in sorted(keylist, key=lambda x: x if x is not None else ""):
     # We don't need a password for things that aren't really keys.
     if k in SPECIAL_CERT_STRINGS or k is None:
       no_passwords.append(k)
diff --git a/tools/releasetools/ota_utils.py b/tools/releasetools/ota_utils.py
index 5737009..6c5fc05 100644
--- a/tools/releasetools/ota_utils.py
+++ b/tools/releasetools/ota_utils.py
@@ -154,7 +154,7 @@
                 compress_type=zipfile.ZIP_STORED)
     return
 
-  with open('{}.pb'.format(output), 'w') as f:
+  with open('{}.pb'.format(output), 'wb') as f:
     f.write(metadata_proto.SerializeToString())
   with open(output, 'w') as f:
     f.write(legacy_metadata)