Merge "Add current build release"
diff --git a/android/allowlists/allowlists.go b/android/allowlists/allowlists.go
index 9bd0693..a932a91 100644
--- a/android/allowlists/allowlists.go
+++ b/android/allowlists/allowlists.go
@@ -307,6 +307,7 @@
 		"libandroid_runtime_vm_headers",
 		"libaudioclient_aidl_conversion_util",
 		"libaudioutils_fixedfft",
+		"libbinder_aidl",
 		"libbinder_headers",
 		"libbinder_headers_platform_shared",
 		"libbluetooth-types-header",
@@ -328,6 +329,8 @@
 		"libpdx_headers",
 		"libprocpartition",
 		"libruy_static",
+		"libandroidio",
+		"libandroidio_srcs",
 		"libserviceutils",
 		"libstagefright_enc_common",
 		"libstagefright_foundation_headers",
@@ -392,6 +395,13 @@
 		//system/libhidl
 		// needed by cc_hidl_library
 		"libhidlbase",
+
+		//frameworks/native
+		"framework_native_aidl_binder",
+		"framework_native_aidl_gui",
+
+		//frameworks/native/libs/input
+		"inputconstants_aidl",
 	}
 
 	Bp2buildModuleTypeAlwaysConvertList = []string{
@@ -487,8 +497,6 @@
 		"libartd-runtime-gtest",                                      // depends on unconverted modules: libgtest_isolated, libartd-compiler, libdexfiled, libprofiled, libartbased, libartbased-art-gtest
 		"libdebuggerd_handler",                                       // depends on unconverted module libdebuggerd_handler_core
 		"libdebuggerd_handler_core", "libdebuggerd_handler_fallback", // depends on unconverted module libdebuggerd
-		"libdexfile",                                              // depends on unconverted modules: dexfile_operator_srcs, libartbase, libartpalette,
-		"libdexfile_static",                                       // depends on unconverted modules: libartbase, libdexfile
 		"libdexfiled",                                             // depends on unconverted modules: dexfile_operator_srcs, libartbased, libartpalette
 		"libfastdeploy_host",                                      // depends on unconverted modules: libandroidfw, libusb, AdbWinApi
 		"libgmock_main_ndk",                                       // depends on unconverted modules: libgtest_ndk_c++
diff --git a/android/apex.go b/android/apex.go
index b583be3..00b7241 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -454,7 +454,8 @@
 	}
 	return InList(what, apex_available) ||
 		(what != AvailableToPlatform && InList(AvailableToAnyApex, apex_available)) ||
-		(what == "com.android.btservices" && InList("com.android.bluetooth", apex_available)) ||
+		(what == "com.android.btservices" && InList("com.android.bluetooth", apex_available)) || // TODO b/243054261
+		(what == "com.android.bluetooth" && InList("com.android.btservices", apex_available)) || // TODO b/243054261
 		(strings.HasPrefix(what, "com.android.gki.") && InList(AvailableToGkiApex, apex_available))
 }
 
diff --git a/android/bazel.go b/android/bazel.go
index 183a2f3..aff6116 100644
--- a/android/bazel.go
+++ b/android/bazel.go
@@ -35,6 +35,12 @@
 	Bp2BuildTopLevel = "."
 )
 
