Remove EarlyMutators and DynamicDependencies

EarlyMutators are identical to BottomUpMutators, except they run before
DynamicDependencies.  DynamicDependencies can be replaced with a
BottomUpMutator.  Replace both EarlyMutators and DynamicDependencies
with BottomUpMutators, which allows setting the order between all
mutators through registration order.

Change-Id: Id1305d798d3d2da592061c89d7c10a71780b71a3
diff --git a/Android.bp b/Android.bp
index 914d673..abae680 100644
--- a/Android.bp
+++ b/Android.bp
@@ -95,6 +95,7 @@
         "common/env.go",
         "common/glob.go",
         "common/module.go",
+        "common/mutator.go",
         "common/paths.go",
         "common/util.go",
         "common/variable.go",
diff --git a/cc/cc.go b/cc/cc.go
index a1b5a42..b23ab43 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -57,8 +57,9 @@
 	// LinkageMutator must be registered after common.ArchMutator, but that is guaranteed by
 	// the Go initialization order because this package depends on common, so common's init
 	// functions will run first.
-	soong.RegisterEarlyMutator("link", LinkageMutator)
-	soong.RegisterEarlyMutator("test_per_src", TestPerSrcMutator)
+	common.RegisterBottomUpMutator("link", linkageMutator)
+	common.RegisterBottomUpMutator("test_per_src", testPerSrcMutator)
+	common.RegisterBottomUpMutator("deps", depsMutator)
 }
 
 var (
@@ -140,20 +141,25 @@
 	pctx.StaticVariable("clangPath", "${SrcDir}/prebuilts/clang/${HostPrebuiltTag}/host/3.6/bin/")
 }
 
+type CCModuleContext common.AndroidBaseContext
+
 // Building C/C++ code is handled by objects that satisfy this interface via composition
 type CCModuleType interface {
 	common.AndroidModule
 
 	// Modify property values after parsing Blueprints file but before starting dependency
 	// resolution or build rule generation
-	ModifyProperties(common.AndroidBaseContext)
+	ModifyProperties(CCModuleContext)
 
 	// Modify the ccFlags
 	flags(common.AndroidModuleContext, CCFlags) CCFlags
 
-	// Return list of dependency names for use in AndroidDynamicDependencies and in depsToPaths
+	// Return list of dependency names for use in depsMutator
 	depNames(common.AndroidBaseContext, CCDeps) CCDeps
 
+	// Add dynamic dependencies
+	depsMutator(common.AndroidBottomUpMutatorContext)
+
 	// Compile objects into final module
 	compileModule(common.AndroidModuleContext, CCFlags, CCDeps, []string)
 
@@ -392,8 +398,6 @@
 	return c.module
 }
 
-var _ common.AndroidDynamicDepender = (*CCBase)(nil)
-
 func (c *CCBase) findToolchain(ctx common.AndroidModuleContext) Toolchain {
 	arch := ctx.Arch()
 	hod := ctx.HostOrDevice()
@@ -405,7 +409,7 @@
 	return factory(arch.ArchVariant, arch.CpuVariant)
 }
 
