Merge "Add zip2zip to dependency of relevant binary targets"
diff --git a/core/Makefile b/core/Makefile
index 05dfaa4..e647919 100644
--- a/core/Makefile
+++ b/core/Makefile
@@ -181,6 +181,7 @@
 
 ifeq ($(HOST_OS),linux)
 $(call dist-for-goals,sdk,$(API_FINGERPRINT))
+$(call dist-for-goals,droidcore,$(API_FINGERPRINT))
 endif
 
 INSTALLED_RECOVERYIMAGE_TARGET :=
@@ -5145,7 +5146,7 @@
 
 ifeq (true,$(PRODUCT_SUPPORTS_VBOOT))
 INTERNAL_OTATOOLS_MODULES += \
-  futility \
+  futility-host \
   vboot_signer
 endif
 
@@ -6161,6 +6162,7 @@
 ifdef BUILDING_INIT_BOOT_IMAGE
 	$(hide) $(call package_files-copy-root, $(TARGET_RAMDISK_OUT),$(zip_root)/INIT_BOOT/RAMDISK)
 	$(hide) $(call fs_config,$(zip_root)/INIT_BOOT/RAMDISK,) > $(zip_root)/META/init_boot_filesystem_config.txt
+	$(hide) cp $(RAMDISK_NODE_LIST) $(zip_root)/META/ramdisk_node_list
 ifdef BOARD_KERNEL_PAGESIZE
 	$(hide) echo "$(BOARD_KERNEL_PAGESIZE)" > $(zip_root)/INIT_BOOT/pagesize
 endif # BOARD_KERNEL_PAGESIZE
diff --git a/core/base_rules.mk b/core/base_rules.mk
index 18730aa..ec5a21e 100644
--- a/core/base_rules.mk
+++ b/core/base_rules.mk
@@ -716,6 +716,15 @@
 ## Compatibility suite files.
 ###########################################################
 ifdef LOCAL_COMPATIBILITY_SUITE
+
+ifneq (,$(LOCAL_FULL_TEST_CONFIG))
+  test_config := $(LOCAL_FULL_TEST_CONFIG)
+else ifneq (,$(LOCAL_TEST_CONFIG))
+  test_config := $(LOCAL_PATH)/$(LOCAL_TEST_CONFIG)
+else
+  test_config := $(wildcard $(LOCAL_PATH)/AndroidTest.xml)
+endif
+
 ifneq (true,$(LOCAL_UNINSTALLABLE_MODULE))
 
 # If we are building a native test or benchmark and its stem variants are not defined,
@@ -762,13 +771,6 @@
 
 
 # Auto-generate build config.
-ifneq (,$(LOCAL_FULL_TEST_CONFIG))
-  test_config := $(LOCAL_FULL_TEST_CONFIG)
-else ifneq (,$(LOCAL_TEST_CONFIG))
-  test_config := $(LOCAL_PATH)/$(LOCAL_TEST_CONFIG)
-else
-  test_config := $(wildcard $(LOCAL_PATH)/AndroidTest.xml)
-endif
 ifeq (,$(test_config))
   ifneq (true,$(is_native))
     is_instrumentation_test := true
@@ -847,16 +849,6 @@
   endif
 endif # $(my_prefix)$(LOCAL_MODULE_CLASS)_$(LOCAL_MODULE)_compat_files
 
-# HACK: pretend a soong LOCAL_FULL_TEST_CONFIG is autogenerated by setting the flag in
-# module-info.json
-# TODO: (b/113029686) Add explicit flag from Soong to determine if a test was
-# autogenerated.
-ifneq (,$(filter $(SOONG_OUT_DIR)%,$(LOCAL_FULL_TEST_CONFIG)))
-  ifeq ($(LOCAL_MODULE_MAKEFILE),$(SOONG_ANDROID_MK))
-    ALL_MODULES.$(my_register_name).auto_test_config := true
-  endif
-endif
-
 
 ifeq ($(use_testcase_folder),true)
 ifneq ($(my_test_data_file_pairs),)
@@ -897,6 +889,17 @@
   $(eval my_compat_dist_test_data_$(suite) := ))
 
 endif  # LOCAL_UNINSTALLABLE_MODULE
+
+# HACK: pretend a soong LOCAL_FULL_TEST_CONFIG is autogenerated by setting the flag in
+# module-info.json
+# TODO: (b/113029686) Add explicit flag from Soong to determine if a test was
+# autogenerated.
+ifneq (,$(filter $(SOONG_OUT_DIR)%,$(LOCAL_FULL_TEST_CONFIG)))
+  ifeq ($(LOCAL_MODULE_MAKEFILE),$(SOONG_ANDROID_MK))
+    ALL_MODULES.$(my_register_name).auto_test_config := true
+  endif
+endif
+
 endif  # LOCAL_COMPATIBILITY_SUITE
 
 my_supported_variant :=
diff --git a/core/tasks/device-tests.mk b/core/tasks/device-tests.mk
index 3196f52..4167a7e 100644
--- a/core/tasks/device-tests.mk
+++ b/core/tasks/device-tests.mk
@@ -39,7 +39,7 @@
 	grep $(HOST_OUT_TESTCASES) $@-shared-libs.list > $@-host-shared-libs.list || true
 	grep $(TARGET_OUT_TESTCASES) $@.list > $@-target.list || true
 	grep -e .*\\.config$$ $@-target.list > $@-target-test-configs.list || true
-	$(hide) $(SOONG_ZIP) -d -o $@ -P host -C $(HOST_OUT) -l $@-host.list -P target -C $(PRODUCT_OUT) -l $@-target.list
+	$(hide) $(SOONG_ZIP) -d -o $@ -P host -C $(HOST_OUT) -l $@-host.list -P target -C $(PRODUCT_OUT) -l $@-target.list -sha256
 	$(hide) $(SOONG_ZIP) -d -o $(device-tests-configs-zip) \
 	  -P host -C $(HOST_OUT) -l $@-host-test-configs.list \
 	  -P target -C $(PRODUCT_OUT) -l $@-target-test-configs.list
diff --git a/core/tasks/general-tests.mk b/core/tasks/general-tests.mk
index 5726ee2..8dbc76f 100644
--- a/core/tasks/general-tests.mk
+++ b/core/tasks/general-tests.mk
@@ -87,7 +87,8 @@
 	$(SOONG_ZIP) -d -o $@ \
 	  -P host -C $(PRIVATE_INTERMEDIATES_DIR) -D $(PRIVATE_INTERMEDIATES_DIR)/tools \
 	  -P host -C $(HOST_OUT) -l $(PRIVATE_INTERMEDIATES_DIR)/host.list \