+// Bp2buildAidlLibrary describes a filegroup module that are converted to aidl_library
+type Bp2buildAidlLibrary interface {
+	ShouldConvertToAidlLibrary(ctx BazelConversionPathContext) bool
+	GetAidlLibraryLabel(ctx BazelConversionPathContext) string
+}
+
 type BazelConversionStatus struct {
 	// Information about _all_ bp2build targets generated by this module. Multiple targets are
 	// supported as Soong handles some things within a single target that we may choose to split into
diff --git a/android/filegroup.go b/android/filegroup.go
index 9e5769a..7d39238 100644
--- a/android/filegroup.go
+++ b/android/filegroup.go
@@ -15,6 +15,7 @@
 package android
 
 import (
+	"path/filepath"
 	"strings"
 
 	"android/soong/bazel"
@@ -41,6 +42,11 @@
 	Srcs bazel.LabelListAttribute
 }
 
+type bazelAidlLibraryAttributes struct {
+	Srcs                bazel.LabelListAttribute
+	Strip_import_prefix *string
+}
+
 // ConvertWithBp2build performs bp2build conversion of filegroup
 func (fg *fileGroup) ConvertWithBp2build(ctx TopDownMutatorContext) {
 	srcs := bazel.MakeLabelListAttribute(
@@ -66,16 +72,33 @@
 		}
 	}
 
-	attrs := &bazelFilegroupAttributes{
-		Srcs: srcs,
-	}
+	// Convert module that has only AIDL files to aidl_library
+	// If the module has a mixed bag of AIDL and non-AIDL files, split the filegroup manually
+	// and then convert
+	if fg.ShouldConvertToAidlLibrary(ctx) {
+		attrs := &bazelAidlLibraryAttributes{
+			Srcs:                srcs,
+			Strip_import_prefix: fg.properties.Path,
+		}
 
-	props := bazel.BazelTargetModuleProperties{
-		Rule_class:        "filegroup",
-		Bzl_load_location: "//build/bazel/rules:filegroup.bzl",
-	}
+		props := bazel.BazelTargetModuleProperties{
+			Rule_class:        "aidl_library",
+			Bzl_load_location: "//build/bazel/rules/aidl:library.bzl",
+		}
 
-	ctx.CreateBazelTargetModule(props, CommonAttributes{Name: fg.Name()}, attrs)
+		ctx.CreateBazelTargetModule(props, CommonAttributes{Name: fg.Name()}, attrs)
+	} else {
+		attrs := &bazelFilegroupAttributes{
+			Srcs: srcs,
+		}
+
+		props := bazel.BazelTargetModuleProperties{
+			Rule_class:        "filegroup",
+			Bzl_load_location: "//build/bazel/rules:filegroup.bzl",
+		}
+
+		ctx.CreateBazelTargetModule(props, CommonAttributes{Name: fg.Name()}, attrs)
+	}
 }
 
 type fileGroupProperties struct {
@@ -98,12 +121,14 @@
 type fileGroup struct {
 	ModuleBase
 	BazelModuleBase
+	Bp2buildAidlLibrary
 	properties fileGroupProperties
 	srcs       Paths
 }
 
 var _ MixedBuildBuildable = (*fileGroup)(nil)
 var _ SourceFileProducer = (*fileGroup)(nil)
+var _ Bp2buildAidlLibrary = (*fileGroup)(nil)
 
 // filegroup contains a list of files that are referenced by other modules
 // properties (such as "srcs") using the syntax ":<name>". filegroup are
@@ -164,12 +189,17 @@
 }
 
 func (fg *fileGroup) ProcessBazelQueryResponse(ctx ModuleContext) {
-	fg.srcs = PathsForModuleSrcExcludes(ctx, fg.properties.Srcs, fg.properties.Exclude_srcs)
+	bazelCtx := ctx.Config().BazelContext
+	// This is a short-term solution because we rely on info from Android.bp to handle
+	// a converted module. This will block when we want to remove Android.bp for all
+	// converted modules at some point.
+	// TODO(b/242847534): Implement a long-term solution in which we don't need to rely
+	// on info form Android.bp for modules that are already converted to Bazel
+	relativeRoot := ctx.ModuleDir()
 	if fg.properties.Path != nil {
-		fg.srcs = PathsWithModuleSrcSubDir(ctx, fg.srcs, String(fg.properties.Path))
+		relativeRoot = filepath.Join(relativeRoot, *fg.properties.Path)
 	}
 
-	bazelCtx := ctx.Config().BazelContext
 	filePaths, err := bazelCtx.GetOutputFiles(fg.GetBazelLabel(ctx, fg), configKey{Common.String(), CommonOS})
 	if err != nil {
 		ctx.ModuleErrorf(err.Error())
@@ -178,8 +208,27 @@
 
 	bazelOuts := make(Paths, 0, len(filePaths))
 	for _, p := range filePaths {
-		bazelOuts = append(bazelOuts, PathForBazelOutRelative(ctx, ctx.ModuleDir(), p))
+		bazelOuts = append(bazelOuts, PathForBazelOutRelative(ctx, relativeRoot, p))
 	}
-
 	fg.srcs = bazelOuts
 }
+
+func (fg *fileGroup) ShouldConvertToAidlLibrary(ctx BazelConversionPathContext) bool {
+	if len(fg.properties.Srcs) == 0 || !fg.ShouldConvertWithBp2build(ctx) {
+		return false
+	}
+	for _, src := range fg.properties.Srcs {
+		if !strings.HasSuffix(src, ".aidl") {
+			return false
+		}
+	}
+	return true
+}
+
+func (fg *fileGroup) GetAidlLibraryLabel(ctx BazelConversionPathContext) string {
+	if ctx.OtherModuleDir(fg.module) == ctx.ModuleDir() {
+		return ":" + fg.Name()
+	} else {
+		return fg.GetBazelLabel(ctx, fg)
+	}
+}
diff --git a/android/filegroup_test.go b/android/filegroup_test.go
new file mode 100644
index 0000000..a7ea805
--- /dev/null
+++ b/android/filegroup_test.go
@@ -0,0 +1,58 @@
+package android
+
+import (
+	"path/filepath"
+	"testing"
+)
+
+func TestFileGroupWithPathProp(t *testing.T) {
+	outBaseDir := "outputbase"
+	pathPrefix := outBaseDir + "/execroot/__main__"
+	expectedOutputfile := filepath.Join(pathPrefix, "a/b/c/d/test.aidl")
+
+	testCases := []struct {
+		bp  string
+		rel string
+	}{
+		{
+			bp: `
+	filegroup {
+		name: "baz",
+		srcs: ["a/b/c/d/test.aidl"],
+		path: "a/b",
+		bazel_module: { label: "//:baz" },
+	}
+`,
+			rel: "c/d/test.aidl",
+		},
+		{
+			bp: `
+	filegroup {
+		name: "baz",
+		srcs: ["a/b/c/d/test.aidl"],
+		bazel_module: { label: "//:baz" },
+	}
+`,
+			rel: "a/b/c/d/test.aidl",
+		},
+	}
+
+	for _, testCase := range testCases {
+		outBaseDir := "outputbase"
+		result := GroupFixturePreparers(
+			PrepareForTestWithFilegroup,
+			FixtureModifyConfig(func(config Config) {
+				config.BazelContext = MockBazelContext{
+					OutputBaseDir: outBaseDir,
+					LabelToOutputFiles: map[string][]string{
+						"//:baz": []string{"a/b/c/d/test.aidl"},
+					},
+				}
+			}),
+		).RunTestWithBp(t, testCase.bp)
+
+		fg := result.Module("baz", "").(*fileGroup)
+		AssertStringEquals(t, "src relativeRoot", testCase.rel, fg.srcs[0].Rel())
+		AssertStringEquals(t, "src full path", expectedOutputfile, fg.srcs[0].String())
+	}
+}
diff --git a/apex/apex.go b/apex/apex.go
index b391a6c..949809a 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -192,6 +192,10 @@
 	// with the tool to sign payload contents.
 	Custom_sign_tool *string
 
+	// Whether this is a dynamic common lib apex, if so the native shared libs will be placed
+	// in a special way that include the digest of the lib file under /lib(64)?
+	Dynamic_common_lib_apex *bool
+
 	// Canonical name of this APEX bundle. Used to determine the path to the
 	// activated APEX on device (i.e. /apex/<apexVariationName>), and used for the
 	// apex mutator variations. For override_apex modules, this is the name of the
@@ -1472,6 +1476,11 @@
 	return proptools.Bool(a.properties.Test_only_force_compression)
 }
 
