Consolidate *MutatorContext and ModuleContext into BaseModuleContext

Following 99bdb2ab4fd5168a71a20aecf10611425be47ec4 in build/blueprint,
move more methods into BaseModuleContext.

This reapplies I9f8df94f1ae2b55d3cccf7b9468247f3e7cb2ebd after fixing
missing errors thrown for missing defaults modules when
AllowMissingDependencies == true.

Test: m checkbuild
Test: defaults_test.go
Change-Id: Ia17b2bcbf2bac6889c419b2e73953946f6aa40ad
diff --git a/android/module.go b/android/module.go
index 3a9ef96..03993e5 100644
--- a/android/module.go
+++ b/android/module.go
@@ -56,14 +56,40 @@
 type ModuleBuildParams BuildParams
 
 // BaseModuleContext is the same as blueprint.BaseModuleContext except that Config() returns
-// a Config instead of an interface{}, plus some extra methods that return Android-specific information
+// a Config instead of an interface{}, and some methods have been wrapped to use an android.Module
+// instead of a blueprint.Module, plus some extra methods that return Android-specific information
 // about the current module.
 type BaseModuleContext interface {
+	Module() Module
 	ModuleName() string
 	ModuleDir() string
 	ModuleType() string
 	Config() Config
 
+	OtherModuleName(m blueprint.Module) string
+	OtherModuleDir(m blueprint.Module) string
+	OtherModuleErrorf(m blueprint.Module, fmt string, args ...interface{})
+	OtherModuleDependencyTag(m blueprint.Module) blueprint.DependencyTag
+	OtherModuleExists(name string) bool
+
+	GetDirectDepsWithTag(tag blueprint.DependencyTag) []Module
+	GetDirectDepWithTag(name string, tag blueprint.DependencyTag) blueprint.Module
+	GetDirectDep(name string) (blueprint.Module, blueprint.DependencyTag)
+
+	VisitDirectDepsBlueprint(visit func(blueprint.Module))
+	VisitDirectDeps(visit func(Module))
+	VisitDirectDepsWithTag(tag blueprint.DependencyTag, visit func(Module))
+	VisitDirectDepsIf(pred func(Module) bool, visit func(Module))
+	// Deprecated: use WalkDeps instead to support multiple dependency tags on the same module
+	VisitDepsDepthFirst(visit func(Module))
+	// Deprecated: use WalkDeps instead to support multiple dependency tags on the same module
+	VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module))
+	WalkDeps(visit func(Module, Module) bool)
+	WalkDepsBlueprint(visit func(blueprint.Module, blueprint.Module) bool)
+	// GetWalkPath is supposed to be called in visit function passed in WalkDeps()
+	// and returns a top-down dependency path from a start module to current child module.
+	GetWalkPath() []Module
+
 	ContainsProperty(name string) bool
 	Errorf(pos scanner.Position, fmt string, args ...interface{})
 	ModuleErrorf(fmt string, args ...interface{})
@@ -76,9 +102,14 @@
 	// file that does not match the pattern is added to a searched directory.
 	GlobWithDeps(pattern string, excludes []string) ([]string, error)
 
+	Glob(globPattern string, excludes []string) Paths
+	GlobFiles(globPattern string, excludes []string) Paths
+
 	Fs() pathtools.FileSystem
 	AddNinjaFileDeps(deps ...string)
 
+	AddMissingDependencies(missingDeps []string)
+
 	Target() Target
 	TargetPrimary() bool
 	MultiTargets() []Target
@@ -114,8 +145,6 @@
 	ExpandSources(srcFiles, excludes []string) Paths
 	ExpandSource(srcFile, prop string) Path
 	ExpandOptionalSource(srcFile *string, prop string) OptionalPath
-	Glob(globPattern string, excludes []string) Paths
-	GlobFiles(globPattern string, excludes []string) Paths
 
 	InstallExecutable(installPath OutputPath, name string, srcPath Path, deps ...Path) OutputPath
 	InstallFile(installPath OutputPath, name string, srcPath Path, deps ...Path) OutputPath
@@ -123,8 +152,6 @@
 	InstallAbsoluteSymlink(installPath OutputPath, name string, absPath string) OutputPath
 	CheckbuildFile(srcPath Path)
 
-	AddMissingDependencies(deps []string)
-
 	InstallInData() bool
 	InstallInSanitizerDir() bool
 	InstallInRecovery() bool
