Let LoadHooks call CreateModule

Move AppendProperties and PrependProperties into TopDownMutatorContext
so that LoadHooks can be a subset of TopDownMutatorContext that also
includes CreateModule.

Test: m checkbuild
Bug: 35570956
Change-Id: Iffa6a6aec96f08821c2446e0e0f4622ab772b54c
diff --git a/android/hooks.go b/android/hooks.go
index 7530f8d..a9bfd33 100644
--- a/android/hooks.go
+++ b/android/hooks.go
@@ -16,7 +16,6 @@
 
 import (
 	"github.com/google/blueprint"
-	"github.com/google/blueprint/proptools"
 )
 
 // This file implements hooks that external module types can use to inject logic into existing
@@ -31,6 +30,7 @@
 	BaseContext
 	AppendProperties(...interface{})
 	PrependProperties(...interface{})
+	CreateModule(blueprint.ModuleFactory, ...interface{})
 }
 
 // Arch hooks are run after the module has been split into architecture variants, and can be used
@@ -51,62 +51,22 @@
 	h.arch = append(h.arch, hook)
 }
 
-type propertyHookContext struct {
-	BaseContext
-
-	module *ModuleBase
-}
-
-func (ctx *propertyHookContext) AppendProperties(props ...interface{}) {
-	for _, p := range props {
-		err := proptools.AppendMatchingProperties(ctx.module.customizableProperties, p, nil)
-		if err != nil {
-			if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok {
-				ctx.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error())
-			} else {
-				panic(err)
-			}
-		}
-	}
-}
-
-func (ctx *propertyHookContext) PrependProperties(props ...interface{}) {
-	for _, p := range props {
-		err := proptools.PrependMatchingProperties(ctx.module.customizableProperties, p, nil)
-		if err != nil {
-			if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok {
-				ctx.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error())
-			} else {
-				panic(err)
-			}
-		}
-	}
-}
-
-func (x *hooks) runLoadHooks(ctx BaseContext, m *ModuleBase) {
+func (x *hooks) runLoadHooks(ctx LoadHookContext, m *ModuleBase) {
 	if len(x.load) > 0 {
-		mctx := &propertyHookContext{
-			BaseContext: ctx,
-			module:      m,
-		}
 		for _, x := range x.load {
-			x(mctx)
-			if mctx.Failed() {
+			x(ctx)
+			if ctx.Failed() {
 				return
 			}
 		}
 	}
 }
 
-func (x *hooks) runArchHooks(ctx BaseContext, m *ModuleBase) {
+func (x *hooks) runArchHooks(ctx ArchHookContext, m *ModuleBase) {
 	if len(x.arch) > 0 {
-		mctx := &propertyHookContext{
-			BaseContext: ctx,
-			module:      m,
-		}
 		for _, x := range x.arch {
-			x(mctx)
-			if mctx.Failed() {
+			x(ctx)
+			if ctx.Failed() {
 				return
 			}
 		}
@@ -165,12 +125,18 @@
 
 func loadHookMutator(ctx TopDownMutatorContext) {
 	if m, ok := ctx.Module().(Module); ok {
-		m.base().hooks.runLoadHooks(ctx, m.base())
+		// Cast through *androidTopDownMutatorContext because AppendProperties is implemented
+		// on *androidTopDownMutatorContext but not exposed through TopDownMutatorContext
+		var loadHookCtx LoadHookContext = ctx.(*androidTopDownMutatorContext)
+		m.base().hooks.runLoadHooks(loadHookCtx, m.base())
 	}
 }
 
 func archHookMutator(ctx TopDownMutatorContext) {
 	if m, ok := ctx.Module().(Module); ok {
-		m.base().hooks.runArchHooks(ctx, m.base())
+		// Cast through *androidTopDownMutatorContext because AppendProperties is implemented
+		// on *androidTopDownMutatorContext but not exposed through TopDownMutatorContext
+		var archHookCtx ArchHookContext = ctx.(*androidTopDownMutatorContext)
+		m.base().hooks.runArchHooks(archHookCtx, m.base())
 	}
 }
diff --git a/android/mutator.go b/android/mutator.go
index afff700..cc3f1f3 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -16,6 +16,7 @@
 
 import (
 	"github.com/google/blueprint"
+	"github.com/google/blueprint/proptools"
 )
 
 // Phases:
@@ -112,7 +113,7 @@
 
 	OtherModuleExists(name string) bool
 	Rename(name string)
-	Module() blueprint.Module
+	Module() Module
 
 	OtherModuleName(m blueprint.Module) string
 	OtherModuleErrorf(m blueprint.Module, fmt string, args ...interface{})
@@ -192,6 +193,11 @@
 	}
 }
 
+func (a *androidTopDownMutatorContext) Module() Module {
+	module, _ := a.TopDownMutatorContext.Module().(Module)
+	return module
+}
+
 func (a *androidTopDownMutatorContext) VisitDirectDeps(visit func(Module)) {
 	a.TopDownMutatorContext.VisitDirectDeps(func(module blueprint.Module) {
 		if aModule, _ := module.(Module); aModule != nil {
@@ -251,3 +257,31 @@
 		}
 	})
 }
+
+func (a *androidTopDownMutatorContext) AppendProperties(props ...interface{}) {
+	for _, p := range props {
+		err := proptools.AppendMatchingProperties(a.Module().base().customizableProperties,
+			p, nil)
+		if err != nil {
+			if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok {
+				a.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error())
+			} else {
+				panic(err)
+			}
+		}
+	}
+}
+
+func (a *androidTopDownMutatorContext) PrependProperties(props ...interface{}) {
+	for _, p := range props {
+		err := proptools.PrependMatchingProperties(a.Module().base().customizableProperties,
+			p, nil)
+		if err != nil {
+			if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok {
+				a.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error())
+			} else {
+				panic(err)
+			}
+		}
+	}
+}