+// See the dynamic_common_lib_apex property
+func (a *apexBundle) dynamic_common_lib_apex() bool {
+	return proptools.BoolDefault(a.properties.Dynamic_common_lib_apex, false)
+}
+
 // These functions are interfacing with cc/sanitizer.go. The entire APEX (along with all of its
 // members) can be sanitized, either forcibly, or by the global configuration. For some of the
 // sanitizers, extra dependencies can be forcibly added as well.
diff --git a/apex/builder.go b/apex/builder.go
index f1b1448..b95b3bd 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -39,6 +39,7 @@
 	pctx.Import("android/soong/cc/config")
 	pctx.Import("android/soong/java")
 	pctx.HostBinToolVariable("apexer", "apexer")
+	pctx.HostBinToolVariable("apexer_with_DCLA_preprocessing", "apexer_with_DCLA_preprocessing")
 	// ART minimal builds (using the master-art manifest) do not have the "frameworks/base"
 	// projects, and hence cannot build 'aapt2'. Use the SDK prebuilt instead.
 	hostBinToolVariableWithPrebuilt := func(name, prebuiltDir, tool string) {
@@ -115,7 +116,35 @@
 		Rspfile:        "${out}.copy_commands",
 		RspfileContent: "${copy_commands}",
 		Description:    "APEX ${image_dir} => ${out}",
-	}, "tool_path", "image_dir", "copy_commands", "file_contexts", "canned_fs_config", "key", "opt_flags", "manifest", "payload_fs_type")
+	}, "tool_path", "image_dir", "copy_commands", "file_contexts", "canned_fs_config", "key",
+		"opt_flags", "manifest")
+
+	DCLAApexRule = pctx.StaticRule("DCLAApexRule", blueprint.RuleParams{
+		Command: `rm -rf ${image_dir} && mkdir -p ${image_dir} && ` +
+			`(. ${out}.copy_commands) && ` +
+			`APEXER_TOOL_PATH=${tool_path} ` +
+			`${apexer_with_DCLA_preprocessing} ` +
+			`--apexer ${apexer} ` +
+			`--canned_fs_config ${canned_fs_config} ` +
+			`${image_dir} ` +
+			`${out} ` +
+			`-- ` +
+			`--include_build_info ` +
+			`--force ` +
+			`--payload_type image ` +
+			`--key ${key} ` +
+			`--file_contexts ${file_contexts} ` +
+			`--manifest ${manifest} ` +
+			`${opt_flags} `,
+		CommandDeps: []string{"${apexer_with_DCLA_preprocessing}", "${apexer}", "${avbtool}", "${e2fsdroid}",
+			"${merge_zips}", "${mke2fs}", "${resize2fs}", "${sefcontext_compile}", "${make_f2fs}",
+			"${sload_f2fs}", "${make_erofs}", "${soong_zip}", "${zipalign}", "${aapt2}",
+			"prebuilts/sdk/current/public/android.jar"},
+		Rspfile:        "${out}.copy_commands",
+		RspfileContent: "${copy_commands}",
+		Description:    "APEX ${image_dir} => ${out}",
+	}, "tool_path", "image_dir", "copy_commands", "file_contexts", "canned_fs_config", "key",
+		"opt_flags", "manifest", "is_DCLA")
 
 	zipApexRule = pctx.StaticRule("zipApexRule", blueprint.RuleParams{
 		Command: `rm -rf ${image_dir} && mkdir -p ${image_dir} && ` +
@@ -662,22 +691,41 @@
 
 		optFlags = append(optFlags, "--payload_fs_type "+a.payloadFsType.string())
 
-		ctx.Build(pctx, android.BuildParams{
-			Rule:        apexRule,
-			Implicits:   implicitInputs,
-			Output:      unsignedOutputFile,
-			Description: "apex (" + apexType.name() + ")",
-			Args: map[string]string{
-				"tool_path":        outHostBinDir + ":" + prebuiltSdkToolsBinDir,
-				"image_dir":        imageDir.String(),
-				"copy_commands":    strings.Join(copyCommands, " && "),
-				"manifest":         a.manifestPbOut.String(),
-				"file_contexts":    fileContexts.String(),
-				"canned_fs_config": cannedFsConfig.String(),
-				"key":              a.privateKeyFile.String(),
-				"opt_flags":        strings.Join(optFlags, " "),
-			},
-		})
+		if a.dynamic_common_lib_apex() {
+			ctx.Build(pctx, android.BuildParams{
+				Rule:        DCLAApexRule,
+				Implicits:   implicitInputs,
+				Output:      unsignedOutputFile,
+				Description: "apex (" + apexType.name() + ")",
+				Args: map[string]string{
+					"tool_path":        outHostBinDir + ":" + prebuiltSdkToolsBinDir,
+					"image_dir":        imageDir.String(),
+					"copy_commands":    strings.Join(copyCommands, " && "),
+					"manifest":         a.manifestPbOut.String(),
+					"file_contexts":    fileContexts.String(),
+					"canned_fs_config": cannedFsConfig.String(),
+					"key":              a.privateKeyFile.String(),
+					"opt_flags":        strings.Join(optFlags, " "),
+				},
+			})
+		} else {
+			ctx.Build(pctx, android.BuildParams{
+				Rule:        apexRule,
+				Implicits:   implicitInputs,
+				Output:      unsignedOutputFile,
+				Description: "apex (" + apexType.name() + ")",
+				Args: map[string]string{
+					"tool_path":        outHostBinDir + ":" + prebuiltSdkToolsBinDir,
+					"image_dir":        imageDir.String(),
+					"copy_commands":    strings.Join(copyCommands, " && "),
+					"manifest":         a.manifestPbOut.String(),
+					"file_contexts":    fileContexts.String(),
+					"canned_fs_config": cannedFsConfig.String(),
+					"key":              a.privateKeyFile.String(),
+					"opt_flags":        strings.Join(optFlags, " "),
+				},
+			})
+		}
 
 		// TODO(jiyong): make the two rules below as separate functions
 		apexProtoFile := android.PathForModuleOut(ctx, a.Name()+".pb"+suffix)
diff --git a/bp2build/cc_binary_conversion_test.go b/bp2build/cc_binary_conversion_test.go
index 95869dd..1f69b5a 100644
--- a/bp2build/cc_binary_conversion_test.go
+++ b/bp2build/cc_binary_conversion_test.go
@@ -543,3 +543,41 @@
 		},
 	})
 }
