Control mutator order

Register mutators inside lambdas that are called in a defined order to
correctly order mutators before and after the arch and deps mutators.

Test: build.ninja identical
Change-Id: Iefe2a3515aee8570e76a6e76925db4cda0e9e822
diff --git a/android/mutator.go b/android/mutator.go
index ff2f9ad..b375bce 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -16,6 +16,61 @@
 
 import "github.com/google/blueprint"
 
+// Mutator phases:
+//   Pre-arch
+//   Arch
+//   Pre-deps
+//   Deps
+//   PostDeps
+
+func registerMutators() {
+	ctx := registerMutatorsContext{}
+
+	register := func(funcs []RegisterMutatorFunc) {
+		for _, f := range funcs {
+			f(ctx)
+		}
+	}
+
+	ctx.TopDown("load_hooks", loadHookMutator).Parallel()
+	ctx.BottomUp("defaults_deps", defaultsDepsMutator).Parallel()
+	ctx.TopDown("defaults", defaultsMutator).Parallel()
+
+	register(preArch)
+
+	ctx.BottomUp("arch", archMutator).Parallel()
+	ctx.TopDown("arch_hooks", archHookMutator).Parallel()
+
+	register(preDeps)
+
+	ctx.BottomUp("deps", depsMutator).Parallel()
+
+	register(postDeps)
+}
+
+type registerMutatorsContext struct{}
+
+type RegisterMutatorsContext interface {
+	TopDown(name string, m AndroidTopDownMutator) MutatorHandle
+	BottomUp(name string, m AndroidBottomUpMutator) MutatorHandle
+}
+
+type RegisterMutatorFunc func(RegisterMutatorsContext)
+
+var preArch, preDeps, postDeps []RegisterMutatorFunc
+
+func PreArchMutators(f RegisterMutatorFunc) {
+	preArch = append(preArch, f)
+}
+
+func PreDepsMutators(f RegisterMutatorFunc) {
+	preDeps = append(preDeps, f)
+}
+
+func PostDepsMutators(f RegisterMutatorFunc) {
+	postDeps = append(postDeps, f)
+}
+
 type AndroidTopDownMutator func(TopDownMutatorContext)
 
 type TopDownMutatorContext interface {
@@ -40,7 +95,7 @@
 	androidBaseContextImpl
 }
 
-func RegisterBottomUpMutator(name string, m AndroidBottomUpMutator) MutatorHandle {
+func (registerMutatorsContext) BottomUp(name string, m AndroidBottomUpMutator) MutatorHandle {
 	f := func(ctx blueprint.BottomUpMutatorContext) {
 		if a, ok := ctx.Module().(Module); ok {
 			actx := &androidBottomUpMutatorContext{
@@ -55,7 +110,7 @@
 	return mutator
 }
 
-func RegisterTopDownMutator(name string, m AndroidTopDownMutator) MutatorHandle {
+func (registerMutatorsContext) TopDown(name string, m AndroidTopDownMutator) MutatorHandle {
 	f := func(ctx blueprint.TopDownMutatorContext) {
 		if a, ok := ctx.Module().(Module); ok {
 			actx := &androidTopDownMutatorContext{
@@ -78,3 +133,9 @@
 	mutator.parallel = true
 	return mutator
 }
+
+func depsMutator(ctx BottomUpMutatorContext) {
+	if m, ok := ctx.Module().(Module); ok {
+		m.DepsMutator(ctx)
+	}
+}