-	  -P target -C $(PRODUCT_OUT) -l $(PRIVATE_INTERMEDIATES_DIR)/target.list
+	  -P target -C $(PRODUCT_OUT) -l $(PRIVATE_INTERMEDIATES_DIR)/target.list \
+	  -sha256
 	$(SOONG_ZIP) -d -o $(PRIVATE_general_tests_configs_zip) \
 	  -P host -C $(HOST_OUT) -l $(PRIVATE_INTERMEDIATES_DIR)/host-test-configs.list \
 	  -P target -C $(PRODUCT_OUT) -l $(PRIVATE_INTERMEDIATES_DIR)/target-test-configs.list
diff --git a/core/tasks/host-unit-tests.mk b/core/tasks/host-unit-tests.mk
index ed2f2a6..733a2e2 100644
--- a/core/tasks/host-unit-tests.mk
+++ b/core/tasks/host-unit-tests.mk
@@ -41,7 +41,7 @@
 	grep $(TARGET_OUT_TESTCASES) $@.list > $@-target.list || true
 	$(hide) $(SOONG_ZIP) -d -o $@ -P host -C $(HOST_OUT) -l $@-host.list \
 	  -P target -C $(PRODUCT_OUT) -l $@-target.list \
-	  -P host/testcases -C $(HOST_OUT) -l $@-host-libs.list
+	  -P host/testcases -C $(HOST_OUT) -l $@-host-libs.list -sha256
 	rm -f $@.list $@-host.list $@-target.list $@-host-libs.list
 
 host-unit-tests: $(host_unit_tests_zip)
diff --git a/core/tasks/tools/compatibility.mk b/core/tasks/tools/compatibility.mk
index a5f162a..9400890 100644
--- a/core/tasks/tools/compatibility.mk
+++ b/core/tasks/tools/compatibility.mk
@@ -51,7 +51,7 @@
 $(test_suite_jdk): PRIVATE_SUBDIR := $(test_suite_subdir)
 $(test_suite_jdk): $(shell find $(test_suite_jdk_dir) -type f | sort)
 $(test_suite_jdk): $(SOONG_ZIP)
-	$(SOONG_ZIP) -o $@ -P $(PRIVATE_SUBDIR)/jdk -C $(PRIVATE_JDK_DIR) -D $(PRIVATE_JDK_DIR)
+	$(SOONG_ZIP) -o $@ -P $(PRIVATE_SUBDIR)/jdk -C $(PRIVATE_JDK_DIR) -D $(PRIVATE_JDK_DIR) -sha256
 
 $(call declare-license-metadata,$(test_suite_jdk),SPDX-license-identifier-GPL-2.0-with-classpath-exception,permissive,\
   $(test_suite_jdk_dir)/legal/java.base/LICENSE,JDK,prebuilts/jdk/$(notdir $(patsubst %/,%,$(dir $(test_suite_jdk_dir)))))
@@ -123,7 +123,7 @@
 	cp $(PRIVATE_TOOLS) $(PRIVATE_OUT_DIR)/tools
 	$(if $(PRIVATE_DYNAMIC_CONFIG),$(hide) cp $(PRIVATE_DYNAMIC_CONFIG) $(PRIVATE_OUT_DIR)/testcases/$(PRIVATE_SUITE_NAME).dynamic)
 	find $(PRIVATE_RESOURCES) | sort >$@.list
-	$(SOONG_ZIP) -d -o $@.tmp -C $(dir $@) -l $@.list
+	$(SOONG_ZIP) -d -o $@.tmp -C $(dir $@) -l $@.list -sha256
 	$(MERGE_ZIPS) $@ $@.tmp $(PRIVATE_JDK)
 	rm -f $@.tmp
 # Build a list of tests
diff --git a/target/product/runtime_libart.mk b/target/product/runtime_libart.mk
index bd4fd1c..39666ea 100644
--- a/target/product/runtime_libart.mk
+++ b/target/product/runtime_libart.mk
@@ -122,6 +122,7 @@
 # without exceptions).
 PRODUCT_SYSTEM_PROPERTIES += \
     pm.dexopt.post-boot?=extract \
+    pm.dexopt.boot-after-mainline-update?=verify \
     pm.dexopt.install?=speed-profile \
     pm.dexopt.install-fast?=skip \
     pm.dexopt.install-bulk?=speed-profile \
diff --git a/tools/Android.bp b/tools/Android.bp
index 1f0d406..f446973 100644
--- a/tools/Android.bp
+++ b/tools/Android.bp
@@ -64,3 +64,8 @@
   name: "check_elf_file",
   srcs: ["check_elf_file.py"],
 }
