Merge "Update unaligned-vector-mem to -munaligned-access" into main
diff --git a/apex/apex.go b/apex/apex.go
index 557b9b7..c6d8234 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -842,10 +842,12 @@
 		}
 
 		addDependenciesForNativeModules(ctx, deps, target, imageVariation)
-		ctx.AddFarVariationDependencies([]blueprint.Variation{
-			{Mutator: "os", Variation: target.OsVariation()},
-			{Mutator: "arch", Variation: target.ArchVariation()},
-		}, shBinaryTag, a.properties.Sh_binaries...)
+		if isPrimaryAbi {
+			ctx.AddFarVariationDependencies([]blueprint.Variation{
+				{Mutator: "os", Variation: target.OsVariation()},
+				{Mutator: "arch", Variation: target.ArchVariation()},
+			}, shBinaryTag, a.properties.Sh_binaries...)
+		}
 	}
 
 	// Common-arch dependencies come next
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 02dc6e6..85d1d71 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -5046,6 +5046,7 @@
 			key: "myapex.key",
 			sh_binaries: ["myscript"],
 			updatable: false,
+			compile_multilib: "both",
 		}
 
 		apex_key {
diff --git a/cc/cc.go b/cc/cc.go
index 39024aa..2770fb2 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -3361,7 +3361,7 @@
 					c.sabi.Properties.ReexportedIncludes, depExporterInfo.IncludeDirs.Strings()...)
 			}
 
-			makeLibName := MakeLibName(ctx, c, ccDep, depName) + libDepTag.makeSuffix
+			makeLibName := MakeLibName(ctx, c, ccDep, ccDep.BaseModuleName()) + libDepTag.makeSuffix
 			switch {
 			case libDepTag.header():
 				c.Properties.AndroidMkHeaderLibs = append(
@@ -3402,7 +3402,7 @@
 			switch depTag {
 			case runtimeDepTag:
 				c.Properties.AndroidMkRuntimeLibs = append(
-					c.Properties.AndroidMkRuntimeLibs, MakeLibName(ctx, c, ccDep, depName)+libDepTag.makeSuffix)
+					c.Properties.AndroidMkRuntimeLibs, MakeLibName(ctx, c, ccDep, ccDep.BaseModuleName())+libDepTag.makeSuffix)
 				// Record BaseLibName for snapshots.
 				c.Properties.SnapshotRuntimeLibs = append(c.Properties.SnapshotRuntimeLibs, BaseLibName(depName))
 			case objDepTag:
diff --git a/cc/prebuilt_test.go b/cc/prebuilt_test.go
index 95fb7ed..f6b5ed5 100644
--- a/cc/prebuilt_test.go
+++ b/cc/prebuilt_test.go
@@ -595,6 +595,9 @@
 		libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module()
 		expectedDependency := ctx.ModuleForTests(tc.expectedDependencyName, "android_arm64_armv8-a_shared").Module()
 		android.AssertBoolEquals(t, fmt.Sprintf("expected dependency from %s to %s\n", libfoo.Name(), tc.expectedDependencyName), true, hasDep(ctx, libfoo, expectedDependency))
+		// check that LOCAL_SHARED_LIBRARIES contains libbar and not libbar.v<N>
+		entries := android.AndroidMkEntriesForTest(t, ctx, libfoo)[0]
+		android.AssertStringListContains(t, "Version should not be present in LOCAL_SHARED_LIBRARIES", entries.EntryMap["LOCAL_SHARED_LIBRARIES"], "libbar")
 
 		// check installation rules
 		// the selected soong module should be exported to make
@@ -603,7 +606,7 @@
 
 		// check LOCAL_MODULE of the selected module name
 		// the prebuilt should have the same LOCAL_MODULE when exported to make
-		entries := android.AndroidMkEntriesForTest(t, ctx, libbar)[0]
+		entries = android.AndroidMkEntriesForTest(t, ctx, libbar)[0]
 		android.AssertStringEquals(t, "unexpected LOCAL_MODULE", "libbar", entries.EntryMap["LOCAL_MODULE"][0])
 	}
 }