+
+func TestCcBinaryRuntimeLibs(t *testing.T) {
+	runCcBinaryTests(t, ccBinaryBp2buildTestCase{
+		description: "cc_binary with runtime libs",
+		blueprint: `
+cc_library {
+    name: "bar",
+    srcs: ["b.cc"],
+}
+
+{rule_name} {
+    name: "foo",
+    srcs: ["a.cc"],
+    runtime_libs: ["bar"],
+}
+`,
+		targets: []testBazelTarget{
+			{"cc_library_static", "bar_bp2build_cc_library_static", AttrNameToString{
+				"local_includes":         `["."]`,
+				"srcs":                   `["b.cc"]`,
+				"target_compatible_with": `["//build/bazel/platforms/os:android"]`,
+			},
+			},
+			{"cc_library_shared", "bar", AttrNameToString{
+				"local_includes":         `["."]`,
+				"srcs":                   `["b.cc"]`,
+				"target_compatible_with": `["//build/bazel/platforms/os:android"]`,
+			},
+			},
+			{"cc_binary", "foo", AttrNameToString{
+				"local_includes": `["."]`,
+				"srcs":           `["a.cc"]`,
+				"runtime_deps":   `[":bar"]`,
+			},
+			},
+		},
+	})
+}
diff --git a/bp2build/cc_library_conversion_test.go b/bp2build/cc_library_conversion_test.go
index 6c56d41..f6d5067 100644
--- a/bp2build/cc_library_conversion_test.go
+++ b/bp2build/cc_library_conversion_test.go
@@ -2514,3 +2514,29 @@
 			})...),
 	})
 }