-func (c *CCBase) ModifyProperties(ctx common.AndroidBaseContext) {
+func (c *CCBase) ModifyProperties(ctx CCModuleContext) {
 }
 
 func (c *CCBase) depNames(ctx common.AndroidBaseContext, depNames CCDeps) CCDeps {
@@ -416,9 +420,7 @@
 	return depNames
 }
 
-func (c *CCBase) AndroidDynamicDependencies(ctx common.AndroidDynamicDependerModuleContext) []string {
-	c.module.ModifyProperties(ctx)
-
+func (c *CCBase) depsMutator(ctx common.AndroidBottomUpMutatorContext) {
 	c.savedDepNames = c.module.depNames(ctx, CCDeps{})
 	c.savedDepNames.WholeStaticLibs = lastUniqueElements(c.savedDepNames.WholeStaticLibs)
 	c.savedDepNames.StaticLibs = lastUniqueElements(c.savedDepNames.StaticLibs)
@@ -431,15 +433,20 @@
 
 	ctx.AddVariationDependencies([]blueprint.Variation{{"link", "shared"}}, c.savedDepNames.SharedLibs...)
 
-	ret := append([]string(nil), c.savedDepNames.ObjFiles...)
+	ctx.AddDependency(ctx.Module(), c.savedDepNames.ObjFiles...)
 	if c.savedDepNames.CrtBegin != "" {
-		ret = append(ret, c.savedDepNames.CrtBegin)
+		ctx.AddDependency(ctx.Module(), c.savedDepNames.CrtBegin)
 	}
 	if c.savedDepNames.CrtEnd != "" {
-		ret = append(ret, c.savedDepNames.CrtEnd)
+		ctx.AddDependency(ctx.Module(), c.savedDepNames.CrtEnd)
 	}
+}
 
-	return ret
+func depsMutator(ctx common.AndroidBottomUpMutatorContext) {
+	if c, ok := ctx.Module().(CCModuleType); ok {
+		c.ModifyProperties(ctx)
+		c.depsMutator(ctx)
+	}
 }
 
 // Create a ccFlags struct that collects the compile flags from global values,
@@ -1285,11 +1292,6 @@
 	return newCCBase(&module.CCBase, module, common.DeviceSupported, common.MultilibBoth)
 }
 
-func (*ccObject) AndroidDynamicDependencies(ctx common.AndroidDynamicDependerModuleContext) []string {
-	// object files can't have any dynamic dependencies
-	return nil
-}
-
 func (*ccObject) depNames(ctx common.AndroidBaseContext, depNames CCDeps) CCDeps {
 	// object files can't have any dynamic dependencies
 	return CCDeps{}
@@ -1418,7 +1420,7 @@
 	return NewCCBinary(module, module, common.HostAndDeviceSupported)
 }
 
-func (c *CCBinary) ModifyProperties(ctx common.AndroidBaseContext) {
+func (c *CCBinary) ModifyProperties(ctx CCModuleContext) {
 	if ctx.Darwin() {
 		c.BinaryProperties.Static_executable = proptools.BoolPtr(false)
 	}
@@ -1519,7 +1521,7 @@
 
 var _ testPerSrc = (*CCBinary)(nil)
 
-func TestPerSrcMutator(mctx blueprint.EarlyMutatorContext) {
+func testPerSrcMutator(mctx common.AndroidBottomUpMutatorContext) {
 	if test, ok := mctx.Module().(testPerSrc); ok {
 		if test.testPerSrc() {
 			testNames := make([]string, len(test.binary().Properties.Srcs))
@@ -1691,11 +1693,6 @@
 	CCLibrary
 }
 
-func (*toolchainLibrary) AndroidDynamicDependencies(ctx common.AndroidDynamicDependerModuleContext) []string {
-	// toolchain libraries can't have any dependencies
-	return nil
-}
-
 func (*toolchainLibrary) depNames(ctx common.AndroidBaseContext, depNames CCDeps) CCDeps {
 	// toolchain libraries can't have any dependencies
 	return CCDeps{}
@@ -1752,13 +1749,6 @@
 	ccObject
 }
 
-func (*ndkPrebuiltObject) AndroidDynamicDependencies(
-	ctx common.AndroidDynamicDependerModuleContext) []string {
-
-	// NDK objects can't have any dependencies
-	return nil
-}
-
 func (*ndkPrebuiltObject) depNames(ctx common.AndroidBaseContext, depNames CCDeps) CCDeps {
 	// NDK objects can't have any dependencies
 	return CCDeps{}
@@ -1789,13 +1779,6 @@
 	CCLibrary
 }
 
-func (*ndkPrebuiltLibrary) AndroidDynamicDependencies(
-	ctx common.AndroidDynamicDependerModuleContext) []string {
-
-	// NDK libraries can't have any dependencies
-	return nil
-}
-
 func (*ndkPrebuiltLibrary) depNames(ctx common.AndroidBaseContext, depNames CCDeps) CCDeps {
 	// NDK libraries can't have any dependencies
 	return CCDeps{}
@@ -1896,7 +1879,7 @@
 	c.out = libDir + "/" + libName + libExt
 }
 
-func LinkageMutator(mctx blueprint.EarlyMutatorContext) {
+func linkageMutator(mctx common.AndroidBottomUpMutatorContext) {
 	if c, ok := mctx.Module().(ccLinkedInterface); ok {
 		var modules []blueprint.Module
 		if c.buildStatic() && c.buildShared() {
diff --git a/common/arch.go b/common/arch.go
index 0594567..f0f4409 100644
--- a/common/arch.go
+++ b/common/arch.go
@@ -20,15 +20,13 @@
 	"runtime"
 	"strings"
 
-	"android/soong"
-
 	"github.com/google/blueprint"
 	"github.com/google/blueprint/proptools"
 )
 
 func init() {
-	soong.RegisterEarlyMutator("host_or_device", HostOrDeviceMutator)
-	soong.RegisterEarlyMutator("arch", ArchMutator)
+	RegisterBottomUpMutator("host_or_device", HostOrDeviceMutator)
+	RegisterBottomUpMutator("arch", ArchMutator)
 }
 
 var (
@@ -303,7 +301,7 @@
 	}
 )
 
-func HostOrDeviceMutator(mctx blueprint.EarlyMutatorContext) {
+func HostOrDeviceMutator(mctx AndroidBottomUpMutatorContext) {
 	var module AndroidModule
 	var ok bool
 	if module, ok = mctx.Module().(AndroidModule); !ok {
@@ -335,7 +333,7 @@
 	}
 }
 
-func ArchMutator(mctx blueprint.EarlyMutatorContext) {
+func ArchMutator(mctx AndroidBottomUpMutatorContext) {
 	var module AndroidModule
 	var ok bool
 	if module, ok = mctx.Module().(AndroidModule); !ok {
@@ -426,7 +424,7 @@
 
 var dashToUnderscoreReplacer = strings.NewReplacer("-", "_")
 
-func (a *AndroidModuleBase) appendProperties(ctx blueprint.EarlyMutatorContext,
+func (a *AndroidModuleBase) appendProperties(ctx AndroidBottomUpMutatorContext,
 	dst, src interface{}, field, srcPrefix string) {
 
 	src = reflect.ValueOf(src).FieldByName(field).Elem().Interface()
@@ -459,7 +457,7 @@
 }
 
 // Rewrite the module's properties structs to contain arch-specific values.
-func (a *AndroidModuleBase) setArchProperties(ctx blueprint.EarlyMutatorContext) {
+func (a *AndroidModuleBase) setArchProperties(ctx AndroidBottomUpMutatorContext) {
 	arch := a.commonProperties.CompileArch
 	hod := a.commonProperties.CompileHostOrDevice
 
diff --git a/common/module.go b/common/module.go
index d31a9fc..1860ecb 100644
--- a/common/module.go
+++ b/common/module.go
@@ -72,15 +72,6 @@
 	HostOrDevice() HostOrDevice
 }
 
-type AndroidDynamicDepender interface {
-	AndroidDynamicDependencies(ctx AndroidDynamicDependerModuleContext) []string
-}
-
-type AndroidDynamicDependerModuleContext interface {
-	blueprint.DynamicDependerModuleContext
-	androidBaseContext
-}
-
 type commonProperties struct {
 	Name string
 	Deps []string
@@ -313,33 +304,20 @@
 	}
 }
 
-func (a *AndroidModuleBase) DynamicDependencies(ctx blueprint.DynamicDependerModuleContext) []string {
-	actx := &androidDynamicDependerContext{
-		DynamicDependerModuleContext: ctx,
-		androidBaseContextImpl: androidBaseContextImpl{
-			arch:   a.commonProperties.CompileArch,
-			hod:    a.commonProperties.CompileHostOrDevice,
-			config: ctx.Config().(Config),
-		},
+func (a *AndroidModuleBase) androidBaseContextFactory(ctx blueprint.BaseModuleContext) androidBaseContextImpl {
+	return androidBaseContextImpl{
+		arch:   a.commonProperties.CompileArch,
+		hod:    a.commonProperties.CompileHostOrDevice,
+		config: ctx.Config().(Config),
 	}
-
-	if dynamic, ok := a.module.(AndroidDynamicDepender); ok {
-		return dynamic.AndroidDynamicDependencies(actx)
-	}
-
-	return nil
 }
 
 func (a *AndroidModuleBase) GenerateBuildActions(ctx blueprint.ModuleContext) {
 	androidCtx := &androidModuleContext{
-		ModuleContext: ctx,
-		androidBaseContextImpl: androidBaseContextImpl{
-			arch:   a.commonProperties.CompileArch,
-			hod:    a.commonProperties.CompileHostOrDevice,
-			config: ctx.Config().(Config),
-		},
-		installDeps:  a.computeInstallDeps(ctx),
-		installFiles: a.installFiles,
+		ModuleContext:          ctx,
+		androidBaseContextImpl: a.androidBaseContextFactory(ctx),
+		installDeps:            a.computeInstallDeps(ctx),
+		installFiles:           a.installFiles,
 	}
 
 	if a.commonProperties.Disabled {
@@ -443,11 +421,6 @@
 	a.checkbuildFiles = append(a.checkbuildFiles, srcPath)
 }
 
-type androidDynamicDependerContext struct {
-	blueprint.DynamicDependerModuleContext
-	androidBaseContextImpl
-}
-
 type fileInstaller interface {
 	filesToInstall() []string
 }
diff --git a/common/mutator.go b/common/mutator.go
new file mode 100644
index 0000000..43721ee
--- /dev/null
+++ b/common/mutator.go
@@ -0,0 +1,69 @@
+// Copyright 2015 Google Inc. All rights reserved.
+//
+// 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.
+
+package common
+
+import (
+	"android/soong"
+
+	"github.com/google/blueprint"
+)
+
+type AndroidTopDownMutator func(AndroidTopDownMutatorContext)
+
+type AndroidTopDownMutatorContext interface {
+	blueprint.TopDownMutatorContext
+	androidBaseContext
+}
+
+type androidTopDownMutatorContext struct {
+	blueprint.TopDownMutatorContext
+	androidBaseContextImpl
+}
+
+type AndroidBottomUpMutator func(AndroidBottomUpMutatorContext)
+
+type AndroidBottomUpMutatorContext interface {
+	blueprint.BottomUpMutatorContext
+	androidBaseContext
+}
+
+type androidBottomUpMutatorContext struct {
+	blueprint.BottomUpMutatorContext
+	androidBaseContextImpl
+}
+
+func RegisterBottomUpMutator(name string, mutator AndroidBottomUpMutator) {
+	soong.RegisterBottomUpMutator(name, func(ctx blueprint.BottomUpMutatorContext) {
+		if a, ok := ctx.Module().(AndroidModule); ok {
+			actx := &androidBottomUpMutatorContext{
+				BottomUpMutatorContext: ctx,
+				androidBaseContextImpl: a.base().androidBaseContextFactory(ctx),
+			}
+			mutator(actx)
+		}
+	})
+}
+
+func RegisterTopDownMutator(name string, mutator AndroidTopDownMutator) {
+	soong.RegisterTopDownMutator(name, func(ctx blueprint.TopDownMutatorContext) {
+		if a, ok := ctx.Module().(AndroidModule); ok {
+			actx := &androidTopDownMutatorContext{
+				TopDownMutatorContext:  ctx,
+				androidBaseContextImpl: a.base().androidBaseContextFactory(ctx),
+			}
+			mutator(actx)
+		}
+	})
+}
diff --git a/common/variable.go b/common/variable.go
index 3949681..9a5998f 100644
--- a/common/variable.go
+++ b/common/variable.go
@@ -19,14 +19,11 @@
 	"reflect"
 	"strings"
 
-	"android/soong"
-
-	"github.com/google/blueprint"
 	"github.com/google/blueprint/proptools"
 )
 
 func init() {
-	soong.RegisterEarlyMutator("variable", VariableMutator)
+	RegisterBottomUpMutator("variable", variableMutator)
 }
 
 type variableProperties struct {
@@ -104,7 +101,7 @@
 	}
 }
 
-func VariableMutator(mctx blueprint.EarlyMutatorContext) {
+func variableMutator(mctx AndroidBottomUpMutatorContext) {
 	var module AndroidModule
 	var ok bool
 	if module, ok = mctx.Module().(AndroidModule); !ok {
@@ -144,7 +141,7 @@
 	}
 }
 
-func (a *AndroidModuleBase) setVariableProperties(ctx blueprint.EarlyMutatorContext,
+func (a *AndroidModuleBase) setVariableProperties(ctx AndroidBottomUpMutatorContext,
 	prefix string, productVariablePropertyValue reflect.Value, variableValue interface{}) {
 
 	if variableValue != nil {
diff --git a/genrule/genrule.go b/genrule/genrule.go
index a5a4c71..fb0dafc 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -27,6 +27,8 @@
 func init() {
 	soong.RegisterModuleType("gensrcs", GenSrcsFactory)
 	soong.RegisterModuleType("genrule", GenRuleFactory)
+
+	common.RegisterBottomUpMutator("genrule_deps", genruleDepsMutator)
 }
 
 var (
@@ -83,12 +85,13 @@
 	return g.outputFiles
 }
 
-func (g *generator) AndroidDynamicDependencies(ctx common.AndroidDynamicDependerModuleContext) []string {
-	if g.properties.Tool != "" {
-		ctx.AddFarVariationDependencies([]blueprint.Variation{{"hostordevice", common.Host.String()}},
-			g.properties.Tool)
+func genruleDepsMutator(ctx common.AndroidBottomUpMutatorContext) {
+	if g, ok := ctx.Module().(*generator); ok {
+		if g.properties.Tool != "" {
+			ctx.AddFarVariationDependencies([]blueprint.Variation{{"hostordevice", common.Host.String()}},
+				g.properties.Tool)
+		}
 	}
-	return nil
 }
 
 func (g *generator) GenerateAndroidBuildActions(ctx common.AndroidModuleContext) {
diff --git a/java/app.go b/java/app.go
index a6e651d..74e3269 100644
--- a/java/app.go
+++ b/java/app.go
@@ -67,8 +67,8 @@
 	exportPackage    string
 }
 
-func (a *AndroidApp) JavaDynamicDependencies(ctx common.AndroidDynamicDependerModuleContext) []string {
-	deps := a.javaBase.JavaDynamicDependencies(ctx)
+func (a *AndroidApp) JavaDependencies(ctx AndroidJavaModuleContext) []string {
+	deps := a.javaBase.JavaDependencies(ctx)
 
 	if !a.properties.No_standard_libraries {
 		switch a.properties.Sdk_version { // TODO: Res_sdk_version?
diff --git a/java/java.go b/java/java.go
index 8b50eff..2bd5bff 100644
--- a/java/java.go
+++ b/java/java.go
@@ -145,9 +145,11 @@
 	installFile string
 }
 
+type AndroidJavaModuleContext common.AndroidBaseContext
+
 type JavaModuleType interface {
 	GenerateJavaBuildActions(ctx common.AndroidModuleContext)
-	JavaDynamicDependencies(ctx common.AndroidDynamicDependerModuleContext) []string
+	JavaDependencies(ctx AndroidJavaModuleContext) []string
 }
 
 type JavaDependency interface {
@@ -191,11 +193,13 @@
 
 var defaultJavaLibraries = []string{"core-libart", "core-junit", "ext", "framework"}
 
-func (j *javaBase) AndroidDynamicDependencies(ctx common.AndroidDynamicDependerModuleContext) []string {
-	return j.module.JavaDynamicDependencies(ctx)
+func javaDepsMutator(ctx common.AndroidBottomUpMutatorContext) {
+	if j, ok := ctx.Module().(JavaModuleType); ok {
+		ctx.AddDependency(ctx.Module(), j.JavaDependencies(ctx)...)
+	}
 }
 
-func (j *javaBase) JavaDynamicDependencies(ctx common.AndroidDynamicDependerModuleContext) []string {
+func (j *javaBase) JavaDependencies(ctx AndroidJavaModuleContext) []string {
 	var deps []string
 
 	if !j.properties.No_standard_libraries {
diff --git a/register.go b/register.go
index c35beae..353094c 100644
--- a/register.go
+++ b/register.go
@@ -30,12 +30,13 @@
 
 var singletons []singleton
 
-type earlyMutator struct {
-	name    string
-	mutator blueprint.EarlyMutator
+type mutator struct {
+	name            string
+	bottomUpMutator blueprint.BottomUpMutator
+	topDownMutator  blueprint.TopDownMutator
 }
 
-var earlyMutators []earlyMutator
+var mutators []mutator
 
 func RegisterModuleType(name string, factory blueprint.ModuleFactory) {
 	moduleTypes = append(moduleTypes, moduleType{name, factory})
@@ -45,8 +46,12 @@
 	singletons = append(singletons, singleton{name, factory})
 }
 
-func RegisterEarlyMutator(name string, mutator blueprint.EarlyMutator) {
-	earlyMutators = append(earlyMutators, earlyMutator{name, mutator})
+func RegisterBottomUpMutator(name string, m blueprint.BottomUpMutator) {
+	mutators = append(mutators, mutator{name: name, bottomUpMutator: m})
+}
+
+func RegisterTopDownMutator(name string, m blueprint.TopDownMutator) {
+	mutators = append(mutators, mutator{name: name, topDownMutator: m})
 }
 
 func NewContext() *blueprint.Context {
@@ -60,8 +65,13 @@
 		ctx.RegisterSingletonType(t.name, t.factory)
 	}
 
-	for _, t := range earlyMutators {
-		ctx.RegisterEarlyMutator(t.name, t.mutator)
+	for _, t := range mutators {
+		if t.bottomUpMutator != nil {
+			ctx.RegisterBottomUpMutator(t.name, t.bottomUpMutator)
+		}
+		if t.topDownMutator != nil {
+			ctx.RegisterTopDownMutator(t.name, t.topDownMutator)
+		}
 	}
 
 	return ctx