Merge "Revert^2 "Add default cc_rustlibs_for_make module to static binaries"" into main
diff --git a/ci/Android.bp b/ci/Android.bp
index 3f28be4..757767c 100644
--- a/ci/Android.bp
+++ b/ci/Android.bp
@@ -35,11 +35,6 @@
     data: [
         ":py3-cmd",
     ],
-    version: {
-        py3: {
-            embedded_launcher: true,
-        },
-    },
 }
 
 // This test is only intended to be run locally since it's slow, not hermetic,
@@ -64,11 +59,6 @@
     test_options: {
         unit_test: false,
     },
-    version: {
-        py3: {
-            embedded_launcher: true,
-        },
-    },
 }
 
 python_test_host {
@@ -88,11 +78,6 @@
     data: [
         ":py3-cmd",
     ],
-    version: {
-        py3: {
-            embedded_launcher: true,
-        },
-    },
 }
 
 python_binary_host {
diff --git a/core/Makefile b/core/Makefile
index 228fa72..591f937 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -839,16 +839,6 @@
 
 
 # -----------------------------------------------------------------
-# build system stats
-BUILD_SYSTEM_STATS := $(PRODUCT_OUT)/build_system_stats.txt
-$(BUILD_SYSTEM_STATS):
-	@rm -f $@
-	@$(foreach s,$(STATS.MODULE_TYPE),echo "modules_type_make,$(s),$(words $(STATS.MODULE_TYPE.$(s)))" >>$@;)
-	@$(foreach s,$(STATS.SOONG_MODULE_TYPE),echo "modules_type_soong,$(s),$(STATS.SOONG_MODULE_TYPE.$(s))" >>$@;)
-$(call declare-1p-target,$(BUILD_SYSTEM_STATS),build)
-$(call dist-for-goals,droidcore-unbundled,$(BUILD_SYSTEM_STATS))
-
-# -----------------------------------------------------------------
 # build /product/etc/security/avb/system_other.avbpubkey if needed
 ifdef BUILDING_SYSTEM_OTHER_IMAGE
 ifeq ($(BOARD_AVB_ENABLE),true)
@@ -923,18 +913,6 @@
 
 $(call dist-for-goals,droidcore-unbundled,$(WALL_WERROR))
 
-# -----------------------------------------------------------------
-# Modules missing profile files
-PGO_PROFILE_MISSING := $(PRODUCT_OUT)/pgo_profile_file_missing.txt
-$(PGO_PROFILE_MISSING):
-	@rm -f $@
-	echo "# Modules missing PGO profile files" >> $@
-	for m in $(SOONG_MODULES_MISSING_PGO_PROFILE_FILE); do echo $$m >> $@; done
-
-$(call declare-0p-target,$(PGO_PROFILE_MISSING))
-
-$(call dist-for-goals,droidcore,$(PGO_PROFILE_MISSING))
-
 CERTIFICATE_VIOLATION_MODULES_FILENAME := $(PRODUCT_OUT)/certificate_violation_modules.txt
 $(CERTIFICATE_VIOLATION_MODULES_FILENAME):
 	rm -f $@
@@ -1948,15 +1926,6 @@
 # need no associated notice file on the device UI.
 exclude_target_dirs := apex
 
-# TODO(b/69865032): Make PRODUCT_NOTICE_SPLIT the default behavior.
-ifneq ($(PRODUCT_NOTICE_SPLIT),true)
-#target_notice_file_html := $(TARGET_OUT_INTERMEDIATES)/NOTICE.html
-target_notice_file_html_gz := $(TARGET_OUT_INTERMEDIATES)/NOTICE.html.gz
-installed_notice_html_or_xml_gz := $(TARGET_OUT)/etc/NOTICE.html.gz
-
-$(call declare-0p-target,$(target_notice_file_html_gz))
-$(call declare-0p-target,$(installed_notice_html_or_xml_gz))
-else
 # target_notice_file_xml := $(TARGET_OUT_INTERMEDIATES)/NOTICE.xml
 target_notice_file_xml_gz := $(TARGET_OUT_INTERMEDIATES)/NOTICE.xml.gz
 installed_notice_html_or_xml_gz := $(TARGET_OUT)/etc/NOTICE.xml.gz
@@ -2076,8 +2045,6 @@
 system_notice_file_message := "Notices for files contained in the system filesystem image in this directory:"
 endif
 
-endif # PRODUCT_NOTICE_SPLIT
-
 ALL_DEFAULT_INSTALLED_MODULES += $(installed_notice_html_or_xml_gz)
 
 need_vendor_notice:=false
@@ -5907,7 +5874,10 @@
 endif # BOARD_AVB_ENABLE
 ifneq (,$(strip $(BOARD_CUSTOMIMAGES_PARTITION_LIST)))
 	$(hide) $(foreach partition,$(BOARD_CUSTOMIMAGES_PARTITION_LIST), \
-	  echo "flash $(partition)" >> $@;)
+		$(if $(BOARD_$(call to-upper,$(partition))_IMAGE_NO_FLASHALL),, \
+	      echo "flash $(partition)" >> $@; \
+		) \
+	)
 endif
 	$(hide) echo "reboot fastboot" >> $@
 	$(hide) echo "update-super" >> $@
@@ -8101,7 +8071,7 @@
 allimages_zip := $(PRODUCT_OUT)/all_images.zip
 $(allimages_zip): PRIVATE_SOONG_ZIP_ARGUMENTS := $(allimages_soong_zip_args)
 $(allimages_zip): $(SOONG_ZIP) $(allimages_deps)
-	$(SOONG_ZIP) -o $@ --sort_entries $(PRIVATE_SOONG_ZIP_ARGUMENTS)
+	$(SOONG_ZIP) -o $@ $(PRIVATE_SOONG_ZIP_ARGUMENTS)
 
 .PHONY: soong_only_diff_test
 soong_only_diff_test: PRIVATE_ALLIMAGES_ZIP := $(allimages_zip)
diff --git a/core/OWNERS b/core/OWNERS
index 35ea83d..d8aa237 100644
--- a/core/OWNERS
+++ b/core/OWNERS
@@ -9,5 +9,5 @@
 per-file version_defaults.mk = amhk@google.com,gurpreetgs@google.com,mkhokhlova@google.com,robertogil@google.com
 
 # For Ravenwood test configs
-per-file ravenwood_test_config_template.xml = jsharkey@google.com,omakoto@google.com
+per-file ravenwood_test_config_template.xml =omakoto@google.com
 
diff --git a/core/base_rules.mk b/core/base_rules.mk
index 8042e0a..9ffe518 100644
--- a/core/base_rules.mk
+++ b/core/base_rules.mk
@@ -931,12 +931,6 @@
     my_supported_variant := DEVICE
   endif
 endif
-###########################################################
-## Add test module to ALL_DISABLED_PRESUBMIT_TESTS if LOCAL_PRESUBMIT_DISABLED is set to true.
-###########################################################
-ifeq ($(LOCAL_PRESUBMIT_DISABLED),true)
-  ALL_DISABLED_PRESUBMIT_TESTS += $(LOCAL_MODULE)
-endif  # LOCAL_PRESUBMIT_DISABLED
 
 ###########################################################
 ## Register with ALL_MODULES
diff --git a/core/clear_vars.mk b/core/clear_vars.mk
index fed19e6..2e67aff 100644
--- a/core/clear_vars.mk
+++ b/core/clear_vars.mk
@@ -204,7 +204,6 @@
 LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES:=
 LOCAL_USE_EMBEDDED_DEX:=
 LOCAL_USE_EMBEDDED_NATIVE_LIBS:=
-LOCAL_PRESUBMIT_DISABLED:=
 LOCAL_PRIVATE_PLATFORM_APIS:=
 LOCAL_PRIVILEGED_MODULE:=
 LOCAL_PROC_MACRO_LIBRARIES:=
diff --git a/core/config.mk b/core/config.mk
index b892924..47018aa 100644
--- a/core/config.mk
+++ b/core/config.mk
@@ -765,7 +765,6 @@
 
 # TODO: remove all code referencing these, and remove override variables
 PRODUCT_FULL_TREBLE := true
-PRODUCT_NOTICE_SPLIT := true
 PRODUCT_TREBLE_LINKER_NAMESPACES := true
 PRODUCT_ENFORCE_VINTF_MANIFEST := true
 
@@ -774,7 +773,6 @@
     PRODUCT_FULL_TREBLE \
     PRODUCT_TREBLE_LINKER_NAMESPACES \
     PRODUCT_ENFORCE_VINTF_MANIFEST \
-    PRODUCT_NOTICE_SPLIT \
 
 # TODO(b/114488870): remove all sets of these everwhere, and disallow them to be used
 $(KATI_obsolete_var PRODUCT_TREBLE_LINKER_NAMESPACES_OVERRIDE,Deprecated.)
diff --git a/core/definitions.mk b/core/definitions.mk
index ade8a9c..60034cd 100644
--- a/core/definitions.mk
+++ b/core/definitions.mk
@@ -90,9 +90,6 @@
 # All installed vintf manifest fragments for a partition at
 ALL_VINTF_MANIFEST_FRAGMENTS_LIST:=
 
-# All tests that should be skipped in presubmit check.
-ALL_DISABLED_PRESUBMIT_TESTS :=
-
 # All compatibility suites mentioned in LOCAL_COMPATIBILITY_SUITE
 ALL_COMPATIBILITY_SUITES :=
 
@@ -839,18 +836,6 @@
 endef
 
 ###########################################################
-## Declare that non-module targets copied from project $(1) and
-## optionally ending in $(2) are non-copyrightable files.
-##
-## e.g. an information-only file merely listing other files.
-###########################################################
-define declare-0p-copy-files
-$(strip \
-  $(foreach _pair,$(filter $(1)%$(2),$(PRODUCT_COPY_FILES)),$(eval $(call declare-0p-target,$(PRODUCT_OUT)/$(call word-colon,2,$(_pair))))) \
-)
-endef
-
-###########################################################
 ## Declare non-module target $(1) to have a first-party license
 ## (Android Apache 2.0)
 ##
diff --git a/core/dex_preopt.mk b/core/dex_preopt.mk
index 8d5567e..b78c10c 100644
--- a/core/dex_preopt.mk
+++ b/core/dex_preopt.mk
@@ -13,34 +13,10 @@
 install-on-system-other = $(filter-out $(PRODUCT_DEXPREOPT_SPEED_APPS) $(PRODUCT_SYSTEM_SERVER_APPS),$(basename $(notdir $(filter $(foreach f,$(SYSTEM_OTHER_ODEX_FILTER),$(TARGET_OUT)/$(f)),$(1)))))
 endif
 
-# Build the boot.zip which contains the boot jars and their compilation output
-# We can do this only if preopt is enabled and if the product uses libart config (which sets the
-# default properties for preopting).
-# At the time of writing, this is only for ART Cloud.
 ifeq ($(WITH_DEXPREOPT), true)
 ifneq ($(WITH_DEXPREOPT_ART_BOOT_IMG_ONLY), true)
 ifeq ($(PRODUCT_USES_DEFAULT_ART_CONFIG), true)
 
-boot_zip := $(PRODUCT_OUT)/boot.zip
-bootclasspath_jars := $(DEXPREOPT_BOOTCLASSPATH_DEX_FILES)
-
-# TODO remove system_server_jars usages from boot.zip and depend directly on system_server.zip file.
-
-# Use "/system" path for JARs with "platform:" prefix.
-# These JARs counterintuitively use "platform" prefix but they will
-# be actually installed to /system partition.
-platform_system_server_jars = $(filter platform:%, $(PRODUCT_SYSTEM_SERVER_JARS))
-system_server_jars := \
-  $(foreach m,$(platform_system_server_jars),\
-    $(PRODUCT_OUT)/system/framework/$(call word-colon,2,$(m)).jar)
-
-# For the remaining system server JARs use the partition signified by the prefix.
-# For example, prefix "system_ext:" will use "/system_ext" path.
-other_system_server_jars = $(filter-out $(platform_system_server_jars), $(PRODUCT_SYSTEM_SERVER_JARS))
-system_server_jars += \
-  $(foreach m,$(other_system_server_jars),\
-    $(PRODUCT_OUT)/$(call word-colon,1,$(m))/framework/$(call word-colon,2,$(m)).jar)
-
 # Infix can be 'art' (ART image for testing), 'boot' (primary), or 'mainline' (mainline extension).
 # Soong creates a set of variables for Make, one or each boot image. The only reason why the ART
 # image is exposed to Make is testing (art gtests) and benchmarking (art golem benchmarks). Install
@@ -48,76 +24,6 @@
 # is always 'boot' or 'mainline'.
 DEXPREOPT_INFIX := $(if $(filter true,$(DEX_PREOPT_WITH_UPDATABLE_BCP)),mainline,boot)
 
-# The input variables are written by build/soong/java/dexpreopt_bootjars.go. Examples can be found
-# at the bottom of build/soong/java/dexpreopt_config_testing.go.
-dexpreopt_root_dir := $(dir $(patsubst %/,%,$(dir $(firstword $(bootclasspath_jars)))))
-bootclasspath_arg := $(subst $(space),:,$(patsubst $(dexpreopt_root_dir)%,%,$(DEXPREOPT_BOOTCLASSPATH_DEX_FILES)))
-bootclasspath_locations_arg := $(subst $(space),:,$(DEXPREOPT_BOOTCLASSPATH_DEX_LOCATIONS))
-boot_images := $(subst :,$(space),$(DEXPREOPT_IMAGE_LOCATIONS_ON_DEVICE$(DEXPREOPT_INFIX)))
-boot_image_arg := $(subst $(space),:,$(patsubst /%,%,$(boot_images)))
-uffd_gc_flag_txt := $(OUT_DIR)/soong/dexpreopt/uffd_gc_flag.txt
-
-boot_zip_metadata_txt := $(dir $(boot_zip))boot_zip/METADATA.txt
-$(boot_zip_metadata_txt): $(uffd_gc_flag_txt)
-$(boot_zip_metadata_txt):
-	rm -f $@
-	echo "bootclasspath = $(bootclasspath_arg)" >> $@
-	echo "bootclasspath-locations = $(bootclasspath_locations_arg)" >> $@
-	echo "boot-image = $(boot_image_arg)" >> $@
-	echo "extra-args = `cat $(uffd_gc_flag_txt)`" >> $@
-
-$(call dist-for-goals, droidcore, $(boot_zip_metadata_txt))
-
-$(boot_zip): PRIVATE_BOOTCLASSPATH_JARS := $(bootclasspath_jars)
-$(boot_zip): PRIVATE_SYSTEM_SERVER_JARS := $(system_server_jars)
-$(boot_zip): $(bootclasspath_jars) $(system_server_jars) $(SOONG_ZIP) $(MERGE_ZIPS) $(DEXPREOPT_IMAGE_ZIP_boot) $(DEXPREOPT_IMAGE_ZIP_art) $(DEXPREOPT_IMAGE_ZIP_mainline) $(boot_zip_metadata_txt)
-	@echo "Create boot package: $@"
-	rm -f $@
-	$(SOONG_ZIP) -o $@.tmp \
-	  -C $(dir $(firstword $(PRIVATE_BOOTCLASSPATH_JARS)))/.. $(addprefix -f ,$(PRIVATE_BOOTCLASSPATH_JARS)) \
-	  -C $(PRODUCT_OUT) $(addprefix -f ,$(PRIVATE_SYSTEM_SERVER_JARS)) \
-	  -j -f $(boot_zip_metadata_txt)
-	$(MERGE_ZIPS) $@ $@.tmp $(DEXPREOPT_IMAGE_ZIP_boot) $(DEXPREOPT_IMAGE_ZIP_art) $(DEXPREOPT_IMAGE_ZIP_mainline)
-	rm -f $@.tmp
-
-$(call dist-for-goals, droidcore, $(boot_zip))
-
-# Build the system_server.zip which contains the Apex system server jars and standalone system server jars
-system_server_dex2oat_dir := $(SOONG_OUT_DIR)/system_server_dexjars
-system_server_zip := $(PRODUCT_OUT)/system_server.zip
-# non_updatable_system_server_jars contains jars in /system and /system_ext that are not part of an apex.
-non_updatable_system_server_jars := \
-  $(foreach m,$(PRODUCT_SYSTEM_SERVER_JARS),\
-    $(system_server_dex2oat_dir)/$(call word-colon,2,$(m)).jar)
-
-apex_system_server_jars := \
-  $(foreach m,$(PRODUCT_APEX_SYSTEM_SERVER_JARS),\
-    $(system_server_dex2oat_dir)/$(call word-colon,2,$(m)).jar)
-
-apex_standalone_system_server_jars := \
-  $(foreach m,$(PRODUCT_APEX_STANDALONE_SYSTEM_SERVER_JARS),\
-    $(system_server_dex2oat_dir)/$(call word-colon,2,$(m)).jar)
-
-standalone_system_server_jars := \
-  $(foreach m,$(PRODUCT_STANDALONE_SYSTEM_SERVER_JARS),\
-    $(system_server_dex2oat_dir)/$(call word-colon,2,$(m)).jar)
-
-$(system_server_zip): PRIVATE_SYSTEM_SERVER_DEX2OAT_DIR := $(system_server_dex2oat_dir)
-$(system_server_zip): PRIVATE_SYSTEM_SERVER_JARS := $(non_updatable_system_server_jars)
-$(system_server_zip): PRIVATE_APEX_SYSTEM_SERVER_JARS := $(apex_system_server_jars)
-$(system_server_zip): PRIVATE_APEX_STANDALONE_SYSTEM_SERVER_JARS := $(apex_standalone_system_server_jars)
-$(system_server_zip): PRIVATE_STANDALONE_SYSTEM_SERVER_JARS := $(standalone_system_server_jars)
-$(system_server_zip): $(non_updatable_system_server_jars) $(apex_system_server_jars) $(apex_standalone_system_server_jars) $(standalone_system_server_jars) $(SOONG_ZIP)
-	@echo "Create system server package: $@"
-	rm -f $@
-	$(SOONG_ZIP) -o $@ \
-	  -C $(PRIVATE_SYSTEM_SERVER_DEX2OAT_DIR) $(addprefix -f ,$(PRIVATE_SYSTEM_SERVER_JARS)) \
-	  -C $(PRIVATE_SYSTEM_SERVER_DEX2OAT_DIR) $(addprefix -f ,$(PRIVATE_APEX_SYSTEM_SERVER_JARS)) \
-	  -C $(PRIVATE_SYSTEM_SERVER_DEX2OAT_DIR) $(addprefix -f ,$(PRIVATE_APEX_STANDALONE_SYSTEM_SERVER_JARS)) \
-	  -C $(PRIVATE_SYSTEM_SERVER_DEX2OAT_DIR) $(addprefix -f ,$(PRIVATE_STANDALONE_SYSTEM_SERVER_JARS))
-
-$(call dist-for-goals, droidcore, $(system_server_zip))
-
 endif  #PRODUCT_USES_DEFAULT_ART_CONFIG
 endif  #WITH_DEXPREOPT_ART_BOOT_IMG_ONLY
 endif  #WITH_DEXPREOPT
diff --git a/core/dex_preopt_odex_install.mk b/core/dex_preopt_odex_install.mk
index e7086b7..6fe9d38 100644
--- a/core/dex_preopt_odex_install.mk
+++ b/core/dex_preopt_odex_install.mk
@@ -152,7 +152,7 @@
 # this dexpreopt.config is generated. So it's necessary to add file-level
 # dependencies between dexpreopt.config files.
 my_dexpreopt_dep_configs := $(foreach lib, \
-  $(filter-out $(my_dexpreopt_libs_compat),$(LOCAL_USES_LIBRARIES) $(my_filtered_optional_uses_libraries)), \
+  $(filter-out $(my_dexpreopt_libs_compat) $(FRAMEWORK_LIBRARIES),$(LOCAL_USES_LIBRARIES) $(my_filtered_optional_uses_libraries)), \
   $(call intermediates-dir-for,JAVA_LIBRARIES,$(lib),,)/dexpreopt.config)
 
 # 1: SDK version
diff --git a/core/main.mk b/core/main.mk
index 41a36ca..9710dc8 100644
--- a/core/main.mk
+++ b/core/main.mk
@@ -1467,7 +1467,6 @@
 # dist_files only for putting your library into the dist directory with a full build.
 .PHONY: dist_files
 
-$(call dist-for-goals, dist_files, $(SOONG_OUT_DIR)/module_bp_java_deps.json)
 $(call dist-for-goals, dist_files, $(PRODUCT_OUT)/module-info.json)
 
 .PHONY: apps_only
diff --git a/core/os_licensing.mk b/core/os_licensing.mk
index 97e55a7..bebaca1 100644
--- a/core/os_licensing.mk
+++ b/core/os_licensing.mk
@@ -7,12 +7,6 @@
 
 SYSTEM_NOTICE_DEPS += $(UNMOUNTED_NOTICE_DEPS) $(UNMOUNTED_NOTICE_VENDOR_DEPS)
 
-ifneq ($(PRODUCT_NOTICE_SPLIT),true)
-$(eval $(call html-notice-rule,$(target_notice_file_html_gz),"System image",$(system_notice_file_message),$(SYSTEM_NOTICE_DEPS),$(SYSTEM_NOTICE_DEPS)))
-
-$(installed_notice_html_or_xml_gz): $(target_notice_file_html_gz)
-	$(copy-file-to-target)
-else
 $(eval $(call xml-notice-rule,$(target_notice_file_xml_gz),"System image",$(system_notice_file_message),$(SYSTEM_NOTICE_DEPS),$(SYSTEM_NOTICE_DEPS)))
 
 $(eval $(call text-notice-rule,$(target_notice_file_txt),"System image",$(system_notice_file_message),$(SYSTEM_NOTICE_DEPS),$(SYSTEM_NOTICE_DEPS)))
@@ -21,7 +15,6 @@
 $(installed_notice_html_or_xml_gz): $(target_notice_file_xml_gz)
 	$(copy-file-to-target)
 endif
-endif
 
 $(call declare-1p-target,$(target_notice_file_xml_gz))
 ifneq ($(PRODUCT_USE_SOONG_NOTICE_XML),true)
diff --git a/core/proguard.flags b/core/proguard.flags
index dc32e15..76655ca 100644
--- a/core/proguard.flags
+++ b/core/proguard.flags
@@ -30,12 +30,12 @@
 # Needed to ensure callback field references are kept in their respective
 # owning classes when the downstream callback registrars only store weak refs.
 -if @com.android.internal.annotations.WeaklyReferencedCallback class *