+
+func TestCCLibraryRuntimeDeps(t *testing.T) {
+	runCcLibrarySharedTestCase(t, Bp2buildTestCase{
+		Blueprint: `cc_library_shared {
+	name: "bar",
+}
+
+cc_library {
+  name: "foo",
+  runtime_libs: ["foo"],
+}`,
+		ExpectedBazelTargets: []string{
+			makeBazelTarget("cc_library_shared", "bar", AttrNameToString{
+				"local_includes": `["."]`,
+			}),
+			makeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
+				"runtime_deps":   `[":foo"]`,
+				"local_includes": `["."]`,
+			}),
+			makeBazelTarget("cc_library_shared", "foo", AttrNameToString{
+				"runtime_deps":   `[":foo"]`,
+				"local_includes": `["."]`,
+			}),
+		},
+	})
+}
diff --git a/bp2build/cc_library_shared_conversion_test.go b/bp2build/cc_library_shared_conversion_test.go
index 6a47862..de57e5a 100644
--- a/bp2build/cc_library_shared_conversion_test.go
+++ b/bp2build/cc_library_shared_conversion_test.go
@@ -624,3 +624,25 @@
 		},
 	})
 }
+
+func TestCCLibrarySharedRuntimeDeps(t *testing.T) {
+	runCcLibrarySharedTestCase(t, Bp2buildTestCase{
+		Blueprint: `cc_library_shared {
+	name: "bar",
+}
+
+cc_library_shared {
+  name: "foo",
+  runtime_libs: ["foo"],
+}`,
+		ExpectedBazelTargets: []string{
+			makeBazelTarget("cc_library_shared", "bar", AttrNameToString{
+				"local_includes": `["."]`,
+			}),
+			makeBazelTarget("cc_library_shared", "foo", AttrNameToString{
+				"runtime_deps":   `[":foo"]`,
+				"local_includes": `["."]`,
+			}),
+		},
+	})
+}
diff --git a/bp2build/cc_library_static_conversion_test.go b/bp2build/cc_library_static_conversion_test.go
index ddb7bf9..1c160ec 100644
--- a/bp2build/cc_library_static_conversion_test.go
+++ b/bp2build/cc_library_static_conversion_test.go
@@ -15,12 +15,12 @@
 package bp2build
 
 import (
+	"fmt"
+	"testing"
+
 	"android/soong/android"
 	"android/soong/cc"
 	"android/soong/genrule"
-	"fmt"
-
-	"testing"
 )
 
 const (
@@ -1559,3 +1559,25 @@
 		})
 	}
 }