diff --git a/java/app_import.go b/java/app_import.go
index 74255b7..8c90e4c 100644
--- a/java/app_import.go
+++ b/java/app_import.go
@@ -70,9 +70,10 @@
 	android.ApexModuleBase
 	prebuilt android.Prebuilt
 
-	properties   AndroidAppImportProperties
-	dpiVariants  interface{}
-	archVariants interface{}
+	properties       AndroidAppImportProperties
+	dpiVariants      interface{}
+	archVariants     interface{}
+	arch_dpiVariants interface{}
 
 	outputFile  android.Path
 	certificate Certificate
@@ -155,8 +156,8 @@
 // soong config variables are applied.
 func (a *AndroidAppImport) processVariants(ctx android.DefaultableHookContext) {
 	config := ctx.Config()
+	dpiProps := reflect.ValueOf(a.dpiVariants).Elem().FieldByName(DpiGroupName)
 
-	dpiProps := reflect.ValueOf(a.dpiVariants).Elem().FieldByName("Dpi_variants")
 	// Try DPI variant matches in the reverse-priority order so that the highest priority match
 	// overwrites everything else.
 	// TODO(jungjw): Can we optimize this by making it priority order?
@@ -166,11 +167,27 @@
 	if config.ProductAAPTPreferredConfig() != "" {
 		MergePropertiesFromVariant(ctx, &a.properties, dpiProps, config.ProductAAPTPreferredConfig())
 	}
-
-	archProps := reflect.ValueOf(a.archVariants).Elem().FieldByName("Arch")
+	archProps := reflect.ValueOf(a.archVariants).Elem().FieldByName(ArchGroupName)
 	archType := ctx.Config().AndroidFirstDeviceTarget.Arch.ArchType
 	MergePropertiesFromVariant(ctx, &a.properties, archProps, archType.Name)
 
+	// Process "arch" includes "dpi_variants"
+	archStructPtr := reflect.ValueOf(a.arch_dpiVariants).Elem().FieldByName(ArchGroupName)
+	if archStruct := archStructPtr.Elem(); archStruct.IsValid() {
+		archPartPropsPtr := archStruct.FieldByName(proptools.FieldNameForProperty(archType.Name))
+		if archPartProps := archPartPropsPtr.Elem(); archPartProps.IsValid() {
+			archDpiPropsPtr := archPartProps.FieldByName(DpiGroupName)
+			if archDpiProps := archDpiPropsPtr.Elem(); archDpiProps.IsValid() {
+				for i := len(config.ProductAAPTPrebuiltDPI()) - 1; i >= 0; i-- {
+					MergePropertiesFromVariant(ctx, &a.properties, archDpiProps, config.ProductAAPTPrebuiltDPI()[i])
+				}
+				if config.ProductAAPTPreferredConfig() != "" {
+					MergePropertiesFromVariant(ctx, &a.properties, archDpiProps, config.ProductAAPTPreferredConfig())
+				}
+			}
+		}
+	}
+
 	if String(a.properties.Apk) == "" {
 		// Disable this module since the apk property is still empty after processing all matching
 		// variants. This likely means there is no matching variant, and the default variant doesn't
@@ -451,18 +468,25 @@
 	return android.OptionalPath{}
 }
 
+const (
+	ArchGroupName = "Arch"
+	DpiGroupName  = "Dpi_variants"
+)
+
 var dpiVariantGroupType reflect.Type
 var archVariantGroupType reflect.Type
+var archdpiVariantGroupType reflect.Type
 var supportedDpis = []string{"ldpi", "mdpi", "hdpi", "xhdpi", "xxhdpi", "xxxhdpi"}
 
 func initAndroidAppImportVariantGroupTypes() {
-	dpiVariantGroupType = createVariantGroupType(supportedDpis, "Dpi_variants")
+	dpiVariantGroupType = createVariantGroupType(supportedDpis, DpiGroupName)
 
 	archNames := make([]string, len(android.ArchTypeList()))
 	for i, archType := range android.ArchTypeList() {
 		archNames[i] = archType.Name
 	}
-	archVariantGroupType = createVariantGroupType(archNames, "Arch")
+	archVariantGroupType = createVariantGroupType(archNames, ArchGroupName)
+	archdpiVariantGroupType = createArchDpiVariantGroupType(archNames, supportedDpis)
 }
 
 // Populates all variant struct properties at creation time.
@@ -472,6 +496,9 @@
 
 	a.archVariants = reflect.New(archVariantGroupType).Interface()
 	a.AddProperties(a.archVariants)
+
+	a.arch_dpiVariants = reflect.New(archdpiVariantGroupType).Interface()
+	a.AddProperties(a.arch_dpiVariants)
 }
 
 func (a *AndroidAppImport) Privileged() bool {
@@ -526,6 +553,42 @@
 	})
 }
 