+
+python_binary_host {
+  name: "generate_gts_shared_report",
+  srcs: ["generate_gts_shared_report.py"],
+}
diff --git a/tools/finalization/build-step-1-and-2.sh b/tools/finalization/build-step-1-and-2.sh
new file mode 100755
index 0000000..eaaf0cd
--- /dev/null
+++ b/tools/finalization/build-step-1-and-2.sh
@@ -0,0 +1,23 @@
+#!/bin/bash
+
+set -ex
+
+function finalize_main_step12() {
+    local top="$(dirname "$0")"/../../../..
+    source $top/build/make/tools/finalization/environment.sh
+
+    # default target to modify tree and build SDK
+    local m="$top/build/soong/soong_ui.bash --make-mode TARGET_PRODUCT=aosp_arm64 TARGET_BUILD_VARIANT=userdebug"
+
+    # SDK codename -> int
+    source $top/build/make/tools/finalization/finalize-aidl-vndk-sdk-resources.sh
+
+    # Platform/Mainline SDKs build and move to prebuilts
+    source $top/build/make/tools/finalization/localonly-finalize-mainline-sdk.sh
+
+    # REL
+    source $top/build/make/tools/finalization/finalize-sdk-rel.sh
+}
+
+finalize_main_step12
+
diff --git a/tools/finalization/build-step-1-and-m.sh b/tools/finalization/build-step-1-and-m.sh
new file mode 100755
index 0000000..0e7129f
--- /dev/null
+++ b/tools/finalization/build-step-1-and-m.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+
+set -ex
+
+function finalize_main_step1_and_m() {
+    local top="$(dirname "$0")"/../../../..
+    source $top/build/make/tools/finalization/build-step-1.sh
+
+    local m="$top/build/soong/soong_ui.bash --make-mode TARGET_PRODUCT=aosp_arm64 TARGET_BUILD_VARIANT=userdebug"
+
+    # This command tests:
+    #   The release state for AIDL.
+    #   ABI difference between user and userdebug builds.
+    #   Resource/SDK finalization.
+    AIDL_FROZEN_REL=true $m
+}
+
+finalize_main_step1_and_m
+
diff --git a/tools/finalization/build-step-1.sh b/tools/finalization/build-step-1.sh
new file mode 100755
index 0000000..edf497e
--- /dev/null
+++ b/tools/finalization/build-step-1.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+
+set -ex
+
+function finalize_main_step1() {
+    local top="$(dirname "$0")"/../../../..
+    source $top/build/make/tools/finalization/environment.sh
+
+    # default target to modify tree and build SDK
+    local m="$top/build/soong/soong_ui.bash --make-mode TARGET_PRODUCT=aosp_arm64 TARGET_BUILD_VARIANT=userdebug"
+
+    # Build finalization artifacts.
+    source $top/build/make/tools/finalization/finalize-aidl-vndk-sdk-resources.sh
+}
+
+finalize_main_step1
+
diff --git a/tools/finalization/build_soong_java_droidstubs.go.apply_hack.diff b/tools/finalization/build_soong_java_droidstubs.go.apply_hack.diff
new file mode 100644
index 0000000..9ced2a9
--- /dev/null
+++ b/tools/finalization/build_soong_java_droidstubs.go.apply_hack.diff
@@ -0,0 +1,30 @@
+From 12eea1512f2612f41b5cf7004ee2e6a189d548d7 Mon Sep 17 00:00:00 2001
+From: Alex Buynytskyy <alexbuy@google.com>
+Date: Thu, 01 Sep 2022 10:44:21 -0700
+Subject: [PATCH] Hacky workaround for half-finalized builds.
+
+Metalava increments the SDK level by one when it's not "REL", so we
+temporarily force the build to be "REL" while we're still in the
+process of finalizing it.
+
+This CL must be reverted as part of actually declaring "REL".
+
+Bug: none
+Test: Build
+Change-Id: I8c24c6dabec0270bc384d8465c582a4ddbe8bd6c
+---
+
+diff --git a/java/droidstubs.go b/java/droidstubs.go
+index 5777b18..ec4a0f4 100644
+--- a/java/droidstubs.go
++++ b/java/droidstubs.go
+@@ -386,7 +386,8 @@
+ 	}
+ 	if apiVersions != nil {
+ 		cmd.FlagWithArg("--current-version ", ctx.Config().PlatformSdkVersion().String())
+-		cmd.FlagWithArg("--current-codename ", ctx.Config().PlatformSdkCodename())
++		// STOPSHIP: RESTORE THIS LOGIC WHEN DECLARING "REL" BUILD
++		// cmd.FlagWithArg("--current-codename ", ctx.Config().PlatformSdkCodename())
+ 		cmd.FlagWithInput("--apply-api-levels ", apiVersions)
+ 	}
+ }
diff --git a/tools/finalization/build_soong_java_droidstubs.go.revert_hack.diff b/tools/finalization/build_soong_java_droidstubs.go.revert_hack.diff
new file mode 100644
index 0000000..7dec97c
--- /dev/null
+++ b/tools/finalization/build_soong_java_droidstubs.go.revert_hack.diff
@@ -0,0 +1,26 @@
+From c0f6e8fe4c3b6803be97aeea6683631d616412f4 Mon Sep 17 00:00:00 2001
+From: Alex Buynytskyy <alexbuy@google.com>
+Date: Thu, 08 Dec 2022 17:52:52 +0000
+Subject: [PATCH] Revert "Hacky workaround for half-finalized builds."
+
+This reverts commit 12eea1512f2612f41b5cf7004ee2e6a189d548d7.
+
+Reason for revert: finalization-2
+
+Change-Id: Ifc801271628808693b1cb20206f8f81c9a6c694d
+---
+
+diff --git a/java/droidstubs.go b/java/droidstubs.go
+index ec4a0f4..5777b18 100644
+--- a/java/droidstubs.go
++++ b/java/droidstubs.go
+@@ -386,8 +386,7 @@
+ 	}
+ 	if apiVersions != nil {
+ 		cmd.FlagWithArg("--current-version ", ctx.Config().PlatformSdkVersion().String())
+-		// STOPSHIP: RESTORE THIS LOGIC WHEN DECLARING "REL" BUILD
+-		// cmd.FlagWithArg("--current-codename ", ctx.Config().PlatformSdkCodename())
++		cmd.FlagWithArg("--current-codename ", ctx.Config().PlatformSdkCodename())
+ 		cmd.FlagWithInput("--apply-api-levels ", apiVersions)
+ 	}
+ }
diff --git a/tools/finalization/environment.sh b/tools/finalization/environment.sh
index 125c704..983e19d 100755
--- a/tools/finalization/environment.sh
+++ b/tools/finalization/environment.sh
@@ -5,12 +5,11 @@
 export FINAL_BUG_ID='0'
 
 export FINAL_PLATFORM_CODENAME='UpsideDownCake'
+export CURRENT_PLATFORM_CODENAME='VanillaIceCream'
 export FINAL_PLATFORM_CODENAME_JAVA='UPSIDE_DOWN_CAKE'
 export FINAL_PLATFORM_SDK_VERSION='34'
 export FINAL_PLATFORM_VERSION='14'
 
 export FINAL_BUILD_PREFIX='UP1A'
 
-export FINAL_MAINLINE_EXTENSION='6'
-export FINAL_MAINLINE_SDK_COMMIT_MESSAGE=''
-export FINAL_MAINLINE_SDK_BUILD_ID=0
+export FINAL_MAINLINE_EXTENSION='6'
\ No newline at end of file
diff --git a/tools/finalization/finalize-aidl-vndk-sdk-resources.sh b/tools/finalization/finalize-aidl-vndk-sdk-resources.sh
index 0426fdd..61910d3 100755
--- a/tools/finalization/finalize-aidl-vndk-sdk-resources.sh
+++ b/tools/finalization/finalize-aidl-vndk-sdk-resources.sh
@@ -2,25 +2,17 @@
 
 set -ex
 