+
+func TestCCLibraryStaticRuntimeDeps(t *testing.T) {
+	runCcLibrarySharedTestCase(t, Bp2buildTestCase{
+		Blueprint: `cc_library_shared {
+	name: "bar",
+}
+
+cc_library_static {
+  name: "foo",
+  runtime_libs: ["foo"],
+}`,
+		ExpectedBazelTargets: []string{
+			makeBazelTarget("cc_library_shared", "bar", AttrNameToString{
+				"local_includes": `["."]`,
+			}),
+			makeBazelTarget("cc_library_static", "foo", AttrNameToString{
+				"runtime_deps":   `[":foo"]`,
+				"local_includes": `["."]`,
+			}),
+		},
+	})
+}
diff --git a/bp2build/filegroup_conversion_test.go b/bp2build/filegroup_conversion_test.go
index b598b85..de09a17 100644
--- a/bp2build/filegroup_conversion_test.go
+++ b/bp2build/filegroup_conversion_test.go
@@ -56,3 +56,68 @@
 		ExpectedErr: fmt.Errorf("filegroup 'foo' cannot contain a file with the same name"),
 	})
 }
+
+func TestFilegroupWithAidlSrcs(t *testing.T) {
+	testcases := []struct {
+		name               string
+		bp                 string
+		expectedBazelAttrs AttrNameToString
+	}{
+		{
+			name: "filegroup with only aidl srcs",
+			bp: `
+	filegroup {
+		name: "foo",
+		srcs: ["aidl/foo.aidl"],
+		path: "aidl",
+	}`,
+			expectedBazelAttrs: AttrNameToString{
+				"srcs":                `["aidl/foo.aidl"]`,
+				"strip_import_prefix": `"aidl"`,
+			},
+		},
+		{
+			name: "filegroup without path",
+			bp: `
+	filegroup {
+		name: "foo",
+		srcs: ["aidl/foo.aidl"],
+	}`,
+			expectedBazelAttrs: AttrNameToString{
+				"srcs": `["aidl/foo.aidl"]`,
+			},
+		},
+	}
+
+	for _, test := range testcases {
+		expectedBazelTargets := []string{
+			MakeBazelTargetNoRestrictions("aidl_library", "foo", test.expectedBazelAttrs),
+		}
+		runFilegroupTestCase(t, Bp2buildTestCase{
+			Description:          test.name,
+			Blueprint:            test.bp,
+			ExpectedBazelTargets: expectedBazelTargets,
+		})
+	}
+}
+
+func TestFilegroupWithAidlAndNonAidlSrcs(t *testing.T) {
+	runFilegroupTestCase(t, Bp2buildTestCase{
+		Description: "filegroup with aidl and non-aidl srcs",
+		Filesystem:  map[string]string{},
+		Blueprint: `
+filegroup {
+    name: "foo",
+    srcs: [
+		"aidl/foo.aidl",
+		"buf.proto",
+	],
+}`,
+		ExpectedBazelTargets: []string{
+			MakeBazelTargetNoRestrictions("filegroup", "foo", AttrNameToString{
+				"srcs": `[
+        "aidl/foo.aidl",
+        "buf.proto",
+    ]`}),
+		}})
+}
diff --git a/cc/binary.go b/cc/binary.go
index b2f2482..849aafa 100644
--- a/cc/binary.go
+++ b/cc/binary.go
@@ -617,6 +617,7 @@
 		Dynamic_deps:       baseAttrs.implementationDynamicDeps,
 		Whole_archive_deps: baseAttrs.wholeArchiveDeps,
 		System_deps:        baseAttrs.systemDynamicDeps,
+		Runtime_deps:       baseAttrs.runtimeDeps,
 
 		Local_includes:    baseAttrs.localIncludes,
 		Absolute_includes: baseAttrs.absoluteIncludes,
@@ -667,6 +668,7 @@
 	Dynamic_deps       bazel.LabelListAttribute
 	Whole_archive_deps bazel.LabelListAttribute
 	System_deps        bazel.LabelListAttribute
+	Runtime_deps       bazel.LabelListAttribute
 
 	Local_includes    bazel.StringListAttribute
 	Absolute_includes bazel.StringListAttribute
