Merge "Document critical path in perf.md"
diff --git a/android/module.go b/android/module.go
index 06079ca..f80f37e 100644
--- a/android/module.go
+++ b/android/module.go
@@ -228,6 +228,16 @@
 	// For more information, see Module.GenerateBuildActions within Blueprint's module_ctx.go
 	GenerateAndroidBuildActions(ModuleContext)
 
+	// Add dependencies to the components of a module, i.e. modules that are created
+	// by the module and which are considered to be part of the creating module.
+	//
+	// This is called before prebuilts are renamed so as to allow a dependency to be
+	// added directly to a prebuilt child module instead of depending on a source module
+	// and relying on prebuilt processing to switch to the prebuilt module if preferred.
+	//
+	// A dependency on a prebuilt must include the "prebuilt_" prefix.
+	ComponentDepsMutator(ctx BottomUpMutatorContext)
+
 	DepsMutator(BottomUpMutatorContext)
 
 	base() *ModuleBase
@@ -769,6 +779,8 @@
 	prefer32 func(ctx BaseModuleContext, base *ModuleBase, class OsClass) bool
 }
 
+func (m *ModuleBase) ComponentDepsMutator(BottomUpMutatorContext) {}
+
 func (m *ModuleBase) DepsMutator(BottomUpMutatorContext) {}
 
 func (m *ModuleBase) AddProperties(props ...interface{}) {
@@ -2099,15 +2111,6 @@
 	m.checkbuildFiles = append(m.checkbuildFiles, srcPath)
 }
 
-func findStringInSlice(str string, slice []string) int {
-	for i, s := range slice {
-		if s == str {
-			return i
-		}
-	}
-	return -1
-}
-
 // SrcIsModule decodes module references in the format ":name" into the module name, or empty string if the input
 // was not a module reference.
 func SrcIsModule(s string) (module string) {
diff --git a/android/mutator.go b/android/mutator.go
index 77d5f43..b70c4ff 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -115,6 +115,18 @@
 	// a DefaultableHook.
 	RegisterDefaultsPreArchMutators,
 
+	// Add dependencies on any components so that any component references can be
+	// resolved within the deps mutator.
+	//
+	// Must be run after defaults so it can be used to create dependencies on the
+	// component modules that are creating in a DefaultableHook.
+	//
+	// Must be run before RegisterPrebuiltsPreArchMutators, i.e. before prebuilts are
+	// renamed. That is so that if a module creates components using a prebuilt module
+	// type that any dependencies (which must use prebuilt_ prefixes) are resolved to
+	// the prebuilt module and not the source module.
+	RegisterComponentsMutator,
+
 	// Create an association between prebuilt modules and their corresponding source
 	// modules (if any).
 	//
@@ -202,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)
 }
 
@@ -252,8 +265,21 @@
 	return mutator
 }
 