+func createArchDpiVariantGroupType(archNames []string, dpiNames []string) reflect.Type {
+	props := reflect.TypeOf((*AndroidAppImportProperties)(nil))
+
+	dpiVariantFields := make([]reflect.StructField, len(dpiNames))
+	for i, variant_dpi := range dpiNames {
+		dpiVariantFields[i] = reflect.StructField{
+			Name: proptools.FieldNameForProperty(variant_dpi),
+			Type: props,
+		}
+	}
+	dpiVariantGroupStruct := reflect.StructOf(dpiVariantFields)
+	dpi_struct := reflect.StructOf([]reflect.StructField{
+		{
+			Name: DpiGroupName,
+			Type: reflect.PointerTo(dpiVariantGroupStruct),
+		},
+	})
+
+	archVariantFields := make([]reflect.StructField, len(archNames))
+	for i, variant_arch := range archNames {
+		archVariantFields[i] = reflect.StructField{
+			Name: proptools.FieldNameForProperty(variant_arch),
+			Type: reflect.PointerTo(dpi_struct),
+		}
+	}
+	archVariantGroupStruct := reflect.StructOf(archVariantFields)
+
+	return_struct := reflect.StructOf([]reflect.StructField{
+		{
+			Name: ArchGroupName,
+			Type: reflect.PointerTo(archVariantGroupStruct),
+		},
+	})
+	return return_struct
+}
+
 // android_app_import imports a prebuilt apk with additional processing specified in the module.
 // DPI-specific apk source files can be specified using dpi_variants. Example:
 //
diff --git a/java/app_import_test.go b/java/app_import_test.go
index 44f8f16..5de50e7 100644
--- a/java/app_import_test.go
+++ b/java/app_import_test.go
@@ -472,6 +472,35 @@
 			artifactPath: "prebuilts/apk/app_arm.apk",
 			installPath:  "/system/app/foo/foo.apk",
 		},