diff --git a/cc/bp2build.go b/cc/bp2build.go
index 61a55ee..ba93439 100644
--- a/cc/bp2build.go
+++ b/cc/bp2build.go
@@ -52,6 +52,7 @@
 	Implementation_dynamic_deps       bazel.LabelListAttribute
 	Whole_archive_deps                bazel.LabelListAttribute
 	Implementation_whole_archive_deps bazel.LabelListAttribute
+	Runtime_deps                      bazel.LabelListAttribute
 
 	System_dynamic_deps bazel.LabelListAttribute
 
@@ -710,6 +711,7 @@
 	implementationDeps               bazel.LabelListAttribute
 	dynamicDeps                      bazel.LabelListAttribute
 	implementationDynamicDeps        bazel.LabelListAttribute
+	runtimeDeps                      bazel.LabelListAttribute
 	wholeArchiveDeps                 bazel.LabelListAttribute
 	implementationWholeArchiveDeps   bazel.LabelListAttribute
 	systemDynamicDeps                bazel.LabelListAttribute
@@ -825,6 +827,11 @@
 	if axisFeatures != nil {
 		la.features.SetSelectValue(axis, config, axisFeatures)
 	}
+
+	runtimeDeps := android.BazelLabelForModuleDepsExcludes(ctx, props.Runtime_libs, props.Exclude_runtime_libs)
+	if !runtimeDeps.IsEmpty() {
+		la.runtimeDeps.SetSelectValue(axis, config, runtimeDeps)
+	}
 }
 
 func (la *linkerAttributes) convertStripProps(ctx android.BazelConversionPathContext, module *Module) {
diff --git a/cc/cc.go b/cc/cc.go
index c71fb34..336771a 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -514,6 +514,7 @@
 	getVndkExtendsModuleName() string
 	isAfdoCompile() bool
 	isPgoCompile() bool
+	isCfi() bool
 	isNDKStubLibrary() bool
 	useClangLld(actx ModuleContext) bool
 	isForPlatform() bool
@@ -1314,6 +1315,13 @@
 	return false
 }
 
+func (c *Module) isCfi() bool {
+	if sanitize := c.sanitize; sanitize != nil {
+		return Bool(sanitize.Properties.Sanitize.Cfi)
+	}
+	return false
+}
+
 func (c *Module) isNDKStubLibrary() bool {
 	if _, ok := c.compiler.(*stubDecorator); ok {
 		return true
@@ -1592,6 +1600,10 @@
 	return ctx.mod.isPgoCompile()
 }
 
+func (ctx *moduleContextImpl) isCfi() bool {
+	return ctx.mod.isCfi()
+}
+
 func (ctx *moduleContextImpl) isNDKStubLibrary() bool {
 	return ctx.mod.isNDKStubLibrary()
 }
diff --git a/cc/library.go b/cc/library.go
index 897b572..621b58c 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -319,6 +319,7 @@
 		Implementation_whole_archive_deps: linkerAttrs.implementationWholeArchiveDeps,
 		Whole_archive_deps:                *linkerAttrs.wholeArchiveDeps.Clone().Append(staticAttrs.Whole_archive_deps),
 		System_dynamic_deps:               *linkerAttrs.systemDynamicDeps.Clone().Append(staticAttrs.System_dynamic_deps),
+		Runtime_deps:                      linkerAttrs.runtimeDeps,
 		sdkAttributes:                     bp2BuildParseSdkAttributes(m),
 	}
 
@@ -335,6 +336,7 @@
 		Implementation_dynamic_deps: *linkerAttrs.implementationDynamicDeps.Clone().Append(sharedAttrs.Implementation_dynamic_deps),
 		Whole_archive_deps:          *linkerAttrs.wholeArchiveDeps.Clone().Append(sharedAttrs.Whole_archive_deps),
 		System_dynamic_deps:         *linkerAttrs.systemDynamicDeps.Clone().Append(sharedAttrs.System_dynamic_deps),
+		Runtime_deps:                linkerAttrs.runtimeDeps,
 		sdkAttributes:               bp2BuildParseSdkAttributes(m),
 	}
 
@@ -1048,9 +1050,7 @@
 		if ctx.Module().(android.ApexModule).NotInPlatform() {
 			flag = "--apex"
 		} else {
-			// TODO(b/239274367) drop --apex when #apex is replaced with #systemapi
-			// in the map.txt files of platform libraries
-			flag = "--systemapi --apex"
+			flag = "--systemapi"
 		}
 		nativeAbiResult := parseNativeAbiDefinition(ctx, symbolFile,
 			android.ApiLevelOrPanic(ctx, library.MutatedProperties.StubsVersion), flag)