-function finalize_aidl_vndk_sdk_resources() {
-    local top="$(dirname "$0")"/../../../..
-    source $top/build/make/tools/finalization/environment.sh
+function apply_droidstubs_hack() {
+    if ! grep -q 'STOPSHIP: RESTORE THIS LOGIC WHEN DECLARING "REL" BUILD' "$top/build/soong/java/droidstubs.go" ; then 
+        git -C "$top/build/soong" apply --allow-empty ../../build/make/tools/finalization/build_soong_java_droidstubs.go.apply_hack.diff
+    fi
+}
 
-    local SDK_CODENAME="public static final int $FINAL_PLATFORM_CODENAME_JAVA = CUR_DEVELOPMENT;"
-    local SDK_VERSION="public static final int $FINAL_PLATFORM_CODENAME_JAVA = $FINAL_PLATFORM_SDK_VERSION;"
-
-    # default target to modify tree and build SDK
-    local m="$top/build/soong/soong_ui.bash --make-mode TARGET_PRODUCT=aosp_arm64 TARGET_BUILD_VARIANT=userdebug"
-
-    # This script is WIP and only finalizes part of the Android branch for release.
-    # The full process can be found at (INTERNAL) go/android-sdk-finalization.
-
-    # Update references in the codebase to new API version (TODO)
-
-    # bionic/NDK
+function finalize_bionic_ndk() {
     # Adding __ANDROID_API_<>__.
     # If this hasn't done then it's not used and not really needed. Still, let's check and add this.
-    if ! grep -q "\__.*$((${FINAL_PLATFORM_SDK_VERSION}))" api-level.h ; then
+    local api_level="$top/bionic/libc/include/android/api-level.h"
+    if ! grep -q "\__.*$((${FINAL_PLATFORM_SDK_VERSION}))" $api_level ; then
         local tmpfile=$(mktemp /tmp/finalization.XXXXXX)
         echo "
 /** Names the \"${FINAL_PLATFORM_CODENAME:0:1}\" API level ($FINAL_PLATFORM_SDK_VERSION), for comparison against \`__ANDROID_API__\`. */
@@ -31,6 +23,61 @@
 
         rm "$tmpfile"
     fi
+}
+
+function finalize_modules_utils() {
+    local shortCodename="${FINAL_PLATFORM_CODENAME:0:1}"
+    local methodPlaceholder="INSERT_NEW_AT_LEAST_${shortCodename}_METHOD_HERE"
+
+    local tmpfile=$(mktemp /tmp/finalization.XXXXXX)
+    echo "    /** Checks if the device is running on a release version of Android $FINAL_PLATFORM_CODENAME or newer */
+    @ChecksSdkIntAtLeast(api = $FINAL_PLATFORM_SDK_VERSION /* BUILD_VERSION_CODES.$FINAL_PLATFORM_CODENAME */)
+    public static boolean isAtLeast${FINAL_PLATFORM_CODENAME:0:1}() {
+        return SDK_INT >= $FINAL_PLATFORM_SDK_VERSION;
+    }" > "$tmpfile"
+
+    local javaFuncRegex='\/\*\*[^{]*isAtLeast'"${shortCodename}"'() {[^{}]*}'
+    local javaFuncReplace="N;N;N;N;N;N;N;N; s/$javaFuncRegex/$methodPlaceholder/; /$javaFuncRegex/!{P;D};"
+
+    local javaSdkLevel="$top/frameworks/libs/modules-utils/java/com/android/modules/utils/build/SdkLevel.java"
+    sed -i "$javaFuncReplace" $javaSdkLevel
+
+    sed -i "/${methodPlaceholder}"'/{
+           r '"$tmpfile"'
+           d}' $javaSdkLevel
+
+    echo "// Checks if the device is running on release version of Android ${FINAL_PLATFORM_CODENAME:0:1} or newer.
+inline bool IsAtLeast${FINAL_PLATFORM_CODENAME:0:1}() { return android_get_device_api_level() >= $FINAL_PLATFORM_SDK_VERSION; }" > "$tmpfile"
+
+    local cppFuncRegex='\/\/[^{]*IsAtLeast'"${shortCodename}"'() {[^{}]*}'
+    local cppFuncReplace="N;N;N;N;N;N; s/$cppFuncRegex/$methodPlaceholder/; /$cppFuncRegex/!{P;D};"
+
+    local cppSdkLevel="$top/frameworks/libs/modules-utils/build/include/android-modules-utils/sdk_level.h"
+    sed -i "$cppFuncReplace" $cppSdkLevel
+    sed -i "/${methodPlaceholder}"'/{
+           r '"$tmpfile"'
+           d}' $cppSdkLevel
+
+    rm "$tmpfile"
+}
+
+function finalize_aidl_vndk_sdk_resources() {
+    local top="$(dirname "$0")"/../../../..
+    source $top/build/make/tools/finalization/environment.sh
+
+    local SDK_CODENAME="public static final int $FINAL_PLATFORM_CODENAME_JAVA = CUR_DEVELOPMENT;"
+    local SDK_VERSION="public static final int $FINAL_PLATFORM_CODENAME_JAVA = $FINAL_PLATFORM_SDK_VERSION;"
+
+    # default target to modify tree and build SDK
+    local m="$top/build/soong/soong_ui.bash --make-mode TARGET_PRODUCT=aosp_arm64 TARGET_BUILD_VARIANT=userdebug"
+
+    # The full process can be found at (INTERNAL) go/android-sdk-finalization.
+
+    # apply droidstubs hack to prevent tools from incrementing an API version
+    apply_droidstubs_hack
+
+    # bionic/NDK
+    finalize_bionic_ndk
 
     # VNDK definitions for new SDK version
     cp "$top/development/vndk/tools/definition-tool/datasets/vndk-lib-extra-list-current.txt" \
@@ -51,6 +98,9 @@
 
     # Finalize SDK
 
+    # frameworks/libs/modules-utils
+    finalize_modules_utils
+
     # build/make
     local version_defaults="$top/build/make/core/version_defaults.mk"
     sed -i -e "s/PLATFORM_SDK_VERSION := .*/PLATFORM_SDK_VERSION := ${FINAL_PLATFORM_SDK_VERSION}/g" $version_defaults
diff --git a/tools/finalization/finalize-sdk-rel.sh b/tools/finalization/finalize-sdk-rel.sh
index 6e62a0e..8f8132c 100755
--- a/tools/finalization/finalize-sdk-rel.sh
+++ b/tools/finalization/finalize-sdk-rel.sh
@@ -2,6 +2,18 @@
 
 set -ex
 
+function revert_droidstubs_hack() {
+    if grep -q 'STOPSHIP: RESTORE THIS LOGIC WHEN DECLARING "REL" BUILD' "$top/build/soong/java/droidstubs.go" ; then 
+        git -C "$top/build/soong" apply --allow-empty ../../build/make/tools/finalization/build_soong_java_droidstubs.go.revert_hack.diff
+    fi
+}
+
+function apply_prerelease_sdk_hack() {
+    if ! grep -q 'STOPSHIP: hack for the pre-release SDK' "$top/frameworks/base/core/java/android/content/pm/parsing/FrameworkParsingPackageUtils.java" ; then 
+        git -C "$top/frameworks/base" apply --allow-empty ../../build/make/tools/finalization/frameworks_base.apply_hack.diff
+    fi
+}
+
 function finalize_sdk_rel() {
     local top="$(dirname "$0")"/../../../..
     source $top/build/make/tools/finalization/environment.sh
@@ -9,6 +21,12 @@
     # default target to modify tree and build SDK
     local m="$top/build/soong/soong_ui.bash --make-mode TARGET_PRODUCT=aosp_arm64 TARGET_BUILD_VARIANT=userdebug"
 
+    # revert droidstubs hack now we are switching to REL
+    revert_droidstubs_hack
+
+    # let the apps built with pre-release SDK parse
+    apply_prerelease_sdk_hack
+
     # adb keys
     $m adb
     LOGNAME=android-eng HOSTNAME=google.com "$top/out/host/linux-x86/bin/adb" keygen "$top/vendor/google/security/adb/${FINAL_PLATFORM_VERSION}.adb_key"
@@ -18,6 +36,9 @@
 
     # cts
     echo "$FINAL_PLATFORM_VERSION" > "$top/cts/tests/tests/os/assets/platform_versions.txt"
+    if [ "$FINAL_PLATFORM_CODENAME" != "$CURRENT_PLATFORM_CODENAME" ]; then
+        echo "$CURRENT_PLATFORM_CODENAME" >> "./cts/tests/tests/os/assets/platform_versions.txt"
+    fi
     git -C "$top/cts" mv hostsidetests/theme/assets/${FINAL_PLATFORM_CODENAME} hostsidetests/theme/assets/${FINAL_PLATFORM_SDK_VERSION}
 
     # system/sepolicy
@@ -29,7 +50,7 @@
     mv "$top/prebuilts/abi-dumps/ndk/current" "$top/prebuilts/abi-dumps/ndk/$FINAL_PLATFORM_SDK_VERSION"
 
     # prebuilts/abi-dumps/vndk
-    mv "$top/prebuilts/abi-dumps/vndk/$FINAL_PLATFORM_CODENAME" "$top/prebuilts/abi-dumps/vndk/$FINAL_PLATFORM_SDK_VERSION"
+    mv "$top/prebuilts/abi-dumps/vndk/$CURRENT_PLATFORM_CODENAME" "$top/prebuilts/abi-dumps/vndk/$FINAL_PLATFORM_SDK_VERSION"
 
     # prebuilts/abi-dumps/platform
     mv "$top/prebuilts/abi-dumps/platform/current" "$top/prebuilts/abi-dumps/platform/$FINAL_PLATFORM_SDK_VERSION"
diff --git a/tools/finalization/frameworks_base.apply_hack.diff b/tools/finalization/frameworks_base.apply_hack.diff
new file mode 100644
index 0000000..545c230
--- /dev/null
+++ b/tools/finalization/frameworks_base.apply_hack.diff
@@ -0,0 +1,129 @@
+From 3c9a5321dc94124367f2f4363d85a8f488f5d4d1 Mon Sep 17 00:00:00 2001
+From: Yurii Zubrytskyi <zyy@google.com>
+Date: Wed, 04 May 2022 01:05:24 -0700
+Subject: [PATCH] HACK: allow apps with pre-release SDK RESTRICT AUTOMERGE
+
+Revert before releasing
+Let the apps built with pre-release Tiramisu SDK parse
++ fix a test that didn't expect REL builds to throw
+  when checking for lettered versions
+
+Test: build
+Bug: 225745567
+Bug: 231407096
+Change-Id: Ia0de2ab1a99e5f186f0d871e6225d88bf3308df6
+---
+
+diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
+index c15b3e0..3f4df4d 100644
+--- a/core/java/android/content/pm/PackageParser.java
++++ b/core/java/android/content/pm/PackageParser.java
+@@ -2628,6 +2628,15 @@
+             return Build.VERSION_CODES.CUR_DEVELOPMENT;
+         }
+ 
++        // STOPSHIP: hack for the pre-release SDK
++        if (platformSdkCodenames.length == 0
++                && Build.VERSION.KNOWN_CODENAMES.stream().max(String::compareTo).orElse("").equals(
++                targetCode)) {
++            Slog.w(TAG, "Package requires development platform " + targetCode
++                    + ", returning current version " + Build.VERSION.SDK_INT);
++            return Build.VERSION.SDK_INT;
++        }
++
+         // Otherwise, we're looking at an incompatible pre-release SDK.
+         if (platformSdkCodenames.length > 0) {
+             outError[0] = "Requires development platform " + targetCode
+@@ -2699,6 +2708,15 @@
+             return Build.VERSION_CODES.CUR_DEVELOPMENT;
+         }
+ 
++        // STOPSHIP: hack for the pre-release SDK
++        if (platformSdkCodenames.length == 0
++                && Build.VERSION.KNOWN_CODENAMES.stream().max(String::compareTo).orElse("").equals(
++                minCode)) {
++            Slog.w(TAG, "Package requires min development platform " + minCode
++                    + ", returning current version " + Build.VERSION.SDK_INT);
++            return Build.VERSION.SDK_INT;
++        }
++
+         // Otherwise, we're looking at an incompatible pre-release SDK.
+         if (platformSdkCodenames.length > 0) {
+             outError[0] = "Requires development platform " + minCode
+diff --git a/core/java/android/content/pm/parsing/FrameworkParsingPackageUtils.java b/core/java/android/content/pm/parsing/FrameworkParsingPackageUtils.java
+index 3e1c5bb..8cc4cdb 100644
+--- a/core/java/android/content/pm/parsing/FrameworkParsingPackageUtils.java
++++ b/core/java/android/content/pm/parsing/FrameworkParsingPackageUtils.java
+@@ -316,6 +316,15 @@
+             return input.success(Build.VERSION_CODES.CUR_DEVELOPMENT);
+         }
+ 
++        // STOPSHIP: hack for the pre-release SDK
++        if (platformSdkCodenames.length == 0
++                && Build.VERSION.KNOWN_CODENAMES.stream().max(String::compareTo).orElse("").equals(
++                        minCode)) {
++            Slog.w(TAG, "Parsed package requires min development platform " + minCode
++                    + ", returning current version " + Build.VERSION.SDK_INT);
++            return input.success(Build.VERSION.SDK_INT);
++        }
++
+         // Otherwise, we're looking at an incompatible pre-release SDK.
+         if (platformSdkCodenames.length > 0) {
+             return input.error(PackageManager.INSTALL_FAILED_OLDER_SDK,
+@@ -368,19 +377,27 @@
+             return input.success(targetVers);
+         }
+ 
++        // If it's a pre-release SDK and the codename matches this platform, it
++        // definitely targets this SDK.
++        if (matchTargetCode(platformSdkCodenames, targetCode)) {
++            return input.success(Build.VERSION_CODES.CUR_DEVELOPMENT);
++        }
++
++        // STOPSHIP: hack for the pre-release SDK
++        if (platformSdkCodenames.length == 0
++                && Build.VERSION.KNOWN_CODENAMES.stream().max(String::compareTo).orElse("").equals(
++                        targetCode)) {
++            Slog.w(TAG, "Parsed package requires development platform " + targetCode
++                    + ", returning current version " + Build.VERSION.SDK_INT);
++            return input.success(Build.VERSION.SDK_INT);
++        }
++
+         try {
+             if (allowUnknownCodenames && UnboundedSdkLevel.isAtMost(targetCode)) {
+                 return input.success(Build.VERSION_CODES.CUR_DEVELOPMENT);
+             }
+         } catch (IllegalArgumentException e) {
+-            // isAtMost() throws it when encountering an older SDK codename
+-            return input.error(PackageManager.INSTALL_FAILED_OLDER_SDK, e.getMessage());
+-        }
+-
+-        // If it's a pre-release SDK and the codename matches this platform, it
+-        // definitely targets this SDK.
+-        if (matchTargetCode(platformSdkCodenames, targetCode)) {
+-            return input.success(Build.VERSION_CODES.CUR_DEVELOPMENT);
++            return input.error(PackageManager.INSTALL_FAILED_OLDER_SDK, "Bad package SDK");
+         }
+ 
+         // Otherwise, we're looking at an incompatible pre-release SDK.
+diff --git a/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java b/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java
+index 92c7871..687e8f7 100644
+--- a/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java
++++ b/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java
+@@ -446,14 +446,14 @@
+                         + "    <library \n"
+                         + "        name=\"foo\"\n"
+                         + "        file=\"" + mFooJar + "\"\n"
+-                        + "        on-bootclasspath-before=\"Q\"\n"
++                        + "        on-bootclasspath-before=\"A\"\n"
+                         + "        on-bootclasspath-since=\"W\"\n"
+                         + "     />\n\n"
+                         + " </permissions>";
+         parseSharedLibraries(contents);
+         assertFooIsOnlySharedLibrary();
+         SystemConfig.SharedLibraryEntry entry = mSysConfig.getSharedLibraries().get("foo");
+-        assertThat(entry.onBootclasspathBefore).isEqualTo("Q");
++        assertThat(entry.onBootclasspathBefore).isEqualTo("A");
+         assertThat(entry.onBootclasspathSince).isEqualTo("W");
+     }
+ 
diff --git a/tools/finalization/frameworks_base.revert_hack.diff b/tools/finalization/frameworks_base.revert_hack.diff
new file mode 100644
index 0000000..1d147b1
--- /dev/null
+++ b/tools/finalization/frameworks_base.revert_hack.diff
@@ -0,0 +1,125 @@
+From b4ae5c71f327d00081bbb0b7b26d48eb88761fbc Mon Sep 17 00:00:00 2001
+From: Alex Buynytskyy <alexbuy@google.com>
+Date: Tue, 21 Feb 2023 01:43:14 +0000
+Subject: [PATCH] Revert "HACK: allow apps with pre-release SDK RESTRICT AUTOMERGE"
+
+This reverts commit 3c9a5321dc94124367f2f4363d85a8f488f5d4d1.
+
+Reason for revert: not needed anymore
+
+Change-Id: I5c5e3af78a41e7bd8cbc99464dccc57c345105f3
+---
+
+diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
+index 3f4df4d..c15b3e0 100644
+--- a/core/java/android/content/pm/PackageParser.java
++++ b/core/java/android/content/pm/PackageParser.java
+@@ -2628,15 +2628,6 @@
+             return Build.VERSION_CODES.CUR_DEVELOPMENT;
+         }
+ 
+-        // STOPSHIP: hack for the pre-release SDK
+-        if (platformSdkCodenames.length == 0
+-                && Build.VERSION.KNOWN_CODENAMES.stream().max(String::compareTo).orElse("").equals(
+-                targetCode)) {
+-            Slog.w(TAG, "Package requires development platform " + targetCode
+-                    + ", returning current version " + Build.VERSION.SDK_INT);
+-            return Build.VERSION.SDK_INT;
+-        }
+-
+         // Otherwise, we're looking at an incompatible pre-release SDK.
+         if (platformSdkCodenames.length > 0) {
+             outError[0] = "Requires development platform " + targetCode
+@@ -2708,15 +2699,6 @@
+             return Build.VERSION_CODES.CUR_DEVELOPMENT;
+         }
+ 
+-        // STOPSHIP: hack for the pre-release SDK
+-        if (platformSdkCodenames.length == 0
+-                && Build.VERSION.KNOWN_CODENAMES.stream().max(String::compareTo).orElse("").equals(
+-                minCode)) {
+-            Slog.w(TAG, "Package requires min development platform " + minCode
+-                    + ", returning current version " + Build.VERSION.SDK_INT);
+-            return Build.VERSION.SDK_INT;
+-        }
+-
+         // Otherwise, we're looking at an incompatible pre-release SDK.
+         if (platformSdkCodenames.length > 0) {
+             outError[0] = "Requires development platform " + minCode
+diff --git a/core/java/android/content/pm/parsing/FrameworkParsingPackageUtils.java b/core/java/android/content/pm/parsing/FrameworkParsingPackageUtils.java
+index 8cc4cdb..3e1c5bb 100644
+--- a/core/java/android/content/pm/parsing/FrameworkParsingPackageUtils.java
++++ b/core/java/android/content/pm/parsing/FrameworkParsingPackageUtils.java
+@@ -316,15 +316,6 @@
+             return input.success(Build.VERSION_CODES.CUR_DEVELOPMENT);
+         }
+ 
+-        // STOPSHIP: hack for the pre-release SDK
+-        if (platformSdkCodenames.length == 0
+-                && Build.VERSION.KNOWN_CODENAMES.stream().max(String::compareTo).orElse("").equals(
+-                        minCode)) {
+-            Slog.w(TAG, "Parsed package requires min development platform " + minCode
+-                    + ", returning current version " + Build.VERSION.SDK_INT);
+-            return input.success(Build.VERSION.SDK_INT);
+-        }
+-
+         // Otherwise, we're looking at an incompatible pre-release SDK.
+         if (platformSdkCodenames.length > 0) {
+             return input.error(PackageManager.INSTALL_FAILED_OLDER_SDK,
+@@ -377,27 +368,19 @@
+             return input.success(targetVers);
+         }
+ 
+-        // If it's a pre-release SDK and the codename matches this platform, it
+-        // definitely targets this SDK.
+-        if (matchTargetCode(platformSdkCodenames, targetCode)) {
+-            return input.success(Build.VERSION_CODES.CUR_DEVELOPMENT);
+-        }
+-
+-        // STOPSHIP: hack for the pre-release SDK
+-        if (platformSdkCodenames.length == 0
+-                && Build.VERSION.KNOWN_CODENAMES.stream().max(String::compareTo).orElse("").equals(
+-                        targetCode)) {
+-            Slog.w(TAG, "Parsed package requires development platform " + targetCode
+-                    + ", returning current version " + Build.VERSION.SDK_INT);
+-            return input.success(Build.VERSION.SDK_INT);
+-        }
+-
+         try {
+             if (allowUnknownCodenames && UnboundedSdkLevel.isAtMost(targetCode)) {
+                 return input.success(Build.VERSION_CODES.CUR_DEVELOPMENT);
+             }
+         } catch (IllegalArgumentException e) {
+-            return input.error(PackageManager.INSTALL_FAILED_OLDER_SDK, "Bad package SDK");
++            // isAtMost() throws it when encountering an older SDK codename
++            return input.error(PackageManager.INSTALL_FAILED_OLDER_SDK, e.getMessage());
++        }
++
++        // If it's a pre-release SDK and the codename matches this platform, it
++        // definitely targets this SDK.
++        if (matchTargetCode(platformSdkCodenames, targetCode)) {
++            return input.success(Build.VERSION_CODES.CUR_DEVELOPMENT);
+         }
+ 
+         // Otherwise, we're looking at an incompatible pre-release SDK.
+diff --git a/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java b/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java
+index 687e8f7..92c7871 100644
+--- a/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java
++++ b/services/tests/servicestests/src/com/android/server/systemconfig/SystemConfigTest.java
+@@ -446,14 +446,14 @@
+                         + "    <library \n"
+                         + "        name=\"foo\"\n"
+                         + "        file=\"" + mFooJar + "\"\n"
+-                        + "        on-bootclasspath-before=\"A\"\n"
++                        + "        on-bootclasspath-before=\"Q\"\n"
+                         + "        on-bootclasspath-since=\"W\"\n"
+                         + "     />\n\n"
+                         + " </permissions>";
+         parseSharedLibraries(contents);
+         assertFooIsOnlySharedLibrary();
+         SystemConfig.SharedLibraryEntry entry = mSysConfig.getSharedLibraries().get("foo");
+-        assertThat(entry.onBootclasspathBefore).isEqualTo("A");
++        assertThat(entry.onBootclasspathBefore).isEqualTo("Q");
+         assertThat(entry.onBootclasspathSince).isEqualTo("W");
+     }
+ 
diff --git a/tools/finalization/localonly-finalize-mainline-sdk.sh b/tools/finalization/localonly-finalize-mainline-sdk.sh
index fc887c3..26af30e 100755
--- a/tools/finalization/localonly-finalize-mainline-sdk.sh
+++ b/tools/finalization/localonly-finalize-mainline-sdk.sh
@@ -6,11 +6,15 @@
     local top="$(dirname "$0")"/../../../..
     source $top/build/make/tools/finalization/environment.sh
 