+		{
+			name: "matching arch and dpi_variants",
+			bp: `
+				android_app_import {
+					name: "foo",
+					apk: "prebuilts/apk/app.apk",
+					arch: {
+						arm64: {
+							apk: "prebuilts/apk/app_arm64.apk",
+							dpi_variants: {
+								mdpi: {
+									apk: "prebuilts/apk/app_arm64_mdpi.apk",
+								},
+								xhdpi: {
+									apk: "prebuilts/apk/app_arm64_xhdpi.apk",
+								},
+							},
+						},
+					},
+					presigned: true,
+					dex_preopt: {
+						enabled: true,
+					},
+				}
+			`,
+			expected:     "verify_uses_libraries/apk/app_arm64_xhdpi.apk",
+			artifactPath: "prebuilts/apk/app_arm64_xhdpi.apk",
+			installPath:  "/system/app/foo/foo.apk",
+		},
 	}
 
 	for _, test := range testCases {
diff --git a/java/droiddoc.go b/java/droiddoc.go
index 6a66f45..df40d01 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -222,6 +222,8 @@
 	stubsSrcJar android.WritablePath
 
 	exportableStubsSrcJar android.WritablePath
+
+	runtimeStubsSrcJar android.WritablePath
 }
 
 func (j *Javadoc) OutputFiles(tag string) (android.Paths, error) {
diff --git a/java/droidstubs.go b/java/droidstubs.go
index 51503f2..b112614 100644
--- a/java/droidstubs.go
+++ b/java/droidstubs.go
@@ -214,6 +214,7 @@
 type annotationFlagsParams struct {
 	migratingNullability    bool
 	validatingNullability   bool
+	extractAnnotations      bool
 	nullabilityWarningsFile android.WritablePath
 	annotationsZip          android.WritablePath
 }
@@ -229,16 +230,19 @@
 	stubConfig              stubsCommandConfigParams
 }
 type stubsCommandConfigParams struct {
-	stubsType             StubsType
-	javaVersion           javaVersion
-	deps                  deps
-	checkApi              bool
-	generateStubs         bool
-	doApiLint             bool
-	doCheckReleased       bool
-	writeSdkValues        bool
-	migratingNullability  bool
-	validatingNullability bool
+	stubsType                   StubsType
+	javaVersion                 javaVersion
+	deps                        deps
+	checkApi                    bool
+	generateStubs               bool
+	doApiLint                   bool
+	doCheckReleased             bool
+	writeSdkValues              bool
+	migratingNullability        bool
+	validatingNullability       bool
+	annotationsEnabled          bool
+	apiLevelsAnnotationsEnabled bool
+	extractAnnotations          bool
 }
 
 // droidstubs passes sources files through Metalava to generate stub .java files that only contain the API to be
@@ -508,30 +512,30 @@
 }
 
 func (d *Droidstubs) annotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, params annotationFlagsParams) {
-	if Bool(d.properties.Annotations_enabled) {
-		cmd.Flag(config.MetalavaAnnotationsFlags)
+	cmd.Flag(config.MetalavaAnnotationsFlags)
 
-		if params.migratingNullability {
-			previousApi := android.PathForModuleSrc(ctx, String(d.properties.Previous_api))
-			cmd.FlagWithInput("--migrate-nullness ", previousApi)
-		}
-
-		if s := String(d.properties.Validate_nullability_from_list); s != "" {
-			cmd.FlagWithInput("--validate-nullability-from-list ", android.PathForModuleSrc(ctx, s))
-		}
-
-		if params.validatingNullability {
-			cmd.FlagWithOutput("--nullability-warnings-txt ", params.nullabilityWarningsFile)
-		}
-
-		cmd.FlagWithOutput("--extract-annotations ", params.annotationsZip)
-
-		if len(d.properties.Merge_annotations_dirs) != 0 {
-			d.mergeAnnoDirFlags(ctx, cmd)
-		}
-
-		cmd.Flag(config.MetalavaAnnotationsWarningsFlags)
+	if params.migratingNullability {
+		previousApi := android.PathForModuleSrc(ctx, String(d.properties.Previous_api))
+		cmd.FlagWithInput("--migrate-nullness ", previousApi)
 	}
+
+	if s := String(d.properties.Validate_nullability_from_list); s != "" {
+		cmd.FlagWithInput("--validate-nullability-from-list ", android.PathForModuleSrc(ctx, s))
+	}
+
+	if params.validatingNullability {
+		cmd.FlagWithOutput("--nullability-warnings-txt ", params.nullabilityWarningsFile)
+	}
+
+	if params.extractAnnotations {
+		cmd.FlagWithOutput("--extract-annotations ", params.annotationsZip)
+	}
+
+	if len(d.properties.Merge_annotations_dirs) != 0 {
+		d.mergeAnnoDirFlags(ctx, cmd)
+	}
+
+	cmd.Flag(config.MetalavaAnnotationsWarningsFlags)
 }
 
 func (d *Droidstubs) mergeAnnoDirFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand) {
@@ -556,9 +560,11 @@
 	})
 }
 