@@ -133,30 +160,8 @@
 	HostRequiredModuleNames() []string
 	TargetRequiredModuleNames() []string
 
-	// android.ModuleContext methods
-	// These are duplicated instead of embedded so that can eventually be wrapped to take an
-	// android.Module instead of a blueprint.Module
-	OtherModuleName(m blueprint.Module) string
-	OtherModuleErrorf(m blueprint.Module, fmt string, args ...interface{})
-	OtherModuleDependencyTag(m blueprint.Module) blueprint.DependencyTag
-
-	GetDirectDepsWithTag(tag blueprint.DependencyTag) []Module
-	GetDirectDepWithTag(name string, tag blueprint.DependencyTag) blueprint.Module
-	GetDirectDep(name string) (blueprint.Module, blueprint.DependencyTag)
-
 	ModuleSubDir() string
 
-	VisitDirectDepsBlueprint(visit func(blueprint.Module))
-	VisitDirectDeps(visit func(Module))
-	VisitDirectDepsWithTag(tag blueprint.DependencyTag, visit func(Module))
-	VisitDirectDepsIf(pred func(Module) bool, visit func(Module))
-	// Deprecated: use WalkDeps instead to support multiple dependency tags on the same module
-	VisitDepsDepthFirst(visit func(Module))
-	// Deprecated: use WalkDeps instead to support multiple dependency tags on the same module
-	VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module))
-	WalkDeps(visit func(Module, Module) bool)
-	WalkDepsBlueprint(visit func(blueprint.Module, blueprint.Module) bool)
-
 	Variable(pctx PackageContext, name, value string)
 	Rule(pctx PackageContext, name string, params blueprint.RuleParams, argNames ...string) blueprint.Rule
 	// Similar to blueprint.ModuleContext.Build, but takes Paths instead of []string,
@@ -839,7 +844,7 @@
 func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext) {
 	ctx := &moduleContext{
 		module:            m.module,
-		ModuleContext:     blueprintCtx,
+		bp:                blueprintCtx,
 		baseModuleContext: m.baseModuleContextFactory(blueprintCtx),
 		installDeps:       m.computeInstallDeps(blueprintCtx),
 		installFiles:      m.installFiles,
@@ -851,6 +856,10 @@
 	// TODO: This will be removed once defaults modules handle missing dependency errors
 	blueprintCtx.GetMissingDependencies()
 
+	// For the final GenerateAndroidBuildActions pass, require that all visited dependencies Soong modules and
+	// are enabled.
+	ctx.baseModuleContext.strictVisitDeps = true
+
 	if ctx.config.captureBuild {
 		ctx.ruleParams = make(map[blueprint.Rule]blueprint.RuleParams)
 	}
@@ -907,6 +916,12 @@
 			noticePath := filepath.Join(ctx.ModuleDir(), notice)
 			m.noticeFile = ExistentPathForSource(ctx, noticePath)
 		}
+	} else if ctx.Config().AllowMissingDependencies() {
+		// If the module is not enabled it will not create any build rules, nothing will call
+		// ctx.GetMissingDependencies(), and blueprint will consider the missing dependencies to be unhandled
+		// and report them as an error even when AllowMissingDependencies = true.  Call
+		// ctx.GetMissingDependencies() here to tell blueprint not to handle them.
+		ctx.GetMissingDependencies()
 	}
 
 	if m == ctx.FinalModule().(Module).base() {
@@ -929,10 +944,14 @@
 	debug         bool
 	kind          moduleKind
 	config        Config
+
+	walkPath []Module
+
+	strictVisitDeps bool // If true, enforce that all dependencies are enabled
 }
 
 type moduleContext struct {
-	blueprint.ModuleContext
+	bp blueprint.ModuleContext
 	baseModuleContext
 	installDeps     Paths
 	installFiles    Paths
@@ -957,10 +976,6 @@
 	}
 }
 
-func (m *moduleContext) Config() Config {
-	return m.ModuleContext.Config().(Config)
-}
-
 func (m *moduleContext) ModuleBuild(pctx PackageContext, params ModuleBuildParams) {
 	m.Build(pctx, BuildParams(params))
 }
@@ -1010,13 +1025,13 @@
 		m.variables[name] = value
 	}
 