-    # Build modules SDKs.
+    # Build Platform SDKs.
+    $top/build/soong/soong_ui.bash --make-mode TARGET_PRODUCT=sdk TARGET_BUILD_VARIANT=userdebug sdk dist sdk_repo
+
+    # Build Modules SDKs.
     TARGET_BUILD_VARIANT=userdebug UNBUNDLED_BUILD_SDKS_FROM_SOURCE=true "$top/vendor/google/build/mainline_modules_sdks.sh"
 
     # Update prebuilts.
     "$top/prebuilts/build-tools/path/linux-x86/python3" "$top/packages/modules/common/tools/finalize_sdk.py" -l -b 0 -f ${FINAL_MAINLINE_EXTENSION} -r '' 0
+    # "$top/prebuilts/build-tools/path/linux-x86/python3" "$top/prebuilts/sdk/update_prebuilts.py" --local_mode -f ${FINAL_PLATFORM_SDK_VERSION} -e ${FINAL_MAINLINE_EXTENSION} --bug 1 1
 }
 
 finalize_locally_mainline_sdk
diff --git a/tools/finalization/step-1.sh b/tools/finalization/step-1.sh
index db7f1cc..cf21e45 100755
--- a/tools/finalization/step-1.sh
+++ b/tools/finalization/step-1.sh
@@ -14,7 +14,6 @@
 Bug: $FINAL_BUG_ID
 Test: build";
             repo upload --cbr --no-verify -o nokeycheck -t -y . ;