-func (d *Droidstubs) apiLevelsAnnotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsType StubsType, apiVersionsXml android.WritablePath) {
+func (d *Droidstubs) apiLevelsAnnotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, params stubsCommandParams) {
 	var apiVersions android.Path
-	if proptools.Bool(d.properties.Api_levels_annotations_enabled) {
+	stubsType := params.stubConfig.stubsType
+	apiVersionsXml := params.apiVersionsXml
+	if params.stubConfig.apiLevelsAnnotationsEnabled {
 		d.apiLevelsGenerationFlags(ctx, cmd, stubsType, apiVersionsXml)
 		apiVersions = apiVersionsXml
 	} else {
@@ -569,7 +575,9 @@
 				} else if stubsType == Exportable {
 					apiVersions = s.exportableArtifacts.apiVersionsXml
 				} else {
-					ctx.ModuleErrorf("%s stubs type does not generate api-versions.xml file", stubsType.String())
+					// if the stubs type does not generate api-versions.xml file, default to using the
+					// everything artifacts
+					apiVersions = s.everythingArtifacts.apiVersionsXml
 				}
 			} else {
 				ctx.PropertyErrorf("api_levels_module",
@@ -803,13 +811,16 @@
 	annotationParams := annotationFlagsParams{
 		migratingNullability:    params.stubConfig.migratingNullability,
 		validatingNullability:   params.stubConfig.validatingNullability,
+		extractAnnotations:      params.stubConfig.extractAnnotations,
 		nullabilityWarningsFile: params.nullabilityWarningsFile,
 		annotationsZip:          params.annotationsZip,
 	}
 
-	d.annotationsFlags(ctx, cmd, annotationParams)
+	if params.stubConfig.annotationsEnabled {
+		d.annotationsFlags(ctx, cmd, annotationParams)
+	}
 	d.inclusionAnnotationsFlags(ctx, cmd)
-	d.apiLevelsAnnotationsFlags(ctx, cmd, params.stubConfig.stubsType, params.apiVersionsXml)
+	d.apiLevelsAnnotationsFlags(ctx, cmd, params)
 
 	d.expandArgs(ctx, cmd)
 
@@ -839,13 +850,13 @@
 		d.everythingArtifacts.metadataZip = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"-metadata.zip")
 	}
 
-	if Bool(d.properties.Annotations_enabled) {
+	if params.annotationsEnabled {
 		if params.validatingNullability {
 			d.everythingArtifacts.nullabilityWarningsFile = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"_nullability_warnings.txt")
 		}
 		d.everythingArtifacts.annotationsZip = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"_annotations.zip")
 	}
-	if Bool(d.properties.Api_levels_annotations_enabled) {
+	if params.apiLevelsAnnotationsEnabled {
 		d.everythingArtifacts.apiVersionsXml = android.PathForModuleOut(ctx, Everything.String(), "api-versions.xml")
 	}
 
@@ -1023,7 +1034,7 @@
 		optionalCmdParams.metadataDir = d.exportableArtifacts.metadataDir
 	}
 
-	if Bool(d.properties.Annotations_enabled) {
+	if params.annotationsEnabled {
 		if params.validatingNullability {
 			d.exportableArtifacts.nullabilityWarningsFile = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"_nullability_warnings.txt")
 			optionalCmdParams.nullabilityWarningsFile = d.exportableArtifacts.nullabilityWarningsFile
@@ -1031,7 +1042,7 @@
 		d.exportableArtifacts.annotationsZip = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"_annotations.zip")
 		optionalCmdParams.annotationsZip = d.exportableArtifacts.annotationsZip
 	}
-	if Bool(d.properties.Api_levels_annotations_enabled) {
+	if params.apiLevelsAnnotationsEnabled {
 		d.exportableArtifacts.apiVersionsXml = android.PathForModuleOut(ctx, params.stubsType.String(), "api-versions.xml")
 		optionalCmdParams.apiVersionsXml = d.exportableArtifacts.apiVersionsXml
 	}
@@ -1049,6 +1060,38 @@
 	d.optionalStubCmd(ctx, optionalCmdParams)
 }
 
