Restrict replacements of source dependencies with prebuilts

Previously, when java_sdk_library_import was preferred over a
java_sdk_library the latter ends up depending on the prebuilt child
modules created by the java_sdk_library_import instead of the source
child modules that it created itself. That was because all dependencies
on those source child modules were replaced with the corresponding
prebuilt child modules.

This change prevents those dependencies from being replaced to preserve
the dependencies from java_sdk_library onto its source child modules by
making the replacement conditional depending on the tag used. It also
updates the affected test.

Bug: 159902351
Test: m nothing
Change-Id: I4441b901dedfd44b9769df1ac2e248b94834cf85
diff --git a/android/mutator.go b/android/mutator.go
index 9454485..b70c4ff 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -214,6 +214,7 @@
 	AddFarVariationDependencies([]blueprint.Variation, blueprint.DependencyTag, ...string)
 	AddInterVariantDependency(tag blueprint.DependencyTag, from, to blueprint.Module)
 	ReplaceDependencies(string)
+	ReplaceDependenciesIf(string, blueprint.ReplaceDependencyPredicate)
 	AliasVariation(variationName string)
 }
 
@@ -428,6 +429,10 @@
 	b.bp.ReplaceDependencies(name)
 }
 
+func (b *bottomUpMutatorContext) ReplaceDependenciesIf(name string, predicate blueprint.ReplaceDependencyPredicate) {
+	b.bp.ReplaceDependenciesIf(name, predicate)
+}
+
 func (b *bottomUpMutatorContext) AliasVariation(variationName string) {
 	b.bp.AliasVariation(variationName)
 }
diff --git a/android/prebuilt.go b/android/prebuilt.go
index a29ec91..9f4df28 100644
--- a/android/prebuilt.go
+++ b/android/prebuilt.go
@@ -30,6 +30,16 @@
 	ctx.PostDepsMutators(RegisterPrebuiltsPostDepsMutators)
 }
 
+// Marks a dependency tag as possibly preventing a reference to a source from being
+// replaced with the prebuilt.
+type ReplaceSourceWithPrebuilt interface {
+	blueprint.DependencyTag
+
+	// Return true if the dependency defined by this tag should be replaced with the
+	// prebuilt.
+	ReplaceSourceWithPrebuilt() bool
+}
+
 type prebuiltDependencyTag struct {
 	blueprint.BaseDependencyTag
 }
@@ -260,7 +270,13 @@
 		name := m.base().BaseModuleName()
 		if p.properties.UsePrebuilt {
 			if p.properties.SourceExists {
-				ctx.ReplaceDependencies(name)
+				ctx.ReplaceDependenciesIf(name, func(from blueprint.Module, tag blueprint.DependencyTag, to blueprint.Module) bool {
+					if t, ok := tag.(ReplaceSourceWithPrebuilt); ok {
+						return t.ReplaceSourceWithPrebuilt()
+					}
+
+					return true
+				})
 			}
 		} else {
 			m.SkipInstall()
diff --git a/java/java_test.go b/java/java_test.go
index 23dcd53..59a2ce7 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -718,9 +718,8 @@
 	checkModuleDependencies(t, ctx, "sdklib", "android_common", []string{
 		`dex2oatd`,
 		`prebuilt_sdklib`,
-		// This should be sdklib.stubs but is switched to the prebuilt because it is preferred.
-		`prebuilt_sdklib.stubs`,
 		`sdklib.impl`,
+		`sdklib.stubs`,
 		`sdklib.stubs.source`,
 		`sdklib.xml`,
 	})
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 1fd109a..a5aa328 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -70,6 +70,12 @@
 	}
 }
 
+var _ android.ReplaceSourceWithPrebuilt = (*scopeDependencyTag)(nil)
+
+func (tag scopeDependencyTag) ReplaceSourceWithPrebuilt() bool {
+	return false
+}
+
 // Provides information about an api scope, e.g. public, system, test.
 type apiScope struct {
 	// The name of the api scope, e.g. public, system, test