-            git clean -fdx ; git reset --hard ;
         fi'
 }
 
@@ -27,11 +26,11 @@
     # vndk etc finalization
     source $top/build/make/tools/finalization/finalize-aidl-vndk-sdk-resources.sh
 
-    # build to confirm everything is OK
-    AIDL_FROZEN_REL=true $m
-
     # move all changes to finalization branch/topic and upload to gerrit
     commit_step_1_changes
+
+    # build to confirm everything is OK
+    AIDL_FROZEN_REL=true $m
 }
 
 finalize_step_1_main
diff --git a/tools/finalization/step-2.sh b/tools/finalization/step-2.sh
index 926b850..d0b24ae 100755
--- a/tools/finalization/step-2.sh
+++ b/tools/finalization/step-2.sh
@@ -12,7 +12,6 @@
 Test: build";
 
             repo upload --cbr --no-verify -o nokeycheck -t -y . ;
-            git clean -fdx ; git reset --hard ;
         fi'
 }
 
@@ -25,14 +24,11 @@
     # prebuilts etc
     source $top/build/make/tools/finalization/finalize-sdk-rel.sh
 
-    # Update prebuilts.
-    "$top/prebuilts/build-tools/path/linux-x86/python3" "$top/packages/modules/common/tools/finalize_sdk.py" -b ${FINAL_BUG_ID} -f ${FINAL_MAINLINE_EXTENSION} -r "${FINAL_MAINLINE_SDK_COMMIT_MESSAGE}" ${FINAL_MAINLINE_SDK_BUILD_ID}
+    # move all changes to finalization branch/topic and upload to gerrit
+    commit_step_2_changes
 
     # build to confirm everything is OK
     AIDL_FROZEN_REL=true $m