+// Sandbox rule for generating runtime stubs
+func (d *Droidstubs) runtimeStubCmd(ctx android.ModuleContext, params stubsCommandConfigParams) {
+
+	// We are only interested in generating the stubs srcjar,
+	// not other artifacts for the runtime stubs
+	params.checkApi = false
+	params.writeSdkValues = false
+	params.validatingNullability = false
+	params.extractAnnotations = false
+	params.apiLevelsAnnotationsEnabled = false
+
+	optionalCmdParams := stubsCommandParams{
+		stubConfig: params,
+	}
+
+	d.Javadoc.runtimeStubsSrcJar = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"-"+"stubs.srcjar")
+	optionalCmdParams.stubsSrcJar = d.Javadoc.runtimeStubsSrcJar
+
+	// If aconfig_declarations property is not defined, all flagged apis symbols are stripped
+	// as no aconfig flags are enabled. In such case, the runtime stubs are identical to the
+	// exportable stubs, thus no additional metalava invocation is needed.
+	if len(d.properties.Aconfig_declarations) == 0 {
+		rule := android.NewRuleBuilder(pctx, ctx)
+		rule.Command().
+			Text("cp").Flag("-f").
+			Input(d.exportableStubsSrcJar).Output(d.runtimeStubsSrcJar)
+		rule.Build(fmt.Sprintf("metalava_%s", params.stubsType.String()), "metalava merged")
+	} else {
+		d.optionalStubCmd(ctx, optionalCmdParams)
+	}
+}
+
 func (d *Droidstubs) optionalStubCmd(ctx android.ModuleContext, params stubsCommandParams) {
 
 	params.srcJarDir = android.PathForModuleOut(ctx, params.stubConfig.stubsType.String(), "srcjars")
@@ -1120,6 +1163,8 @@
 
 	annotationsEnabled := Bool(d.properties.Annotations_enabled)
 
+	extractAnnotations := annotationsEnabled
+
 	migratingNullability := annotationsEnabled && String(d.properties.Previous_api) != ""
 	validatingNullability := annotationsEnabled && (strings.Contains(String(d.Javadoc.properties.Args), "--validate-nullability-from-merged-stubs") ||
 		String(d.properties.Validate_nullability_from_list) != "")
@@ -1127,27 +1172,40 @@
 	checkApi := apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") ||
 		apiCheckEnabled(ctx, d.properties.Check_api.Last_released, "last_released")
 
+	apiLevelsAnnotationsEnabled := proptools.Bool(d.properties.Api_levels_annotations_enabled)
+
 	stubCmdParams := stubsCommandConfigParams{
-		javaVersion:           javaVersion,
-		deps:                  deps,
-		checkApi:              checkApi,
-		generateStubs:         generateStubs,
-		doApiLint:             doApiLint,
-		doCheckReleased:       doCheckReleased,
-		writeSdkValues:        writeSdkValues,
-		migratingNullability:  migratingNullability,
-		validatingNullability: validatingNullability,
+		javaVersion:                 javaVersion,
+		deps:                        deps,
+		checkApi:                    checkApi,
+		generateStubs:               generateStubs,
+		doApiLint:                   doApiLint,
+		doCheckReleased:             doCheckReleased,
+		writeSdkValues:              writeSdkValues,
+		migratingNullability:        migratingNullability,
+		validatingNullability:       validatingNullability,
+		annotationsEnabled:          annotationsEnabled,
+		apiLevelsAnnotationsEnabled: apiLevelsAnnotationsEnabled,
+		extractAnnotations:          extractAnnotations,
 	}
 	stubCmdParams.stubsType = Everything
 	// Create default (i.e. "everything" stubs) rule for metalava
 	d.everythingStubCmd(ctx, stubCmdParams)
 
-	// The module generates "exportable" (and "runtime" eventually) stubs regardless of whether
+	// The module generates "exportable" stubs regardless of whether
 	// aconfig_declarations property is defined or not. If the property is not defined, the module simply
 	// strips all flagged apis to generate the "exportable" stubs
 	stubCmdParams.stubsType = Exportable
 	d.exportableStubCmd(ctx, stubCmdParams)
 
+	// "runtime" stubs do not generate any other artifacts than the stubs.
+	// Therefore, metalava does not have to run for "runtime" configuration
+	// when the module does not generate stubs.
+	if stubCmdParams.generateStubs {
+		stubCmdParams.stubsType = Runtime
+		d.runtimeStubCmd(ctx, stubCmdParams)
+	}
+
 	if apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") {
 
 		if len(d.Javadoc.properties.Out) > 0 {
diff --git a/java/droidstubs_test.go b/java/droidstubs_test.go
index e5ffd28..ca34e0e 100644
--- a/java/droidstubs_test.go
+++ b/java/droidstubs_test.go
@@ -396,23 +396,47 @@
 			"bar",
 		],
 	}