--keepclassmembers,allowaccessmodification class * {
-  <1> *;
+-keepclassmembers,allowaccessmodification,allowobfuscation,allowshrinking class * {
+  !synthetic <1> *;
 }
 -if class * extends @com.android.internal.annotations.WeaklyReferencedCallback **
--keepclassmembers,allowaccessmodification class * {
-  <1> *;
+-keepclassmembers,allowaccessmodification,allowobfuscation,allowshrinking class * {
+  !synthetic <1> *;
 }
 
 # Understand the common @Keep annotation from various Android packages:
diff --git a/core/proguard/checknotnull.flags b/core/proguard/checknotnull.flags
new file mode 100644
index 0000000..1e1e5ce
--- /dev/null
+++ b/core/proguard/checknotnull.flags
@@ -0,0 +1,25 @@
+# Tell R8 that the following methods are check not null methods, and to
+# replace invocations to them with a more concise nullness check that produces
+# (slightly) less informative error messages
+
+-convertchecknotnull class com.google.common.base.Preconditions {
+  ** checkNotNull(...);
+}
+
+-convertchecknotnull class java.util.Objects {
+  ** requireNonNull(...);
+}
+
+-convertchecknotnull class kotlin.jvm.internal.Intrinsics {
+  void checkNotNull(...);
+  void checkExpressionValueIsNotNull(...);
+  void checkNotNullExpressionValue(...);
+  void checkReturnedValueIsNotNull(...);
+  void checkFieldIsNotNull(...);
+  void checkParameterIsNotNull(...);
+  void checkNotNullParameter(...);
+}
+
+-convertchecknotnull class dagger.internal.Preconditions {
+  ** checkNotNull*(...);
+}
diff --git a/core/soong_config.mk b/core/soong_config.mk
index bd52d88..c3cbaf3 100644
--- a/core/soong_config.mk
+++ b/core/soong_config.mk
@@ -488,6 +488,7 @@
   $(call add_json_list, AbOtaPartitions, $(AB_OTA_PARTITIONS))
   $(call add_json_list, AbOtaKeys, $(PRODUCT_OTA_PUBLIC_KEYS))
   $(call add_json_list, AbOtaPostInstallConfig, $(AB_OTA_POSTINSTALL_CONFIG))
+  $(call add_json_bool, BoardSuperImageInUpdatePackage, $(filter true,$(BOARD_SUPER_IMAGE_IN_UPDATE_PACKAGE)))
 
   # Avb (android verified boot) stuff
   $(call add_json_bool, BoardAvbEnable, $(filter true,$(BOARD_AVB_ENABLE)))
@@ -568,6 +569,9 @@
 
   $(call add_json_str, ReleaseToolsExtensionDir, $(firstword $(TARGET_RELEASETOOLS_EXTENSIONS) $($(TARGET_DEVICE_DIR)/../common)))
 
+  # Fastboot
+  $(call add_json_str, BoardFastbootInfoFile, $(TARGET_BOARD_FASTBOOT_INFO_FILE))
+
 $(call end_json_map)
 
 # For converting vintf_data
diff --git a/core/tasks/cts.mk b/core/tasks/cts.mk
index 1a55bf4..1321c69 100644
--- a/core/tasks/cts.mk
+++ b/core/tasks/cts.mk
@@ -151,6 +151,7 @@
 cts-v-host-api-map-xml-report := $(api_map_out)/cts-v-host-api-map.xml
 cts-combined-api-map-xml-report := $(api_map_out)/cts-combined-api-map.xml
 cts-combined-api-map-html-report := $(api_map_out)/cts-combined-api-map.html
+cts-combined-api-inherit-xml-report := $(api_map_out)/cts-combined-api-inherit.xml
 
 cts_api_map_dependencies := $(cts_api_map_exe) $(combined_api_xml_description) $(cts_jar_files)
 cts_v_host_api_map_dependencies := $(cts_api_map_exe) $(combined_api_xml_description) $(cts_v_host_jar_files)
@@ -262,6 +263,13 @@
 	$(call generate-api-map-report-cts,"CTS Combined API MAP Report - HTML",\
 			$(PRIVATE_JAR_FILES),html)
 
+$(cts-combined-api-inherit-xml-report): PRIVATE_CTS_API_MAP_EXE := $(cts_api_map_exe)
+$(cts-combined-api-inherit-xml-report): PRIVATE_API_XML_DESC := $(combined_api_xml_description)
+$(cts-combined-api-inherit-xml-report): PRIVATE_JAR_FILES := $(cts_all_jar_files)
+$(cts-combined-api-inherit-xml-report) : $(verifier_zip) $(android_cts_zip) $(cts_combined_api_map_dependencies) | $(ACP)
+	$(call generate-api-inherit-report-cts,"CTS Combined API Inherit Report - XML",\
+			$(PRIVATE_JAR_FILES),xml)
+
 .PHONY: cts-api-map-xml
 cts-api-map-xml : $(cts-api-map-xml-report)
 
@@ -271,6 +279,9 @@
 .PHONY: cts-combined-api-map-xml
 cts-combined-api-map-xml : $(cts-combined-api-map-xml-report)
 
+.PHONY: cts-combined-api-inherit-xml
+cts-combined-api-inherit-xml : $(cts-combined-api-inherit-xml-report)
+
 .PHONY: cts-api-map-all
 
 # Put the test coverage report in the dist dir if "cts-api-coverage" is among the build goals.
@@ -291,11 +302,13 @@
 # Put the test api map report in the dist dir if "cts-api-map-all" is among the build goals.
 $(call dist-for-goals, cts-api-map-all, $(cts-combined-api-map-xml-report):cts-api-map-report.xml)
 $(call dist-for-goals, cts-api-map-all, $(cts-combined-api-map-html-report):cts-api-map-report.html)
+$(call dist-for-goals, cts-api-map-all, $(cts-combined-api-inherit-xml-report):cts-api-inherit-report.xml)
 
 ALL_TARGETS.$(cts-api-map-xml-report).META_LIC:=$(module_license_metadata)
 ALL_TARGETS.$(cts-v-host-api-map-xml-report).META_LIC:=$(module_license_metadata)
 ALL_TARGETS.$(cts-combined-api-map-xml-report).META_LIC:=$(module_license_metadata)
 ALL_TARGETS.$(cts-combined-api-map-html-report).META_LIC:=$(module_license_metadata)
+ALL_TARGETS.$(cts-combined-api-map-inherit-report).META_LIC:=$(module_license_metadata)
 
 # Arguments;
 #  1 - Name of the report printed out on the screen
@@ -313,7 +326,18 @@
 #  3 - Format of the report
 define generate-api-map-report-cts
 	$(hide) mkdir -p $(dir $@)
-	$(hide) $(PRIVATE_CTS_API_MAP_EXE) -j 8 -a $(shell echo "$(PRIVATE_API_XML_DESC)" | tr ' ' ',') -i $(2) -f $(3) -o $@
+	$(hide) $(PRIVATE_CTS_API_MAP_EXE) -j 8 -m api_map -m xts_annotation -a $(shell echo "$(PRIVATE_API_XML_DESC)" | tr ' ' ',') -i $(2) -f $(3) -o $@
+	@ echo $(1): file://$$(cd $(dir $@); pwd)/$(notdir $@)
+endef
+
+
+# Arguments;
+#  1 - Name of the report printed out on the screen
+#  2 - A file containing list of files that to be analyzed
+#  3 - Format of the report
+define generate-api-inherit-report-cts
+	$(hide) mkdir -p $(dir $@)
+	$(hide) $(PRIVATE_CTS_API_MAP_EXE) -j 8 -m xts_api_inherit -a $(shell echo "$(PRIVATE_API_XML_DESC)" | tr ' ' ',') -i $(2) -f $(3) -o $@
 	@ echo $(1): file://$$(cd $(dir $@); pwd)/$(notdir $@)
 endef
 
@@ -333,6 +357,7 @@
 cts-v-host-api-map-xml-report :=
 cts-combined-api-map-xml-report :=
 cts-combined-api-map-html-report :=
+cts-combined-api-map-inherit-report :=
 api_xml_description :=
 api_text_description :=
 system_api_xml_description :=
diff --git a/core/tasks/test_mapping.mk b/core/tasks/test_mapping.mk
deleted file mode 100644
index eb2a585..0000000
--- a/core/tasks/test_mapping.mk
+++ /dev/null
@@ -1,40 +0,0 @@
-# Copyright (C) 2017 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.
-
-# Create an artifact to include TEST_MAPPING files in source tree. Also include
-# a file (out/disabled-presubmit-tests) containing the tests that should be
-# skipped in presubmit check.
-
-.PHONY: test_mapping
-
-intermediates := $(call intermediates-dir-for,PACKAGING,test_mapping)
-test_mappings_zip := $(intermediates)/test_mappings.zip
-test_mapping_list := $(OUT_DIR)/.module_paths/TEST_MAPPING.list
-$(test_mappings_zip) : PRIVATE_all_disabled_presubmit_tests := $(ALL_DISABLED_PRESUBMIT_TESTS)
-$(test_mappings_zip) : PRIVATE_test_mapping_list := $(test_mapping_list)
-
-$(test_mappings_zip) : .KATI_DEPFILE := $(test_mappings_zip).d
-$(test_mappings_zip) : $(test_mapping_list) $(SOONG_ZIP)
-	@echo "Building artifact to include TEST_MAPPING files and tests to skip in presubmit check."
-	rm -rf $@ $(dir $@)/disabled-presubmit-tests
-	echo $(sort $(PRIVATE_all_disabled_presubmit_tests)) | tr " " "\n" > $(dir $@)/disabled-presubmit-tests
-	$(SOONG_ZIP) -o $@ -C . -l $(PRIVATE_test_mapping_list) -C $(dir $@) -f $(dir $@)/disabled-presubmit-tests
-	echo "$@ : " $$(cat $(PRIVATE_test_mapping_list)) > $@.d
-	rm -f $(dir $@)/disabled-presubmit-tests
-
-test_mapping : $(test_mappings_zip)
-
-$(call dist-for-goals, dist_files test_mapping,$(test_mappings_zip))
-
-$(call declare-1p-target,$(test_mappings_zip),)
diff --git a/core/tasks/tradefed-tests-list.mk b/core/tasks/tradefed-tests-list.mk
index 47c360d..e437f89 100644
--- a/core/tasks/tradefed-tests-list.mk
+++ b/core/tasks/tradefed-tests-list.mk
@@ -18,11 +18,19 @@
 COMPATIBILITY.tradefed_tests_dir := \
   $(COMPATIBILITY.tradefed_tests_dir) \
   tools/tradefederation/core/res/config \
-  tools/tradefederation/core/javatests/res/config
+  tools/tradefederation/core/javatests/res/config \
+  vendor/google_tradefederation/contrib/res/config \
+  vendor/google_tradefederation/core/res/config \
+  vendor/google_tradefederation/core/javatests/res/config \
+  vendor/google_tradefederation/core/prod_tests/res/config
 
 tradefed_tests :=
 $(foreach dir, $(COMPATIBILITY.tradefed_tests_dir), \
-  $(eval tradefed_tests += $(shell find $(dir) -type f -name "*.xml")))
+  $(if $(wildcard $(dir)/*), \
+    $(eval tradefed_tests += $(shell find $(dir) -type f -name "*.xml")) \
+  ) \
+)
+
 tradefed_tests_list_intermediates := $(call intermediates-dir-for,PACKAGING,tradefed_tests_list,HOST,COMMON)
 tradefed_tests_list_zip := $(tradefed_tests_list_intermediates)/tradefed-tests_list.zip
 all_tests :=
diff --git a/target/product/generic/Android.bp b/target/product/generic/Android.bp
index 12abea9..5bfff66 100644
--- a/target/product/generic/Android.bp
+++ b/target/product/generic/Android.bp
@@ -880,11 +880,6 @@
                 default: [
                     "framework-connectivity-b", // base_system
                 ],
-            }) + select(release_flag("RELEASE_AVATAR_PICKER_APP"), {
-                true: [
-                    "AvatarPicker", // generic_system (RELEASE_AVATAR_PICKER_APP)
-                ],
-                default: [],
             }) + select(release_flag("RELEASE_UPROBESTATS_MODULE"), {
                 true: [
                     "com.android.uprobestats", // base_system (RELEASE_UPROBESTATS_MODULE)
diff --git a/target/product/gsi/Android.bp b/target/product/gsi/Android.bp
index dafbe46..8c200a1 100644
--- a/target/product/gsi/Android.bp
+++ b/target/product/gsi/Android.bp
@@ -209,4 +209,14 @@
         true: true,
         default: false,
     }),
+    multilib: {
+        common: {
+            deps: select(release_flag("RELEASE_AVATAR_PICKER_APP"), {
+                true: [
+                    "AvatarPicker", // handheld_system_ext (RELEASE_AVATAR_PICKER_APP)
+                ],
+                default: [],
+            }),
+        },
+    },
 }
diff --git a/target/product/handheld_system.mk b/target/product/handheld_system.mk
index 6799066..2b055c7 100644
--- a/target/product/handheld_system.mk
+++ b/target/product/handheld_system.mk
@@ -34,7 +34,6 @@
 
 PRODUCT_PACKAGES += \
     android.software.window_magnification.prebuilt.xml \
-    $(if $(RELEASE_AVATAR_PICKER_APP), AvatarPicker,) \
     BasicDreams \
     BlockedNumberProvider \
     BluetoothMidiService \
diff --git a/target/product/handheld_system_ext.mk b/target/product/handheld_system_ext.mk
index 187b627..6d686c5 100644
--- a/target/product/handheld_system_ext.mk
+++ b/target/product/handheld_system_ext.mk
@@ -23,6 +23,7 @@
 # /system_ext packages
 PRODUCT_PACKAGES += \
     AccessibilityMenu \
+    $(if $(RELEASE_AVATAR_PICKER_APP), AvatarPicker,) \
     Launcher3QuickStep \
     Provision \
     Settings \
diff --git a/tools/Android.bp b/tools/Android.bp
index 243cb56..f1ff1c4 100644
--- a/tools/Android.bp
+++ b/tools/Android.bp
@@ -85,11 +85,6 @@
     srcs: [
         "list_files.py",
     ],
-    version: {
-        py3: {
-            embedded_launcher: true,
-        },
-    },
 }
 
 python_test_host {
@@ -109,11 +104,6 @@
 python_binary_host {
     name: "characteristics_rro_generator",
     srcs: ["characteristics_rro_generator.py"],
-    version: {
-        py3: {
-            embedded_launcher: true,
-        },
-    },
 }
 
 python_binary_host {
diff --git a/tools/aconfig/Cargo.toml b/tools/aconfig/Cargo.toml
index bf5e1a9..a031b7f 100644
--- a/tools/aconfig/Cargo.toml
+++ b/tools/aconfig/Cargo.toml
@@ -8,7 +8,8 @@
     "aconfig_storage_read_api",
     "aconfig_storage_write_api",
     "aflags",
-    "printflags"
+    "printflags",
+    "convert_finalized_flags"
 ]
 
 resolver = "2"
diff --git a/tools/aconfig/aconfig/Android.bp b/tools/aconfig/aconfig/Android.bp
index cce0ca9..7bdec58 100644
--- a/tools/aconfig/aconfig/Android.bp
+++ b/tools/aconfig/aconfig/Android.bp
@@ -7,7 +7,10 @@
     edition: "2021",
     clippy_lints: "android",
     lints: "android",
-    srcs: ["src/main.rs"],
+    srcs: [
+        "src/main.rs",
+        ":finalized_flags_record.json",
+    ],
     rustlibs: [
         "libaconfig_protos",
         "libaconfig_storage_file",
@@ -18,6 +21,7 @@
         "libserde",
         "libserde_json",
         "libtinytemplate",
+        "libconvert_finalized_flags",
     ],
 }
 
diff --git a/tools/aconfig/aconfig/Cargo.toml b/tools/aconfig/aconfig/Cargo.toml
index abd3ee0..7e4bdf2 100644
--- a/tools/aconfig/aconfig/Cargo.toml
+++ b/tools/aconfig/aconfig/Cargo.toml
@@ -17,3 +17,11 @@
 tinytemplate = "1.2.1"
 aconfig_protos = { path = "../aconfig_protos" }
 aconfig_storage_file = { path = "../aconfig_storage_file" }
+convert_finalized_flags = { path = "../convert_finalized_flags" }
+
+[build-dependencies]
+anyhow = "1.0.69"
+itertools = "0.10.5"
+serde = { version = "1.0.152", features = ["derive"] }
+serde_json = "1.0.93"
+convert_finalized_flags = { path = "../convert_finalized_flags" }
diff --git a/tools/aconfig/aconfig/build.rs b/tools/aconfig/aconfig/build.rs
new file mode 100644
index 0000000..8aaec3c
--- /dev/null
+++ b/tools/aconfig/aconfig/build.rs
@@ -0,0 +1,93 @@
+use anyhow::{anyhow, Result};
+use std::env;
+use std::fs;
+use std::fs::File;
+use std::io::Write;
+use std::path::{Path, PathBuf};
+
+use convert_finalized_flags::read_files_to_map_using_path;
+use convert_finalized_flags::FinalizedFlagMap;
+
+// This fn makes assumptions about the working directory which we should not rely
+// on for actual (Soong) builds. It is reasonable to assume that this is being
+// called from the aconfig directory as cargo is used for local development and
+// the cargo workspace for our project is build/make/tools/aconfig.
+// This is meant to get the list of finalized flag
+// files provided by the filegroup + "locations" in soong.
+// Cargo-only usage is asserted via implementation of
+// read_files_to_map_using_env, the only public cargo-only fn.
+fn read_files_to_map_using_env() -> Result<FinalizedFlagMap> {
+    let mut current_dir = std::env::current_dir()?;
+
+    // Path of aconfig from the top of tree.
+    let aconfig_path = PathBuf::from("build/make/tools/aconfig");
+
+    // Path of SDK files from the top of tree.
+    let sdk_dir_path = PathBuf::from("prebuilts/sdk");
+
+    // Iterate up the directory structure until we have the base aconfig dir.
+    while !current_dir.canonicalize()?.ends_with(&aconfig_path) {
+        if let Some(parent) = current_dir.parent() {
+            current_dir = parent.to_path_buf();
+        } else {
+            return Err(anyhow!("Cannot execute outside of aconfig."));
+        }
+    }
+
+    // Remove the aconfig path, leaving the top of the tree.
+    for _ in 0..aconfig_path.components().count() {
+        current_dir.pop();
+    }
+
+    // Get the absolute path of the sdk files.
+    current_dir.push(sdk_dir_path);
+
+    let mut flag_files = Vec::new();
+
+    // Search all sub-dirs in prebuilts/sdk for finalized-flags.txt files.
+    // The files are in prebuilts/sdk/<api level>/finalized-flags.txt.
+    let api_level_dirs = fs::read_dir(current_dir)?;
+    for api_level_dir in api_level_dirs {
+        if api_level_dir.is_err() {
+            eprintln!("Error opening directory: {}", api_level_dir.err().unwrap());
+            continue;
+        }
+
+        // Skip non-directories.
+        let api_level_dir_path = api_level_dir.unwrap().path();
+        if !api_level_dir_path.is_dir() {
+            continue;
+        }
+
+        // Some directories were created before trunk stable and don't have
+        // flags, or aren't api level directories at all.
+        let flag_file_path = api_level_dir_path.join("finalized-flags.txt");
+        if !flag_file_path.exists() {
+            continue;
+        }
+
+        if let Some(path) = flag_file_path.to_str() {
+            flag_files.push(path.to_string());
+        } else {
+            eprintln!("Error converting path to string: {:?}", flag_file_path);
+        }
+    }
+
+    read_files_to_map_using_path(flag_files)
+}
+
+fn main() {
+    let out_dir = env::var_os("OUT_DIR").unwrap();
+    let dest_path = Path::new(&out_dir).join("finalized_flags_record.json");
+
+    let finalized_flags_map: Result<FinalizedFlagMap> = read_files_to_map_using_env();
+    if finalized_flags_map.is_err() {
+        return;
+    }
+    let json_str = serde_json::to_string(&finalized_flags_map.unwrap()).unwrap();
+
+    let mut f = File::create(&dest_path).unwrap();
+    f.write_all(json_str.as_bytes()).unwrap();
+
+    //println!("cargo:rerun-if-changed=input.txt");
+}
diff --git a/tools/aconfig/aconfig/data/Android.bp b/tools/aconfig/aconfig/data/Android.bp
deleted file mode 100644
index 1b5eef0..0000000
--- a/tools/aconfig/aconfig/data/Android.bp
+++ /dev/null
@@ -1,14 +0,0 @@
-package {
-    default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-python_binary_host {
-    name: "convert_finalized_flags_to_proto",
-    srcs: ["convert_finalized_flags_to_proto.py"],
-    libs: ["aconfig_internal_proto_python"],
-    version: {
-        py3: {
-            embedded_launcher: true,
-        },
-    },
-}
diff --git a/tools/aconfig/aconfig/data/convert_finalized_flags_to_proto.py b/tools/aconfig/aconfig/data/convert_finalized_flags_to_proto.py
deleted file mode 100644
index 15ff03c..0000000
--- a/tools/aconfig/aconfig/data/convert_finalized_flags_to_proto.py
+++ /dev/null
@@ -1,83 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright (C) 2024 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.
-
-import collections
-import sys
-import os
-
-from io import TextIOWrapper
-from protos import aconfig_internal_pb2
-from typing import Dict, List, Set
-
-def extract_finalized_flags(flag_file: TextIOWrapper):
-  finalized_flags_for_sdk = list()
-
-  for line in f:
-    flag_name = line.strip()
-    if flag_name:
-      finalized_flags_for_sdk.append(flag_name)
-
-  return finalized_flags_for_sdk
-
-def remove_duplicate_flags(all_flags_with_duplicates: Dict[int, List]):
-  result_flags = collections.defaultdict(set)
-
-  for api_level in sorted(all_flags_with_duplicates.keys(), key=int):
-    for flag in all_flags_with_duplicates[api_level]:
-      if not any(flag in value_set for value_set in result_flags.values()):
-        result_flags[api_level].add(flag)
-
-  return result_flags
-
-def build_proto(all_flags: Set):
-  finalized_flags = aconfig_internal_pb2.finalized_flags()
-  for api_level, qualified_name_list in all_flags.items():
-    for qualified_name in qualified_name_list:
-      package_name, flag_name = qualified_name.rsplit('.', 1)
-      finalized_flag = aconfig_internal_pb2.finalized_flag()
-      finalized_flag.name = flag_name
-      finalized_flag.package = package_name
-      finalized_flag.min_sdk = api_level
-      finalized_flags.finalized_flag.append(finalized_flag)
-  return finalized_flags
-
-if __name__ == '__main__':
-  if len(sys.argv) == 1:
-    sys.exit('No prebuilts/sdk directory provided.')
-  all_api_info_dir = sys.argv[1]
-
-  all_flags_with_duplicates = {}
-  for sdk_dir in os.listdir(all_api_info_dir):
-    api_level = sdk_dir.rsplit('/', 1)[0].rstrip('0').rstrip('.')
-
-    # No support for minor versions yet. This also removes non-numeric dirs.
-    # Update once floats are acceptable.
-    if not api_level.isdigit():
-      continue
-
-    flag_file_path = os.path.join(all_api_info_dir, sdk_dir, 'finalized-flags.txt')
-    try:
-      with open(flag_file_path, 'r') as f:
-        finalized_flags_for_sdk = extract_finalized_flags(f)
-        all_flags_with_duplicates[int(api_level)] = finalized_flags_for_sdk
-    except FileNotFoundError:
-      # Either this version is not finalized yet or looking at a
-      # /prebuilts/sdk/version before finalized-flags.txt was introduced.
-      continue
-
-  all_flags = remove_duplicate_flags(all_flags_with_duplicates)
-  finalized_flags = build_proto(all_flags)
-  sys.stdout.buffer.write(finalized_flags.SerializeToString())
diff --git a/tools/aconfig/aconfig/src/codegen/java.rs b/tools/aconfig/aconfig/src/codegen/java.rs
index 6bd9416..550ab5f 100644
--- a/tools/aconfig/aconfig/src/codegen/java.rs
+++ b/tools/aconfig/aconfig/src/codegen/java.rs
@@ -24,6 +24,7 @@
 use crate::codegen::CodegenMode;
 use crate::commands::{should_include_flag, OutputFile};
 use aconfig_protos::{ProtoFlagPermission, ProtoFlagState, ProtoParsedFlag};
+use convert_finalized_flags::{FinalizedFlag, FinalizedFlagMap};
 use std::collections::HashMap;
 
 // Arguments to configure codegen for generate_java_code.
@@ -34,7 +35,7 @@
     pub package_fingerprint: u64,
     pub new_exported: bool,
     pub single_exported_file: bool,
-    pub check_api_level: bool,
+    pub finalized_flags: FinalizedFlagMap,
 }
 
 pub fn generate_java_code<I>(
@@ -47,7 +48,7 @@
 {
     let flag_elements: Vec<FlagElement> = parsed_flags_iter
         .map(|pf| {
-            create_flag_element(package, &pf, config.flag_ids.clone(), config.check_api_level)
+            create_flag_element(package, &pf, config.flag_ids.clone(), &config.finalized_flags)
         })
         .collect();
     let namespace_flags = gen_flags_by_namespace(&flag_elements);
@@ -182,7 +183,7 @@
     package: &str,
     pf: &ProtoParsedFlag,
     flag_offsets: HashMap<String, u16>,
-    check_api_level: bool,
+    finalized_flags: &FinalizedFlagMap,
 ) -> FlagElement {
     let device_config_flag = codegen::create_device_config_ident(package, pf.name())
         .expect("values checked at flag parse time");
@@ -204,6 +205,18 @@
         }
     };
 
+    // An empty map is provided if check_api_level is disabled.
+    let mut finalized_sdk_present: bool = false;
+    let mut finalized_sdk_value: i32 = 0;
+    if !finalized_flags.is_empty() {
+        let finalized_sdk = finalized_flags.get_finalized_level(&FinalizedFlag {
+            flag_name: pf.name().to_string(),
+            package_name: package.to_string(),
+        });
+        finalized_sdk_present = finalized_sdk.is_some();
+        finalized_sdk_value = finalized_sdk.map(|f| f.0).unwrap_or_default();
+    }
+
     FlagElement {
         container: pf.container().to_string(),
         default_value: pf.state() == ProtoFlagState::ENABLED,
@@ -215,8 +228,8 @@
         is_read_write: pf.permission() == ProtoFlagPermission::READ_WRITE,
         method_name: format_java_method_name(pf.name()),
         properties: format_property_name(pf.namespace()),
-        finalized_sdk_present: check_api_level,
-        finalized_sdk_value: i32::MAX, // TODO: b/378936061 - Read value from artifact.
+        finalized_sdk_present,
+        finalized_sdk_value,
     }
 }
 
@@ -300,6 +313,8 @@
 
 #[cfg(test)]
 mod tests {
+    use convert_finalized_flags::ApiLevel;
+
     use super::*;
     use crate::commands::assign_flag_ids;
     use std::collections::HashMap;
@@ -609,7 +624,7 @@
             package_fingerprint: 5801144784618221668,
             new_exported: false,
             single_exported_file: false,
-            check_api_level: false,
+            finalized_flags: FinalizedFlagMap::new(),
         };
         let generated_files = generate_java_code(
             crate::test::TEST_PACKAGE,
@@ -770,7 +785,7 @@
             package_fingerprint: 5801144784618221668,
             new_exported: false,
             single_exported_file: false,
-            check_api_level: false,
+            finalized_flags: FinalizedFlagMap::new(),
         };
         let generated_files = generate_java_code(
             crate::test::TEST_PACKAGE,
@@ -781,6 +796,7 @@
 
         let expect_flags_content = r#"
         package com.android.aconfig.test;
+        import android.os.Build;
         /** @hide */
         public final class Flags {
             /** @hide */
@@ -975,7 +991,7 @@
             package_fingerprint: 5801144784618221668,
             new_exported: true,
             single_exported_file: false,
-            check_api_level: false,
+            finalized_flags: FinalizedFlagMap::new(),
         };
         let generated_files = generate_java_code(
             crate::test::TEST_PACKAGE,
@@ -986,6 +1002,7 @@
 
         let expect_flags_content = r#"
         package com.android.aconfig.test;
+        import android.os.Build;
         /** @hide */
         public final class Flags {
             /** @hide */
@@ -1156,6 +1173,213 @@
     }
 
     #[test]
+    fn test_generate_java_code_new_exported_with_sdk_check() {
+        let parsed_flags = crate::test::parse_test_flags();
+        let mode = CodegenMode::Exported;
+        let modified_parsed_flags =
+            crate::commands::modify_parsed_flags_based_on_mode(parsed_flags, mode).unwrap();
+        let flag_ids =
+            assign_flag_ids(crate::test::TEST_PACKAGE, modified_parsed_flags.iter()).unwrap();
+        let mut finalized_flags = FinalizedFlagMap::new();
+        finalized_flags.insert_if_new(
+            ApiLevel(36),
+            FinalizedFlag {
+                flag_name: "disabled_rw_exported".to_string(),
+                package_name: "com.android.aconfig.test".to_string(),
+            },
+        );
+        let config = JavaCodegenConfig {
+            codegen_mode: mode,
+            flag_ids,
+            allow_instrumentation: true,
+            package_fingerprint: 5801144784618221668,
+            new_exported: true,
+            single_exported_file: false,
+            finalized_flags,
+        };
+        let generated_files = generate_java_code(
+            crate::test::TEST_PACKAGE,
+            modified_parsed_flags.into_iter(),
+            config,
+        )
+        .unwrap();
+
+        let expect_flags_content = r#"
+        package com.android.aconfig.test;
+        import android.os.Build;
+        /** @hide */
+        public final class Flags {
+            /** @hide */
+            public static final String FLAG_DISABLED_RW_EXPORTED = "com.android.aconfig.test.disabled_rw_exported";
+            /** @hide */
+            public static final String FLAG_ENABLED_FIXED_RO_EXPORTED = "com.android.aconfig.test.enabled_fixed_ro_exported";
+            /** @hide */
+            public static final String FLAG_ENABLED_RO_EXPORTED = "com.android.aconfig.test.enabled_ro_exported";
+            public static boolean disabledRwExported() {
+                if (Build.VERSION.SDK_INT >= 36) {
+                  return true;
+                }
+                return FEATURE_FLAGS.disabledRwExported();
+            }
+            public static boolean enabledFixedRoExported() {
+                return FEATURE_FLAGS.enabledFixedRoExported();
+            }
+            public static boolean enabledRoExported() {
+                return FEATURE_FLAGS.enabledRoExported();
+            }
+            private static FeatureFlags FEATURE_FLAGS = new FeatureFlagsImpl();
+        }
+        "#;
+
+        let expect_feature_flags_content = r#"
+        package com.android.aconfig.test;
+        /** @hide */
+        public interface FeatureFlags {
+            boolean disabledRwExported();
+            boolean enabledFixedRoExported();
+            boolean enabledRoExported();
+        }
+        "#;
+
+        let expect_feature_flags_impl_content = r#"
+        package com.android.aconfig.test;
+        import android.os.Build;
+        import android.os.flagging.AconfigPackage;
+        import android.util.Log;
+        /** @hide */
+        public final class FeatureFlagsImpl implements FeatureFlags {
+            private static final String TAG = "FeatureFlagsImplExport";
+            private static volatile boolean isCached = false;
+            private static boolean disabledRwExported = false;
+            private static boolean enabledFixedRoExported = false;
+            private static boolean enabledRoExported = false;
+            private void init() {
+                try {
+                    AconfigPackage reader = AconfigPackage.load("com.android.aconfig.test");
+                    disabledRwExported = Build.VERSION.SDK_INT >= 36 ? true : reader.getBooleanFlagValue("disabled_rw_exported", false);
+                    enabledFixedRoExported = reader.getBooleanFlagValue("enabled_fixed_ro_exported", false);
+                    enabledRoExported = reader.getBooleanFlagValue("enabled_ro_exported", false);
+                } catch (Exception e) {
+                    // pass
+                    Log.e(TAG, e.toString());
+                } catch (LinkageError e) {
+                    // for mainline module running on older devices.
+                    // This should be replaces to version check, after the version bump.
+                    Log.w(TAG, e.toString());
+                }
+                isCached = true;
+            }
+            @Override
+            public boolean disabledRwExported() {
+                if (!isCached) {
+                    init();
+                }
+                return disabledRwExported;
+            }
+            @Override
+            public boolean enabledFixedRoExported() {
+                if (!isCached) {
+                    init();
+                }
+                return enabledFixedRoExported;
+            }
+            @Override
+            public boolean enabledRoExported() {
+                if (!isCached) {
+                    init();
+                }
+                return enabledRoExported;
+            }
+        }"#;
+
+        let expect_custom_feature_flags_content = r#"
+        package com.android.aconfig.test;
+
+        import java.util.Arrays;
+        import java.util.HashSet;
+        import java.util.List;
+        import java.util.Set;
+        import java.util.function.BiPredicate;
+        import java.util.function.Predicate;
+
+        /** @hide */
+        public class CustomFeatureFlags implements FeatureFlags {
+
+            private BiPredicate<String, Predicate<FeatureFlags>> mGetValueImpl;
+
+            public CustomFeatureFlags(BiPredicate<String, Predicate<FeatureFlags>> getValueImpl) {
+                mGetValueImpl = getValueImpl;
+            }
+
+            @Override
+            public boolean disabledRwExported() {
+                return getValue(Flags.FLAG_DISABLED_RW_EXPORTED,
+                    FeatureFlags::disabledRwExported);
+            }
+            @Override
+            public boolean enabledFixedRoExported() {
+                return getValue(Flags.FLAG_ENABLED_FIXED_RO_EXPORTED,
+                    FeatureFlags::enabledFixedRoExported);
+            }
+            @Override
+            public boolean enabledRoExported() {
+                return getValue(Flags.FLAG_ENABLED_RO_EXPORTED,
+                    FeatureFlags::enabledRoExported);
+            }
+
+            protected boolean getValue(String flagName, Predicate<FeatureFlags> getter) {
+                return mGetValueImpl.test(flagName, getter);
+            }
+
+            public List<String> getFlagNames() {
+                return Arrays.asList(
+                    Flags.FLAG_DISABLED_RW_EXPORTED,
+                    Flags.FLAG_ENABLED_FIXED_RO_EXPORTED,
+                    Flags.FLAG_ENABLED_RO_EXPORTED
+                );
+            }
+
+            private Set<String> mReadOnlyFlagsSet = new HashSet<>(
+                Arrays.asList(
+                    ""
+                )
+            );
+        }
+    "#;
+
+        let mut file_set = HashMap::from([
+            ("com/android/aconfig/test/Flags.java", expect_flags_content),
+            ("com/android/aconfig/test/FeatureFlags.java", expect_feature_flags_content),
+            ("com/android/aconfig/test/FeatureFlagsImpl.java", expect_feature_flags_impl_content),
+            (
+                "com/android/aconfig/test/CustomFeatureFlags.java",
+                expect_custom_feature_flags_content,
+            ),
+            (
+                "com/android/aconfig/test/FakeFeatureFlagsImpl.java",
+                EXPECTED_FAKEFEATUREFLAGSIMPL_CONTENT,
+            ),
+        ]);
+
+        for file in generated_files {
+            let file_path = file.path.to_str().unwrap();
+            assert!(file_set.contains_key(file_path), "Cannot find {}", file_path);
+            assert_eq!(
+                None,
+                crate::test::first_significant_code_diff(
+                    file_set.get(file_path).unwrap(),
+                    &String::from_utf8(file.contents).unwrap()
+                ),
+                "File {} content is not correct",
+                file_path
+            );
+            file_set.remove(file_path);
+        }
+
+        assert!(file_set.is_empty());
+    }
+
+    #[test]
     fn test_generate_java_code_test() {
         let parsed_flags = crate::test::parse_test_flags();
         let mode = CodegenMode::Test;
@@ -1170,7 +1394,7 @@
             package_fingerprint: 5801144784618221668,
             new_exported: false,
             single_exported_file: false,
-            check_api_level: false,
+            finalized_flags: FinalizedFlagMap::new(),
         };
         let generated_files = generate_java_code(
             crate::test::TEST_PACKAGE,
@@ -1298,7 +1522,7 @@
             package_fingerprint: 5801144784618221668,
             new_exported: false,
             single_exported_file: false,
-            check_api_level: false,
+            finalized_flags: FinalizedFlagMap::new(),
         };
         let generated_files = generate_java_code(
             crate::test::TEST_PACKAGE,
@@ -1570,6 +1794,109 @@
     }
 
     #[test]
+    fn test_generate_java_code_exported_flags() {
+        let parsed_flags = crate::test::parse_test_flags();
+        let mode = CodegenMode::Exported;
+        let modified_parsed_flags =
+            crate::commands::modify_parsed_flags_based_on_mode(parsed_flags, mode).unwrap();
+        let flag_ids =
+            assign_flag_ids(crate::test::TEST_PACKAGE, modified_parsed_flags.iter()).unwrap();
+        let mut finalized_flags = FinalizedFlagMap::new();
+        finalized_flags.insert_if_new(
+            ApiLevel(36),
+            FinalizedFlag {
+                flag_name: "disabled_rw_exported".to_string(),
+                package_name: "com.android.aconfig.test".to_string(),
+            },
+        );
+        let config = JavaCodegenConfig {
+            codegen_mode: mode,
+            flag_ids,
+            allow_instrumentation: true,
+            package_fingerprint: 5801144784618221668,
+            new_exported: true,
+            single_exported_file: true,
+            finalized_flags,
+        };
+        let generated_files = generate_java_code(
+            crate::test::TEST_PACKAGE,
+            modified_parsed_flags.into_iter(),
+            config,
+        )
+        .unwrap();
+
+        let expect_exported_flags_content = r#"
+        package com.android.aconfig.test;
+
+        import android.os.Build;
+        import android.os.flagging.AconfigPackage;
+        import android.util.Log;
+        public final class ExportedFlags {
+
+            public static final String FLAG_DISABLED_RW_EXPORTED = "com.android.aconfig.test.disabled_rw_exported";
+            public static final String FLAG_ENABLED_FIXED_RO_EXPORTED = "com.android.aconfig.test.enabled_fixed_ro_exported";
+            public static final String FLAG_ENABLED_RO_EXPORTED = "com.android.aconfig.test.enabled_ro_exported";
+            private static final String TAG = "ExportedFlags";
+            private static volatile boolean isCached = false;
+
+            private static boolean disabledRwExported = false;
+            private static boolean enabledFixedRoExported = false;
+            private static boolean enabledRoExported = false;
+            private ExportedFlags() {}
+
+            private void init() {
+                try {
+                    AconfigPackage reader = AconfigPackage.load("com.android.aconfig.test");
+                    disabledRwExported = reader.getBooleanFlagValue("disabled_rw_exported", false);
+                    enabledFixedRoExported = reader.getBooleanFlagValue("enabled_fixed_ro_exported", false);
+                    enabledRoExported = reader.getBooleanFlagValue("enabled_ro_exported", false);
+                } catch (Exception e) {
+                    // pass
+                    Log.e(TAG, e.toString());
+                } catch (LinkageError e) {
+                    // for mainline module running on older devices.
+                    // This should be replaces to version check, after the version bump.
+                    Log.w(TAG, e.toString());
+                }
+                isCached = true;
+            }
+            public static boolean disabledRwExported() {
+                if (Build.VERSION.SDK_INT >= 36) {
+                  return true;
+                }
+
+                if (!featureFlags.isCached) {
+                    featureFlags.init();
+                }
+                return featureFlags.disabledRwExported;
+            }
+            public static boolean enabledFixedRoExported() {
+                if (!featureFlags.isCached) {
+                    featureFlags.init();
+                }
+                return featureFlags.enabledFixedRoExported;
+            }
+            public static boolean enabledRoExported() {
+                if (!featureFlags.isCached) {
+                    featureFlags.init();
+                }
+                return featureFlags.enabledRoExported;
+            }
+            private static ExportedFlags featureFlags = new ExportedFlags();
+        }"#;
+
+        let file = generated_files.iter().find(|f| f.path.ends_with("ExportedFlags.java")).unwrap();
+        assert_eq!(
+            None,
+            crate::test::first_significant_code_diff(
+                expect_exported_flags_content,
+                &String::from_utf8(file.contents.clone()).unwrap()
+            ),
+            "ExportedFlags content is not correct"
+        );
+    }
+
+    #[test]
     fn test_format_java_method_name() {
         let expected = "someSnakeName";
         let input = "____some_snake___name____";
diff --git a/tools/aconfig/aconfig/src/commands.rs b/tools/aconfig/aconfig/src/commands.rs
index ea63c7a..0c80d3b 100644
--- a/tools/aconfig/aconfig/src/commands.rs
+++ b/tools/aconfig/aconfig/src/commands.rs
@@ -15,6 +15,7 @@
  */
 
 use anyhow::{bail, ensure, Context, Result};
+use convert_finalized_flags::FinalizedFlagMap;
 use itertools::Itertools;
 use protobuf::Message;
 use std::collections::HashMap;
@@ -220,7 +221,7 @@
     allow_instrumentation: bool,
     new_exported: bool,
     single_exported_file: bool,
-    check_api_level: bool,
+    finalized_flags: FinalizedFlagMap,
 ) -> Result<Vec<OutputFile>> {
     let parsed_flags = input.try_parse_flags()?;
     let modified_parsed_flags =
@@ -239,7 +240,7 @@
         package_fingerprint,
         new_exported,
         single_exported_file,
-        check_api_level,
+        finalized_flags,
     };
     generate_java_code(&package, modified_parsed_flags.into_iter(), config)
 }
diff --git a/tools/aconfig/aconfig/src/main.rs b/tools/aconfig/aconfig/src/main.rs
index 16b8272..6b29423 100644
--- a/tools/aconfig/aconfig/src/main.rs
+++ b/tools/aconfig/aconfig/src/main.rs
@@ -33,6 +33,7 @@
 
 use aconfig_storage_file::StorageFileType;
 use codegen::CodegenMode;
+use convert_finalized_flags::FinalizedFlagMap;
 use dump::DumpFormat;
 
 #[cfg(test)]
@@ -348,6 +349,12 @@
     Ok(())
 }
 
+fn load_finalized_flags() -> Result<FinalizedFlagMap> {
+    let json_str = include_str!(concat!(env!("OUT_DIR"), "/finalized_flags_record.json"));
+    let map = serde_json::from_str(json_str)?;
+    Ok(map)
+}
+
 fn main() -> Result<()> {
     let matches = cli().get_matches();
     match matches.subcommand() {
@@ -383,14 +390,18 @@
             let new_exported = get_required_arg::<bool>(sub_matches, "new-exported")?;
             let single_exported_file =
                 get_required_arg::<bool>(sub_matches, "single-exported-file")?;
+
             let check_api_level = get_required_arg::<bool>(sub_matches, "check-api-level")?;
+            let finalized_flags: FinalizedFlagMap =
+                if *check_api_level { load_finalized_flags()? } else { FinalizedFlagMap::new() };
+
             let generated_files = commands::create_java_lib(
                 cache,
                 *mode,
                 *allow_instrumentation,
                 *new_exported,
                 *single_exported_file,
-                *check_api_level,
+                finalized_flags,
             )
             .context("failed to create java lib")?;
             let dir = PathBuf::from(get_required_arg::<String>(sub_matches, "out")?);
diff --git a/tools/aconfig/aconfig/templates/ExportedFlags.java.template b/tools/aconfig/aconfig/templates/ExportedFlags.java.template
index 4e36942..176da18 100644
--- a/tools/aconfig/aconfig/templates/ExportedFlags.java.template
+++ b/tools/aconfig/aconfig/templates/ExportedFlags.java.template
@@ -19,11 +19,8 @@
             AconfigPackage reader = AconfigPackage.load("{package_name}");
             {{ -for namespace_with_flags in namespace_flags }}
             {{ -for flag in namespace_with_flags.flags }}
-            {{ -if flag.finalized_sdk_present }}
-            {flag.method_name} = Build.VERSION.SDK_INT >= {flag.finalized_sdk_value} ? true : reader.getBooleanFlagValue("{flag.flag_name}", {flag.default_value});
-            {{ - else }} {#- else finalized_sdk_present #}
             {flag.method_name} = reader.getBooleanFlagValue("{flag.flag_name}", {flag.default_value});
-            {{ -endif}}  {#- end finalized_sdk_present#}
+
             {{ -endfor }} {#- end namespace_with_flags.flags #}
             {{ -endfor }} {#- end namespace_flags #}
         } catch (Exception e) \{
@@ -39,6 +36,11 @@
 
 {{ -for flag in flag_elements }}
     public static boolean {flag.method_name}() \{
+        {{ -if flag.finalized_sdk_present }}
+        if (Build.VERSION.SDK_INT >= {flag.finalized_sdk_value}) \{
+          return true;
+        }
+        {{ -endif}}  {#- end finalized_sdk_present#}
         if (!featureFlags.isCached) \{
             featureFlags.init();
         }
diff --git a/tools/aconfig/aconfig/templates/Flags.java.template b/tools/aconfig/aconfig/templates/Flags.java.template
index 8a92d33..6fa2701 100644
--- a/tools/aconfig/aconfig/templates/Flags.java.template
+++ b/tools/aconfig/aconfig/templates/Flags.java.template
@@ -2,6 +2,8 @@
 {{ if not library_exported- }}
 // TODO(b/303773055): Remove the annotation after access issue is resolved.
 import android.compat.annotation.UnsupportedAppUsage;
+{{ else }}
+import android.os.Build;
 {{ -endif }}
 {{ -if single_exported_file }}
 {{ -if library_exported }}
@@ -31,6 +33,11 @@
     @UnsupportedAppUsage
 {{ -endif }}
     public static boolean {item.method_name}() \{
+        {{ -if item.finalized_sdk_present }}
+        if (Build.VERSION.SDK_INT >= {item.finalized_sdk_value}) \{
+          return true;
+        }
+        {{ -endif}}  {#- end finalized_sdk_present#}
         return FEATURE_FLAGS.{item.method_name}();
     }
 {{ -endfor }}
diff --git a/tools/aconfig/aconfig_storage_file/srcs/android/aconfig/storage/ByteBufferReader.java b/tools/aconfig/aconfig_storage_file/srcs/android/aconfig/storage/ByteBufferReader.java
index 1fbcb85..14fc468 100644
--- a/tools/aconfig/aconfig_storage_file/srcs/android/aconfig/storage/ByteBufferReader.java
+++ b/tools/aconfig/aconfig_storage_file/srcs/android/aconfig/storage/ByteBufferReader.java
@@ -19,10 +19,12 @@
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
 import java.nio.charset.StandardCharsets;
+import java.util.Objects;
 
 public class ByteBufferReader {
 
     private ByteBuffer mByteBuffer;
+    private int mPosition;
 
     public ByteBufferReader(ByteBuffer byteBuffer) {
         this.mByteBuffer = byteBuffer;
@@ -30,19 +32,19 @@
     }
 
     public int readByte() {
-        return Byte.toUnsignedInt(mByteBuffer.get());
+        return Byte.toUnsignedInt(mByteBuffer.get(nextGetIndex(1)));
     }
 
     public int readShort() {
-        return Short.toUnsignedInt(mByteBuffer.getShort());
+        return Short.toUnsignedInt(mByteBuffer.getShort(nextGetIndex(2)));
     }
 
     public int readInt() {
-        return this.mByteBuffer.getInt();
+        return this.mByteBuffer.getInt(nextGetIndex(4));
     }
 
     public long readLong() {
-        return this.mByteBuffer.getLong();
+        return this.mByteBuffer.getLong(nextGetIndex(8));
     }
 
     public String readString() {
@@ -52,7 +54,7 @@
                     "String length exceeds maximum allowed size (1024 bytes): " + length);
         }
         byte[] bytes = new byte[length];
-        mByteBuffer.get(bytes, 0, length);
+        getArray(nextGetIndex(length), bytes, 0, length);
         return new String(bytes, StandardCharsets.UTF_8);
     }
 
@@ -61,10 +63,26 @@
     }
 
     public void position(int newPosition) {
-        mByteBuffer.position(newPosition);
+        mPosition = newPosition;
     }
 
     public int position() {
-        return mByteBuffer.position();
+        return mPosition;
+    }
+
+    private int nextGetIndex(int nb) {
+        int p = mPosition;
+        mPosition += nb;
+        return p;
+    }
+
+    private void getArray(int index, byte[] dst, int offset, int length) {
+        Objects.checkFromIndexSize(index, length, mByteBuffer.limit());
+        Objects.checkFromIndexSize(offset, length, dst.length);
+
+        int end = offset + length;
+        for (int i = offset, j = index; i < end; i++, j++) {
+            dst[i] = mByteBuffer.get(j);
+        }
     }
 }
diff --git a/tools/aconfig/aconfig_storage_file/srcs/android/aconfig/storage/FlagTable.java b/tools/aconfig/aconfig_storage_file/srcs/android/aconfig/storage/FlagTable.java
index 757844a..ee60b18 100644
--- a/tools/aconfig/aconfig_storage_file/srcs/android/aconfig/storage/FlagTable.java
+++ b/tools/aconfig/aconfig_storage_file/srcs/android/aconfig/storage/FlagTable.java
@@ -24,12 +24,12 @@
 public class FlagTable {
 
     private Header mHeader;
-    private ByteBufferReader mReader;
+    private ByteBuffer mBuffer;
 
     public static FlagTable fromBytes(ByteBuffer bytes) {
         FlagTable flagTable = new FlagTable();
-        flagTable.mReader = new ByteBufferReader(bytes);
-        flagTable.mHeader = Header.fromBytes(flagTable.mReader);
+        flagTable.mBuffer = bytes;
+        flagTable.mHeader = Header.fromBytes(new ByteBufferReader(bytes));
 
         return flagTable;
     }
@@ -41,16 +41,16 @@
         if (newPosition >= mHeader.mNodeOffset) {
             return null;
         }
-
-        mReader.position(newPosition);
-        int nodeIndex = mReader.readInt();
+        ByteBufferReader reader = new ByteBufferReader(mBuffer) ;
+        reader.position(newPosition);
+        int nodeIndex = reader.readInt();
         if (nodeIndex < mHeader.mNodeOffset || nodeIndex >= mHeader.mFileSize) {
             return null;
         }
 
         while (nodeIndex != -1) {
-            mReader.position(nodeIndex);
-            Node node = Node.fromBytes(mReader);
+            reader.position(nodeIndex);
+            Node node = Node.fromBytes(reader);
             if (Objects.equals(flagName, node.mFlagName) && packageId == node.mPackageId) {
                 return node;
             }
diff --git a/tools/aconfig/aconfig_storage_file/srcs/android/aconfig/storage/PackageTable.java b/tools/aconfig/aconfig_storage_file/srcs/android/aconfig/storage/PackageTable.java
index 1e7c2ca..215616e 100644
--- a/tools/aconfig/aconfig_storage_file/srcs/android/aconfig/storage/PackageTable.java
+++ b/tools/aconfig/aconfig_storage_file/srcs/android/aconfig/storage/PackageTable.java
@@ -30,12 +30,12 @@
     private static final int NODE_SKIP_BYTES = 12;
 
     private Header mHeader;
-    private ByteBufferReader mReader;
+    private ByteBuffer mBuffer;
 
     public static PackageTable fromBytes(ByteBuffer bytes) {
         PackageTable packageTable = new PackageTable();
-        packageTable.mReader = new ByteBufferReader(bytes);
-        packageTable.mHeader = Header.fromBytes(packageTable.mReader);
+        packageTable.mBuffer = bytes;
+        packageTable.mHeader = Header.fromBytes(new ByteBufferReader(bytes));
 
         return packageTable;
     }
@@ -47,16 +47,17 @@
         if (newPosition >= mHeader.mNodeOffset) {
             return null;
         }
-        mReader.position(newPosition);
-        int nodeIndex = mReader.readInt();
+        ByteBufferReader reader = new ByteBufferReader(mBuffer);
+        reader.position(newPosition);
+        int nodeIndex = reader.readInt();
 
         if (nodeIndex < mHeader.mNodeOffset || nodeIndex >= mHeader.mFileSize) {
             return null;
         }
 
         while (nodeIndex != -1) {
-            mReader.position(nodeIndex);
-            Node node = Node.fromBytes(mReader, mHeader.mVersion);
+            reader.position(nodeIndex);
+            Node node = Node.fromBytes(reader, mHeader.mVersion);
             if (Objects.equals(packageName, node.mPackageName)) {
                 return node;
             }
@@ -68,12 +69,13 @@
 
     public List<String> getPackageList() {
         List<String> list = new ArrayList<>(mHeader.mNumPackages);
-        mReader.position(mHeader.mNodeOffset);
+        ByteBufferReader reader = new ByteBufferReader(mBuffer);
+        reader.position(mHeader.mNodeOffset);
         int fingerprintBytes = mHeader.mVersion == 1 ? 0 : FINGERPRINT_BYTES;
         int skipBytes = fingerprintBytes + NODE_SKIP_BYTES;
         for (int i = 0; i < mHeader.mNumPackages; i++) {
-            list.add(mReader.readString());
-            mReader.position(mReader.position() + skipBytes);
+            list.add(reader.readString());
+            reader.position(reader.position() + skipBytes);
         }
         return list;
     }
diff --git a/tools/aconfig/aconfig_storage_file/tests/srcs/PackageTableTest.java b/tools/aconfig/aconfig_storage_file/tests/srcs/PackageTableTest.java
index 812ce35..4b68e5b 100644
--- a/tools/aconfig/aconfig_storage_file/tests/srcs/PackageTableTest.java
+++ b/tools/aconfig/aconfig_storage_file/tests/srcs/PackageTableTest.java
@@ -28,7 +28,9 @@
 import org.junit.runners.JUnit4;
 
 import java.util.HashSet;
+import java.util.Objects;
 import java.util.Set;
+import java.util.concurrent.CyclicBarrier;
 
 @RunWith(JUnit4.class)
 public class PackageTableTest {
@@ -142,4 +144,46 @@
         assertTrue(packages.contains("com.android.aconfig.storage.test_2"));
         assertTrue(packages.contains("com.android.aconfig.storage.test_4"));
     }
+
+    @Test
+    public void testPackageTable_multithreadsRead() throws Exception {
+        PackageTable packageTable =
+                PackageTable.fromBytes(TestDataUtils.getTestPackageMapByteBuffer(2));
+        int numberOfThreads = 3;
+        Thread[] threads = new Thread[numberOfThreads];
+        final CyclicBarrier gate = new CyclicBarrier(numberOfThreads + 1);
+        String[] expects = {
+            "com.android.aconfig.storage.test_1",
+            "com.android.aconfig.storage.test_2",
+            "com.android.aconfig.storage.test_4"
+        };
+
+        for (int i = 0; i < numberOfThreads; i++) {
+            final String packageName = expects[i];
+            threads[i] =
+                    new Thread() {
+                        @Override
+                        public void run() {
+                            try {
+                                gate.await();
+                            } catch (Exception e) {
+                            }
+                            for (int j = 0; j < 10; j++) {
+                                if (!Objects.equals(
+                                        packageName,
+                                        packageTable.get(packageName).getPackageName())) {
+                                    throw new RuntimeException();
+                                }
+                            }
+                        }
+                    };
+            threads[i].start();
+        }
+
+        gate.await();
+
+        for (int i = 0; i < numberOfThreads; i++) {
+            threads[i].join();
+        }
+    }
 }
diff --git a/tools/aconfig/convert_finalized_flags/Android.bp b/tools/aconfig/convert_finalized_flags/Android.bp
new file mode 100644
index 0000000..5b39560
--- /dev/null
+++ b/tools/aconfig/convert_finalized_flags/Android.bp
@@ -0,0 +1,56 @@
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+rust_defaults {
+    name: "convert_finalized_flags.defaults",
+    edition: "2021",
+    clippy_lints: "android",
+    lints: "android",
+    rustlibs: [
+        "libanyhow",
+        "libclap",
+        "libitertools",
+        "libprotobuf",
+        "libserde",
+        "libserde_json",
+        "libtempfile",
+        "libtinytemplate",
+    ],
+}
+
+rust_library_host {
+    name: "libconvert_finalized_flags",
+    crate_name: "convert_finalized_flags",
+    defaults: ["convert_finalized_flags.defaults"],
+    srcs: [
+        "src/lib.rs",
+    ],
+}
+
+rust_binary_host {
+    name: "convert_finalized_flags",
+    defaults: ["convert_finalized_flags.defaults"],
+    srcs: ["src/main.rs"],
+    rustlibs: [
+        "libconvert_finalized_flags",
+        "libserde_json",
+    ],
+}
+
+rust_test_host {
+    name: "convert_finalized_flags.test",
+    defaults: ["convert_finalized_flags.defaults"],
+    test_suites: ["general-tests"],
+    srcs: ["src/lib.rs"],
+}
+
+genrule {
+    name: "finalized_flags_record.json",
+    srcs: [
+        "//prebuilts/sdk:finalized-api-flags",
+    ],
+    out: ["finalized_flags_record.json"],
+    tools: ["convert_finalized_flags"],
+    cmd: "args=\"\" && for f in $(locations //prebuilts/sdk:finalized-api-flags); do args=\"$$args --flag_file_path $$f\"; done && $(location convert_finalized_flags) $$args > $(out)",
+}
diff --git a/tools/aconfig/convert_finalized_flags/Cargo.toml b/tools/aconfig/convert_finalized_flags/Cargo.toml
new file mode 100644
index 0000000..e34e030
--- /dev/null
+++ b/tools/aconfig/convert_finalized_flags/Cargo.toml
@@ -0,0 +1,15 @@
+[package]
+name = "convert_finalized_flags"
+version = "0.1.0"
+edition = "2021"
+
+[features]
+default = ["cargo"]
+cargo = []
+
+[dependencies]
+anyhow = "1.0.69"
+clap = { version = "4.1.8", features = ["derive"] }
+serde = { version = "1.0.152", features = ["derive"] }
+serde_json = "1.0.93"
+tempfile = "3.13.0"
diff --git a/tools/aconfig/convert_finalized_flags/src/lib.rs b/tools/aconfig/convert_finalized_flags/src/lib.rs
new file mode 100644
index 0000000..10faa39
--- /dev/null
+++ b/tools/aconfig/convert_finalized_flags/src/lib.rs
@@ -0,0 +1,395 @@
+/*
+* Copyright (C) 2025 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.
+*/
+//! Functions to extract finalized flag information from
+//! /prebuilts/sdk/#/finalized-flags.txt.
+//! These functions are very specific to that file setup as well as the format
+//! of the files (just a list of the fully-qualified flag names).
+//! There are also some helper functions for local building using cargo. These
+//! functions are only invoked via cargo for quick local testing and will not
+//! be used during actual soong building. They are marked as such.
+use anyhow::{anyhow, Result};
+use serde::{Deserialize, Serialize};
+use std::collections::{HashMap, HashSet};
+use std::fs;
+use std::io::{self, BufRead};
+
+/// Just the fully qualified flag name (package_name.flag_name).
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)]
+pub struct FinalizedFlag {
+    /// Name of the flag.
+    pub flag_name: String,
+    /// Name of the package.
+    pub package_name: String,
+}
+
+/// API level in which the flag was finalized.
+#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)]
+pub struct ApiLevel(pub i32);
+
+/// Contains all flags finalized for a given API level.
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Default)]
+pub struct FinalizedFlagMap(HashMap<ApiLevel, HashSet<FinalizedFlag>>);
+
+impl FinalizedFlagMap {
+    /// Creates a new, empty instance.
+    pub fn new() -> Self {
+        Self(HashMap::new())
+    }
+
+    /// Convenience method for is_empty on the underlying map.
+    pub fn is_empty(&self) -> bool {
+        self.0.is_empty()
+    }
+
+    /// Returns the API level in which the flag was finalized .
+    pub fn get_finalized_level(&self, flag: &FinalizedFlag) -> Option<ApiLevel> {
+        for (api_level, flags_for_level) in &self.0 {
+            if flags_for_level.contains(flag) {
+                return Some(*api_level);
+            }
+        }
+        None
+    }
+
+    /// Insert the flag into the map for the given level if the flag is not
+    /// present in the map already - for *any* level (not just the one given).
+    pub fn insert_if_new(&mut self, level: ApiLevel, flag: FinalizedFlag) {
+        if self.contains(&flag) {
+            return;
+        }
+        self.0.entry(level).or_default().insert(flag);
+    }
+
+    fn contains(&self, flag: &FinalizedFlag) -> bool {
+        self.0.values().any(|flags_set| flags_set.contains(flag))
+    }
+}
+
+/// Converts a string to an int. Will parse to int even if the string is "X.0".
+/// Returns error for "X.1".
+fn str_to_api_level(numeric_string: &str) -> Result<ApiLevel> {
+    let float_value = numeric_string.parse::<f64>()?;
+
+    if float_value.fract() == 0.0 {
+        Ok(ApiLevel(float_value as i32))
+    } else {
+        Err(anyhow!("Numeric string is float, can't parse to int."))
+    }
+}
+
+/// For each file, extracts the qualified flag names into a FinalizedFlag, then
+/// enters them in a map at the API level corresponding to their directory.
+/// Ex: /prebuilts/sdk/35/finalized-flags.txt -> {36, [flag1, flag2]}.
+pub fn read_files_to_map_using_path(flag_files: Vec<String>) -> Result<FinalizedFlagMap> {
+    let mut data_map = FinalizedFlagMap::new();
+
+    for flag_file in flag_files {
+        // Split /path/sdk/<int.int>/finalized-flags.txt -> ['/path/sdk', 'int.int', 'finalized-flags.txt'].
+        let flag_file_split: Vec<String> =
+            flag_file.clone().rsplitn(3, '/').map(|s| s.to_string()).collect();
+
+        if &flag_file_split[0] != "finalized-flags.txt" {
+            return Err(anyhow!("Provided incorrect file, must be finalized-flags.txt"));
+        }
+
+        let api_level_string = &flag_file_split[1];
+
+        // For now, skip any directory with full API level, e.g. "36.1". The
+        // finalized flag files each contain all flags finalized *up to* that
+        // level (including prior levels), so skipping intermediate levels means
+        // the flags will be included at the next full number.
+        // TODO: b/378936061 - Support full SDK version.
+        // In the future, we should error if provided a non-numeric directory.
+        let Ok(api_level) = str_to_api_level(api_level_string) else {
+            continue;
+        };
+
+        let file = fs::File::open(flag_file)?;
+        let reader = io::BufReader::new(file);
+
+        for qualified_flag_name in reader.lines() {
+            // Split the qualified flag name into package and flag name:
+            // com.my.package.name.my_flag_name -> ['com.my.package.name', 'my_flag_name'].
+            let mut flag: Vec<String> =
+                qualified_flag_name?.rsplitn(2, '.').map(|s| s.to_string()).collect();
+
+            if flag.len() != 2 {
+                continue;
+            }
+
+            let package_name = flag.pop().ok_or(anyhow!("Missing flag package."))?;
+            let flag_name = flag.pop().ok_or(anyhow!("Missing flag name."))?;
+
+            // Only add the flag if it wasn't added in a prior file.
+            data_map.insert_if_new(api_level, FinalizedFlag { flag_name, package_name });
+        }
+    }
+
+    Ok(data_map)
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use std::fs::File;
+    use std::io::Write;
+    use tempfile::tempdir;
+
+    const FLAG_FILE_NAME: &str = "finalized-flags.txt";
+
+    // Creates some flags for testing.
+    fn create_test_flags() -> Vec<FinalizedFlag> {
+        vec![
+            FinalizedFlag { flag_name: "name1".to_string(), package_name: "package1".to_string() },
+            FinalizedFlag { flag_name: "name2".to_string(), package_name: "package2".to_string() },
+            FinalizedFlag { flag_name: "name3".to_string(), package_name: "package3".to_string() },
+        ]
+    }
+
+    // Writes the fully qualified flag names in the given file.
+    fn add_flags_to_file(flag_file: &mut File, flags: &[FinalizedFlag]) {
+        for flag in flags {
+            let _unused = writeln!(flag_file, "{}.{}", flag.package_name, flag.flag_name);
+        }
+    }
+
+    #[test]
+    fn test_read_flags_one_file() {
+        let flags = create_test_flags();
+
+        // Create the file <temp_dir>/35/finalized-flags.txt.
+        let temp_dir = tempdir().unwrap();
+        let mut file_path = temp_dir.path().to_path_buf();
+        file_path.push("35");
+        fs::create_dir_all(&file_path).unwrap();
+        file_path.push(FLAG_FILE_NAME);
+        let mut file = File::create(&file_path).unwrap();
+
+        // Write all flags to the file.
+        add_flags_to_file(&mut file, &[flags[0].clone(), flags[1].clone()]);
+        let flag_file_path = file_path.to_string_lossy().to_string();
+
+        // Convert to map.
+        let map = read_files_to_map_using_path(vec![flag_file_path]).unwrap();
+
+        assert_eq!(map.0.len(), 1);
+        assert!(map.0.get(&ApiLevel(35)).unwrap().contains(&flags[0]));
+        assert!(map.0.get(&ApiLevel(35)).unwrap().contains(&flags[1]));
+    }
+
+    #[test]
+    fn test_read_flags_two_files() {
+        let flags = create_test_flags();
+
+        // Create the file <temp_dir>/35/finalized-flags.txt and for 36.
+        let temp_dir = tempdir().unwrap();
+        let mut file_path1 = temp_dir.path().to_path_buf();
+        file_path1.push("35");
+        fs::create_dir_all(&file_path1).unwrap();
+        file_path1.push(FLAG_FILE_NAME);
+        let mut file1 = File::create(&file_path1).unwrap();
+
+        let mut file_path2 = temp_dir.path().to_path_buf();
+        file_path2.push("36");
+        fs::create_dir_all(&file_path2).unwrap();
+        file_path2.push(FLAG_FILE_NAME);
+        let mut file2 = File::create(&file_path2).unwrap();
+
+        // Write all flags to the files.
+        add_flags_to_file(&mut file1, &[flags[0].clone()]);
+        add_flags_to_file(&mut file2, &[flags[0].clone(), flags[1].clone(), flags[2].clone()]);
+        let flag_file_path1 = file_path1.to_string_lossy().to_string();
+        let flag_file_path2 = file_path2.to_string_lossy().to_string();
+
+        // Convert to map.
+        let map = read_files_to_map_using_path(vec![flag_file_path1, flag_file_path2]).unwrap();
+
+        // Assert there are two API levels, 35 and 36.
+        assert_eq!(map.0.len(), 2);
+        assert!(map.0.get(&ApiLevel(35)).unwrap().contains(&flags[0]));
+
+        // 36 should not have the first flag in the set, as it was finalized in
+        // an earlier API level.
+        assert!(map.0.get(&ApiLevel(36)).unwrap().contains(&flags[1]));
+        assert!(map.0.get(&ApiLevel(36)).unwrap().contains(&flags[2]));
+    }
+
+    #[test]
+    fn test_read_flags_full_numbers() {
+        let flags = create_test_flags();
+
+        // Create the file <temp_dir>/35/finalized-flags.txt and for 36.
+        let temp_dir = tempdir().unwrap();
+        let mut file_path1 = temp_dir.path().to_path_buf();
+        file_path1.push("35.0");
+        fs::create_dir_all(&file_path1).unwrap();
+        file_path1.push(FLAG_FILE_NAME);
+        let mut file1 = File::create(&file_path1).unwrap();
+
+        let mut file_path2 = temp_dir.path().to_path_buf();
+        file_path2.push("36.0");
+        fs::create_dir_all(&file_path2).unwrap();
+        file_path2.push(FLAG_FILE_NAME);
+        let mut file2 = File::create(&file_path2).unwrap();
+
+        // Write all flags to the files.
+        add_flags_to_file(&mut file1, &[flags[0].clone()]);
+        add_flags_to_file(&mut file2, &[flags[0].clone(), flags[1].clone(), flags[2].clone()]);
+        let flag_file_path1 = file_path1.to_string_lossy().to_string();
+        let flag_file_path2 = file_path2.to_string_lossy().to_string();
+
+        // Convert to map.
+        let map = read_files_to_map_using_path(vec![flag_file_path1, flag_file_path2]).unwrap();
+
+        assert_eq!(map.0.len(), 2);
+        assert!(map.0.get(&ApiLevel(35)).unwrap().contains(&flags[0]));
+        assert!(map.0.get(&ApiLevel(36)).unwrap().contains(&flags[1]));
+        assert!(map.0.get(&ApiLevel(36)).unwrap().contains(&flags[2]));
+    }
+
+    #[test]
+    fn test_read_flags_fractions_round_up() {
+        let flags = create_test_flags();
+
+        // Create the file <temp_dir>/35/finalized-flags.txt and for 36.
+        let temp_dir = tempdir().unwrap();
+        let mut file_path1 = temp_dir.path().to_path_buf();
+        file_path1.push("35.1");
+        fs::create_dir_all(&file_path1).unwrap();
+        file_path1.push(FLAG_FILE_NAME);
+        let mut file1 = File::create(&file_path1).unwrap();
+
+        let mut file_path2 = temp_dir.path().to_path_buf();
+        file_path2.push("36.0");
+        fs::create_dir_all(&file_path2).unwrap();
+        file_path2.push(FLAG_FILE_NAME);
+        let mut file2 = File::create(&file_path2).unwrap();
+
+        // Write all flags to the files.
+        add_flags_to_file(&mut file1, &[flags[0].clone()]);
+        add_flags_to_file(&mut file2, &[flags[0].clone(), flags[1].clone(), flags[2].clone()]);
+        let flag_file_path1 = file_path1.to_string_lossy().to_string();
+        let flag_file_path2 = file_path2.to_string_lossy().to_string();
+
+        // Convert to map.
+        let map = read_files_to_map_using_path(vec![flag_file_path1, flag_file_path2]).unwrap();
+
+        // No flags were added in 35. All 35.1 flags were rolled up to 36.
+        assert_eq!(map.0.len(), 1);
+        assert!(!map.0.contains_key(&ApiLevel(35)));
+        assert!(map.0.get(&ApiLevel(36)).unwrap().contains(&flags[0]));
+        assert!(map.0.get(&ApiLevel(36)).unwrap().contains(&flags[1]));
+        assert!(map.0.get(&ApiLevel(36)).unwrap().contains(&flags[2]));
+    }
+
+    #[test]
+    fn test_read_flags_non_numeric() {
+        let flags = create_test_flags();
+
+        // Create the file <temp_dir>/35/finalized-flags.txt.
+        let temp_dir = tempdir().unwrap();
+        let mut file_path = temp_dir.path().to_path_buf();
+        file_path.push("35");
+        fs::create_dir_all(&file_path).unwrap();
+        file_path.push(FLAG_FILE_NAME);
+        let mut flag_file = File::create(&file_path).unwrap();
+
+        let mut invalid_path = temp_dir.path().to_path_buf();
+        invalid_path.push("sdk-annotations");
+        fs::create_dir_all(&invalid_path).unwrap();
+        invalid_path.push(FLAG_FILE_NAME);
+        File::create(&invalid_path).unwrap();
+
+        // Write all flags to the file.
+        add_flags_to_file(&mut flag_file, &[flags[0].clone(), flags[1].clone()]);
+        let flag_file_path = file_path.to_string_lossy().to_string();
+
+        // Convert to map.
+        let map = read_files_to_map_using_path(vec![
+            flag_file_path,
+            invalid_path.to_string_lossy().to_string(),
+        ])
+        .unwrap();
+
+        // No set should be created for sdk-annotations.
+        assert_eq!(map.0.len(), 1);
+        assert!(map.0.get(&ApiLevel(35)).unwrap().contains(&flags[0]));
+        assert!(map.0.get(&ApiLevel(35)).unwrap().contains(&flags[1]));
+    }
+
+    #[test]
+    fn test_read_flags_wrong_file_err() {
+        let flags = create_test_flags();
+
+        // Create the file <temp_dir>/35/finalized-flags.txt.
+        let temp_dir = tempdir().unwrap();
+        let mut file_path = temp_dir.path().to_path_buf();
+        file_path.push("35");
+        fs::create_dir_all(&file_path).unwrap();
+        file_path.push(FLAG_FILE_NAME);
+        let mut flag_file = File::create(&file_path).unwrap();
+
+        let mut pre_flag_path = temp_dir.path().to_path_buf();
+        pre_flag_path.push("18");
+        fs::create_dir_all(&pre_flag_path).unwrap();
+        pre_flag_path.push("some_random_file.txt");
+        File::create(&pre_flag_path).unwrap();
+
+        // Write all flags to the file.
+        add_flags_to_file(&mut flag_file, &[flags[0].clone(), flags[1].clone()]);
+        let flag_file_path = file_path.to_string_lossy().to_string();
+
+        // Convert to map.
+        let map = read_files_to_map_using_path(vec![
+            flag_file_path,
+            pre_flag_path.to_string_lossy().to_string(),
+        ]);
+
+        assert!(map.is_err());
+    }
+
+    #[test]
+    fn test_flags_map_insert_if_new() {
+        let flags = create_test_flags();
+        let mut map = FinalizedFlagMap::new();
+        let l35 = ApiLevel(35);
+        let l36 = ApiLevel(36);
+
+        map.insert_if_new(l35, flags[0].clone());
+        map.insert_if_new(l35, flags[1].clone());
+        map.insert_if_new(l35, flags[2].clone());
+        map.insert_if_new(l36, flags[0].clone());
+
+        assert!(map.0.get(&l35).unwrap().contains(&flags[0]));
+        assert!(map.0.get(&l35).unwrap().contains(&flags[1]));
+        assert!(map.0.get(&l35).unwrap().contains(&flags[2]));
+        assert!(!map.0.contains_key(&l36));
+    }
+
+    #[test]
+    fn test_flags_map_get_level() {
+        let flags = create_test_flags();
+        let mut map = FinalizedFlagMap::new();
+        let l35 = ApiLevel(35);
+        let l36 = ApiLevel(36);
+
+        map.insert_if_new(l35, flags[0].clone());
+        map.insert_if_new(l36, flags[1].clone());
+
+        assert_eq!(map.get_finalized_level(&flags[0]).unwrap(), l35);
+        assert_eq!(map.get_finalized_level(&flags[1]).unwrap(), l36);
+    }
+}
diff --git a/tools/aconfig/convert_finalized_flags/src/main.rs b/tools/aconfig/convert_finalized_flags/src/main.rs
new file mode 100644
index 0000000..38300f6
--- /dev/null
+++ b/tools/aconfig/convert_finalized_flags/src/main.rs
@@ -0,0 +1,57 @@
+/*
+* Copyright (C) 2025 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.
+*/
+//! convert_finalized_flags is a build time tool used to convert the finalized
+//! flags text files under prebuilts/sdk into structured data (FinalizedFlag
+//! struct).
+//! This binary is intended to run as part of a genrule to create a json file
+//! which is provided to the aconfig binary that creates the codegen.
+//! Usage:
+//! cargo run -- --flag-files-path path/to/prebuilts/sdk/finalized-flags.txt file2.txt etc
+use anyhow::Result;
+use clap::Parser;
+
+use convert_finalized_flags::read_files_to_map_using_path;
+
+const ABOUT_TEXT: &str = "Tool for processing finalized-flags.txt files.
+
+These files contain the list of qualified flag names that have been finalized,
+each on a newline. The directory of the flag file is the finalized API level.
+
+The output is a json map of API level to set of FinalizedFlag objects. The only
+supported use case for this tool is via a genrule at build time for aconfig
+codegen.
+
+Args:
+* `flag-files-path`: Space-separated list of absolute paths for the finalized
+flags files.
+";
+
+#[derive(Parser, Debug)]
+#[clap(long_about=ABOUT_TEXT, bin_name="convert-finalized-flags")]
+struct Cli {
+    /// Flags files.
+    #[arg(long = "flag_file_path")]
+    flag_file_path: Vec<String>,
+}
+
+fn main() -> Result<()> {
+    let cli = Cli::parse();
+    let finalized_flags_map = read_files_to_map_using_path(cli.flag_file_path)?;
+
+    let json_str = serde_json::to_string(&finalized_flags_map)?;
+    println!("{}", json_str);
+    Ok(())
+}
diff --git a/tools/compliance/Android.bp b/tools/compliance/Android.bp
index ef5c760..2527df7 100644
--- a/tools/compliance/Android.bp
+++ b/tools/compliance/Android.bp
@@ -131,22 +131,6 @@
     testSrcs: ["cmd/xmlnotice/xmlnotice_test.go"],
 }
 
-blueprint_go_binary {
-    name: "compliance_sbom",
-    srcs: ["cmd/sbom/sbom.go"],
-    deps: [
-        "compliance-module",
-        "blueprint-deptools",
-        "soong-response",
-        "spdx-tools-spdxv2_2",
-        "spdx-tools-builder2v2",
-        "spdx-tools-spdxcommon",
-        "spdx-tools-spdx-json",
-        "spdx-tools-spdxlib",
-    ],
-    testSrcs: ["cmd/sbom/sbom_test.go"],
-}
-
 bootstrap_go_package {
     name: "compliance-module",
     srcs: [
diff --git a/tools/compliance/cmd/sbom/sbom.go b/tools/compliance/cmd/sbom/sbom.go
deleted file mode 100644
index a53741f..0000000
--- a/tools/compliance/cmd/sbom/sbom.go
+++ /dev/null
@@ -1,547 +0,0 @@
-// Copyright 2022 Google LLC
-//
-// 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.
-
-package main
-
-import (
-	"bytes"
-	"crypto/sha1"
-	"encoding/hex"
-	"flag"
-	"fmt"
-	"io"
-	"io/fs"
-	"os"
-	"path/filepath"
-	"sort"
-	"strings"
-	"time"
-
-	"android/soong/response"
-	"android/soong/tools/compliance"
-	"android/soong/tools/compliance/projectmetadata"
-
-	"github.com/google/blueprint/deptools"
-
-	"github.com/spdx/tools-golang/builder/builder2v2"
-	spdx_json "github.com/spdx/tools-golang/json"
-	"github.com/spdx/tools-golang/spdx/common"
-	spdx "github.com/spdx/tools-golang/spdx/v2_2"
-	"github.com/spdx/tools-golang/spdxlib"
-)
-
-var (
-	failNoneRequested = fmt.Errorf("\nNo license metadata files requested")
-	failNoLicenses    = fmt.Errorf("No licenses found")
-)
-
-const NOASSERTION = "NOASSERTION"
-
-type context struct {
-	stdout       io.Writer
-	stderr       io.Writer
-	rootFS       fs.FS
-	product      string
-	stripPrefix  []string
-	creationTime creationTimeGetter
-	buildid      string
-}
-
-func (ctx context) strip(installPath string) string {
-	for _, prefix := range ctx.stripPrefix {
-		if strings.HasPrefix(installPath, prefix) {
-			p := strings.TrimPrefix(installPath, prefix)
-			if 0 == len(p) {
-				p = ctx.product
-			}
-			if 0 == len(p) {
-				continue
-			}
-			return p
-		}
-	}
-	return installPath
-}
-
-// newMultiString creates a flag that allows multiple values in an array.
-func newMultiString(flags *flag.FlagSet, name, usage string) *multiString {
-	var f multiString
-	flags.Var(&f, name, usage)
-	return &f
-}
-
-// multiString implements the flag `Value` interface for multiple strings.
-type multiString []string
-
-func (ms *multiString) String() string     { return strings.Join(*ms, ", ") }
-func (ms *multiString) Set(s string) error { *ms = append(*ms, s); return nil }
-
-func main() {
-	var expandedArgs []string
-	for _, arg := range os.Args[1:] {
-		if strings.HasPrefix(arg, "@") {
-			f, err := os.Open(strings.TrimPrefix(arg, "@"))
-			if err != nil {
-				fmt.Fprintln(os.Stderr, err.Error())
-				os.Exit(1)
-			}
-
-			respArgs, err := response.ReadRspFile(f)
-			f.Close()
-			if err != nil {
-				fmt.Fprintln(os.Stderr, err.Error())
-				os.Exit(1)
-			}
-			expandedArgs = append(expandedArgs, respArgs...)
-		} else {
-			expandedArgs = append(expandedArgs, arg)
-		}
-	}
-
-	flags := flag.NewFlagSet("flags", flag.ExitOnError)
-
-	flags.Usage = func() {
-		fmt.Fprintf(os.Stderr, `Usage: %s {options} file.meta_lic {file.meta_lic...}
-
-Outputs an SBOM.spdx.
-
-Options:
-`, filepath.Base(os.Args[0]))
-		flags.PrintDefaults()
-	}
-
-	outputFile := flags.String("o", "-", "Where to write the SBOM spdx file. (default stdout)")
-	depsFile := flags.String("d", "", "Where to write the deps file")
-	product := flags.String("product", "", "The name of the product for which the notice is generated.")
-	stripPrefix := newMultiString(flags, "strip_prefix", "Prefix to remove from paths. i.e. path to root (multiple allowed)")
-	buildid := flags.String("build_id", "", "Uniquely identifies the build. (default timestamp)")
-
-	flags.Parse(expandedArgs)
-
-	// Must specify at least one root target.
-	if flags.NArg() == 0 {
-		flags.Usage()
-		os.Exit(2)
-	}
-
-	if len(*outputFile) == 0 {
-		flags.Usage()
-		fmt.Fprintf(os.Stderr, "must specify file for -o; use - for stdout\n")
-		os.Exit(2)
-	} else {
-		dir, err := filepath.Abs(filepath.Dir(*outputFile))
-		if err != nil {
-			fmt.Fprintf(os.Stderr, "cannot determine path to %q: %s\n", *outputFile, err)
-			os.Exit(1)
-		}
-		fi, err := os.Stat(dir)
-		if err != nil {
-			fmt.Fprintf(os.Stderr, "cannot read directory %q of %q: %s\n", dir, *outputFile, err)
-			os.Exit(1)
-		}
-		if !fi.IsDir() {
-			fmt.Fprintf(os.Stderr, "parent %q of %q is not a directory\n", dir, *outputFile)
-			os.Exit(1)
-		}
-	}
-
-	var ofile io.Writer
-	ofile = os.Stdout
-	var obuf *bytes.Buffer
-	if *outputFile != "-" {
-		obuf = &bytes.Buffer{}
-		ofile = obuf
-	}
-
-	ctx := &context{ofile, os.Stderr, compliance.FS, *product, *stripPrefix, actualTime, *buildid}
-
-	spdxDoc, deps, err := sbomGenerator(ctx, flags.Args()...)
-
-	if err != nil {
-		if err == failNoneRequested {
-			flags.Usage()
-		}
-		fmt.Fprintf(os.Stderr, "%s\n", err.Error())
-		os.Exit(1)
-	}
-
-	// writing the spdx Doc created
-	if err := spdx_json.Save2_2(spdxDoc, ofile); err != nil {
-		fmt.Fprintf(os.Stderr, "failed to write document to %v: %v", *outputFile, err)
-		os.Exit(1)
-	}
-
-	if *outputFile != "-" {
-		err := os.WriteFile(*outputFile, obuf.Bytes(), 0666)
-		if err != nil {
-			fmt.Fprintf(os.Stderr, "could not write output to %q: %s\n", *outputFile, err)
-			os.Exit(1)
-		}
-	}
-
-	if *depsFile != "" {
-		err := deptools.WriteDepFile(*depsFile, *outputFile, deps)
-		if err != nil {
-			fmt.Fprintf(os.Stderr, "could not write deps to %q: %s\n", *depsFile, err)
-			os.Exit(1)
-		}
-	}
-	os.Exit(0)
-}
-
-type creationTimeGetter func() string
-
-// actualTime returns current time in UTC
-func actualTime() string {
-	t := time.Now().UTC()
-	return t.UTC().Format("2006-01-02T15:04:05Z")
-}
-
-// replaceSlashes replaces "/" by "-" for the library path to be used for packages & files SPDXID
-func replaceSlashes(x string) string {
-	return strings.ReplaceAll(x, "/", "-")
-}
-
-// stripDocName removes the outdir prefix and meta_lic suffix from a target Name
-func stripDocName(name string) string {
-	// remove outdir prefix
-	if strings.HasPrefix(name, "out/") {
-		name = name[4:]
-	}
-
-	// remove suffix
-	if strings.HasSuffix(name, ".meta_lic") {
-		name = name[:len(name)-9]
-	} else if strings.HasSuffix(name, "/meta_lic") {
-		name = name[:len(name)-9] + "/"
-	}
-
-	return name
-}
-
-// getPackageName returns a package name of a target Node
-func getPackageName(_ *context, tn *compliance.TargetNode) string {
-	return replaceSlashes(tn.Name())
-}
-
-// getDocumentName returns a package name of a target Node
-func getDocumentName(ctx *context, tn *compliance.TargetNode, pm *projectmetadata.ProjectMetadata) string {
-	if len(ctx.product) > 0 {
-		return replaceSlashes(ctx.product)
-	}
-	if len(tn.ModuleName()) > 0 {
-		if pm != nil {
-			return replaceSlashes(pm.Name() + ":" + tn.ModuleName())
-		}
-		return replaceSlashes(tn.ModuleName())
-	}
-
-	return stripDocName(replaceSlashes(tn.Name()))
-}
-
-// getDownloadUrl returns the download URL if available (GIT, SVN, etc..),
-// or NOASSERTION if not available, none determined or ambiguous
-func getDownloadUrl(_ *context, pm *projectmetadata.ProjectMetadata) string {
-	if pm == nil {
-		return NOASSERTION
-	}
-
-	urlsByTypeName := pm.UrlsByTypeName()
-	if urlsByTypeName == nil {
-		return NOASSERTION
-	}
-
-	url := urlsByTypeName.DownloadUrl()
-	if url == "" {
-		return NOASSERTION
-	}
-	return url
-}
-
-// getProjectMetadata returns the optimal project metadata for the target node
-func getProjectMetadata(_ *context, pmix *projectmetadata.Index,
-	tn *compliance.TargetNode) (*projectmetadata.ProjectMetadata, error) {
-	pms, err := pmix.MetadataForProjects(tn.Projects()...)
-	if err != nil {
-		return nil, fmt.Errorf("Unable to read projects for %q: %w\n", tn.Name(), err)
-	}
-	if len(pms) == 0 {
-		return nil, nil
-	}
-
-	// Getting the project metadata that contains most of the info needed for sbomGenerator
-	score := -1
-	index := -1
-	for i := 0; i < len(pms); i++ {
-		tempScore := 0
-		if pms[i].Name() != "" {
-			tempScore += 1
-		}
-		if pms[i].Version() != "" {
-			tempScore += 1
-		}
-		if pms[i].UrlsByTypeName().DownloadUrl() != "" {
-			tempScore += 1
-		}
-
-		if tempScore == score {
-			if pms[i].Project() < pms[index].Project() {
-				index = i
-			}
-		} else if tempScore > score {
-			score = tempScore
-			index = i
-		}
-	}
-	return pms[index], nil
-}
-
-// inputFiles returns the complete list of files read
-func inputFiles(lg *compliance.LicenseGraph, pmix *projectmetadata.Index, licenseTexts []string) []string {
-	projectMeta := pmix.AllMetadataFiles()
-	targets := lg.TargetNames()
-	files := make([]string, 0, len(licenseTexts)+len(targets)+len(projectMeta))
-	files = append(files, licenseTexts...)
-	files = append(files, targets...)
-	files = append(files, projectMeta...)
-	return files
-}
-
-// generateSPDXNamespace generates a unique SPDX Document Namespace using a SHA1 checksum
-func generateSPDXNamespace(buildid string, created string, files ...string) string {
-
-	seed := strings.Join(files, "")
-
-	if buildid == "" {
-		seed += created
-	} else {
-		seed += buildid
-	}
-
-	// Compute a SHA1 checksum of the seed.
-	hash := sha1.Sum([]byte(seed))
-	uuid := hex.EncodeToString(hash[:])
-
-	namespace := fmt.Sprintf("SPDXRef-DOCUMENT-%s", uuid)
-
-	return namespace
-}
-
-// sbomGenerator implements the spdx bom utility
-
-// SBOM is part of the new government regulation issued to improve national cyber security
-// and enhance software supply chain and transparency, see https://www.cisa.gov/sbom
-
-// sbomGenerator uses the SPDX standard, see the SPDX specification (https://spdx.github.io/spdx-spec/)
-// sbomGenerator is also following the internal google SBOM styleguide (http://goto.google.com/spdx-style-guide)
-func sbomGenerator(ctx *context, files ...string) (*spdx.Document, []string, error) {
-	// Must be at least one root file.
-	if len(files) < 1 {
-		return nil, nil, failNoneRequested
-	}
-
-	pmix := projectmetadata.NewIndex(ctx.rootFS)
-
-	lg, err := compliance.ReadLicenseGraph(ctx.rootFS, ctx.stderr, files)
-
-	if err != nil {
-		return nil, nil, fmt.Errorf("Unable to read license text file(s) for %q: %v\n", files, err)
-	}
-
-	// creating the packages section
-	pkgs := []*spdx.Package{}
-
-	// creating the relationship section
-	relationships := []*spdx.Relationship{}
-
-	// creating the license section
-	otherLicenses := []*spdx.OtherLicense{}
-
-	// spdx document name
-	var docName string
-
-	// main package name
-	var mainPkgName string
-
-	// implementing the licenses references for the packages
-	licenses := make(map[string]string)
-	concludedLicenses := func(licenseTexts []string) string {
-		licenseRefs := make([]string, 0, len(licenseTexts))
-		for _, licenseText := range licenseTexts {
-			license := strings.SplitN(licenseText, ":", 2)[0]
-			if _, ok := licenses[license]; !ok {
-				licenseRef := "LicenseRef-" + replaceSlashes(license)
-				licenses[license] = licenseRef
-			}
-
-			licenseRefs = append(licenseRefs, licenses[license])
-		}
-		if len(licenseRefs) > 1 {
-			return "(" + strings.Join(licenseRefs, " AND ") + ")"
-		} else if len(licenseRefs) == 1 {
-			return licenseRefs[0]
-		}
-		return "NONE"
-	}
-
-	isMainPackage := true
-	visitedNodes := make(map[*compliance.TargetNode]struct{})
-
-	// performing a Breadth-first top down walk of licensegraph and building package information
-	compliance.WalkTopDownBreadthFirst(nil, lg,
-		func(lg *compliance.LicenseGraph, tn *compliance.TargetNode, path compliance.TargetEdgePath) bool {
-			if err != nil {
-				return false
-			}
-			var pm *projectmetadata.ProjectMetadata
-			pm, err = getProjectMetadata(ctx, pmix, tn)
-			if err != nil {
-				return false
-			}
-
-			if isMainPackage {
-				docName = getDocumentName(ctx, tn, pm)
-				mainPkgName = replaceSlashes(getPackageName(ctx, tn))
-				isMainPackage = false
-			}
-
-			if len(path) == 0 {
-				// Add the describe relationship for the main package
-				rln := &spdx.Relationship{
-					RefA:         common.MakeDocElementID("" /* this document */, "DOCUMENT"),
-					RefB:         common.MakeDocElementID("", mainPkgName),
-					Relationship: "DESCRIBES",
-				}
-				relationships = append(relationships, rln)
-
-			} else {
-				// Check parent and identify annotation
-				parent := path[len(path)-1]
-				targetEdge := parent.Edge()
-				if targetEdge.IsRuntimeDependency() {
-					// Adding the dynamic link annotation RUNTIME_DEPENDENCY_OF relationship
-					rln := &spdx.Relationship{
-						RefA:         common.MakeDocElementID("", replaceSlashes(getPackageName(ctx, tn))),
-						RefB:         common.MakeDocElementID("", replaceSlashes(getPackageName(ctx, targetEdge.Target()))),
-						Relationship: "RUNTIME_DEPENDENCY_OF",
-					}
-					relationships = append(relationships, rln)
-
-				} else if targetEdge.IsDerivation() {
-					// Adding the  derivation annotation as a CONTAINS relationship
-					rln := &spdx.Relationship{
-						RefA:         common.MakeDocElementID("", replaceSlashes(getPackageName(ctx, targetEdge.Target()))),
-						RefB:         common.MakeDocElementID("", replaceSlashes(getPackageName(ctx, tn))),
-						Relationship: "CONTAINS",
-					}
-					relationships = append(relationships, rln)
-
-				} else if targetEdge.IsBuildTool() {
-					// Adding the toolchain annotation as a BUILD_TOOL_OF relationship
-					rln := &spdx.Relationship{
-						RefA:         common.MakeDocElementID("", replaceSlashes(getPackageName(ctx, tn))),
-						RefB:         common.MakeDocElementID("", replaceSlashes(getPackageName(ctx, targetEdge.Target()))),
-						Relationship: "BUILD_TOOL_OF",
-					}
-					relationships = append(relationships, rln)
-
-				} else {
-					panic(fmt.Errorf("Unknown dependency type: %v", targetEdge.Annotations()))
-				}
-			}
-
-			if _, alreadyVisited := visitedNodes[tn]; alreadyVisited {
-				return false
-			}
-			visitedNodes[tn] = struct{}{}
-			pkgName := getPackageName(ctx, tn)
-
-			// Making an spdx package and adding it to pkgs
-			pkg := &spdx.Package{
-				PackageName:             replaceSlashes(pkgName),
-				PackageDownloadLocation: getDownloadUrl(ctx, pm),
-				PackageSPDXIdentifier:   common.ElementID(replaceSlashes(pkgName)),
-				PackageLicenseConcluded: concludedLicenses(tn.LicenseTexts()),
-			}
-
-			if pm != nil && pm.Version() != "" {
-				pkg.PackageVersion = pm.Version()
-			} else {
-				pkg.PackageVersion = NOASSERTION
-			}
-
-			pkgs = append(pkgs, pkg)
-
-			return true
-		})
-
-	// Adding Non-standard licenses
-
-	licenseTexts := make([]string, 0, len(licenses))
-
-	for licenseText := range licenses {
-		licenseTexts = append(licenseTexts, licenseText)
-	}
-
-	sort.Strings(licenseTexts)
-
-	for _, licenseText := range licenseTexts {
-		// open the file
-		f, err := ctx.rootFS.Open(filepath.Clean(licenseText))
-		if err != nil {
-			return nil, nil, fmt.Errorf("error opening license text file %q: %w", licenseText, err)
-		}
-
-		// read the file
-		text, err := io.ReadAll(f)
-		if err != nil {
-			return nil, nil, fmt.Errorf("error reading license text file %q: %w", licenseText, err)
-		}
-		// Making an spdx License and adding it to otherLicenses
-		otherLicenses = append(otherLicenses, &spdx.OtherLicense{
-			LicenseName:       strings.Replace(licenses[licenseText], "LicenseRef-", "", -1),
-			LicenseIdentifier: string(licenses[licenseText]),
-			ExtractedText:     string(text),
-		})
-	}
-
-	deps := inputFiles(lg, pmix, licenseTexts)
-	sort.Strings(deps)
-
-	// Making the SPDX doc
-	ci, err := builder2v2.BuildCreationInfoSection2_2("Organization", "Google LLC", nil)
-	if err != nil {
-		return nil, nil, fmt.Errorf("Unable to build creation info section for SPDX doc: %v\n", err)
-	}
-
-	ci.Created = ctx.creationTime()
-
-	doc := &spdx.Document{
-		SPDXVersion:       "SPDX-2.2",
-		DataLicense:       "CC0-1.0",
-		SPDXIdentifier:    "DOCUMENT",
-		DocumentName:      docName,
-		DocumentNamespace: generateSPDXNamespace(ctx.buildid, ci.Created, files...),
-		CreationInfo:      ci,
-		Packages:          pkgs,
-		Relationships:     relationships,
-		OtherLicenses:     otherLicenses,
-	}
-
-	if err := spdxlib.ValidateDocument2_2(doc); err != nil {
-		return nil, nil, fmt.Errorf("Unable to validate the SPDX doc: %v\n", err)
-	}
-
-	return doc, deps, nil
-}
diff --git a/tools/compliance/cmd/sbom/sbom_test.go b/tools/compliance/cmd/sbom/sbom_test.go
deleted file mode 100644
index 13ba66d..0000000
--- a/tools/compliance/cmd/sbom/sbom_test.go
+++ /dev/null
@@ -1,2558 +0,0 @@
-// Copyright 2022 Google LLC
-//
-// 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.
-
-package main
-
-import (
-	"bytes"
-	"encoding/json"
-	"fmt"
-	"os"
-	"reflect"
-	"strings"
-	"testing"
-	"time"
-
-	"android/soong/tools/compliance"
-
-	"github.com/spdx/tools-golang/builder/builder2v2"
-	"github.com/spdx/tools-golang/spdx/common"
-	spdx "github.com/spdx/tools-golang/spdx/v2_2"
-)
-
-func TestMain(m *testing.M) {
-	// Change into the parent directory before running the tests
-	// so they can find the testdata directory.
-	if err := os.Chdir(".."); err != nil {
-		fmt.Printf("failed to change to testdata directory: %s\n", err)
-		os.Exit(1)
-	}
-	os.Exit(m.Run())
-}
-
-func Test(t *testing.T) {
-	tests := []struct {
-		condition    string
-		name         string
-		outDir       string
-		roots        []string
-		stripPrefix  string
-		expectedOut  *spdx.Document
-		expectedDeps []string
-	}{
-		{
-			condition: "firstparty",
-			name:      "apex",
-			roots:     []string{"highest.apex.meta_lic"},
-			expectedOut: &spdx.Document{
-				SPDXVersion:       "SPDX-2.2",
-				DataLicense:       "CC0-1.0",
-				SPDXIdentifier:    "DOCUMENT",
-				DocumentName:      "testdata-firstparty-highest.apex",
-				DocumentNamespace: generateSPDXNamespace("", "1970-01-01T00:00:00Z", "testdata/firstparty/highest.apex.meta_lic"),
-				CreationInfo:      getCreationInfo(t),
-				Packages: []*spdx.Package{
-					{
-						PackageName:             "testdata-firstparty-highest.apex.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-firstparty-highest.apex.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-firstparty-FIRST_PARTY_LICENSE",
-					},
-					{
-						PackageName:             "testdata-firstparty-bin-bin1.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-firstparty-bin-bin1.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-firstparty-FIRST_PARTY_LICENSE",
-					},
-					{
-						PackageName:             "testdata-firstparty-bin-bin2.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-firstparty-bin-bin2.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-firstparty-FIRST_PARTY_LICENSE",
-					},
-					{
-						PackageName:             "testdata-firstparty-lib-liba.so.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-firstparty-lib-liba.so.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-firstparty-FIRST_PARTY_LICENSE",
-					},
-					{
-						PackageName:             "testdata-firstparty-lib-libb.so.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-firstparty-lib-libb.so.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-firstparty-FIRST_PARTY_LICENSE",
-					},
-					{
-						PackageName:             "testdata-firstparty-lib-libc.a.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-firstparty-lib-libc.a.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-firstparty-FIRST_PARTY_LICENSE",
-					},
-					{
-						PackageName:             "testdata-firstparty-lib-libd.so.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-firstparty-lib-libd.so.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-firstparty-FIRST_PARTY_LICENSE",
-					},
-				},
-				Relationships: []*spdx.Relationship{
-					{
-						RefA:         common.MakeDocElementID("", "DOCUMENT"),
-						RefB:         common.MakeDocElementID("", "testdata-firstparty-highest.apex.meta_lic"),
-						Relationship: "DESCRIBES",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-firstparty-highest.apex.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-firstparty-bin-bin1.meta_lic"),
-						Relationship: "CONTAINS",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-firstparty-highest.apex.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-firstparty-bin-bin2.meta_lic"),
-						Relationship: "CONTAINS",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-firstparty-highest.apex.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-firstparty-lib-liba.so.meta_lic"),
-						Relationship: "CONTAINS",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-firstparty-highest.apex.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-firstparty-lib-libb.so.meta_lic"),
-						Relationship: "CONTAINS",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-firstparty-bin-bin1.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-firstparty-lib-liba.so.meta_lic"),
-						Relationship: "CONTAINS",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-firstparty-bin-bin1.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-firstparty-lib-libc.a.meta_lic"),
-						Relationship: "CONTAINS",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-firstparty-lib-libb.so.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-firstparty-bin-bin2.meta_lic"),
-						Relationship: "RUNTIME_DEPENDENCY_OF",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-firstparty-lib-libd.so.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-firstparty-bin-bin2.meta_lic"),
-						Relationship: "RUNTIME_DEPENDENCY_OF",
-					},
-				},
-				OtherLicenses: []*spdx.OtherLicense{
-					{
-						LicenseIdentifier: "LicenseRef-testdata-firstparty-FIRST_PARTY_LICENSE",
-						ExtractedText:     "&&&First Party License&&&\n",
-						LicenseName:       "testdata-firstparty-FIRST_PARTY_LICENSE",
-					},
-				},
-			},
-			expectedDeps: []string{
-				"testdata/firstparty/FIRST_PARTY_LICENSE",
-				"testdata/firstparty/bin/bin1.meta_lic",
-				"testdata/firstparty/bin/bin2.meta_lic",
-				"testdata/firstparty/highest.apex.meta_lic",
-				"testdata/firstparty/lib/liba.so.meta_lic",
-				"testdata/firstparty/lib/libb.so.meta_lic",
-				"testdata/firstparty/lib/libc.a.meta_lic",
-				"testdata/firstparty/lib/libd.so.meta_lic",
-			},
-		},
-		{
-			condition: "firstparty",
-			name:      "application",
-			roots:     []string{"application.meta_lic"},
-			expectedOut: &spdx.Document{
-				SPDXVersion:       "SPDX-2.2",
-				DataLicense:       "CC0-1.0",
-				SPDXIdentifier:    "DOCUMENT",
-				DocumentName:      "testdata-firstparty-application",
-				DocumentNamespace: generateSPDXNamespace("", "1970-01-01T00:00:00Z", "testdata/firstparty/application.meta_lic"),
-				CreationInfo:      getCreationInfo(t),
-				Packages: []*spdx.Package{
-					{
-						PackageName:             "testdata-firstparty-application.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-firstparty-application.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-firstparty-FIRST_PARTY_LICENSE",
-					},
-					{
-						PackageName:             "testdata-firstparty-bin-bin3.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-firstparty-bin-bin3.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-firstparty-FIRST_PARTY_LICENSE",
-					},
-					{
-						PackageName:             "testdata-firstparty-lib-liba.so.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-firstparty-lib-liba.so.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-firstparty-FIRST_PARTY_LICENSE",
-					},
-					{
-						PackageName:             "testdata-firstparty-lib-libb.so.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-firstparty-lib-libb.so.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-firstparty-FIRST_PARTY_LICENSE",
-					},
-				},
-				Relationships: []*spdx.Relationship{
-					{
-						RefA:         common.MakeDocElementID("", "DOCUMENT"),
-						RefB:         common.MakeDocElementID("", "testdata-firstparty-application.meta_lic"),
-						Relationship: "DESCRIBES",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-firstparty-bin-bin3.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-firstparty-application.meta_lic"),
-						Relationship: "BUILD_TOOL_OF",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-firstparty-application.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-firstparty-lib-liba.so.meta_lic"),
-						Relationship: "CONTAINS",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-firstparty-lib-libb.so.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-firstparty-application.meta_lic"),
-						Relationship: "RUNTIME_DEPENDENCY_OF",
-					},
-				},
-				OtherLicenses: []*spdx.OtherLicense{
-					{
-						LicenseIdentifier: "LicenseRef-testdata-firstparty-FIRST_PARTY_LICENSE",
-						ExtractedText:     "&&&First Party License&&&\n",
-						LicenseName:       "testdata-firstparty-FIRST_PARTY_LICENSE",
-					},
-				},
-			},
-			expectedDeps: []string{
-				"testdata/firstparty/FIRST_PARTY_LICENSE",
-				"testdata/firstparty/application.meta_lic",
-				"testdata/firstparty/bin/bin3.meta_lic",
-				"testdata/firstparty/lib/liba.so.meta_lic",
-				"testdata/firstparty/lib/libb.so.meta_lic",
-			},
-		},
-		{
-			condition: "firstparty",
-			name:      "container",
-			roots:     []string{"container.zip.meta_lic"},
-			expectedOut: &spdx.Document{
-				SPDXVersion:       "SPDX-2.2",
-				DataLicense:       "CC0-1.0",
-				SPDXIdentifier:    "DOCUMENT",
-				DocumentName:      "testdata-firstparty-container.zip",
-				DocumentNamespace: generateSPDXNamespace("", "1970-01-01T00:00:00Z", "testdata/firstparty/container.zip.meta_lic"),
-				CreationInfo:      getCreationInfo(t),
-				Packages: []*spdx.Package{
-					{
-						PackageName:             "testdata-firstparty-container.zip.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-firstparty-container.zip.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-firstparty-FIRST_PARTY_LICENSE",
-					},
-					{
-						PackageName:             "testdata-firstparty-bin-bin1.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-firstparty-bin-bin1.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-firstparty-FIRST_PARTY_LICENSE",
-					},
-					{
-						PackageName:             "testdata-firstparty-bin-bin2.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-firstparty-bin-bin2.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-firstparty-FIRST_PARTY_LICENSE",
-					},
-					{
-						PackageName:             "testdata-firstparty-lib-liba.so.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-firstparty-lib-liba.so.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-firstparty-FIRST_PARTY_LICENSE",
-					},
-					{
-						PackageName:             "testdata-firstparty-lib-libb.so.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-firstparty-lib-libb.so.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-firstparty-FIRST_PARTY_LICENSE",
-					},
-					{
-						PackageName:             "testdata-firstparty-lib-libc.a.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-firstparty-lib-libc.a.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-firstparty-FIRST_PARTY_LICENSE",
-					},
-					{
-						PackageName:             "testdata-firstparty-lib-libd.so.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-firstparty-lib-libd.so.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-firstparty-FIRST_PARTY_LICENSE",
-					},
-				},
-				Relationships: []*spdx.Relationship{
-					{
-						RefA:         common.MakeDocElementID("", "DOCUMENT"),
-						RefB:         common.MakeDocElementID("", "testdata-firstparty-container.zip.meta_lic"),
-						Relationship: "DESCRIBES",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-firstparty-container.zip.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-firstparty-bin-bin1.meta_lic"),
-						Relationship: "CONTAINS",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-firstparty-container.zip.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-firstparty-bin-bin2.meta_lic"),
-						Relationship: "CONTAINS",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-firstparty-container.zip.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-firstparty-lib-liba.so.meta_lic"),
-						Relationship: "CONTAINS",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-firstparty-container.zip.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-firstparty-lib-libb.so.meta_lic"),
-						Relationship: "CONTAINS",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-firstparty-bin-bin1.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-firstparty-lib-liba.so.meta_lic"),
-						Relationship: "CONTAINS",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-firstparty-bin-bin1.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-firstparty-lib-libc.a.meta_lic"),
-						Relationship: "CONTAINS",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-firstparty-lib-libb.so.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-firstparty-bin-bin2.meta_lic"),
-						Relationship: "RUNTIME_DEPENDENCY_OF",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-firstparty-lib-libd.so.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-firstparty-bin-bin2.meta_lic"),
-						Relationship: "RUNTIME_DEPENDENCY_OF",
-					},
-				},
-				OtherLicenses: []*spdx.OtherLicense{
-					{
-						LicenseIdentifier: "LicenseRef-testdata-firstparty-FIRST_PARTY_LICENSE",
-						ExtractedText:     "&&&First Party License&&&\n",
-						LicenseName:       "testdata-firstparty-FIRST_PARTY_LICENSE",
-					},
-				},
-			},
-			expectedDeps: []string{
-				"testdata/firstparty/FIRST_PARTY_LICENSE",
-				"testdata/firstparty/bin/bin1.meta_lic",
-				"testdata/firstparty/bin/bin2.meta_lic",
-				"testdata/firstparty/container.zip.meta_lic",
-				"testdata/firstparty/lib/liba.so.meta_lic",
-				"testdata/firstparty/lib/libb.so.meta_lic",
-				"testdata/firstparty/lib/libc.a.meta_lic",
-				"testdata/firstparty/lib/libd.so.meta_lic",
-			},
-		},
-		{
-			condition: "firstparty",
-			name:      "binary",
-			roots:     []string{"bin/bin1.meta_lic"},
-			expectedOut: &spdx.Document{
-				SPDXVersion:       "SPDX-2.2",
-				DataLicense:       "CC0-1.0",
-				SPDXIdentifier:    "DOCUMENT",
-				DocumentName:      "testdata-firstparty-bin-bin1",
-				DocumentNamespace: generateSPDXNamespace("", "1970-01-01T00:00:00Z", "testdata/firstparty/bin/bin1.meta_lic"),
-				CreationInfo:      getCreationInfo(t),
-				Packages: []*spdx.Package{
-					{
-						PackageName:             "testdata-firstparty-bin-bin1.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-firstparty-bin-bin1.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-firstparty-FIRST_PARTY_LICENSE",
-					},
-					{
-						PackageName:             "testdata-firstparty-lib-liba.so.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-firstparty-lib-liba.so.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-firstparty-FIRST_PARTY_LICENSE",
-					},
-					{
-						PackageName:             "testdata-firstparty-lib-libc.a.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-firstparty-lib-libc.a.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-firstparty-FIRST_PARTY_LICENSE",
-					},
-				},
-				Relationships: []*spdx.Relationship{
-					{
-						RefA:         common.MakeDocElementID("", "DOCUMENT"),
-						RefB:         common.MakeDocElementID("", "testdata-firstparty-bin-bin1.meta_lic"),
-						Relationship: "DESCRIBES",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-firstparty-bin-bin1.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-firstparty-lib-liba.so.meta_lic"),
-						Relationship: "CONTAINS",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-firstparty-bin-bin1.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-firstparty-lib-libc.a.meta_lic"),
-						Relationship: "CONTAINS",
-					},
-				},
-				OtherLicenses: []*spdx.OtherLicense{
-					{
-						LicenseIdentifier: "LicenseRef-testdata-firstparty-FIRST_PARTY_LICENSE",
-						ExtractedText:     "&&&First Party License&&&\n",
-						LicenseName:       "testdata-firstparty-FIRST_PARTY_LICENSE",
-					},
-				},
-			},
-			expectedDeps: []string{
-				"testdata/firstparty/FIRST_PARTY_LICENSE",
-				"testdata/firstparty/bin/bin1.meta_lic",
-				"testdata/firstparty/lib/liba.so.meta_lic",
-				"testdata/firstparty/lib/libc.a.meta_lic",
-			},
-		},
-		{
-			condition: "firstparty",
-			name:      "library",
-			roots:     []string{"lib/libd.so.meta_lic"},
-			expectedOut: &spdx.Document{
-				SPDXVersion:       "SPDX-2.2",
-				DataLicense:       "CC0-1.0",
-				SPDXIdentifier:    "DOCUMENT",
-				DocumentName:      "testdata-firstparty-lib-libd.so",
-				DocumentNamespace: generateSPDXNamespace("", "1970-01-01T00:00:00Z", "testdata/firstparty/lib/libd.so.meta_lic"),
-				CreationInfo:      getCreationInfo(t),
-				Packages: []*spdx.Package{
-					{
-						PackageName:             "testdata-firstparty-lib-libd.so.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-firstparty-lib-libd.so.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-firstparty-FIRST_PARTY_LICENSE",
-					},
-				},
-				Relationships: []*spdx.Relationship{
-					{
-						RefA:         common.MakeDocElementID("", "DOCUMENT"),
-						RefB:         common.MakeDocElementID("", "testdata-firstparty-lib-libd.so.meta_lic"),
-						Relationship: "DESCRIBES",
-					},
-				},
-				OtherLicenses: []*spdx.OtherLicense{
-					{
-						LicenseIdentifier: "LicenseRef-testdata-firstparty-FIRST_PARTY_LICENSE",
-						ExtractedText:     "&&&First Party License&&&\n",
-						LicenseName:       "testdata-firstparty-FIRST_PARTY_LICENSE",
-					},
-				},
-			},
-			expectedDeps: []string{
-				"testdata/firstparty/FIRST_PARTY_LICENSE",
-				"testdata/firstparty/lib/libd.so.meta_lic",
-			},
-		},
-		{
-			condition: "notice",
-			name:      "apex",
-			roots:     []string{"highest.apex.meta_lic"},
-			expectedOut: &spdx.Document{
-				SPDXVersion:       "SPDX-2.2",
-				DataLicense:       "CC0-1.0",
-				SPDXIdentifier:    "DOCUMENT",
-				DocumentName:      "testdata-notice-highest.apex",
-				DocumentNamespace: generateSPDXNamespace("", "1970-01-01T00:00:00Z", "testdata/notice/highest.apex.meta_lic"),
-				CreationInfo:      getCreationInfo(t),
-				Packages: []*spdx.Package{
-					{
-						PackageName:             "testdata-notice-highest.apex.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-notice-highest.apex.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-firstparty-FIRST_PARTY_LICENSE",
-					},
-					{
-						PackageName:             "testdata-notice-bin-bin1.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-notice-bin-bin1.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-firstparty-FIRST_PARTY_LICENSE",
-					},
-					{
-						PackageName:             "testdata-notice-bin-bin2.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-notice-bin-bin2.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-firstparty-FIRST_PARTY_LICENSE",
-					},
-					{
-						PackageName:             "testdata-notice-lib-liba.so.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-notice-lib-liba.so.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-notice-NOTICE_LICENSE",
-					},
-					{
-						PackageName:             "testdata-notice-lib-libb.so.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-notice-lib-libb.so.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-firstparty-FIRST_PARTY_LICENSE",
-					},
-					{
-						PackageName:             "testdata-notice-lib-libc.a.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-notice-lib-libc.a.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-notice-NOTICE_LICENSE",
-					},
-					{
-						PackageName:             "testdata-notice-lib-libd.so.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-notice-lib-libd.so.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-notice-NOTICE_LICENSE",
-					},
-				},
-				Relationships: []*spdx.Relationship{
-					{
-						RefA:         common.MakeDocElementID("", "DOCUMENT"),
-						RefB:         common.MakeDocElementID("", "testdata-notice-highest.apex.meta_lic"),
-						Relationship: "DESCRIBES",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-notice-highest.apex.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-notice-bin-bin1.meta_lic"),
-						Relationship: "CONTAINS",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-notice-highest.apex.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-notice-bin-bin2.meta_lic"),
-						Relationship: "CONTAINS",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-notice-highest.apex.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-notice-lib-liba.so.meta_lic"),
-						Relationship: "CONTAINS",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-notice-highest.apex.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-notice-lib-libb.so.meta_lic"),
-						Relationship: "CONTAINS",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-notice-bin-bin1.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-notice-lib-liba.so.meta_lic"),
-						Relationship: "CONTAINS",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-notice-bin-bin1.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-notice-lib-libc.a.meta_lic"),
-						Relationship: "CONTAINS",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-notice-lib-libb.so.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-notice-bin-bin2.meta_lic"),
-						Relationship: "RUNTIME_DEPENDENCY_OF",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-notice-lib-libd.so.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-notice-bin-bin2.meta_lic"),
-						Relationship: "RUNTIME_DEPENDENCY_OF",
-					},
-				},
-				OtherLicenses: []*spdx.OtherLicense{
-					{
-						LicenseIdentifier: "LicenseRef-testdata-firstparty-FIRST_PARTY_LICENSE",
-						ExtractedText:     "&&&First Party License&&&\n",
-						LicenseName:       "testdata-firstparty-FIRST_PARTY_LICENSE",
-					},
-					{
-						LicenseIdentifier: "LicenseRef-testdata-notice-NOTICE_LICENSE",
-						ExtractedText:     "%%%Notice License%%%\n",
-						LicenseName:       "testdata-notice-NOTICE_LICENSE",
-					},
-				},
-			},
-			expectedDeps: []string{
-				"testdata/firstparty/FIRST_PARTY_LICENSE",
-				"testdata/notice/NOTICE_LICENSE",
-				"testdata/notice/bin/bin1.meta_lic",
-				"testdata/notice/bin/bin2.meta_lic",
-				"testdata/notice/highest.apex.meta_lic",
-				"testdata/notice/lib/liba.so.meta_lic",
-				"testdata/notice/lib/libb.so.meta_lic",
-				"testdata/notice/lib/libc.a.meta_lic",
-				"testdata/notice/lib/libd.so.meta_lic",
-			},
-		},
-		{
-			condition: "notice",
-			name:      "container",
-			roots:     []string{"container.zip.meta_lic"},
-			expectedOut: &spdx.Document{
-				SPDXVersion:       "SPDX-2.2",
-				DataLicense:       "CC0-1.0",
-				SPDXIdentifier:    "DOCUMENT",
-				DocumentName:      "testdata-notice-container.zip",
-				DocumentNamespace: generateSPDXNamespace("", "1970-01-01T00:00:00Z", "testdata/notice/container.zip.meta_lic"),
-				CreationInfo:      getCreationInfo(t),
-				Packages: []*spdx.Package{
-					{
-						PackageName:             "testdata-notice-container.zip.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-notice-container.zip.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-firstparty-FIRST_PARTY_LICENSE",
-					},
-					{
-						PackageName:             "testdata-notice-bin-bin1.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-notice-bin-bin1.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-firstparty-FIRST_PARTY_LICENSE",
-					},
-					{
-						PackageName:             "testdata-notice-bin-bin2.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-notice-bin-bin2.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-firstparty-FIRST_PARTY_LICENSE",
-					},
-					{
-						PackageName:             "testdata-notice-lib-liba.so.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-notice-lib-liba.so.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-notice-NOTICE_LICENSE",
-					},
-					{
-						PackageName:             "testdata-notice-lib-libb.so.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-notice-lib-libb.so.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-firstparty-FIRST_PARTY_LICENSE",
-					},
-					{
-						PackageName:             "testdata-notice-lib-libc.a.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-notice-lib-libc.a.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-notice-NOTICE_LICENSE",
-					},
-					{
-						PackageName:             "testdata-notice-lib-libd.so.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-notice-lib-libd.so.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-notice-NOTICE_LICENSE",
-					},
-				},
-				Relationships: []*spdx.Relationship{
-					{
-						RefA:         common.MakeDocElementID("", "DOCUMENT"),
-						RefB:         common.MakeDocElementID("", "testdata-notice-container.zip.meta_lic"),
-						Relationship: "DESCRIBES",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-notice-container.zip.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-notice-bin-bin1.meta_lic"),
-						Relationship: "CONTAINS",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-notice-container.zip.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-notice-bin-bin2.meta_lic"),
-						Relationship: "CONTAINS",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-notice-container.zip.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-notice-lib-liba.so.meta_lic"),
-						Relationship: "CONTAINS",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-notice-container.zip.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-notice-lib-libb.so.meta_lic"),
-						Relationship: "CONTAINS",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-notice-bin-bin1.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-notice-lib-liba.so.meta_lic"),
-						Relationship: "CONTAINS",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-notice-bin-bin1.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-notice-lib-libc.a.meta_lic"),
-						Relationship: "CONTAINS",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-notice-lib-libb.so.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-notice-bin-bin2.meta_lic"),
-						Relationship: "RUNTIME_DEPENDENCY_OF",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-notice-lib-libd.so.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-notice-bin-bin2.meta_lic"),
-						Relationship: "RUNTIME_DEPENDENCY_OF",
-					},
-				},
-				OtherLicenses: []*spdx.OtherLicense{
-					{
-						LicenseIdentifier: "LicenseRef-testdata-firstparty-FIRST_PARTY_LICENSE",
-						ExtractedText:     "&&&First Party License&&&\n",
-						LicenseName:       "testdata-firstparty-FIRST_PARTY_LICENSE",
-					},
-					{
-						LicenseIdentifier: "LicenseRef-testdata-notice-NOTICE_LICENSE",
-						ExtractedText:     "%%%Notice License%%%\n",
-						LicenseName:       "testdata-notice-NOTICE_LICENSE",
-					},
-				},
-			},
-			expectedDeps: []string{
-				"testdata/firstparty/FIRST_PARTY_LICENSE",
-				"testdata/notice/NOTICE_LICENSE",
-				"testdata/notice/bin/bin1.meta_lic",
-				"testdata/notice/bin/bin2.meta_lic",
-				"testdata/notice/container.zip.meta_lic",
-				"testdata/notice/lib/liba.so.meta_lic",
-				"testdata/notice/lib/libb.so.meta_lic",
-				"testdata/notice/lib/libc.a.meta_lic",
-				"testdata/notice/lib/libd.so.meta_lic",
-			},
-		},
-		{
-			condition: "notice",
-			name:      "application",
-			roots:     []string{"application.meta_lic"},
-			expectedOut: &spdx.Document{
-				SPDXVersion:       "SPDX-2.2",
-				DataLicense:       "CC0-1.0",
-				SPDXIdentifier:    "DOCUMENT",
-				DocumentName:      "testdata-notice-application",
-				DocumentNamespace: generateSPDXNamespace("", "1970-01-01T00:00:00Z", "testdata/notice/application.meta_lic"),
-				CreationInfo:      getCreationInfo(t),
-				Packages: []*spdx.Package{
-					{
-						PackageName:             "testdata-notice-application.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-notice-application.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-firstparty-FIRST_PARTY_LICENSE",
-					},
-					{
-						PackageName:             "testdata-notice-bin-bin3.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-notice-bin-bin3.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-notice-NOTICE_LICENSE",
-					},
-					{
-						PackageName:             "testdata-notice-lib-liba.so.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-notice-lib-liba.so.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-notice-NOTICE_LICENSE",
-					},
-					{
-						PackageName:             "testdata-notice-lib-libb.so.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-notice-lib-libb.so.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-firstparty-FIRST_PARTY_LICENSE",
-					},
-				},
-				Relationships: []*spdx.Relationship{
-					{
-						RefA:         common.MakeDocElementID("", "DOCUMENT"),
-						RefB:         common.MakeDocElementID("", "testdata-notice-application.meta_lic"),
-						Relationship: "DESCRIBES",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-notice-bin-bin3.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-notice-application.meta_lic"),
-						Relationship: "BUILD_TOOL_OF",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-notice-application.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-notice-lib-liba.so.meta_lic"),
-						Relationship: "CONTAINS",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-notice-lib-libb.so.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-notice-application.meta_lic"),
-						Relationship: "RUNTIME_DEPENDENCY_OF",
-					},
-				},
-				OtherLicenses: []*spdx.OtherLicense{
-					{
-						LicenseIdentifier: "LicenseRef-testdata-firstparty-FIRST_PARTY_LICENSE",
-						ExtractedText:     "&&&First Party License&&&\n",
-						LicenseName:       "testdata-firstparty-FIRST_PARTY_LICENSE",
-					},
-					{
-						LicenseIdentifier: "LicenseRef-testdata-notice-NOTICE_LICENSE",
-						ExtractedText:     "%%%Notice License%%%\n",
-						LicenseName:       "testdata-notice-NOTICE_LICENSE",
-					},
-				},
-			},
-			expectedDeps: []string{
-				"testdata/firstparty/FIRST_PARTY_LICENSE",
-				"testdata/notice/NOTICE_LICENSE",
-				"testdata/notice/application.meta_lic",
-				"testdata/notice/bin/bin3.meta_lic",
-				"testdata/notice/lib/liba.so.meta_lic",
-				"testdata/notice/lib/libb.so.meta_lic",
-			},
-		},
-		{
-			condition: "notice",
-			name:      "binary",
-			roots:     []string{"bin/bin1.meta_lic"},
-			expectedOut: &spdx.Document{
-				SPDXVersion:       "SPDX-2.2",
-				DataLicense:       "CC0-1.0",
-				SPDXIdentifier:    "DOCUMENT",
-				DocumentName:      "testdata-notice-bin-bin1",
-				DocumentNamespace: generateSPDXNamespace("", "1970-01-01T00:00:00Z", "testdata/notice/bin/bin1.meta_lic"),
-				CreationInfo:      getCreationInfo(t),
-				Packages: []*spdx.Package{
-					{
-						PackageName:             "testdata-notice-bin-bin1.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-notice-bin-bin1.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-firstparty-FIRST_PARTY_LICENSE",
-					},
-					{
-						PackageName:             "testdata-notice-lib-liba.so.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-notice-lib-liba.so.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-notice-NOTICE_LICENSE",
-					},
-					{
-						PackageName:             "testdata-notice-lib-libc.a.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-notice-lib-libc.a.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-notice-NOTICE_LICENSE",
-					},
-				},
-				Relationships: []*spdx.Relationship{
-					{
-						RefA:         common.MakeDocElementID("", "DOCUMENT"),
-						RefB:         common.MakeDocElementID("", "testdata-notice-bin-bin1.meta_lic"),
-						Relationship: "DESCRIBES",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-notice-bin-bin1.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-notice-lib-liba.so.meta_lic"),
-						Relationship: "CONTAINS",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-notice-bin-bin1.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-notice-lib-libc.a.meta_lic"),
-						Relationship: "CONTAINS",
-					},
-				},
-				OtherLicenses: []*spdx.OtherLicense{
-					{
-						LicenseIdentifier: "LicenseRef-testdata-firstparty-FIRST_PARTY_LICENSE",
-						ExtractedText:     "&&&First Party License&&&\n",
-						LicenseName:       "testdata-firstparty-FIRST_PARTY_LICENSE",
-					},
-					{
-						LicenseIdentifier: "LicenseRef-testdata-notice-NOTICE_LICENSE",
-						ExtractedText:     "%%%Notice License%%%\n",
-						LicenseName:       "testdata-notice-NOTICE_LICENSE",
-					},
-				},
-			},
-			expectedDeps: []string{
-				"testdata/firstparty/FIRST_PARTY_LICENSE",
-				"testdata/notice/NOTICE_LICENSE",
-				"testdata/notice/bin/bin1.meta_lic",
-				"testdata/notice/lib/liba.so.meta_lic",
-				"testdata/notice/lib/libc.a.meta_lic",
-			},
-		},
-		{
-			condition: "notice",
-			name:      "library",
-			roots:     []string{"lib/libd.so.meta_lic"},
-			expectedOut: &spdx.Document{
-				SPDXVersion:       "SPDX-2.2",
-				DataLicense:       "CC0-1.0",
-				SPDXIdentifier:    "DOCUMENT",
-				DocumentName:      "testdata-notice-lib-libd.so",
-				DocumentNamespace: generateSPDXNamespace("", "1970-01-01T00:00:00Z", "testdata/notice/lib/libd.so.meta_lic"),
-				CreationInfo:      getCreationInfo(t),
-				Packages: []*spdx.Package{
-					{
-						PackageName:             "testdata-notice-lib-libd.so.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-notice-lib-libd.so.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-notice-NOTICE_LICENSE",
-					},
-				},
-				Relationships: []*spdx.Relationship{
-					{
-						RefA:         common.MakeDocElementID("", "DOCUMENT"),
-						RefB:         common.MakeDocElementID("", "testdata-notice-lib-libd.so.meta_lic"),
-						Relationship: "DESCRIBES",
-					},
-				},
-				OtherLicenses: []*spdx.OtherLicense{
-					{
-						LicenseIdentifier: "LicenseRef-testdata-notice-NOTICE_LICENSE",
-						ExtractedText:     "%%%Notice License%%%\n",
-						LicenseName:       "testdata-notice-NOTICE_LICENSE",
-					},
-				},
-			},
-			expectedDeps: []string{
-				"testdata/notice/NOTICE_LICENSE",
-				"testdata/notice/lib/libd.so.meta_lic",
-			},
-		},
-		{
-			condition: "reciprocal",
-			name:      "apex",
-			roots:     []string{"highest.apex.meta_lic"},
-			expectedOut: &spdx.Document{
-				SPDXVersion:       "SPDX-2.2",
-				DataLicense:       "CC0-1.0",
-				SPDXIdentifier:    "DOCUMENT",
-				DocumentName:      "testdata-reciprocal-highest.apex",
-				DocumentNamespace: generateSPDXNamespace("", "1970-01-01T00:00:00Z", "testdata/reciprocal/highest.apex.meta_lic"),
-				CreationInfo:      getCreationInfo(t),
-				Packages: []*spdx.Package{
-					{
-						PackageName:             "testdata-reciprocal-highest.apex.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-reciprocal-highest.apex.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-firstparty-FIRST_PARTY_LICENSE",
-					},
-					{
-						PackageName:             "testdata-reciprocal-bin-bin1.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-reciprocal-bin-bin1.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-firstparty-FIRST_PARTY_LICENSE",
-					},
-					{
-						PackageName:             "testdata-reciprocal-bin-bin2.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-reciprocal-bin-bin2.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-firstparty-FIRST_PARTY_LICENSE",
-					},
-					{
-						PackageName:             "testdata-reciprocal-lib-liba.so.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-reciprocal-lib-liba.so.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-reciprocal-RECIPROCAL_LICENSE",
-					},
-					{
-						PackageName:             "testdata-reciprocal-lib-libb.so.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-reciprocal-lib-libb.so.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-firstparty-FIRST_PARTY_LICENSE",
-					},
-					{
-						PackageName:             "testdata-reciprocal-lib-libc.a.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-reciprocal-lib-libc.a.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-reciprocal-RECIPROCAL_LICENSE",
-					},
-					{
-						PackageName:             "testdata-reciprocal-lib-libd.so.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-reciprocal-lib-libd.so.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-notice-NOTICE_LICENSE",
-					},
-				},
-				Relationships: []*spdx.Relationship{
-					{
-						RefA:         common.MakeDocElementID("", "DOCUMENT"),
-						RefB:         common.MakeDocElementID("", "testdata-reciprocal-highest.apex.meta_lic"),
-						Relationship: "DESCRIBES",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-reciprocal-highest.apex.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-reciprocal-bin-bin1.meta_lic"),
-						Relationship: "CONTAINS",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-reciprocal-highest.apex.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-reciprocal-bin-bin2.meta_lic"),
-						Relationship: "CONTAINS",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-reciprocal-highest.apex.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-reciprocal-lib-liba.so.meta_lic"),
-						Relationship: "CONTAINS",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-reciprocal-highest.apex.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-reciprocal-lib-libb.so.meta_lic"),
-						Relationship: "CONTAINS",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-reciprocal-bin-bin1.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-reciprocal-lib-liba.so.meta_lic"),
-						Relationship: "CONTAINS",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-reciprocal-bin-bin1.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-reciprocal-lib-libc.a.meta_lic"),
-						Relationship: "CONTAINS",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-reciprocal-lib-libb.so.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-reciprocal-bin-bin2.meta_lic"),
-						Relationship: "RUNTIME_DEPENDENCY_OF",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-reciprocal-lib-libd.so.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-reciprocal-bin-bin2.meta_lic"),
-						Relationship: "RUNTIME_DEPENDENCY_OF",
-					},
-				},
-				OtherLicenses: []*spdx.OtherLicense{
-					{
-						LicenseIdentifier: "LicenseRef-testdata-firstparty-FIRST_PARTY_LICENSE",
-						ExtractedText:     "&&&First Party License&&&\n",
-						LicenseName:       "testdata-firstparty-FIRST_PARTY_LICENSE",
-					},
-					{
-						LicenseIdentifier: "LicenseRef-testdata-notice-NOTICE_LICENSE",
-						ExtractedText:     "%%%Notice License%%%\n",
-						LicenseName:       "testdata-notice-NOTICE_LICENSE",
-					},
-					{
-						LicenseIdentifier: "LicenseRef-testdata-reciprocal-RECIPROCAL_LICENSE",
-						ExtractedText:     "$$$Reciprocal License$$$\n",
-						LicenseName:       "testdata-reciprocal-RECIPROCAL_LICENSE",
-					},
-				},
-			},
-			expectedDeps: []string{
-				"testdata/firstparty/FIRST_PARTY_LICENSE",
-				"testdata/notice/NOTICE_LICENSE",
-				"testdata/reciprocal/RECIPROCAL_LICENSE",
-				"testdata/reciprocal/bin/bin1.meta_lic",
-				"testdata/reciprocal/bin/bin2.meta_lic",
-				"testdata/reciprocal/highest.apex.meta_lic",
-				"testdata/reciprocal/lib/liba.so.meta_lic",
-				"testdata/reciprocal/lib/libb.so.meta_lic",
-				"testdata/reciprocal/lib/libc.a.meta_lic",
-				"testdata/reciprocal/lib/libd.so.meta_lic",
-			},
-		},
-		{
-			condition: "reciprocal",
-			name:      "application",
-			roots:     []string{"application.meta_lic"},
-			expectedOut: &spdx.Document{
-				SPDXVersion:       "SPDX-2.2",
-				DataLicense:       "CC0-1.0",
-				SPDXIdentifier:    "DOCUMENT",
-				DocumentName:      "testdata-reciprocal-application",
-				DocumentNamespace: generateSPDXNamespace("", "1970-01-01T00:00:00Z", "testdata/reciprocal/application.meta_lic"),
-				CreationInfo:      getCreationInfo(t),
-				Packages: []*spdx.Package{
-					{
-						PackageName:             "testdata-reciprocal-application.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-reciprocal-application.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-firstparty-FIRST_PARTY_LICENSE",
-					},
-					{
-						PackageName:             "testdata-reciprocal-bin-bin3.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-reciprocal-bin-bin3.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-notice-NOTICE_LICENSE",
-					},
-					{
-						PackageName:             "testdata-reciprocal-lib-liba.so.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-reciprocal-lib-liba.so.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-reciprocal-RECIPROCAL_LICENSE",
-					},
-					{
-						PackageName:             "testdata-reciprocal-lib-libb.so.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-reciprocal-lib-libb.so.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-firstparty-FIRST_PARTY_LICENSE",
-					},
-				},
-				Relationships: []*spdx.Relationship{
-					{
-						RefA:         common.MakeDocElementID("", "DOCUMENT"),
-						RefB:         common.MakeDocElementID("", "testdata-reciprocal-application.meta_lic"),
-						Relationship: "DESCRIBES",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-reciprocal-bin-bin3.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-reciprocal-application.meta_lic"),
-						Relationship: "BUILD_TOOL_OF",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-reciprocal-application.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-reciprocal-lib-liba.so.meta_lic"),
-						Relationship: "CONTAINS",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-reciprocal-lib-libb.so.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-reciprocal-application.meta_lic"),
-						Relationship: "RUNTIME_DEPENDENCY_OF",
-					},
-				},
-				OtherLicenses: []*spdx.OtherLicense{
-					{
-						LicenseIdentifier: "LicenseRef-testdata-firstparty-FIRST_PARTY_LICENSE",
-						ExtractedText:     "&&&First Party License&&&\n",
-						LicenseName:       "testdata-firstparty-FIRST_PARTY_LICENSE",
-					},
-					{
-						LicenseIdentifier: "LicenseRef-testdata-notice-NOTICE_LICENSE",
-						ExtractedText:     "%%%Notice License%%%\n",
-						LicenseName:       "testdata-notice-NOTICE_LICENSE",
-					},
-					{
-						LicenseIdentifier: "LicenseRef-testdata-reciprocal-RECIPROCAL_LICENSE",
-						ExtractedText:     "$$$Reciprocal License$$$\n",
-						LicenseName:       "testdata-reciprocal-RECIPROCAL_LICENSE",
-					},
-				},
-			},
-			expectedDeps: []string{
-				"testdata/firstparty/FIRST_PARTY_LICENSE",
-				"testdata/notice/NOTICE_LICENSE",
-				"testdata/reciprocal/RECIPROCAL_LICENSE",
-				"testdata/reciprocal/application.meta_lic",
-				"testdata/reciprocal/bin/bin3.meta_lic",
-				"testdata/reciprocal/lib/liba.so.meta_lic",
-				"testdata/reciprocal/lib/libb.so.meta_lic",
-			},
-		},
-		{
-			condition: "reciprocal",
-			name:      "binary",
-			roots:     []string{"bin/bin1.meta_lic"},
-			expectedOut: &spdx.Document{
-				SPDXVersion:       "SPDX-2.2",
-				DataLicense:       "CC0-1.0",
-				SPDXIdentifier:    "DOCUMENT",
-				DocumentName:      "testdata-reciprocal-bin-bin1",
-				DocumentNamespace: generateSPDXNamespace("", "1970-01-01T00:00:00Z", "testdata/reciprocal/bin/bin1.meta_lic"),
-				CreationInfo:      getCreationInfo(t),
-				Packages: []*spdx.Package{
-					{
-						PackageName:             "testdata-reciprocal-bin-bin1.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-reciprocal-bin-bin1.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-firstparty-FIRST_PARTY_LICENSE",
-					},
-					{
-						PackageName:             "testdata-reciprocal-lib-liba.so.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-reciprocal-lib-liba.so.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-reciprocal-RECIPROCAL_LICENSE",
-					},
-					{
-						PackageName:             "testdata-reciprocal-lib-libc.a.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-reciprocal-lib-libc.a.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-reciprocal-RECIPROCAL_LICENSE",
-					},
-				},
-				Relationships: []*spdx.Relationship{
-					{
-						RefA:         common.MakeDocElementID("", "DOCUMENT"),
-						RefB:         common.MakeDocElementID("", "testdata-reciprocal-bin-bin1.meta_lic"),
-						Relationship: "DESCRIBES",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-reciprocal-bin-bin1.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-reciprocal-lib-liba.so.meta_lic"),
-						Relationship: "CONTAINS",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-reciprocal-bin-bin1.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-reciprocal-lib-libc.a.meta_lic"),
-						Relationship: "CONTAINS",
-					},
-				},
-				OtherLicenses: []*spdx.OtherLicense{
-					{
-						LicenseIdentifier: "LicenseRef-testdata-firstparty-FIRST_PARTY_LICENSE",
-						ExtractedText:     "&&&First Party License&&&\n",
-						LicenseName:       "testdata-firstparty-FIRST_PARTY_LICENSE",
-					},
-					{
-						LicenseIdentifier: "LicenseRef-testdata-reciprocal-RECIPROCAL_LICENSE",
-						ExtractedText:     "$$$Reciprocal License$$$\n",
-						LicenseName:       "testdata-reciprocal-RECIPROCAL_LICENSE",
-					},
-				},
-			},
-			expectedDeps: []string{
-				"testdata/firstparty/FIRST_PARTY_LICENSE",
-				"testdata/reciprocal/RECIPROCAL_LICENSE",
-				"testdata/reciprocal/bin/bin1.meta_lic",
-				"testdata/reciprocal/lib/liba.so.meta_lic",
-				"testdata/reciprocal/lib/libc.a.meta_lic",
-			},
-		},
-		{
-			condition: "reciprocal",
-			name:      "library",
-			roots:     []string{"lib/libd.so.meta_lic"},
-			expectedOut: &spdx.Document{
-				SPDXVersion:       "SPDX-2.2",
-				DataLicense:       "CC0-1.0",
-				SPDXIdentifier:    "DOCUMENT",
-				DocumentName:      "testdata-reciprocal-lib-libd.so",
-				DocumentNamespace: generateSPDXNamespace("", "1970-01-01T00:00:00Z", "testdata/reciprocal/lib/libd.so.meta_lic"),
-				CreationInfo:      getCreationInfo(t),
-				Packages: []*spdx.Package{
-					{
-						PackageName:             "testdata-reciprocal-lib-libd.so.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-reciprocal-lib-libd.so.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-notice-NOTICE_LICENSE",
-					},
-				},
-				Relationships: []*spdx.Relationship{
-					{
-						RefA:         common.MakeDocElementID("", "DOCUMENT"),
-						RefB:         common.MakeDocElementID("", "testdata-reciprocal-lib-libd.so.meta_lic"),
-						Relationship: "DESCRIBES",
-					},
-				},
-				OtherLicenses: []*spdx.OtherLicense{
-					{
-						LicenseIdentifier: "LicenseRef-testdata-notice-NOTICE_LICENSE",
-						ExtractedText:     "%%%Notice License%%%\n",
-						LicenseName:       "testdata-notice-NOTICE_LICENSE",
-					},
-				},
-			},
-			expectedDeps: []string{
-				"testdata/notice/NOTICE_LICENSE",
-				"testdata/reciprocal/lib/libd.so.meta_lic",
-			},
-		},
-		{
-			condition: "restricted",
-			name:      "apex",
-			roots:     []string{"highest.apex.meta_lic"},
-			expectedOut: &spdx.Document{
-				SPDXVersion:       "SPDX-2.2",
-				DataLicense:       "CC0-1.0",
-				SPDXIdentifier:    "DOCUMENT",
-				DocumentName:      "testdata-restricted-highest.apex",
-				DocumentNamespace: generateSPDXNamespace("", "1970-01-01T00:00:00Z", "testdata/restricted/highest.apex.meta_lic"),
-				CreationInfo:      getCreationInfo(t),
-				Packages: []*spdx.Package{
-					{
-						PackageName:             "testdata-restricted-highest.apex.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-restricted-highest.apex.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-firstparty-FIRST_PARTY_LICENSE",
-					},
-					{
-						PackageName:             "testdata-restricted-bin-bin1.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-restricted-bin-bin1.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-firstparty-FIRST_PARTY_LICENSE",
-					},
-					{
-						PackageName:             "testdata-restricted-bin-bin2.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-restricted-bin-bin2.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-firstparty-FIRST_PARTY_LICENSE",
-					},
-					{
-						PackageName:             "testdata-restricted-lib-liba.so.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-restricted-lib-liba.so.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-restricted-RESTRICTED_LICENSE",
-					},
-					{
-						PackageName:             "testdata-restricted-lib-libb.so.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-restricted-lib-libb.so.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-restricted-RESTRICTED_LICENSE",
-					},
-					{
-						PackageName:             "testdata-restricted-lib-libc.a.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-restricted-lib-libc.a.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-reciprocal-RECIPROCAL_LICENSE",
-					},
-					{
-						PackageName:             "testdata-restricted-lib-libd.so.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-restricted-lib-libd.so.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-notice-NOTICE_LICENSE",
-					},
-				},
-				Relationships: []*spdx.Relationship{
-					{
-						RefA:         common.MakeDocElementID("", "DOCUMENT"),
-						RefB:         common.MakeDocElementID("", "testdata-restricted-highest.apex.meta_lic"),
-						Relationship: "DESCRIBES",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-restricted-highest.apex.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-restricted-bin-bin1.meta_lic"),
-						Relationship: "CONTAINS",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-restricted-highest.apex.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-restricted-bin-bin2.meta_lic"),
-						Relationship: "CONTAINS",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-restricted-highest.apex.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-restricted-lib-liba.so.meta_lic"),
-						Relationship: "CONTAINS",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-restricted-highest.apex.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-restricted-lib-libb.so.meta_lic"),
-						Relationship: "CONTAINS",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-restricted-bin-bin1.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-restricted-lib-liba.so.meta_lic"),
-						Relationship: "CONTAINS",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-restricted-bin-bin1.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-restricted-lib-libc.a.meta_lic"),
-						Relationship: "CONTAINS",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-restricted-lib-libb.so.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-restricted-bin-bin2.meta_lic"),
-						Relationship: "RUNTIME_DEPENDENCY_OF",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-restricted-lib-libd.so.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-restricted-bin-bin2.meta_lic"),
-						Relationship: "RUNTIME_DEPENDENCY_OF",
-					},
-				},
-				OtherLicenses: []*spdx.OtherLicense{
-					{
-						LicenseIdentifier: "LicenseRef-testdata-firstparty-FIRST_PARTY_LICENSE",
-						ExtractedText:     "&&&First Party License&&&\n",
-						LicenseName:       "testdata-firstparty-FIRST_PARTY_LICENSE",
-					},
-					{
-						LicenseIdentifier: "LicenseRef-testdata-notice-NOTICE_LICENSE",
-						ExtractedText:     "%%%Notice License%%%\n",
-						LicenseName:       "testdata-notice-NOTICE_LICENSE",
-					},
-					{
-						LicenseIdentifier: "LicenseRef-testdata-reciprocal-RECIPROCAL_LICENSE",
-						ExtractedText:     "$$$Reciprocal License$$$\n",
-						LicenseName:       "testdata-reciprocal-RECIPROCAL_LICENSE",
-					},
-					{
-						LicenseIdentifier: "LicenseRef-testdata-restricted-RESTRICTED_LICENSE",
-						ExtractedText:     "###Restricted License###\n",
-						LicenseName:       "testdata-restricted-RESTRICTED_LICENSE",
-					},
-				},
-			},
-			expectedDeps: []string{
-				"testdata/firstparty/FIRST_PARTY_LICENSE",
-				"testdata/notice/NOTICE_LICENSE",
-				"testdata/reciprocal/RECIPROCAL_LICENSE",
-				"testdata/restricted/RESTRICTED_LICENSE",
-				"testdata/restricted/bin/bin1.meta_lic",
-				"testdata/restricted/bin/bin2.meta_lic",
-				"testdata/restricted/highest.apex.meta_lic",
-				"testdata/restricted/lib/liba.so.meta_lic",
-				"testdata/restricted/lib/libb.so.meta_lic",
-				"testdata/restricted/lib/libc.a.meta_lic",
-				"testdata/restricted/lib/libd.so.meta_lic",
-			},
-		},
-		{
-			condition: "restricted",
-			name:      "container",
-			roots:     []string{"container.zip.meta_lic"},
-			expectedOut: &spdx.Document{
-				SPDXVersion:       "SPDX-2.2",
-				DataLicense:       "CC0-1.0",
-				SPDXIdentifier:    "DOCUMENT",
-				DocumentName:      "testdata-restricted-container.zip",
-				DocumentNamespace: generateSPDXNamespace("", "1970-01-01T00:00:00Z", "testdata/restricted/container.zip.meta_lic"),
-				CreationInfo:      getCreationInfo(t),
-				Packages: []*spdx.Package{
-					{
-						PackageName:             "testdata-restricted-container.zip.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-restricted-container.zip.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-firstparty-FIRST_PARTY_LICENSE",
-					},
-					{
-						PackageName:             "testdata-restricted-bin-bin1.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-restricted-bin-bin1.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-firstparty-FIRST_PARTY_LICENSE",
-					},
-					{
-						PackageName:             "testdata-restricted-bin-bin2.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-restricted-bin-bin2.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-firstparty-FIRST_PARTY_LICENSE",
-					},
-					{
-						PackageName:             "testdata-restricted-lib-liba.so.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-restricted-lib-liba.so.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-restricted-RESTRICTED_LICENSE",
-					},
-					{
-						PackageName:             "testdata-restricted-lib-libb.so.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-restricted-lib-libb.so.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-restricted-RESTRICTED_LICENSE",
-					},
-					{
-						PackageName:             "testdata-restricted-lib-libc.a.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-restricted-lib-libc.a.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-reciprocal-RECIPROCAL_LICENSE",
-					},
-					{
-						PackageName:             "testdata-restricted-lib-libd.so.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-restricted-lib-libd.so.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-notice-NOTICE_LICENSE",
-					},
-				},
-				Relationships: []*spdx.Relationship{
-					{
-						RefA:         common.MakeDocElementID("", "DOCUMENT"),
-						RefB:         common.MakeDocElementID("", "testdata-restricted-container.zip.meta_lic"),
-						Relationship: "DESCRIBES",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-restricted-container.zip.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-restricted-bin-bin1.meta_lic"),
-						Relationship: "CONTAINS",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-restricted-container.zip.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-restricted-bin-bin2.meta_lic"),
-						Relationship: "CONTAINS",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-restricted-container.zip.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-restricted-lib-liba.so.meta_lic"),
-						Relationship: "CONTAINS",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-restricted-container.zip.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-restricted-lib-libb.so.meta_lic"),
-						Relationship: "CONTAINS",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-restricted-bin-bin1.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-restricted-lib-liba.so.meta_lic"),
-						Relationship: "CONTAINS",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-restricted-bin-bin1.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-restricted-lib-libc.a.meta_lic"),
-						Relationship: "CONTAINS",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-restricted-lib-libb.so.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-restricted-bin-bin2.meta_lic"),
-						Relationship: "RUNTIME_DEPENDENCY_OF",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-restricted-lib-libd.so.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-restricted-bin-bin2.meta_lic"),
-						Relationship: "RUNTIME_DEPENDENCY_OF",
-					},
-				},
-				OtherLicenses: []*spdx.OtherLicense{
-					{
-						LicenseIdentifier: "LicenseRef-testdata-firstparty-FIRST_PARTY_LICENSE",
-						ExtractedText:     "&&&First Party License&&&\n",
-						LicenseName:       "testdata-firstparty-FIRST_PARTY_LICENSE",
-					},
-					{
-						LicenseIdentifier: "LicenseRef-testdata-notice-NOTICE_LICENSE",
-						ExtractedText:     "%%%Notice License%%%\n",
-						LicenseName:       "testdata-notice-NOTICE_LICENSE",
-					},
-					{
-						LicenseIdentifier: "LicenseRef-testdata-reciprocal-RECIPROCAL_LICENSE",
-						ExtractedText:     "$$$Reciprocal License$$$\n",
-						LicenseName:       "testdata-reciprocal-RECIPROCAL_LICENSE",
-					},
-					{
-						LicenseIdentifier: "LicenseRef-testdata-restricted-RESTRICTED_LICENSE",
-						ExtractedText:     "###Restricted License###\n",
-						LicenseName:       "testdata-restricted-RESTRICTED_LICENSE",
-					},
-				},
-			},
-			expectedDeps: []string{
-				"testdata/firstparty/FIRST_PARTY_LICENSE",
-				"testdata/notice/NOTICE_LICENSE",
-				"testdata/reciprocal/RECIPROCAL_LICENSE",
-				"testdata/restricted/RESTRICTED_LICENSE",
-				"testdata/restricted/bin/bin1.meta_lic",
-				"testdata/restricted/bin/bin2.meta_lic",
-				"testdata/restricted/container.zip.meta_lic",
-				"testdata/restricted/lib/liba.so.meta_lic",
-				"testdata/restricted/lib/libb.so.meta_lic",
-				"testdata/restricted/lib/libc.a.meta_lic",
-				"testdata/restricted/lib/libd.so.meta_lic",
-			},
-		},
-		{
-			condition: "restricted",
-			name:      "binary",
-			roots:     []string{"bin/bin1.meta_lic"},
-			expectedOut: &spdx.Document{
-				SPDXVersion:       "SPDX-2.2",
-				DataLicense:       "CC0-1.0",
-				SPDXIdentifier:    "DOCUMENT",
-				DocumentName:      "testdata-restricted-bin-bin1",
-				DocumentNamespace: generateSPDXNamespace("", "1970-01-01T00:00:00Z", "testdata/restricted/bin/bin1.meta_lic"),
-				CreationInfo:      getCreationInfo(t),
-				Packages: []*spdx.Package{
-					{
-						PackageName:             "testdata-restricted-bin-bin1.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-restricted-bin-bin1.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-firstparty-FIRST_PARTY_LICENSE",
-					},
-					{
-						PackageName:             "testdata-restricted-lib-liba.so.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-restricted-lib-liba.so.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-restricted-RESTRICTED_LICENSE",
-					},
-					{
-						PackageName:             "testdata-restricted-lib-libc.a.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-restricted-lib-libc.a.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-reciprocal-RECIPROCAL_LICENSE",
-					},
-				},
-				Relationships: []*spdx.Relationship{
-					{
-						RefA:         common.MakeDocElementID("", "DOCUMENT"),
-						RefB:         common.MakeDocElementID("", "testdata-restricted-bin-bin1.meta_lic"),
-						Relationship: "DESCRIBES",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-restricted-bin-bin1.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-restricted-lib-liba.so.meta_lic"),
-						Relationship: "CONTAINS",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-restricted-bin-bin1.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-restricted-lib-libc.a.meta_lic"),
-						Relationship: "CONTAINS",
-					},
-				},
-				OtherLicenses: []*spdx.OtherLicense{
-					{
-						LicenseIdentifier: "LicenseRef-testdata-firstparty-FIRST_PARTY_LICENSE",
-						ExtractedText:     "&&&First Party License&&&\n",
-						LicenseName:       "testdata-firstparty-FIRST_PARTY_LICENSE",
-					},
-					{
-						LicenseIdentifier: "LicenseRef-testdata-reciprocal-RECIPROCAL_LICENSE",
-						ExtractedText:     "$$$Reciprocal License$$$\n",
-						LicenseName:       "testdata-reciprocal-RECIPROCAL_LICENSE",
-					},
-					{
-						LicenseIdentifier: "LicenseRef-testdata-restricted-RESTRICTED_LICENSE",
-						ExtractedText:     "###Restricted License###\n",
-						LicenseName:       "testdata-restricted-RESTRICTED_LICENSE",
-					},
-				},
-			},
-			expectedDeps: []string{
-				"testdata/firstparty/FIRST_PARTY_LICENSE",
-				"testdata/reciprocal/RECIPROCAL_LICENSE",
-				"testdata/restricted/RESTRICTED_LICENSE",
-				"testdata/restricted/bin/bin1.meta_lic",
-				"testdata/restricted/lib/liba.so.meta_lic",
-				"testdata/restricted/lib/libc.a.meta_lic",
-			},
-		},
-		{
-			condition: "restricted",
-			name:      "library",
-			roots:     []string{"lib/libd.so.meta_lic"},
-			expectedOut: &spdx.Document{
-				SPDXVersion:       "SPDX-2.2",
-				DataLicense:       "CC0-1.0",
-				SPDXIdentifier:    "DOCUMENT",
-				DocumentName:      "testdata-restricted-lib-libd.so",
-				DocumentNamespace: generateSPDXNamespace("", "1970-01-01T00:00:00Z", "testdata/restricted/lib/libd.so.meta_lic"),
-				CreationInfo:      getCreationInfo(t),
-				Packages: []*spdx.Package{
-					{
-						PackageName:             "testdata-restricted-lib-libd.so.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-restricted-lib-libd.so.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-notice-NOTICE_LICENSE",
-					},
-				},
-				Relationships: []*spdx.Relationship{
-					{
-						RefA:         common.MakeDocElementID("", "DOCUMENT"),
-						RefB:         common.MakeDocElementID("", "testdata-restricted-lib-libd.so.meta_lic"),
-						Relationship: "DESCRIBES",
-					},
-				},
-				OtherLicenses: []*spdx.OtherLicense{
-					{
-						LicenseIdentifier: "LicenseRef-testdata-notice-NOTICE_LICENSE",
-						ExtractedText:     "%%%Notice License%%%\n",
-						LicenseName:       "testdata-notice-NOTICE_LICENSE",
-					},
-				},
-			},
-			expectedDeps: []string{
-				"testdata/notice/NOTICE_LICENSE",
-				"testdata/restricted/lib/libd.so.meta_lic",
-			},
-		},
-		{
-			condition: "proprietary",
-			name:      "apex",
-			roots:     []string{"highest.apex.meta_lic"},
-			expectedOut: &spdx.Document{
-				SPDXVersion:       "SPDX-2.2",
-				DataLicense:       "CC0-1.0",
-				SPDXIdentifier:    "DOCUMENT",
-				DocumentName:      "testdata-proprietary-highest.apex",
-				DocumentNamespace: generateSPDXNamespace("", "1970-01-01T00:00:00Z", "testdata/proprietary/highest.apex.meta_lic"),
-				CreationInfo:      getCreationInfo(t),
-				Packages: []*spdx.Package{
-					{
-						PackageName:             "testdata-proprietary-highest.apex.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-proprietary-highest.apex.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-firstparty-FIRST_PARTY_LICENSE",
-					},
-					{
-						PackageName:             "testdata-proprietary-bin-bin1.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-proprietary-bin-bin1.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-firstparty-FIRST_PARTY_LICENSE",
-					},
-					{
-						PackageName:             "testdata-proprietary-bin-bin2.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-proprietary-bin-bin2.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-proprietary-PROPRIETARY_LICENSE",
-					},
-					{
-						PackageName:             "testdata-proprietary-lib-liba.so.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-proprietary-lib-liba.so.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-proprietary-PROPRIETARY_LICENSE",
-					},
-					{
-						PackageName:             "testdata-proprietary-lib-libb.so.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-proprietary-lib-libb.so.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-restricted-RESTRICTED_LICENSE",
-					},
-					{
-						PackageName:             "testdata-proprietary-lib-libc.a.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-proprietary-lib-libc.a.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-proprietary-PROPRIETARY_LICENSE",
-					},
-					{
-						PackageName:             "testdata-proprietary-lib-libd.so.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-proprietary-lib-libd.so.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-notice-NOTICE_LICENSE",
-					},
-				},
-				Relationships: []*spdx.Relationship{
-					{
-						RefA:         common.MakeDocElementID("", "DOCUMENT"),
-						RefB:         common.MakeDocElementID("", "testdata-proprietary-highest.apex.meta_lic"),
-						Relationship: "DESCRIBES",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-proprietary-highest.apex.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-proprietary-bin-bin1.meta_lic"),
-						Relationship: "CONTAINS",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-proprietary-highest.apex.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-proprietary-bin-bin2.meta_lic"),
-						Relationship: "CONTAINS",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-proprietary-highest.apex.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-proprietary-lib-liba.so.meta_lic"),
-						Relationship: "CONTAINS",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-proprietary-highest.apex.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-proprietary-lib-libb.so.meta_lic"),
-						Relationship: "CONTAINS",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-proprietary-bin-bin1.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-proprietary-lib-liba.so.meta_lic"),
-						Relationship: "CONTAINS",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-proprietary-bin-bin1.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-proprietary-lib-libc.a.meta_lic"),
-						Relationship: "CONTAINS",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-proprietary-lib-libb.so.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-proprietary-bin-bin2.meta_lic"),
-						Relationship: "RUNTIME_DEPENDENCY_OF",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-proprietary-lib-libd.so.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-proprietary-bin-bin2.meta_lic"),
-						Relationship: "RUNTIME_DEPENDENCY_OF",
-					},
-				},
-				OtherLicenses: []*spdx.OtherLicense{
-					{
-						LicenseIdentifier: "LicenseRef-testdata-firstparty-FIRST_PARTY_LICENSE",
-						ExtractedText:     "&&&First Party License&&&\n",
-						LicenseName:       "testdata-firstparty-FIRST_PARTY_LICENSE",
-					},
-					{
-						LicenseIdentifier: "LicenseRef-testdata-notice-NOTICE_LICENSE",
-						ExtractedText:     "%%%Notice License%%%\n",
-						LicenseName:       "testdata-notice-NOTICE_LICENSE",
-					},
-					{
-						LicenseIdentifier: "LicenseRef-testdata-proprietary-PROPRIETARY_LICENSE",
-						ExtractedText:     "@@@Proprietary License@@@\n",
-						LicenseName:       "testdata-proprietary-PROPRIETARY_LICENSE",
-					},
-					{
-						LicenseIdentifier: "LicenseRef-testdata-restricted-RESTRICTED_LICENSE",
-						ExtractedText:     "###Restricted License###\n",
-						LicenseName:       "testdata-restricted-RESTRICTED_LICENSE",
-					},
-				},
-			},
-			expectedDeps: []string{
-				"testdata/firstparty/FIRST_PARTY_LICENSE",
-				"testdata/notice/NOTICE_LICENSE",
-				"testdata/proprietary/PROPRIETARY_LICENSE",
-				"testdata/proprietary/bin/bin1.meta_lic",
-				"testdata/proprietary/bin/bin2.meta_lic",
-				"testdata/proprietary/highest.apex.meta_lic",
-				"testdata/proprietary/lib/liba.so.meta_lic",
-				"testdata/proprietary/lib/libb.so.meta_lic",
-				"testdata/proprietary/lib/libc.a.meta_lic",
-				"testdata/proprietary/lib/libd.so.meta_lic",
-				"testdata/restricted/RESTRICTED_LICENSE",
-			},
-		},
-		{
-			condition: "proprietary",
-			name:      "container",
-			roots:     []string{"container.zip.meta_lic"},
-			expectedOut: &spdx.Document{
-				SPDXVersion:       "SPDX-2.2",
-				DataLicense:       "CC0-1.0",
-				SPDXIdentifier:    "DOCUMENT",
-				DocumentName:      "testdata-proprietary-container.zip",
-				DocumentNamespace: generateSPDXNamespace("", "1970-01-01T00:00:00Z", "testdata/proprietary/container.zip.meta_lic"),
-				CreationInfo:      getCreationInfo(t),
-				Packages: []*spdx.Package{
-					{
-						PackageName:             "testdata-proprietary-container.zip.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-proprietary-container.zip.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-firstparty-FIRST_PARTY_LICENSE",
-					},
-					{
-						PackageName:             "testdata-proprietary-bin-bin1.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-proprietary-bin-bin1.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-firstparty-FIRST_PARTY_LICENSE",
-					},
-					{
-						PackageName:             "testdata-proprietary-bin-bin2.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-proprietary-bin-bin2.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-proprietary-PROPRIETARY_LICENSE",
-					},
-					{
-						PackageName:             "testdata-proprietary-lib-liba.so.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-proprietary-lib-liba.so.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-proprietary-PROPRIETARY_LICENSE",
-					},
-					{
-						PackageName:             "testdata-proprietary-lib-libb.so.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-proprietary-lib-libb.so.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-restricted-RESTRICTED_LICENSE",
-					},
-					{
-						PackageName:             "testdata-proprietary-lib-libc.a.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-proprietary-lib-libc.a.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-proprietary-PROPRIETARY_LICENSE",
-					},
-					{
-						PackageName:             "testdata-proprietary-lib-libd.so.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-proprietary-lib-libd.so.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-notice-NOTICE_LICENSE",
-					},
-				},
-				Relationships: []*spdx.Relationship{
-					{
-						RefA:         common.MakeDocElementID("", "DOCUMENT"),
-						RefB:         common.MakeDocElementID("", "testdata-proprietary-container.zip.meta_lic"),
-						Relationship: "DESCRIBES",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-proprietary-container.zip.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-proprietary-bin-bin1.meta_lic"),
-						Relationship: "CONTAINS",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-proprietary-container.zip.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-proprietary-bin-bin2.meta_lic"),
-						Relationship: "CONTAINS",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-proprietary-container.zip.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-proprietary-lib-liba.so.meta_lic"),
-						Relationship: "CONTAINS",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-proprietary-container.zip.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-proprietary-lib-libb.so.meta_lic"),
-						Relationship: "CONTAINS",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-proprietary-bin-bin1.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-proprietary-lib-liba.so.meta_lic"),
-						Relationship: "CONTAINS",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-proprietary-bin-bin1.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-proprietary-lib-libc.a.meta_lic"),
-						Relationship: "CONTAINS",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-proprietary-lib-libb.so.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-proprietary-bin-bin2.meta_lic"),
-						Relationship: "RUNTIME_DEPENDENCY_OF",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-proprietary-lib-libd.so.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-proprietary-bin-bin2.meta_lic"),
-						Relationship: "RUNTIME_DEPENDENCY_OF",
-					},
-				},
-				OtherLicenses: []*spdx.OtherLicense{
-					{
-						LicenseIdentifier: "LicenseRef-testdata-firstparty-FIRST_PARTY_LICENSE",
-						ExtractedText:     "&&&First Party License&&&\n",
-						LicenseName:       "testdata-firstparty-FIRST_PARTY_LICENSE",
-					},
-					{
-						LicenseIdentifier: "LicenseRef-testdata-notice-NOTICE_LICENSE",
-						ExtractedText:     "%%%Notice License%%%\n",
-						LicenseName:       "testdata-notice-NOTICE_LICENSE",
-					},
-					{
-						LicenseIdentifier: "LicenseRef-testdata-proprietary-PROPRIETARY_LICENSE",
-						ExtractedText:     "@@@Proprietary License@@@\n",
-						LicenseName:       "testdata-proprietary-PROPRIETARY_LICENSE",
-					},
-					{
-						LicenseIdentifier: "LicenseRef-testdata-restricted-RESTRICTED_LICENSE",
-						ExtractedText:     "###Restricted License###\n",
-						LicenseName:       "testdata-restricted-RESTRICTED_LICENSE",
-					},
-				},
-			},
-			expectedDeps: []string{
-				"testdata/firstparty/FIRST_PARTY_LICENSE",
-				"testdata/notice/NOTICE_LICENSE",
-				"testdata/proprietary/PROPRIETARY_LICENSE",
-				"testdata/proprietary/bin/bin1.meta_lic",
-				"testdata/proprietary/bin/bin2.meta_lic",
-				"testdata/proprietary/container.zip.meta_lic",
-				"testdata/proprietary/lib/liba.so.meta_lic",
-				"testdata/proprietary/lib/libb.so.meta_lic",
-				"testdata/proprietary/lib/libc.a.meta_lic",
-				"testdata/proprietary/lib/libd.so.meta_lic",
-				"testdata/restricted/RESTRICTED_LICENSE",
-			},
-		},
-		{
-			condition: "proprietary",
-			name:      "application",
-			roots:     []string{"application.meta_lic"},
-			expectedOut: &spdx.Document{
-				SPDXVersion:       "SPDX-2.2",
-				DataLicense:       "CC0-1.0",
-				SPDXIdentifier:    "DOCUMENT",
-				DocumentName:      "testdata-proprietary-application",
-				DocumentNamespace: generateSPDXNamespace("", "1970-01-01T00:00:00Z", "testdata/proprietary/application.meta_lic"),
-				CreationInfo:      getCreationInfo(t),
-				Packages: []*spdx.Package{
-					{
-						PackageName:             "testdata-proprietary-application.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-proprietary-application.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-firstparty-FIRST_PARTY_LICENSE",
-					},
-					{
-						PackageName:             "testdata-proprietary-bin-bin3.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-proprietary-bin-bin3.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-restricted-RESTRICTED_LICENSE",
-					},
-					{
-						PackageName:             "testdata-proprietary-lib-liba.so.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-proprietary-lib-liba.so.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-proprietary-PROPRIETARY_LICENSE",
-					},
-					{
-						PackageName:             "testdata-proprietary-lib-libb.so.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-proprietary-lib-libb.so.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-restricted-RESTRICTED_LICENSE",
-					},
-				},
-				Relationships: []*spdx.Relationship{
-					{
-						RefA:         common.MakeDocElementID("", "DOCUMENT"),
-						RefB:         common.MakeDocElementID("", "testdata-proprietary-application.meta_lic"),
-						Relationship: "DESCRIBES",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-proprietary-bin-bin3.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-proprietary-application.meta_lic"),
-						Relationship: "BUILD_TOOL_OF",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-proprietary-application.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-proprietary-lib-liba.so.meta_lic"),
-						Relationship: "CONTAINS",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-proprietary-lib-libb.so.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-proprietary-application.meta_lic"),
-						Relationship: "RUNTIME_DEPENDENCY_OF",
-					},
-				},
-				OtherLicenses: []*spdx.OtherLicense{
-					{
-						LicenseIdentifier: "LicenseRef-testdata-firstparty-FIRST_PARTY_LICENSE",
-						ExtractedText:     "&&&First Party License&&&\n",
-						LicenseName:       "testdata-firstparty-FIRST_PARTY_LICENSE",
-					},
-					{
-						LicenseIdentifier: "LicenseRef-testdata-proprietary-PROPRIETARY_LICENSE",
-						ExtractedText:     "@@@Proprietary License@@@\n",
-						LicenseName:       "testdata-proprietary-PROPRIETARY_LICENSE",
-					},
-					{
-						LicenseIdentifier: "LicenseRef-testdata-restricted-RESTRICTED_LICENSE",
-						ExtractedText:     "###Restricted License###\n",
-						LicenseName:       "testdata-restricted-RESTRICTED_LICENSE",
-					},
-				},
-			},
-			expectedDeps: []string{
-				"testdata/firstparty/FIRST_PARTY_LICENSE",
-				"testdata/proprietary/PROPRIETARY_LICENSE",
-				"testdata/proprietary/application.meta_lic",
-				"testdata/proprietary/bin/bin3.meta_lic",
-				"testdata/proprietary/lib/liba.so.meta_lic",
-				"testdata/proprietary/lib/libb.so.meta_lic",
-				"testdata/restricted/RESTRICTED_LICENSE",
-			},
-		},
-		{
-			condition: "proprietary",
-			name:      "binary",
-			roots:     []string{"bin/bin1.meta_lic"},
-			expectedOut: &spdx.Document{
-				SPDXVersion:       "SPDX-2.2",
-				DataLicense:       "CC0-1.0",
-				SPDXIdentifier:    "DOCUMENT",
-				DocumentName:      "testdata-proprietary-bin-bin1",
-				DocumentNamespace: generateSPDXNamespace("", "1970-01-01T00:00:00Z", "testdata/proprietary/bin/bin1.meta_lic"),
-				CreationInfo:      getCreationInfo(t),
-				Packages: []*spdx.Package{
-					{
-						PackageName:             "testdata-proprietary-bin-bin1.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-proprietary-bin-bin1.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-firstparty-FIRST_PARTY_LICENSE",
-					},
-					{
-						PackageName:             "testdata-proprietary-lib-liba.so.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-proprietary-lib-liba.so.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-proprietary-PROPRIETARY_LICENSE",
-					},
-					{
-						PackageName:             "testdata-proprietary-lib-libc.a.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-proprietary-lib-libc.a.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-proprietary-PROPRIETARY_LICENSE",
-					},
-				},
-				Relationships: []*spdx.Relationship{
-					{
-						RefA:         common.MakeDocElementID("", "DOCUMENT"),
-						RefB:         common.MakeDocElementID("", "testdata-proprietary-bin-bin1.meta_lic"),
-						Relationship: "DESCRIBES",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-proprietary-bin-bin1.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-proprietary-lib-liba.so.meta_lic"),
-						Relationship: "CONTAINS",
-					},
-					{
-						RefA:         common.MakeDocElementID("", "testdata-proprietary-bin-bin1.meta_lic"),
-						RefB:         common.MakeDocElementID("", "testdata-proprietary-lib-libc.a.meta_lic"),
-						Relationship: "CONTAINS",
-					},
-				},
-				OtherLicenses: []*spdx.OtherLicense{
-					{
-						LicenseIdentifier: "LicenseRef-testdata-firstparty-FIRST_PARTY_LICENSE",
-						ExtractedText:     "&&&First Party License&&&\n",
-						LicenseName:       "testdata-firstparty-FIRST_PARTY_LICENSE",
-					},
-					{
-						LicenseIdentifier: "LicenseRef-testdata-proprietary-PROPRIETARY_LICENSE",
-						ExtractedText:     "@@@Proprietary License@@@\n",
-						LicenseName:       "testdata-proprietary-PROPRIETARY_LICENSE",
-					},
-				},
-			},
-			expectedDeps: []string{
-				"testdata/firstparty/FIRST_PARTY_LICENSE",
-				"testdata/proprietary/PROPRIETARY_LICENSE",
-				"testdata/proprietary/bin/bin1.meta_lic",
-				"testdata/proprietary/lib/liba.so.meta_lic",
-				"testdata/proprietary/lib/libc.a.meta_lic",
-			},
-		},
-		{
-			condition: "proprietary",
-			name:      "library",
-			roots:     []string{"lib/libd.so.meta_lic"},
-			expectedOut: &spdx.Document{
-				SPDXVersion:       "SPDX-2.2",
-				DataLicense:       "CC0-1.0",
-				SPDXIdentifier:    "DOCUMENT",
-				DocumentName:      "testdata-proprietary-lib-libd.so",
-				DocumentNamespace: generateSPDXNamespace("", "1970-01-01T00:00:00Z", "testdata/proprietary/lib/libd.so.meta_lic"),
-				CreationInfo:      getCreationInfo(t),
-				Packages: []*spdx.Package{
-					{
-						PackageName:             "testdata-proprietary-lib-libd.so.meta_lic",
-						PackageVersion:          "NOASSERTION",
-						PackageDownloadLocation: "NOASSERTION",
-						PackageSPDXIdentifier:   common.ElementID("testdata-proprietary-lib-libd.so.meta_lic"),
-						PackageLicenseConcluded: "LicenseRef-testdata-notice-NOTICE_LICENSE",
-					},
-				},
-				Relationships: []*spdx.Relationship{
-					{
-						RefA:         common.MakeDocElementID("", "DOCUMENT"),
-						RefB:         common.MakeDocElementID("", "testdata-proprietary-lib-libd.so.meta_lic"),
-						Relationship: "DESCRIBES",
-					},
-				},
-				OtherLicenses: []*spdx.OtherLicense{
-					{
-						LicenseIdentifier: "LicenseRef-testdata-notice-NOTICE_LICENSE",
-						ExtractedText:     "%%%Notice License%%%\n",
-						LicenseName:       "testdata-notice-NOTICE_LICENSE",
-					},
-				},
-			},
-			expectedDeps: []string{
-				"testdata/notice/NOTICE_LICENSE",
-				"testdata/proprietary/lib/libd.so.meta_lic",
-			},
-		},
-	}
-	for _, tt := range tests {
-		t.Run(tt.condition+" "+tt.name, func(t *testing.T) {
-			stdout := &bytes.Buffer{}
-			stderr := &bytes.Buffer{}
-
-			rootFiles := make([]string, 0, len(tt.roots))
-			for _, r := range tt.roots {
-				rootFiles = append(rootFiles, "testdata/"+tt.condition+"/"+r)
-			}
-
-			ctx := context{stdout, stderr, compliance.GetFS(tt.outDir), "", []string{tt.stripPrefix}, fakeTime, ""}
-
-			spdxDoc, deps, err := sbomGenerator(&ctx, rootFiles...)
-			if err != nil {
-				t.Fatalf("sbom: error = %v, stderr = %v", err, stderr)
-				return
-			}
-			if stderr.Len() > 0 {
-				t.Errorf("sbom: gotStderr = %v, want none", stderr)
-			}
-
-			if err := validate(spdxDoc); err != nil {
-				t.Fatalf("sbom: document fails to validate: %v", err)
-			}
-
-			gotData, err := json.Marshal(spdxDoc)
-			if err != nil {
-				t.Fatalf("sbom: failed to marshal spdx doc: %v", err)
-				return
-			}
-
-			t.Logf("Got SPDX Doc: %s", string(gotData))
-
-			expectedData, err := json.Marshal(tt.expectedOut)
-			if err != nil {
-				t.Fatalf("sbom: failed to marshal spdx doc: %v", err)
-				return
-			}
-
-			t.Logf("Want SPDX Doc: %s", string(expectedData))
-
-			// compare the spdx Docs
-			compareSpdxDocs(t, spdxDoc, tt.expectedOut)
-
-			// compare deps
-			t.Logf("got deps: %q", deps)
-
-			t.Logf("want deps: %q", tt.expectedDeps)
-
-			if g, w := deps, tt.expectedDeps; !reflect.DeepEqual(g, w) {
-				t.Errorf("unexpected deps, wanted:\n%s\ngot:\n%s\n",
-					strings.Join(w, "\n"), strings.Join(g, "\n"))
-			}
-		})
-	}
-}
-
-func TestGenerateSPDXNamespace(t *testing.T) {
-
-	buildID1 := "example-1"
-	buildID2 := "example-2"
-	files1 := "file1"
-	timestamp1 := "2022-05-01"
-	timestamp2 := "2022-05-02"
-	files2 := "file2"
-
-	// Test case 1: different timestamps, same files
-	nsh1 := generateSPDXNamespace("", timestamp1, files1)
-	nsh2 := generateSPDXNamespace("", timestamp2, files1)
-
-	if nsh1 == "" {
-		t.Errorf("generateSPDXNamespace(%s, %s, %s): expected non-empty string, but got empty string", "", timestamp1, files1)
-	}
-
-	if nsh2 == "" {
-		t.Errorf("generateSPDXNamespace(%s, %s, %s): expected non-empty string, but got empty string", "", timestamp2, files1)
-	}
-
-	if nsh1 == nsh2 {
-		t.Errorf("generateSPDXNamespace(%s, %s, %s) and generateSPDXNamespace(%s, %s, %s): expected different namespace hashes, but got the same", "", timestamp1, files1, "", timestamp2, files1)
-	}
-
-	// Test case 2: different build ids, same timestamps and files
-	nsh1 = generateSPDXNamespace(buildID1, timestamp1, files1)
-	nsh2 = generateSPDXNamespace(buildID2, timestamp1, files1)
-
-	if nsh1 == "" {
-		t.Errorf("generateSPDXNamespace(%s, %s, %s): expected non-empty string, but got empty string", buildID1, timestamp1, files1)
-	}
-
-	if nsh2 == "" {
-		t.Errorf("generateSPDXNamespace(%s, %s, %s): expected non-empty string, but got empty string", buildID2, timestamp1, files1)
-	}
-
-	if nsh1 == nsh2 {
-		t.Errorf("generateSPDXNamespace(%s, %s, %s) and generateSPDXNamespace(%s, %s, %s): expected different namespace hashes, but got the same", buildID1, timestamp1, files1, buildID2, timestamp1, files1)
-	}
-
-	// Test case 3: same build ids and files, different timestamps
-	nsh1 = generateSPDXNamespace(buildID1, timestamp1, files1)
-	nsh2 = generateSPDXNamespace(buildID1, timestamp2, files1)
-
-	if nsh1 == "" {
-		t.Errorf("generateSPDXNamespace(%s, %s, %s): expected non-empty string, but got empty string", buildID1, timestamp1, files1)
-	}
-
-	if nsh2 == "" {
-		t.Errorf("generateSPDXNamespace(%s, %s, %s): expected non-empty string, but got empty string", buildID1, timestamp2, files1)
-	}
-
-	if nsh1 != nsh2 {
-		t.Errorf("generateSPDXNamespace(%s, %s, %s) and generateSPDXNamespace(%s, %s, %s): expected same namespace hashes, but got different: %s and %s", buildID1, timestamp1, files1, buildID2, timestamp1, files1, nsh1, nsh2)
-	}
-
-	// Test case 4: same build ids and timestamps, different files
-	nsh1 = generateSPDXNamespace(buildID1, timestamp1, files1)
-	nsh2 = generateSPDXNamespace(buildID1, timestamp1, files2)
-
-	if nsh1 == "" {
-		t.Errorf("generateSPDXNamespace(%s, %s, %s): expected non-empty string, but got empty string", buildID1, timestamp1, files1)
-	}
-
-	if nsh2 == "" {
-		t.Errorf("generateSPDXNamespace(%s, %s, %s): expected non-empty string, but got empty string", buildID1, timestamp1, files2)
-	}
-
-	if nsh1 == nsh2 {
-		t.Errorf("generateSPDXNamespace(%s, %s, %s) and generateSPDXNamespace(%s, %s, %s): expected different namespace hashes, but got the same", buildID1, timestamp1, files1, buildID1, timestamp1, files2)
-	}
-
-	// Test case 5: empty build ids, same timestamps and different files
-	nsh1 = generateSPDXNamespace("", timestamp1, files1)
-	nsh2 = generateSPDXNamespace("", timestamp1, files2)
-
-	if nsh1 == "" {
-		t.Errorf("generateSPDXNamespace(%s, %s, %s): expected non-empty string, but got empty string", "", timestamp1, files1)
-	}
-
-	if nsh2 == "" {
-		t.Errorf("generateSPDXNamespace(%s, %s, %s): expected non-empty string, but got empty string", "", timestamp1, files2)
-	}
-
-	if nsh1 == nsh2 {
-		t.Errorf("generateSPDXNamespace(%s, %s, %s) and generateSPDXNamespace(%s, %s, %s): expected different namespace hashes, but got the same", "", timestamp1, files1, "", timestamp1, files2)
-	}
-}
-
-func getCreationInfo(t *testing.T) *spdx.CreationInfo {
-	ci, err := builder2v2.BuildCreationInfoSection2_2("Organization", "Google LLC", nil)
-	if err != nil {
-		t.Errorf("Unable to get creation info: %v", err)
-		return nil
-	}
-	return ci
-}
-
-// validate returns an error if the Document is found to be invalid
-func validate(doc *spdx.Document) error {
-	if doc.SPDXVersion == "" {
-		return fmt.Errorf("SPDXVersion: got nothing, want spdx version")
-	}
-	if doc.DataLicense == "" {
-		return fmt.Errorf("DataLicense: got nothing, want Data License")
-	}
-	if doc.SPDXIdentifier == "" {
-		return fmt.Errorf("SPDXIdentifier: got nothing, want SPDX Identifier")
-	}
-	if doc.DocumentName == "" {
-		return fmt.Errorf("DocumentName: got nothing, want Document Name")
-	}
-	if c := fmt.Sprintf("%v", doc.CreationInfo.Creators[1].Creator); c != "Google LLC" {
-		return fmt.Errorf("Creator: got %v, want  'Google LLC'", c)
-	}
-	_, err := time.Parse(time.RFC3339, doc.CreationInfo.Created)
-	if err != nil {
-		return fmt.Errorf("Invalid time spec: %q: got error %q, want no error", doc.CreationInfo.Created, err)
-	}
-
-	for _, license := range doc.OtherLicenses {
-		if license.ExtractedText == "" {
-			return fmt.Errorf("License file: %q: got nothing, want license text", license.LicenseName)
-		}
-	}
-	return nil
-}
-
-// compareSpdxDocs deep-compares two spdx docs by going through the info section, packages, relationships and licenses
-func compareSpdxDocs(t *testing.T, actual, expected *spdx.Document) {
-
-	if actual == nil || expected == nil {
-		t.Errorf("SBOM: SPDX Doc is nil! Got %v: Expected %v", actual, expected)
-	}
-
-	if actual.DocumentName != expected.DocumentName {
-		t.Errorf("sbom: unexpected SPDX Document Name got %q, want %q", actual.DocumentName, expected.DocumentName)
-	}
-
-	if actual.SPDXVersion != expected.SPDXVersion {
-		t.Errorf("sbom: unexpected SPDX Version got %s, want %s", actual.SPDXVersion, expected.SPDXVersion)
-	}
-
-	if actual.DataLicense != expected.DataLicense {
-		t.Errorf("sbom: unexpected SPDX DataLicense got %s, want %s", actual.DataLicense, expected.DataLicense)
-	}
-
-	if actual.SPDXIdentifier != expected.SPDXIdentifier {
-		t.Errorf("sbom: unexpected SPDX Identified got %s, want %s", actual.SPDXIdentifier, expected.SPDXIdentifier)
-	}
-
-	if actual.DocumentNamespace != expected.DocumentNamespace {
-		t.Errorf("sbom: unexpected SPDX Document Namespace got %s, want %s", actual.DocumentNamespace, expected.DocumentNamespace)
-	}
-
-	// compare creation info
-	compareSpdxCreationInfo(t, actual.CreationInfo, expected.CreationInfo)
-
-	// compare packages
-	if len(actual.Packages) != len(expected.Packages) {
-		t.Errorf("SBOM: Number of Packages is different! Got %d: Expected %d", len(actual.Packages), len(expected.Packages))
-	}
-
-	for i, pkg := range actual.Packages {
-		if !compareSpdxPackages(t, i, pkg, expected.Packages[i]) {
-			break
-		}
-	}
-
-	// compare licenses
-	if len(actual.OtherLicenses) != len(expected.OtherLicenses) {
-		t.Errorf("SBOM: Number of Licenses in actual is different! Got %d: Expected %d", len(actual.OtherLicenses), len(expected.OtherLicenses))
-	}
-	for i, license := range actual.OtherLicenses {
-		if !compareLicenses(t, i, license, expected.OtherLicenses[i]) {
-			break
-		}
-	}
-
-	//compare Relationships
-	if len(actual.Relationships) != len(expected.Relationships) {
-		t.Errorf("SBOM: Number of Licenses in actual is different! Got %d: Expected %d", len(actual.Relationships), len(expected.Relationships))
-	}
-	for i, rl := range actual.Relationships {
-		if !compareRelationShips(t, i, rl, expected.Relationships[i]) {
-			break
-		}
-	}
-}
-
-func compareSpdxCreationInfo(t *testing.T, actual, expected *spdx.CreationInfo) {
-	if actual == nil || expected == nil {
-		t.Errorf("SBOM: Creation info is nil! Got %q: Expected %q", actual, expected)
-	}
-
-	if actual.LicenseListVersion != expected.LicenseListVersion {
-		t.Errorf("SBOM: Creation info license version Error! Got %s: Expected %s", actual.LicenseListVersion, expected.LicenseListVersion)
-	}
-
-	if len(actual.Creators) != len(expected.Creators) {
-		t.Errorf("SBOM: Creation info creators Error! Got %d: Expected %d", len(actual.Creators), len(expected.Creators))
-	}
-
-	for i, info := range actual.Creators {
-		if info != expected.Creators[i] {
-			t.Errorf("SBOM: Creation info creators Error! Got %q: Expected %q", info, expected.Creators[i])
-		}
-	}
-}
-
-func compareSpdxPackages(t *testing.T, i int, actual, expected *spdx.Package) bool {
-	if actual == nil || expected == nil {
-		t.Errorf("SBOM: Packages are nil at index %d! Got %v: Expected %v", i, actual, expected)
-		return false
-	}
-	if actual.PackageName != expected.PackageName {
-		t.Errorf("SBOM: Package name Error at index %d! Got %s: Expected %s", i, actual.PackageName, expected.PackageName)
-		return false
-	}
-
-	if actual.PackageVersion != expected.PackageVersion {
-		t.Errorf("SBOM: Package version Error at index %d! Got %s: Expected %s", i, actual.PackageVersion, expected.PackageVersion)
-		return false
-	}
-
-	if actual.PackageSPDXIdentifier != expected.PackageSPDXIdentifier {
-		t.Errorf("SBOM: Package identifier Error at index %d! Got %s: Expected %s", i, actual.PackageSPDXIdentifier, expected.PackageSPDXIdentifier)
-		return false
-	}
-
-	if actual.PackageDownloadLocation != expected.PackageDownloadLocation {
-		t.Errorf("SBOM: Package download location Error at index %d! Got %s: Expected %s", i, actual.PackageDownloadLocation, expected.PackageDownloadLocation)
-		return false
-	}
-
-	if actual.PackageLicenseConcluded != expected.PackageLicenseConcluded {
-		t.Errorf("SBOM: Package license concluded Error at index %d! Got %s: Expected %s", i, actual.PackageLicenseConcluded, expected.PackageLicenseConcluded)
-		return false
-	}
-	return true
-}
-
-func compareRelationShips(t *testing.T, i int, actual, expected *spdx.Relationship) bool {
-	if actual == nil || expected == nil {
-		t.Errorf("SBOM: Relationships is nil at index %d! Got %v: Expected %v", i, actual, expected)
-		return false
-	}
-
-	if actual.RefA != expected.RefA {
-		t.Errorf("SBOM: Relationship RefA Error at index %d! Got %s: Expected %s", i, actual.RefA, expected.RefA)
-		return false
-	}
-
-	if actual.RefB != expected.RefB {
-		t.Errorf("SBOM: Relationship RefB Error at index %d! Got %s: Expected %s", i, actual.RefB, expected.RefB)
-		return false
-	}
-
-	if actual.Relationship != expected.Relationship {
-		t.Errorf("SBOM: Relationship type Error at index %d! Got %s: Expected %s", i, actual.Relationship, expected.Relationship)
-		return false
-	}
-	return true
-}
-
-func compareLicenses(t *testing.T, i int, actual, expected *spdx.OtherLicense) bool {
-	if actual == nil || expected == nil {
-		t.Errorf("SBOM: Licenses is nil at index %d! Got %v: Expected %v", i, actual, expected)
-		return false
-	}
-
-	if actual.LicenseName != expected.LicenseName {
-		t.Errorf("SBOM: License Name Error at index %d! Got %s: Expected %s", i, actual.LicenseName, expected.LicenseName)
-		return false
-	}
-
-	if actual.LicenseIdentifier != expected.LicenseIdentifier {
-		t.Errorf("SBOM: License Identifier Error at index %d! Got %s: Expected %s", i, actual.LicenseIdentifier, expected.LicenseIdentifier)
-		return false
-	}
-
-	if actual.ExtractedText != expected.ExtractedText {
-		t.Errorf("SBOM: License Extracted Text Error at index %d! Got: %q want: %q", i, actual.ExtractedText, expected.ExtractedText)
-		return false
-	}
-	return true
-}
-
-func fakeTime() string {
-	t := time.UnixMicro(0)
-	return t.UTC().Format("2006-01-02T15:04:05Z")
-}
diff --git a/tools/protos/Android.bp b/tools/protos/Android.bp
index c6ad19e..65f13cb 100644
--- a/tools/protos/Android.bp
+++ b/tools/protos/Android.bp
@@ -18,11 +18,6 @@
 
 python_library_host {
     name: "metadata_file_proto_py",
-    version: {
-        py3: {
-            enabled: true,
-        },
-    },
     srcs: [
         "metadata_file.proto",
     ],
diff --git a/tools/releasetools/Android.bp b/tools/releasetools/Android.bp
index e371b23..3467152 100644
--- a/tools/releasetools/Android.bp
+++ b/tools/releasetools/Android.bp
@@ -296,11 +296,6 @@
 
 python_defaults {
     name: "releasetools_binary_defaults",
-    version: {
-        py3: {
-            embedded_launcher: true,
-        },
-    },
     // TODO (b/140144201) Build imgdiff from releasetools_common
     required: [
         "aapt2",
@@ -338,11 +333,6 @@
 
 python_binary_host {
     name: "merge_ota",
-    version: {
-        py3: {
-            embedded_launcher: true,
-        },
-    },
     srcs: [
         "merge_ota.py",
     ],
@@ -357,11 +347,6 @@
 
 python_binary_host {
     name: "create_brick_ota",
-    version: {
-        py3: {
-            embedded_launcher: true,
-        },
-    },
     srcs: [
         "create_brick_ota.py",
     ],
diff --git a/tools/releasetools/add_img_to_target_files.py b/tools/releasetools/add_img_to_target_files.py
index 30a6acc..180bf15 100644
--- a/tools/releasetools/add_img_to_target_files.py
+++ b/tools/releasetools/add_img_to_target_files.py
@@ -572,7 +572,7 @@
 
   default = os.path.join(OPTIONS.input_tmp, "IMAGES", partition_name + ".img")
   assert os.path.exists(default), \
-      "There should be one %s.img" % (partition_name)
+      "Can't find %s for image %s" % (default, partition_name)
   return default
 
 
diff --git a/tools/sbom/Android.bp b/tools/sbom/Android.bp
index 7e2840f..d2e6b55 100644
--- a/tools/sbom/Android.bp
+++ b/tools/sbom/Android.bp
@@ -21,11 +21,6 @@
     srcs: [
         "generate-sbom.py",
     ],
-    version: {
-        py3: {
-            embedded_launcher: true,
-        },
-    },
     libs: [
         "metadata_file_proto_py",
         "libprotobuf-python",
@@ -45,11 +40,6 @@
     srcs: [
         "gen_sbom.py",
     ],
-    version: {
-        py3: {
-            embedded_launcher: true,
-        },
-    },
     libs: [
         "compliance_metadata",
         "metadata_file_proto_py",
@@ -78,11 +68,6 @@
     libs: [
         "sbom_lib",
     ],
-    version: {
-        py3: {
-            embedded_launcher: true,
-        },
-    },
     test_suites: ["general-tests"],
 }
 
@@ -95,11 +80,6 @@
     libs: [
         "sbom_lib",
     ],
-    version: {
-        py3: {
-            embedded_launcher: true,
-        },
-    },
     test_suites: ["general-tests"],
 }
 
@@ -108,11 +88,6 @@
     srcs: [
         "generate-sbom-framework_res.py",
     ],
-    version: {
-        py3: {
-            embedded_launcher: true,
-        },
-    },
     libs: [
         "sbom_lib",
     ],
@@ -123,11 +98,6 @@
     srcs: [
         "gen_notice_xml.py",
     ],
-    version: {
-        py3: {
-            embedded_launcher: true,
-        },
-    },
     libs: [
         "compliance_metadata",
         "metadata_file_proto_py",
diff --git a/tools/tool_event_logger/Android.bp b/tools/tool_event_logger/Android.bp
index 7a1d2aa..d242db8 100644
--- a/tools/tool_event_logger/Android.bp
+++ b/tools/tool_event_logger/Android.bp
@@ -58,10 +58,4 @@
         "asuite_cc_client",
         "tool_event_proto",
     ],
-    version: {
-        py3: {
-            embedded_launcher: true,
-            enabled: true,
-        },
-    },
 }
diff --git a/tools/warn/OWNERS b/tools/warn/OWNERS
index 8551802..93ccd28 100644
--- a/tools/warn/OWNERS
+++ b/tools/warn/OWNERS
@@ -1 +1 @@
-per-file * = chh@google.com,srhines@google.com
+per-file * =srhines@google.com