-
-    # move all changes to finalization branch/topic and upload to gerrit
-    commit_step_2_changes
 }
 
 finalize_step_2_main
diff --git a/tools/generate_gts_shared_report.py b/tools/generate_gts_shared_report.py
new file mode 100644
index 0000000..11c9364
--- /dev/null
+++ b/tools/generate_gts_shared_report.py
@@ -0,0 +1,128 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2022 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.
+"""
+Checks and generates a report for gts modules that should be open-sourced.
+
+Usage:
+  generate_gts_open_source_report.py
+    --gtsv-metalic [gts-verifier meta_lic]
+    --gts-test-metalic [android-gts meta_lic]
+    --checkshare [COMPLIANCE_CHECKSHARE]
+    --gts-test-dir [directory of android-gts]
+    --output [output file]
+
+Output example:
+  GTS-Verifier: PASS/FAIL
+  GTS-Modules: PASS/FAIL
+    GtsIncrementalInstallTestCases_BackgroundProcess
+    GtsUnsignedNetworkStackTestCases
+"""
+import sys
+import argparse
+import subprocess
+import re
+
+def _get_args():
+    """Parses input arguments."""
+    parser = argparse.ArgumentParser()
+    parser.add_argument(
+        '--gtsv-metalic', required=True,
+        help='license meta_lic file path of gts-verifier.zip')
+    parser.add_argument(
+        '--gts-test-metalic', required=True,
+        help='license meta_lic file path of android-gts.zip')
+    parser.add_argument(
+        '--checkshare', required=True,
+        help='path of the COMPLIANCE_CHECKSHARE tool')
+    parser.add_argument(
+        '--gts-test-dir', required=True,
+        help='directory of android-gts')
+    parser.add_argument(
+        '-o', '--output', required=True,
+        help='file path of the output report')
+    return parser.parse_args()
+
+def _check_gtsv(checkshare: str, gtsv_metalic: str) -> str:
+    """Checks gts-verifier license.
+
+    Args:
+      checkshare: path of the COMPLIANCE_CHECKSHARE tool
+      gtsv_metalic: license meta_lic file path of gts-verifier.zip
+
+    Returns:
+      PASS when gts-verifier.zip doesn't need to be shared, and FAIL
+      when gts-verifier.zip need to be shared.
+    """
+    cmd = f'{checkshare} {gtsv_metalic}'
+    proc = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE,
+                            stderr=subprocess.PIPE)
+    proc.communicate()
+    return 'PASS' if proc.returncode == 0 else 'FAIL'
+
+def _check_gts_test(checkshare: str, gts_test_metalic: str,
+                    gts_test_dir: str) -> tuple[str, set[str]]:
+    """Checks android-gts license.
+
+    Args:
+      checkshare: path of the COMPLIANCE_CHECKSHARE tool
+      gts_test_metalic: license meta_lic file path of android-gts.zip
+      gts_test_dir: directory of android-gts
+
+    Returns:
+      Check result (PASS when android-gts doesn't need to be shared,
+      FAIL when some gts modules need to be shared) and gts modules
+      that need to be shared.
+    """
+    cmd = f'{checkshare} {gts_test_metalic}'
+    proc = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE,
+                            stderr=subprocess.PIPE)
+    _, str_stderr = map(lambda b: b.decode(), proc.communicate())
+    if proc.returncode == 0:
+        return 'PASS', []
+    open_source_modules = set()
+    for error_line in str_stderr.split('\n'):
+        # Skip the empty liness
+        if not error_line:
+            continue
+        module_meta_lic = error_line.strip().split()[0]
+        groups = re.fullmatch(
+            re.compile(f'.*/{gts_test_dir}/(.*)'), module_meta_lic)
+        if groups:
+            open_source_modules.add(
+                groups[1].removesuffix('.meta_lic'))
+    return 'FAIL', open_source_modules
+
+
+def main(argv):
+    args = _get_args()
+
+    gtsv_metalic = args.gtsv_metalic
+    gts_test_metalic = args.gts_test_metalic
+    output_file = args.output
+    checkshare = args.checkshare
+    gts_test_dir = args.gts_test_dir
+
+    with open(output_file, 'w') as file:
+        result = _check_gtsv(checkshare, gtsv_metalic)
+        file.write(f'GTS-Verifier: {result}\n')
+        result, open_source_modules = _check_gts_test(
+            checkshare, gts_test_metalic, gts_test_dir)
+        file.write(f'GTS-Modules: {result}\n')
+        for open_source_module in open_source_modules:
+            file.write(f'\t{open_source_module}\n')
+
+if __name__ == "__main__":
+    main(sys.argv)
\ No newline at end of file
diff --git a/tools/releasetools/add_img_to_target_files.py b/tools/releasetools/add_img_to_target_files.py
index b45b0a3..e154a0f 100644
--- a/tools/releasetools/add_img_to_target_files.py
+++ b/tools/releasetools/add_img_to_target_files.py
@@ -1001,7 +1001,8 @@
   if has_init_boot:
     banner("init_boot")
     init_boot_image = common.GetBootableImage(
-        "IMAGES/init_boot.img", "init_boot.img", OPTIONS.input_tmp, "INIT_BOOT")
+        "IMAGES/init_boot.img", "init_boot.img", OPTIONS.input_tmp, "INIT_BOOT",
+        dev_nodes=True)
     if init_boot_image:
       partitions['init_boot'] = os.path.join(
           OPTIONS.input_tmp, "IMAGES", "init_boot.img")