@@ -2552,6 +2552,7 @@
 		Implementation_whole_archive_deps: linkerAttrs.implementationWholeArchiveDeps,
 		System_dynamic_deps:               linkerAttrs.systemDynamicDeps,
 		sdkAttributes:                     bp2BuildParseSdkAttributes(module),
+		Runtime_deps:                      linkerAttrs.runtimeDeps,
 	}
 
 	var attrs interface{}
diff --git a/cc/lto.go b/cc/lto.go
index 1da69bf..455ff7e 100644
--- a/cc/lto.go
+++ b/cc/lto.go
@@ -136,10 +136,16 @@
 }
 
 func (lto *lto) DefaultThinLTO(ctx BaseModuleContext) bool {
+	// LP32 has many subtle issues and less test coverage.
 	lib32 := ctx.Arch().ArchType.Multilib == "lib32"
+	// CFI enables full LTO.
+	cfi := ctx.isCfi()
+	// Performance and binary size are less important for host binaries.
 	host := ctx.Host()
-	vndk := ctx.isVndk() // b/169217596
-	return GlobalThinLTO(ctx) && !lto.Never() && !lib32 && !host && !vndk
+	// FIXME: ThinLTO for VNDK produces different output.
+	// b/169217596
+	vndk := ctx.isVndk()
+	return GlobalThinLTO(ctx) && !lto.Never() && !lib32 && !cfi && !host && !vndk
 }
 
 func (lto *lto) FullLTO() bool {
diff --git a/java/java_test.go b/java/java_test.go
index 9e5cf0c..bfd97eb 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -1287,6 +1287,41 @@
 	}
 }
 
+func TestAidlIncludeDirFromConvertedFileGroupWithPathPropInMixedBuilds(t *testing.T) {
+	bp := `
+	filegroup {
+		name: "foo_aidl",
+		srcs: ["aidl/foo/IFoo.aidl"],
+		path: "aidl/foo",
+		bazel_module: { label: "//:foo_aidl" },
+	}
+	java_library {
+		name: "foo",
+		srcs: [":foo_aidl"],
+	}
+`
+
+	outBaseDir := "out/bazel/output"
+	result := android.GroupFixturePreparers(
+		prepareForJavaTest,
+		android.PrepareForTestWithFilegroup,
+		android.FixtureModifyConfig(func(config android.Config) {
+			config.BazelContext = android.MockBazelContext{
+				OutputBaseDir: outBaseDir,
+				LabelToOutputFiles: map[string][]string{
+					"//:foo_aidl": []string{"aidl/foo/IFoo.aidl"},
+				},
+			}
+		}),
+	).RunTestWithBp(t, bp)
+
+	aidlCommand := result.ModuleForTests("foo", "android_common").Rule("aidl").RuleParams.Command
+	expectedAidlFlag := "-I" + outBaseDir + "/execroot/__main__/aidl/foo"
+	if !strings.Contains(aidlCommand, expectedAidlFlag) {
+		t.Errorf("aidl command %q does not contain %q", aidlCommand, expectedAidlFlag)
+	}
+}
+
 func TestAidlFlagsArePassedToTheAidlCompiler(t *testing.T) {
 	ctx, _ := testJava(t, `
 		java_library {
diff --git a/ui/build/soong.go b/ui/build/soong.go
index 29c3b65..519506e 100644
--- a/ui/build/soong.go
+++ b/ui/build/soong.go
@@ -22,6 +22,7 @@
 	"os"
 	"path/filepath"
 	"strconv"
+	"strings"
 
 	"android/soong/ui/metrics"
 	soong_metrics_proto "android/soong/ui/metrics/metrics_proto"
@@ -445,6 +446,11 @@
 			"-f", filepath.Join(config.SoongOutDir(), ninjaFile),
 		}
 
+		if extra, ok := config.Environment().Get("SOONG_UI_NINJA_ARGS"); ok {
+			ctx.Printf(`CAUTION: arguments in $SOONG_UI_NINJA_ARGS=%q, e.g. "-n", can make soong_build FAIL or INCORRECT`, extra)
+			ninjaArgs = append(ninjaArgs, strings.Fields(extra)...)
+		}
+
 		ninjaArgs = append(ninjaArgs, targets...)
 		cmd := Command(ctx, config, "soong "+name,
 			config.PrebuiltBuildTool("ninja"), ninjaArgs...)