+func RegisterComponentsMutator(ctx RegisterMutatorsContext) {
+	ctx.BottomUp("component-deps", componentDepsMutator).Parallel()
+}
+
+// A special mutator that runs just prior to the deps mutator to allow the dependencies
+// on component modules to be added so that they can depend directly on a prebuilt
+// module.
+func componentDepsMutator(ctx BottomUpMutatorContext) {
+	if m := ctx.Module(); m.Enabled() {
+		m.ComponentDepsMutator(ctx)
+	}
+}
+
 func depsMutator(ctx BottomUpMutatorContext) {
-	if m, ok := ctx.Module().(Module); ok && m.Enabled() {
+	if m := ctx.Module(); m.Enabled() {
 		m.DepsMutator(ctx)
 	}
 }
@@ -403,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/paths.go b/android/paths.go
index 066baf2..d13b6d8 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -380,6 +380,18 @@
 }
 
 func expandOneSrcPath(ctx ModuleContext, s string, expandedExcludes []string) (Paths, error) {
+	excludePaths := func(paths Paths) Paths {
+		if len(expandedExcludes) == 0 {
+			return paths
+		}
+		remainder := make(Paths, 0, len(paths))
+		for _, p := range paths {
+			if !InList(p.String(), expandedExcludes) {
+				remainder = append(remainder, p)
+			}
+		}
+		return remainder
+	}
 	if m, t := SrcIsModuleWithTag(s); m != "" {
 		module := ctx.GetDirectDepWithTag(m, sourceOrOutputDepTag(t))
 		if module == nil {
@@ -390,20 +402,11 @@
 			if err != nil {
 				return nil, fmt.Errorf("path dependency %q: %s", s, err)
 			}
-			return outputFiles, nil
+			return excludePaths(outputFiles), nil
 		} else if t != "" {
 			return nil, fmt.Errorf("path dependency %q is not an output file producing module", s)
 		} else if srcProducer, ok := module.(SourceFileProducer); ok {
-			moduleSrcs := srcProducer.Srcs()
-			for _, e := range expandedExcludes {
-				for j := 0; j < len(moduleSrcs); j++ {
-					if moduleSrcs[j].String() == e {
-						moduleSrcs = append(moduleSrcs[:j], moduleSrcs[j+1:]...)
-						j--
-					}
-				}
-			}
-			return moduleSrcs, nil
+			return excludePaths(srcProducer.Srcs()), nil
 		} else {
 			return nil, fmt.Errorf("path dependency %q is not a source file producing module", s)
 		}
@@ -418,8 +421,7 @@
 			reportPathErrorf(ctx, "module source path %q does not exist", p)
 		}
 
-		j := findStringInSlice(p.String(), expandedExcludes)
-		if j >= 0 {
+		if InList(p.String(), expandedExcludes) {
 			return nil, nil
 		}
 		return Paths{p}, nil
diff --git a/android/paths_test.go b/android/paths_test.go
index 9b45d3f..a9cd22b 100644
--- a/android/paths_test.go
+++ b/android/paths_test.go
@@ -1091,6 +1091,21 @@
 			rels: []string{"gen/c"},
 		},
 		{
+			name: "output file provider with exclude",
+			bp: `
+			test {
+				name: "foo",
+				srcs: [":b", ":c"],
+				exclude_srcs: [":c"]
+			}
+			output_file_provider {
+				name: "c",
+				outs: ["gen/c"],
+			}`,
+			srcs: []string{buildDir + "/.intermediates/ofp/b/gen/b"},
+			rels: []string{"gen/b"},
+		},
+		{
 			name: "special characters glob",
 			bp: `
 			test {
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/apex/apex_test.go b/apex/apex_test.go
index befb814..c2cb200 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -233,6 +233,7 @@
 	ctx.RegisterModuleType("apex_set", apexSetFactory)
 
 	ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
+	ctx.PreArchMutators(android.RegisterComponentsMutator)
 	ctx.PostDepsMutators(android.RegisterOverridePostDepsMutators)
 
 	cc.RegisterRequiredBuildComponentsForTest(ctx)
diff --git a/java/java_test.go b/java/java_test.go
index def42db..59a2ce7 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -86,6 +86,7 @@
 	RegisterStubsBuildComponents(ctx)
 	RegisterSdkLibraryBuildComponents(ctx)
 	ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
+	ctx.PreArchMutators(android.RegisterComponentsMutator)
 
 	RegisterPrebuiltApisBuildComponents(ctx)
 
@@ -684,11 +685,11 @@
 	})
 
 	checkModuleDependencies(t, ctx, "prebuilt_sdklib", "android_common", []string{
+		`prebuilt_sdklib.stubs`,
 		`sdklib.impl`,
 		// This should be prebuilt_sdklib.stubs but is set to sdklib.stubs because the
 		// dependency is added after prebuilts may have been renamed and so has to use
 		// the renamed name.
-		`sdklib.stubs`,
 		`sdklib.xml`,
 	})
 }
@@ -717,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 8f8f8ce..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
@@ -973,7 +979,8 @@
 
 var implLibraryTag = sdkLibraryComponentTag{name: "impl-library"}
 
-func (module *SdkLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {
+// Add the dependencies on the child modules in the component deps mutator.
+func (module *SdkLibrary) ComponentDepsMutator(ctx android.BottomUpMutatorContext) {
 	for _, apiScope := range module.getGeneratedApiScopes(ctx) {
 		// Add dependencies to the stubs library
 		ctx.AddVariationDependencies(nil, apiScope.stubsTag, module.stubsLibraryModuleName(apiScope))
@@ -998,7 +1005,12 @@
 			// Add dependency to the rule for generating the xml permissions file
 			ctx.AddDependency(module, xmlPermissionsFileTag, module.xmlPermissionsModuleName())
 		}
+	}
+}
 
+// Add other dependencies as normal.
+func (module *SdkLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {
+	if module.requiresRuntimeImplementationLibrary() {
 		// Only add the deps for the library if it is actually going to be built.
 		module.Library.deps(ctx)
 	}
@@ -1874,20 +1886,26 @@
 	props.Prefer = proptools.BoolPtr(module.prebuilt.Prefer())
 }
 
-func (module *SdkLibraryImport) DepsMutator(ctx android.BottomUpMutatorContext) {
+// Add the dependencies on the child module in the component deps mutator so that it
+// creates references to the prebuilt and not the source modules.
+func (module *SdkLibraryImport) ComponentDepsMutator(ctx android.BottomUpMutatorContext) {
 	for apiScope, scopeProperties := range module.scopeProperties {
 		if len(scopeProperties.Jars) == 0 {
 			continue
 		}
 
 		// Add dependencies to the prebuilt stubs library
-		ctx.AddVariationDependencies(nil, apiScope.stubsTag, module.stubsLibraryModuleName(apiScope))
+		ctx.AddVariationDependencies(nil, apiScope.stubsTag, "prebuilt_"+module.stubsLibraryModuleName(apiScope))
 
 		if len(scopeProperties.Stub_srcs) > 0 {
 			// Add dependencies to the prebuilt stubs source library
-			ctx.AddVariationDependencies(nil, apiScope.stubsSourceTag, module.stubsSourceModuleName(apiScope))
+			ctx.AddVariationDependencies(nil, apiScope.stubsSourceTag, "prebuilt_"+module.stubsSourceModuleName(apiScope))
 		}
 	}
+}
+
+// Add other dependencies as normal.
+func (module *SdkLibraryImport) DepsMutator(ctx android.BottomUpMutatorContext) {
 
 	implName := module.implLibraryModuleName()
 	if ctx.OtherModuleExists(implName) {
diff --git a/sdk/testing.go b/sdk/testing.go
index 4361754..40abdcd 100644
--- a/sdk/testing.go
+++ b/sdk/testing.go
@@ -84,6 +84,7 @@
 	android.RegisterPackageBuildComponents(ctx)
 	ctx.PreArchMutators(android.RegisterVisibilityRuleChecker)
 	ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
+	ctx.PreArchMutators(android.RegisterComponentsMutator)
 	ctx.PreArchMutators(android.RegisterVisibilityRuleGatherer)
 	ctx.PostDepsMutators(android.RegisterVisibilityRuleEnforcer)