-	m.ModuleContext.Variable(pctx.PackageContext, name, value)
+	m.bp.Variable(pctx.PackageContext, name, value)
 }
 
 func (m *moduleContext) Rule(pctx PackageContext, name string, params blueprint.RuleParams,
 	argNames ...string) blueprint.Rule {
 
-	rule := m.ModuleContext.Rule(pctx.PackageContext, name, params, argNames...)
+	rule := m.bp.Rule(pctx.PackageContext, name, params, argNames...)
 
 	if m.config.captureBuild {
 		m.ruleParams[rule] = params
@@ -1039,57 +1054,66 @@
 		m.buildParams = append(m.buildParams, params)
 	}
 
-	m.ModuleContext.Build(pctx.PackageContext, convertBuildParams(params))
+	m.bp.Build(pctx.PackageContext, convertBuildParams(params))
 }
 
-func (m *moduleContext) Module() Module {
-	return m.ModuleContext.Module().(Module)
+func (b *baseModuleContext) Module() Module {
+	module, _ := b.BaseModuleContext.Module().(Module)
+	return module
+}
+
+func (b *baseModuleContext) Config() Config {
+	return b.BaseModuleContext.Config().(Config)
 }
 
 func (m *moduleContext) GetMissingDependencies() []string {
 	var missingDeps []string
 	missingDeps = append(missingDeps, m.Module().base().commonProperties.MissingDeps...)
-	missingDeps = append(missingDeps, m.ModuleContext.GetMissingDependencies()...)
+	missingDeps = append(missingDeps, m.bp.GetMissingDependencies()...)
 	missingDeps = FirstUniqueStrings(missingDeps)
 	return missingDeps
 }
 
-func (m *moduleContext) AddMissingDependencies(deps []string) {
+func (b *baseModuleContext) AddMissingDependencies(deps []string) {
 	if deps != nil {
-		missingDeps := &m.Module().base().commonProperties.MissingDeps
+		missingDeps := &b.Module().base().commonProperties.MissingDeps
 		*missingDeps = append(*missingDeps, deps...)
 		*missingDeps = FirstUniqueStrings(*missingDeps)
 	}
 }
 
-func (m *moduleContext) validateAndroidModule(module blueprint.Module) Module {
+func (b *baseModuleContext) validateAndroidModule(module blueprint.Module, strict bool) Module {
 	aModule, _ := module.(Module)
+
+	if !strict {
+		return aModule
+	}
+
 	if aModule == nil {
-		m.ModuleErrorf("module %q not an android module", m.OtherModuleName(aModule))
+		b.ModuleErrorf("module %q not an android module", b.OtherModuleName(module))
 		return nil
 	}
 
 	if !aModule.Enabled() {
-		if m.Config().AllowMissingDependencies() {
-			m.AddMissingDependencies([]string{m.OtherModuleName(aModule)})
+		if b.Config().AllowMissingDependencies() {
+			b.AddMissingDependencies([]string{b.OtherModuleName(aModule)})
 		} else {
-			m.ModuleErrorf("depends on disabled module %q", m.OtherModuleName(aModule))
+			b.ModuleErrorf("depends on disabled module %q", b.OtherModuleName(aModule))
 		}
 		return nil
 	}
-
 	return aModule
 }
 
-func (m *moduleContext) getDirectDepInternal(name string, tag blueprint.DependencyTag) (blueprint.Module, blueprint.DependencyTag) {
+func (b *baseModuleContext) getDirectDepInternal(name string, tag blueprint.DependencyTag) (blueprint.Module, blueprint.DependencyTag) {
 	type dep struct {
 		mod blueprint.Module
 		tag blueprint.DependencyTag
 	}
 	var deps []dep
-	m.VisitDirectDepsBlueprint(func(module blueprint.Module) {
+	b.VisitDirectDepsBlueprint(func(module blueprint.Module) {
 		if aModule, _ := module.(Module); aModule != nil && aModule.base().BaseModuleName() == name {
-			returnedTag := m.ModuleContext.OtherModuleDependencyTag(aModule)
+			returnedTag := b.BaseModuleContext.OtherModuleDependencyTag(aModule)
 			if tag == nil || returnedTag == tag {
 				deps = append(deps, dep{aModule, returnedTag})
 			}
@@ -1099,17 +1123,17 @@
 		return deps[0].mod, deps[0].tag
 	} else if len(deps) >= 2 {
 		panic(fmt.Errorf("Multiple dependencies having same BaseModuleName() %q found from %q",
-			name, m.ModuleName()))
+			name, b.ModuleName()))
 	} else {
 		return nil, nil
 	}
 }
 
-func (m *moduleContext) GetDirectDepsWithTag(tag blueprint.DependencyTag) []Module {
+func (b *baseModuleContext) GetDirectDepsWithTag(tag blueprint.DependencyTag) []Module {
 	var deps []Module
-	m.VisitDirectDepsBlueprint(func(module blueprint.Module) {
+	b.VisitDirectDepsBlueprint(func(module blueprint.Module) {
 		if aModule, _ := module.(Module); aModule != nil {
-			if m.ModuleContext.OtherModuleDependencyTag(aModule) == tag {
+			if b.BaseModuleContext.OtherModuleDependencyTag(aModule) == tag {
 				deps = append(deps, aModule)
 			}
 		}
@@ -1122,37 +1146,37 @@
 	return module
 }
 
-func (m *moduleContext) GetDirectDep(name string) (blueprint.Module, blueprint.DependencyTag) {
-	return m.getDirectDepInternal(name, nil)
+func (b *baseModuleContext) GetDirectDep(name string) (blueprint.Module, blueprint.DependencyTag) {
+	return b.getDirectDepInternal(name, nil)
 }
 
-func (m *moduleContext) VisitDirectDepsBlueprint(visit func(blueprint.Module)) {
-	m.ModuleContext.VisitDirectDeps(visit)
+func (b *baseModuleContext) VisitDirectDepsBlueprint(visit func(blueprint.Module)) {
+	b.BaseModuleContext.VisitDirectDeps(visit)
 }
 
-func (m *moduleContext) VisitDirectDeps(visit func(Module)) {
-	m.ModuleContext.VisitDirectDeps(func(module blueprint.Module) {
-		if aModule := m.validateAndroidModule(module); aModule != nil {
+func (b *baseModuleContext) VisitDirectDeps(visit func(Module)) {
+	b.BaseModuleContext.VisitDirectDeps(func(module blueprint.Module) {
+		if aModule := b.validateAndroidModule(module, b.strictVisitDeps); aModule != nil {
 			visit(aModule)
 		}
 	})
 }
 
-func (m *moduleContext) VisitDirectDepsWithTag(tag blueprint.DependencyTag, visit func(Module)) {
-	m.ModuleContext.VisitDirectDeps(func(module blueprint.Module) {
-		if aModule := m.validateAndroidModule(module); aModule != nil {
-			if m.ModuleContext.OtherModuleDependencyTag(aModule) == tag {
+func (b *baseModuleContext) VisitDirectDepsWithTag(tag blueprint.DependencyTag, visit func(Module)) {
+	b.BaseModuleContext.VisitDirectDeps(func(module blueprint.Module) {
+		if aModule := b.validateAndroidModule(module, b.strictVisitDeps); aModule != nil {
+			if b.BaseModuleContext.OtherModuleDependencyTag(aModule) == tag {
 				visit(aModule)
 			}
 		}
 	})
 }
 
-func (m *moduleContext) VisitDirectDepsIf(pred func(Module) bool, visit func(Module)) {
-	m.ModuleContext.VisitDirectDepsIf(
+func (b *baseModuleContext) VisitDirectDepsIf(pred func(Module) bool, visit func(Module)) {
+	b.BaseModuleContext.VisitDirectDepsIf(
 		// pred
 		func(module blueprint.Module) bool {
-			if aModule := m.validateAndroidModule(module); aModule != nil {
+			if aModule := b.validateAndroidModule(module, b.strictVisitDeps); aModule != nil {
 				return pred(aModule)
 			} else {
 				return false
@@ -1164,19 +1188,19 @@
 		})
 }
 
-func (m *moduleContext) VisitDepsDepthFirst(visit func(Module)) {
-	m.ModuleContext.VisitDepsDepthFirst(func(module blueprint.Module) {
-		if aModule := m.validateAndroidModule(module); aModule != nil {
+func (b *baseModuleContext) VisitDepsDepthFirst(visit func(Module)) {
+	b.BaseModuleContext.VisitDepsDepthFirst(func(module blueprint.Module) {
+		if aModule := b.validateAndroidModule(module, b.strictVisitDeps); aModule != nil {
 			visit(aModule)
 		}
 	})
 }
 
-func (m *moduleContext) VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module)) {
-	m.ModuleContext.VisitDepsDepthFirstIf(
+func (b *baseModuleContext) VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module)) {
+	b.BaseModuleContext.VisitDepsDepthFirstIf(
 		// pred
 		func(module blueprint.Module) bool {
-			if aModule := m.validateAndroidModule(module); aModule != nil {
+			if aModule := b.validateAndroidModule(module, b.strictVisitDeps); aModule != nil {
 				return pred(aModule)
 			} else {
 				return false
@@ -1188,15 +1212,21 @@
 		})
 }
 
-func (m *moduleContext) WalkDepsBlueprint(visit func(blueprint.Module, blueprint.Module) bool) {
-	m.ModuleContext.WalkDeps(visit)
+func (b *baseModuleContext) WalkDepsBlueprint(visit func(blueprint.Module, blueprint.Module) bool) {
+	b.BaseModuleContext.WalkDeps(visit)
 }
 
-func (m *moduleContext) WalkDeps(visit func(Module, Module) bool) {
-	m.ModuleContext.WalkDeps(func(child, parent blueprint.Module) bool {
-		childAndroidModule := m.validateAndroidModule(child)
-		parentAndroidModule := m.validateAndroidModule(parent)
+func (b *baseModuleContext) WalkDeps(visit func(Module, Module) bool) {
+	b.walkPath = []Module{b.Module()}
+	b.BaseModuleContext.WalkDeps(func(child, parent blueprint.Module) bool {
+		childAndroidModule, _ := child.(Module)
+		parentAndroidModule, _ := parent.(Module)
 		if childAndroidModule != nil && parentAndroidModule != nil {
+			// record walkPath before visit
+			for b.walkPath[len(b.walkPath)-1] != parentAndroidModule {
+				b.walkPath = b.walkPath[0 : len(b.walkPath)-1]
+			}
+			b.walkPath = append(b.walkPath, childAndroidModule)
 			return visit(childAndroidModule, parentAndroidModule)
 		} else {
 			return false
@@ -1204,18 +1234,26 @@
 	})
 }
 
+func (b *baseModuleContext) GetWalkPath() []Module {
+	return b.walkPath
+}
+
 func (m *moduleContext) VisitAllModuleVariants(visit func(Module)) {
-	m.ModuleContext.VisitAllModuleVariants(func(module blueprint.Module) {
+	m.bp.VisitAllModuleVariants(func(module blueprint.Module) {
 		visit(module.(Module))
 	})
 }
 
 func (m *moduleContext) PrimaryModule() Module {
-	return m.ModuleContext.PrimaryModule().(Module)
+	return m.bp.PrimaryModule().(Module)
 }
 
 func (m *moduleContext) FinalModule() Module {
-	return m.ModuleContext.FinalModule().(Module)
+	return m.bp.FinalModule().(Module)
+}
+
+func (m *moduleContext) ModuleSubDir() string {
+	return m.bp.ModuleSubDir()
 }
 
 func (b *baseModuleContext) Target() Target {
@@ -1593,20 +1631,20 @@
 	return m.module.base().commonProperties.Target_required
 }
 
-func (m *moduleContext) Glob(globPattern string, excludes []string) Paths {
-	ret, err := m.GlobWithDeps(globPattern, excludes)
+func (b *baseModuleContext) Glob(globPattern string, excludes []string) Paths {
+	ret, err := b.GlobWithDeps(globPattern, excludes)
 	if err != nil {
-		m.ModuleErrorf("glob: %s", err.Error())
+		b.ModuleErrorf("glob: %s", err.Error())
 	}
-	return pathsForModuleSrcFromFullPath(m, ret, true)
+	return pathsForModuleSrcFromFullPath(b, ret, true)
 }
 
-func (m *moduleContext) GlobFiles(globPattern string, excludes []string) Paths {
-	ret, err := m.GlobWithDeps(globPattern, excludes)
+func (b *baseModuleContext) GlobFiles(globPattern string, excludes []string) Paths {
+	ret, err := b.GlobWithDeps(globPattern, excludes)
 	if err != nil {
-		m.ModuleErrorf("glob: %s", err.Error())
+		b.ModuleErrorf("glob: %s", err.Error())
 	}
-	return pathsForModuleSrcFromFullPath(m, ret, false)
+	return pathsForModuleSrcFromFullPath(b, ret, false)
 }
 
 func init() {
diff --git a/android/mutator.go b/android/mutator.go
index cd0d152..081c2b2 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -115,35 +115,14 @@
 type TopDownMutatorContext interface {
 	BaseModuleContext
 
-	OtherModuleExists(name string) bool
 	Rename(name string)
-	Module() Module
-
-	OtherModuleName(m blueprint.Module) string
-	OtherModuleDir(m blueprint.Module) string
-	OtherModuleErrorf(m blueprint.Module, fmt string, args ...interface{})
-	OtherModuleDependencyTag(m blueprint.Module) blueprint.DependencyTag
 
 	CreateModule(blueprint.ModuleFactory, ...interface{})
-
-	GetDirectDepWithTag(name string, tag blueprint.DependencyTag) blueprint.Module
-	GetDirectDep(name string) (blueprint.Module, blueprint.DependencyTag)
-
-	VisitDirectDeps(visit func(Module))
-	VisitDirectDepsWithTag(tag blueprint.DependencyTag, visit func(Module))
-	VisitDirectDepsIf(pred func(Module) bool, visit func(Module))
-	VisitDepsDepthFirst(visit func(Module))
-	VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module))
-	WalkDeps(visit func(Module, Module) bool)
-	// GetWalkPath is supposed to be called in visit function passed in WalkDeps()
-	// and returns a top-down dependency path from a start module to current child module.
-	GetWalkPath() []Module
 }
 
 type topDownMutatorContext struct {
-	blueprint.TopDownMutatorContext
+	bp blueprint.TopDownMutatorContext
 	baseModuleContext
-	walkPath []Module
 }
 
 type BottomUpMutator func(BottomUpMutatorContext)
@@ -151,9 +130,7 @@
 type BottomUpMutatorContext interface {
 	BaseModuleContext
 
-	OtherModuleExists(name string) bool
 	Rename(name string)
-	Module() blueprint.Module
 
 	AddDependency(module blueprint.Module, tag blueprint.DependencyTag, name ...string)
 	AddReverseDependency(module blueprint.Module, tag blueprint.DependencyTag, name string)
@@ -167,7 +144,7 @@
 }
 
 type bottomUpMutatorContext struct {
-	blueprint.BottomUpMutatorContext
+	bp blueprint.BottomUpMutatorContext
 	baseModuleContext
 }
 
@@ -175,8 +152,8 @@
 	f := func(ctx blueprint.BottomUpMutatorContext) {
 		if a, ok := ctx.Module().(Module); ok {
 			actx := &bottomUpMutatorContext{
-				BottomUpMutatorContext: ctx,
-				baseModuleContext:      a.base().baseModuleContextFactory(ctx),
+				bp:                ctx,
+				baseModuleContext: a.base().baseModuleContextFactory(ctx),
 			}
 			m(actx)
 		}
@@ -190,8 +167,8 @@
 	f := func(ctx blueprint.TopDownMutatorContext) {
 		if a, ok := ctx.Module().(Module); ok {
 			actx := &topDownMutatorContext{
-				TopDownMutatorContext: ctx,
-				baseModuleContext:     a.base().baseModuleContextFactory(ctx),
+				bp:                ctx,
+				baseModuleContext: a.base().baseModuleContextFactory(ctx),
 			}
 			m(actx)
 		}
@@ -216,99 +193,6 @@
 	}
 }
 
-func (t *topDownMutatorContext) Config() Config {
-	return t.config
-}
-
-func (b *bottomUpMutatorContext) Config() Config {
-	return b.config
-}
-
-func (t *topDownMutatorContext) Module() Module {
-	module, _ := t.TopDownMutatorContext.Module().(Module)
-	return module
-}
-
-func (t *topDownMutatorContext) VisitDirectDeps(visit func(Module)) {
-	t.TopDownMutatorContext.VisitDirectDeps(func(module blueprint.Module) {
-		if aModule, _ := module.(Module); aModule != nil {
-			visit(aModule)
-		}
-	})
-}
-
-func (t *topDownMutatorContext) VisitDirectDepsWithTag(tag blueprint.DependencyTag, visit func(Module)) {
-	t.TopDownMutatorContext.VisitDirectDeps(func(module blueprint.Module) {
-		if aModule, _ := module.(Module); aModule != nil {
-			if t.TopDownMutatorContext.OtherModuleDependencyTag(aModule) == tag {
-				visit(aModule)
-			}
-		}
-	})
-}
-
-func (t *topDownMutatorContext) VisitDirectDepsIf(pred func(Module) bool, visit func(Module)) {
-	t.TopDownMutatorContext.VisitDirectDepsIf(
-		// pred
-		func(module blueprint.Module) bool {
-			if aModule, _ := module.(Module); aModule != nil {
-				return pred(aModule)
-			} else {
-				return false
-			}
-		},
-		// visit
-		func(module blueprint.Module) {
-			visit(module.(Module))
-		})
-}
-
-func (t *topDownMutatorContext) VisitDepsDepthFirst(visit func(Module)) {
-	t.TopDownMutatorContext.VisitDepsDepthFirst(func(module blueprint.Module) {
-		if aModule, _ := module.(Module); aModule != nil {
-			visit(aModule)
-		}
-	})
-}
-
-func (t *topDownMutatorContext) VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module)) {
-	t.TopDownMutatorContext.VisitDepsDepthFirstIf(
-		// pred
-		func(module blueprint.Module) bool {
-			if aModule, _ := module.(Module); aModule != nil {
-				return pred(aModule)
-			} else {
-				return false
-			}
-		},
-		// visit
-		func(module blueprint.Module) {
-			visit(module.(Module))
-		})
-}
-
-func (t *topDownMutatorContext) WalkDeps(visit func(Module, Module) bool) {
-	t.walkPath = []Module{t.Module()}
-	t.TopDownMutatorContext.WalkDeps(func(child, parent blueprint.Module) bool {
-		childAndroidModule, _ := child.(Module)
-		parentAndroidModule, _ := parent.(Module)
-		if childAndroidModule != nil && parentAndroidModule != nil {
-			// record walkPath before visit
-			for t.walkPath[len(t.walkPath)-1] != parentAndroidModule {
-				t.walkPath = t.walkPath[0 : len(t.walkPath)-1]
-			}
-			t.walkPath = append(t.walkPath, childAndroidModule)
-			return visit(childAndroidModule, parentAndroidModule)
-		} else {
-			return false
-		}
-	})
-}
-
-func (t *topDownMutatorContext) GetWalkPath() []Module {
-	return t.walkPath
-}
-
 func (t *topDownMutatorContext) AppendProperties(props ...interface{}) {
 	for _, p := range props {
 		err := proptools.AppendMatchingProperties(t.Module().base().customizableProperties,
@@ -336,3 +220,61 @@
 		}
 	}
 }
+
+// android.topDownMutatorContext either has to embed blueprint.TopDownMutatorContext, in which case every method that
+// has an overridden version in android.BaseModuleContext has to be manually forwarded to BaseModuleContext to avoid
+// ambiguous method errors, or it has to store a blueprint.TopDownMutatorContext non-embedded, in which case every
+// non-overridden method has to be forwarded.  There are fewer non-overridden methods, so use the latter.  The following
+// methods forward to the identical blueprint versions for topDownMutatorContext and bottomUpMutatorContext.
+
+func (t *topDownMutatorContext) Rename(name string) {
+	t.bp.Rename(name)
+}
+
+func (t *topDownMutatorContext) CreateModule(factory blueprint.ModuleFactory, props ...interface{}) {
+	t.bp.CreateModule(factory, props...)
+}
+
+func (b *bottomUpMutatorContext) Rename(name string) {
+	b.bp.Rename(name)
+}
+
+func (b *bottomUpMutatorContext) AddDependency(module blueprint.Module, tag blueprint.DependencyTag, name ...string) {
+	b.bp.AddDependency(module, tag, name...)
+}
+
+func (b *bottomUpMutatorContext) AddReverseDependency(module blueprint.Module, tag blueprint.DependencyTag, name string) {
+	b.bp.AddReverseDependency(module, tag, name)
+}
+
+func (b *bottomUpMutatorContext) CreateVariations(variations ...string) []blueprint.Module {
+	return b.bp.CreateVariations(variations...)
+}
+
+func (b *bottomUpMutatorContext) CreateLocalVariations(variations ...string) []blueprint.Module {
+	return b.bp.CreateLocalVariations(variations...)
+}
+
+func (b *bottomUpMutatorContext) SetDependencyVariation(variation string) {
+	b.bp.SetDependencyVariation(variation)
+}
+
+func (b *bottomUpMutatorContext) AddVariationDependencies(variations []blueprint.Variation, tag blueprint.DependencyTag,
+	names ...string) {
+
+	b.bp.AddVariationDependencies(variations, tag, names...)
+}
+
+func (b *bottomUpMutatorContext) AddFarVariationDependencies(variations []blueprint.Variation,
+	tag blueprint.DependencyTag, names ...string) {
+
+	b.bp.AddFarVariationDependencies(variations, tag, names...)
+}
+
+func (b *bottomUpMutatorContext) AddInterVariantDependency(tag blueprint.DependencyTag, from, to blueprint.Module) {
+	b.bp.AddInterVariantDependency(tag, from, to)
+}
+
+func (b *bottomUpMutatorContext) ReplaceDependencies(name string) {
+	b.bp.ReplaceDependencies(name)
+}
diff --git a/android/mutator_test.go b/android/mutator_test.go
new file mode 100644
index 0000000..4cef400
--- /dev/null
+++ b/android/mutator_test.go
@@ -0,0 +1,99 @@
+// 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 android
+
+import (
+	"io/ioutil"
+	"os"
+	"reflect"
+	"testing"
+
+	"github.com/google/blueprint/proptools"
+)
+
+type mutatorTestModule struct {
+	ModuleBase
+	props struct {
+	}
+
+	missingDeps []string
+}
+
+func mutatorTestModuleFactory() Module {
+	module := &mutatorTestModule{}
+	module.AddProperties(&module.props)
+	InitAndroidModule(module)
+	return module
+}
+
+func (m *mutatorTestModule) GenerateAndroidBuildActions(ctx ModuleContext) {
+	ctx.Build(pctx, BuildParams{
+		Rule:   Touch,
+		Output: PathForModuleOut(ctx, "output"),
+	})
+
+	m.missingDeps = ctx.GetMissingDependencies()
+}
+
+func (m *mutatorTestModule) DepsMutator(ctx BottomUpMutatorContext) {
+	ctx.AddDependency(ctx.Module(), nil, "regular_missing_dep")
+}
+
+func addMissingDependenciesMutator(ctx TopDownMutatorContext) {
+	ctx.AddMissingDependencies([]string{"added_missing_dep"})
+}
+
+func TestMutatorAddMissingDependencies(t *testing.T) {
+	buildDir, err := ioutil.TempDir("", "soong_mutator_test")
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer os.RemoveAll(buildDir)
+
+	config := TestConfig(buildDir, nil)
+	config.TestProductVariables.Allow_missing_dependencies = proptools.BoolPtr(true)
+
+	ctx := NewTestContext()
+	ctx.SetAllowMissingDependencies(true)
+
+	ctx.RegisterModuleType("test", ModuleFactoryAdaptor(mutatorTestModuleFactory))
+	ctx.PreDepsMutators(func(ctx RegisterMutatorsContext) {
+		ctx.TopDown("add_missing_dependencies", addMissingDependenciesMutator)
+	})
+
+	bp := `
+		test {
+			name: "foo",
+		}
+	`
+
+	mockFS := map[string][]byte{
+		"Android.bp": []byte(bp),
+	}
+
+	ctx.MockFileSystem(mockFS)
+
+	ctx.Register()
+	_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
+	FailIfErrored(t, errs)
+	_, errs = ctx.PrepareBuildActions(config)
+	FailIfErrored(t, errs)
+
+	foo := ctx.ModuleForTests("foo", "").Module().(*mutatorTestModule)
+
+	if g, w := foo.missingDeps, []string{"added_missing_dep", "regular_missing_dep"}; !reflect.DeepEqual(g, w) {
+		t.Errorf("want foo missing deps %q, got %q", w, g)
+	}
+}
diff --git a/android/paths.go b/android/paths.go
index 52d22d5..20b8b82 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -367,7 +367,7 @@
 // each string. If incDirs is false, strip paths with a trailing '/' from the list.
 // It intended for use in globs that only list files that exist, so it allows '$' in
 // filenames.
-func pathsForModuleSrcFromFullPath(ctx ModuleContext, paths []string, incDirs bool) Paths {
+func pathsForModuleSrcFromFullPath(ctx BaseModuleContext, paths []string, incDirs bool) Paths {
 	prefix := filepath.Join(ctx.Config().srcDir, ctx.ModuleDir()) + "/"
 	if prefix == "./" {
 		prefix = ""