diff --git a/tools/releasetools/common.py b/tools/releasetools/common.py
index 2ae3964..8d16ca0 100644
--- a/tools/releasetools/common.py
+++ b/tools/releasetools/common.py
@@ -1547,14 +1547,20 @@
 
 
 def _MakeRamdisk(sourcedir, fs_config_file=None,
+                 dev_node_file=None,
                  ramdisk_format=RamdiskFormat.GZ):
   ramdisk_img = tempfile.NamedTemporaryFile()
 
-  if fs_config_file is not None and os.access(fs_config_file, os.F_OK):
-    cmd = ["mkbootfs", "-f", fs_config_file,
-           os.path.join(sourcedir, "RAMDISK")]
-  else:
-    cmd = ["mkbootfs", os.path.join(sourcedir, "RAMDISK")]
+  cmd = ["mkbootfs"]
+
+  if fs_config_file and os.access(fs_config_file, os.F_OK):
+    cmd.extend(["-f", fs_config_file])
+
+  if dev_node_file and os.access(dev_node_file, os.F_OK):
+    cmd.extend(["-n", dev_node_file])
+
+  cmd.append(os.path.join(sourcedir, "RAMDISK"))
+
   p1 = Run(cmd, stdout=subprocess.PIPE)
   if ramdisk_format == RamdiskFormat.LZ4:
     p2 = Run(["lz4", "-l", "-12", "--favor-decSpeed"], stdin=p1.stdout,
@@ -1572,7 +1578,8 @@
   return ramdisk_img
 
 
-def _BuildBootableImage(image_name, sourcedir, fs_config_file, info_dict=None,
+def _BuildBootableImage(image_name, sourcedir, fs_config_file,
+                        dev_node_file=None, info_dict=None,
                         has_ramdisk=False, two_step_image=False):
   """Build a bootable image from the specified sourcedir.
 
@@ -1614,7 +1621,7 @@
 
   if has_ramdisk:
     ramdisk_format = GetRamdiskFormat(info_dict)
-    ramdisk_img = _MakeRamdisk(sourcedir, fs_config_file,
+    ramdisk_img = _MakeRamdisk(sourcedir, fs_config_file, dev_node_file,
                                ramdisk_format=ramdisk_format)
 
   # use MKBOOTIMG from environ, or "mkbootimg" if empty or not set
@@ -1822,7 +1829,8 @@
 
 
 def GetBootableImage(name, prebuilt_name, unpack_dir, tree_subdir,
-                     info_dict=None, two_step_image=False):
+                     info_dict=None, two_step_image=False,
+                     dev_nodes=False):
   """Return a File object with the desired bootable image.
 
   Look for it in 'unpack_dir'/BOOTABLE_IMAGES under the name 'prebuilt_name',
@@ -1858,6 +1866,8 @@
   fs_config = "META/" + tree_subdir.lower() + "_filesystem_config.txt"
   data = _BuildBootableImage(prebuilt_name, os.path.join(unpack_dir, tree_subdir),
                              os.path.join(unpack_dir, fs_config),
+                             os.path.join(unpack_dir, 'META/ramdisk_node_list')
+                                if dev_nodes else None,
                              info_dict, has_ramdisk, two_step_image)
   if data:
     return File(name, data)