+	droidstubs {
+		name: "baz",
+		srcs: ["a/A.java"],
+		api_surface: "public",
+		check_api: {
+			current: {
+				api_file: "a/current.txt",
+				removed_api_file: "a/removed.txt",
+			}
+		},
+	}
 	`)
 
 	// Check that droidstubs depend on aconfig_declarations
 	android.AssertBoolEquals(t, "foo expected to depend on bar",
 		CheckModuleHasDependency(t, result.TestContext, "foo", "android_common", "bar"), true)
 
-	m := result.ModuleForTests("foo", "android_common")
+	fooModule := result.ModuleForTests("foo", "android_common")
 	android.AssertStringDoesContain(t, "foo generates revert annotations file",
-		strings.Join(m.AllOutputs(), ""), "revert-annotations-exportable.txt")
+		strings.Join(fooModule.AllOutputs(), ""), "revert-annotations-exportable.txt")
 
 	// revert-annotations.txt passed to exportable stubs generation metalava command
-	manifest := m.Output("metalava_exportable.sbox.textproto")
-	cmdline := String(android.RuleBuilderSboxProtoForTests(t, result.TestContext, manifest).Commands[0].Command)
-	android.AssertStringDoesContain(t, "flagged api hide command not included", cmdline, "revert-annotations-exportable.txt")
+	exportableManifest := fooModule.Output("metalava_exportable.sbox.textproto")
+	exportableCmdline := String(android.RuleBuilderSboxProtoForTests(t, result.TestContext, exportableManifest).Commands[0].Command)
+	android.AssertStringDoesContain(t, "flagged api hide command not included", exportableCmdline, "revert-annotations-exportable.txt")
 
 	android.AssertStringDoesContain(t, "foo generates exportable stubs jar",
-		strings.Join(m.AllOutputs(), ""), "exportable/foo-stubs.srcjar")
+		strings.Join(fooModule.AllOutputs(), ""), "exportable/foo-stubs.srcjar")
+
+	// revert-annotations.txt passed to runtime stubs generation metalava command
+	runtimeManifest := fooModule.Output("metalava_runtime.sbox.textproto")
+	runtimeCmdline := String(android.RuleBuilderSboxProtoForTests(t, result.TestContext, runtimeManifest).Commands[0].Command)
+	android.AssertStringDoesContain(t, "flagged api hide command not included", runtimeCmdline, "revert-annotations-runtime.txt")
+
+	android.AssertStringDoesContain(t, "foo generates runtime stubs jar",
+		strings.Join(fooModule.AllOutputs(), ""), "runtime/foo-stubs.srcjar")
+
+	// If aconfig_declarations property is not defined, the runtime stubs is a copy of the exportable stubs
+	bazModule := result.ModuleForTests("baz", "android_common")
+	bazRuntimeCmdline := bazModule.Rule("metalava_runtime").RuleParams.Command
+	android.AssertStringDoesContain(t, "copy command should include the input stub", bazRuntimeCmdline, "exportable/baz-stubs.srcjar")
 }
 
 func TestReleaseExportRuntimeApis(t *testing.T) {