// Copyright (C) 2018 The Android Open Source Project
//
// 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 aidl

import (
	"android/soong/android"
	"android/soong/cc"
	"android/soong/java"
	"android/soong/phony"
	"android/soong/rust"

	"fmt"
	"path/filepath"
	"regexp"
	"sort"
	"strconv"
	"strings"
	"sync"

	"github.com/google/blueprint/proptools"
)

const (
	aidlInterfaceSuffix       = "_interface"
	aidlMetadataSingletonName = "aidl_metadata_json"
	aidlApiDir                = "aidl_api"
	aidlApiSuffix             = "-api"
	langCpp                   = "cpp"
	langJava                  = "java"
	langNdk                   = "ndk"
	langRust                  = "rust"
	// TODO(b/161456198) remove the NDK platform backend as the 'platform' variant of the NDK
	// backend serves the same purpose.
	langNdkPlatform = "ndk_platform"

	currentVersion = "current"
)

var (
	pctx = android.NewPackageContext("android/aidl")
)

func init() {
	pctx.Import("android/soong/android")
	pctx.HostBinToolVariable("aidlCmd", "aidl")
	pctx.SourcePathVariable("aidlToJniCmd", "system/tools/aidl/build/aidl_to_jni.py")
	pctx.SourcePathVariable("aidlRustGlueCmd", "system/tools/aidl/build/aidl_rust_glue.py")
	android.RegisterModuleType("aidl_interface", aidlInterfaceFactory)
	android.PreArchMutators(registerPreDepsMutators)
	android.PreArchBp2BuildMutators(registerPreDepsMutators)
	android.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
		ctx.BottomUp("checkUnstableModule", checkUnstableModuleMutator).Parallel()
		ctx.BottomUp("recordVersions", recordVersions).Parallel()
		ctx.BottomUp("checkDuplicatedVersions", checkDuplicatedVersions).Parallel()
	})
}

func registerPreDepsMutators(ctx android.RegisterMutatorsContext) {
	ctx.BottomUp("checkImports", checkImports).Parallel()
	ctx.TopDown("createAidlInterface", createAidlInterfaceMutator).Parallel()
}

func createAidlInterfaceMutator(mctx android.TopDownMutatorContext) {
	if g, ok := mctx.Module().(*aidlImplementationGenerator); ok {
		g.GenerateImplementation(mctx)
	}
}

func checkUnstableModuleMutator(mctx android.BottomUpMutatorContext) {
	// If it is an aidl interface, we don't need to check its dependencies.
	if isAidlModule(mctx.ModuleName(), mctx.Config()) {
		return
	}
	mctx.VisitDirectDepsIf(func(m android.Module) bool {
		return android.InList(m.Name(), *unstableModules(mctx.Config()))
	}, func(m android.Module) {
		if mctx.ModuleName() == m.Name() {
			return
		}
		// TODO(b/154066686): Replace it with a common method instead of listing up module types.
		// Test libraries are exempted.
		if android.InList(mctx.ModuleType(), []string{"cc_test_library", "android_test", "cc_benchmark", "cc_test"}) {
			return
		}

		mctx.ModuleErrorf(m.Name() + " is disallowed in release version because it is unstable, and its \"owner\" property is missing.")
	})
}

func isAidlModule(moduleName string, config android.Config) bool {
	for _, i := range *aidlInterfaces(config) {
		if android.InList(moduleName, i.internalModuleNames) {
			return true
		}
	}
	return false
}

func recordVersions(mctx android.BottomUpMutatorContext) {
	switch mctx.Module().(type) {
	case *java.Library:
	case *cc.Module:
	case *rust.Module:
	case *aidlGenRule:
	default:
		return
	}

	isAidlModule := isAidlModule(mctx.ModuleName(), mctx.Config())

	// First, gather all the AIDL interfaces modules that are directly or indirectly
	// depended on by this module
	myAidlDeps := make(map[DepInfo]bool)
	mctx.VisitDirectDeps(func(dep android.Module) {
		switch dep.(type) {
		case *java.Library:
		case *cc.Module:
		case *rust.Module:
		case *aidlGenRule:
			// Dependencies to the source module is tracked only when it's from a client
			// module, i.e. not from an AIDL-generated stub library
			if isAidlModule {
				return
			}
		default:
			return
		}
		depName := mctx.OtherModuleName(dep)
		isSource := strings.HasSuffix(depName, "-source")
		depName = strings.TrimSuffix(depName, "-source")
		// If this module depends on one of the aidl interface module, record it
		for _, i := range *aidlInterfaces(mctx.Config()) {
			if android.InList(depName, i.internalModuleNames) {
				ifaceName := i.ModuleBase.Name()
				verLang := depName[len(ifaceName):]
				myAidlDeps[DepInfo{ifaceName, verLang, isSource}] = true
				break
			}
		}
		// If dep is in aidlDeps, that means dep has direct or indirect dependencies to AIDL interfaces
		// That becomes this module's aidlDeps as well
		aidlDepsMutex.RLock()
		if depsOfDep, ok := aidlDeps(mctx.Config())[dep]; ok {
			for _, d := range depsOfDep {
				myAidlDeps[d] = true
			}
		}
		aidlDepsMutex.RUnlock()
	})

	if len(myAidlDeps) == 0 {
		// This should be usual case.
		return
	}

	// Then, record the aidl deps of this module to the global map so that it can be used by
	// next runs of this mutator for the modules that depend on this module.
	var list []DepInfo
	for d := range myAidlDeps {
		list = append(list, d)
	}
	aidlDepsMutex.Lock()
	aidlDeps(mctx.Config())[mctx.Module()] = list
	aidlDepsMutex.Unlock()
}

func checkDuplicatedVersions(mctx android.BottomUpMutatorContext) {
	switch mctx.Module().(type) {
	case *java.Library:
	case *cc.Module:
	case *rust.Module:
	case *aidlGenRule:
	default:
		return
	}

	aidlDepsMutex.RLock()
	myAidlDeps := aidlDeps(mctx.Config())[mctx.Module()]
	aidlDepsMutex.RUnlock()
	if myAidlDeps == nil || len(myAidlDeps) == 0 {
		return // This should be the usual case
	}

	// Lastly, report an error if there is any duplicated versions of the same interface * lang
	for _, lang := range []string{langJava, langCpp, langNdk, langNdkPlatform} {
		// interfaceName -> verLang -> list of module names
		versionsOf := make(map[string]map[string][]string)
		for _, dep := range myAidlDeps {
			if !strings.HasSuffix(dep.verLang, lang) {
				continue
			}
			versions := versionsOf[dep.ifaceName]
			if versions == nil {
				versions = make(map[string][]string)
				versionsOf[dep.ifaceName] = versions
			}
			versions[dep.verLang] = append(versions[dep.verLang], dep.moduleName())
		}

		for _, versions := range versionsOf {
			if len(versions) >= 2 {
				var violators []string
				for _, modules := range versions {
					violators = append(violators, modules...)
				}
				violators = android.SortedUniqueStrings(violators)
				mctx.ModuleErrorf("depends on multiple versions of the same aidl_interface: %s", strings.Join(violators, ", "))
				mctx.WalkDeps(func(child android.Module, parent android.Module) bool {
					if android.InList(child.Name(), violators) {
						mctx.ModuleErrorf("Dependency path: %s", mctx.GetPathString(true))
						return false
					}
					return true
				})
			}
		}
	}
}

func getPaths(ctx android.ModuleContext, rawSrcs []string, root string) (srcs android.Paths, imports []string) {
	// TODO(b/189288369): move this to android.PathsForModuleSrcSubDir(ctx, srcs, subdir)
	for _, src := range rawSrcs {
		if m, _ := android.SrcIsModuleWithTag(src); m != "" {
			srcs = append(srcs, android.PathsForModuleSrc(ctx, []string{src})...)
		} else {
			srcs = append(srcs, android.PathsWithModuleSrcSubDir(ctx, android.PathsForModuleSrc(ctx, []string{src}), root)...)
		}
	}

	if len(srcs) == 0 {
		ctx.PropertyErrorf("srcs", "No sources provided.")
	}

	// gather base directories from input .aidl files
	for _, src := range srcs {
		if src.Ext() != ".aidl" {
			// Silently ignore non-aidl files as some filegroups have both java and aidl files together
			continue
		}
		baseDir := strings.TrimSuffix(src.String(), src.Rel())
		baseDir = strings.TrimSuffix(baseDir, "/")
		if baseDir != "" && !android.InList(baseDir, imports) {
			imports = append(imports, baseDir)
		}
	}

	return srcs, imports
}

func isRelativePath(path string) bool {
	if path == "" {
		return true
	}
	return filepath.Clean(path) == path && path != ".." &&
		!strings.HasPrefix(path, "../") && !strings.HasPrefix(path, "/")
}

type CommonBackendProperties struct {
	// Whether to generate code in the corresponding backend.
	// Default: true
	Enabled        *bool
	Apex_available []string

	// The minimum version of the sdk that the compiled artifacts will run against
	// For native modules, the property needs to be set when a module is a part of mainline modules(APEX).
	// Forwarded to generated java/native module.
	Min_sdk_version *string

	// Determines whether the generated source files are available or not. When set to true,
	// the source files can be added to `srcs` property via `:<ifacename>-<backend>-source`,
	// e.g., ":myaidl-java-source"
	Srcs_available *bool
}

type CommonNativeBackendProperties struct {
	CommonBackendProperties
	// Whether to generate additional code for gathering information
	// about the transactions.
	// Default: false
	Gen_log *bool

	// VNDK properties for correspdoning backend.
	cc.VndkProperties
}

type DumpApiProperties struct {
	// Dumps without license header (assuming it is the first comment in .aidl file). Default: false
	No_license *bool
}

type aidlInterfaceProperties struct {
	// Vndk properties for C++/NDK libraries only (preferred to use backend-specific settings)
	cc.VndkProperties

	// How to interpret VNDK options. We only want one library in the VNDK (not multiple
	// versions, since this would be a waste of space/unclear, and ultimately we want all
	// code in a given release to be updated to use a specific version). By default, this
	// puts either the latest stable version of the library or, if there is no stable
	// version, the unstable version of the library in the VNDK. When using this field,
	// explicitly set it to one of the values in the 'versions' field to put that version
	// in the VNDK or set it to the next version (1 higher than this) to mean the version
	// that will be frozen in the next update.
	Vndk_use_version *string

	// Whether the library can be installed on the vendor image.
	Vendor_available *bool

	// Whether the library can be installed on the odm image.
	Odm_available *bool

	// Whether the library can be installed on the product image.
	Product_available *bool

	// Whether the library can be loaded multiple times into the same process
	Double_loadable *bool

	// Whether the library can be used on host
	Host_supported *bool

	// Whether tracing should be added to the interface.
	Gen_trace *bool

	// Top level directories for includes.
	// TODO(b/128940869): remove it if aidl_interface can depend on framework.aidl
	Include_dirs []string
	// Relative path for includes. By default assumes AIDL path is relative to current directory.
	Local_include_dir string

	// List of .aidl files which compose this interface.
	Srcs []string `android:"path"`

	// List of aidl_interface modules that this uses. If one of your AIDL interfaces uses an
	// interface or parcelable from another aidl_interface, you should put its name here.
	// It could be an aidl_interface solely or with version(such as -V1)
	Imports []string

	// List of aidl_interface modules that this uses. It trims version suffix in 'Imports' field.
	ImportsWithoutVersion []string `blueprint:"mutated"`

	// Used by gen dependency to fill out aidl include path
	Full_import_paths []string `blueprint:"mutated"`

	// Stability promise. Currently only supports "vintf".
	// If this is unset, this corresponds to an interface with stability within
	// this compilation context (so an interface loaded here can only be used
	// with things compiled together, e.g. on the system.img).
	// If this is set to "vintf", this corresponds to a stability promise: the
	// interface must be kept stable as long as it is used.
	Stability *string

	// Previous API versions that are now frozen. The version that is last in
	// the list is considered as the most recent version.
	Versions []string

	Backend struct {
		// Backend of the compiler generating code for Java clients.
		// When enabled, this creates a target called "<name>-java".
		Java struct {
			CommonBackendProperties
			// Set to the version of the sdk to compile against
			// Default: system_current
			Sdk_version *string
			// Whether to compile against platform APIs instead of
			// an SDK.
			Platform_apis *bool
			// Lint properties for generated java module
			java.LintProperties
		}
		// Backend of the compiler generating code for C++ clients using
		// libbinder (unstable C++ interface)
		// When enabled, this creates a target called "<name>-cpp".
		Cpp struct {
			CommonNativeBackendProperties
		}
		// Backend of the compiler generating code for C++ clients using libbinder_ndk
		// (stable C interface to system's libbinder) When enabled, this creates a target
		// called "<name>-V<ver>-ndk" (for both apps and platform) and
		// "<name>-V<ver>-ndk_platform" (for platform only).
		// TODO(b/161456198): remove the ndk_platform backend as the ndk backend can serve
		// the same purpose.
		Ndk struct {
			CommonNativeBackendProperties

			// If set to false, the ndk backend is exclusive to platform and is not
			// available to applications. Default is true (i.e. available to both
			// applications and platform).
			Apps_enabled *bool
		}
		// Backend of the compiler generating code for Rust clients.
		// When enabled, this creates a target called "<name>-rust".
		Rust struct {
			CommonBackendProperties
		}
	}

	// Marks that this interface does not need to be stable. When set to true, the build system
	// doesn't create the API dump and require it to be updated. Default is false.
	Unstable *bool

	// Optional flags to be passed to the AIDL compiler. e.g. "-Weverything"
	Flags []string

	// --dumpapi options
	Dumpapi DumpApiProperties
}

type aidlInterface struct {
	android.ModuleBase

	properties aidlInterfaceProperties

	computedTypes []string

	// list of module names that are created for this interface
	internalModuleNames []string
}

func (i *aidlInterface) shouldGenerateJavaBackend() bool {
	// explicitly true if not specified to give early warning to devs
	return proptools.BoolDefault(i.properties.Backend.Java.Enabled, true)
}

func (i *aidlInterface) shouldGenerateCppBackend() bool {
	// explicitly true if not specified to give early warning to devs
	return proptools.BoolDefault(i.properties.Backend.Cpp.Enabled, true)
}

func (i *aidlInterface) shouldGenerateNdkBackend() bool {
	// explicitly true if not specified to give early warning to devs
	return proptools.BoolDefault(i.properties.Backend.Ndk.Enabled, true)
	return i.properties.Backend.Ndk.Enabled == nil || *i.properties.Backend.Ndk.Enabled
}

// Returns whether the ndk backend supports applications or not. Default is `true`. `false` is
// returned only when `apps_enabled` is explicitly set to false. Note that the ndk_platform backend
// (which will be removed in the future) is not affected by this. In other words, it is always
// exclusive for the platform, as its name clearly shows.
func (i *aidlInterface) shouldGenerateAppNdkBackend() bool {
	return i.shouldGenerateNdkBackend() &&
		proptools.BoolDefault(i.properties.Backend.Ndk.Apps_enabled, true)
}

func (i *aidlInterface) shouldGenerateRustBackend() bool {
	return i.properties.Backend.Rust.Enabled != nil && *i.properties.Backend.Rust.Enabled
}

func (i *aidlInterface) gatherInterface(mctx android.LoadHookContext) {
	aidlInterfaces := aidlInterfaces(mctx.Config())
	aidlInterfaceMutex.Lock()
	defer aidlInterfaceMutex.Unlock()
	*aidlInterfaces = append(*aidlInterfaces, i)
}

func addUnstableModule(mctx android.LoadHookContext, moduleName string) {
	unstableModules := unstableModules(mctx.Config())
	unstableModuleMutex.Lock()
	defer unstableModuleMutex.Unlock()
	*unstableModules = append(*unstableModules, moduleName)
}

func checkImports(mctx android.BottomUpMutatorContext) {
	if i, ok := mctx.Module().(*aidlInterface); ok {
		for _, anImportWithVersion := range i.properties.Imports {
			anImport, version := parseModuleWithVersion(anImportWithVersion)
			other := lookupInterface(anImport, mctx.Config())

			if other == nil {
				if mctx.Config().AllowMissingDependencies() {
					continue
				}
				mctx.PropertyErrorf("imports", "Import does not exist: "+anImport)
			}
			if version != "" {
				candidateVersions := concat(other.properties.Versions, []string{other.nextVersion()})
				if !android.InList(version, candidateVersions) {
					mctx.PropertyErrorf("imports", "%q depends on %q version %q(%q), which doesn't exist. The version must be one of %q", i.ModuleBase.Name(), anImport, version, anImportWithVersion, candidateVersions)
				}
			}
			if i.shouldGenerateJavaBackend() && !other.shouldGenerateJavaBackend() {
				mctx.PropertyErrorf("backend.java.enabled",
					"Java backend not enabled in the imported AIDL interface %q", anImport)
			}

			if i.shouldGenerateCppBackend() && !other.shouldGenerateCppBackend() {
				mctx.PropertyErrorf("backend.cpp.enabled",
					"C++ backend not enabled in the imported AIDL interface %q", anImport)
			}

			if i.shouldGenerateNdkBackend() && !other.shouldGenerateNdkBackend() {
				mctx.PropertyErrorf("backend.ndk.enabled",
					"NDK backend not enabled in the imported AIDL interface %q", anImport)
			}

			if i.shouldGenerateRustBackend() && !other.shouldGenerateRustBackend() {
				mctx.PropertyErrorf("backend.rust.enabled",
					"Rust backend not enabled in the imported AIDL interface %q", anImport)
			}
		}
	}
}

func (i *aidlInterface) checkGenTrace(mctx android.LoadHookContext) {
	if !proptools.Bool(i.properties.Gen_trace) {
		return
	}
	if i.shouldGenerateJavaBackend() && !proptools.Bool(i.properties.Backend.Java.Platform_apis) {
		mctx.PropertyErrorf("gen_trace", "must be false when Java backend is enabled and platform_apis is false")
	}
}

func (i *aidlInterface) checkStability(mctx android.LoadHookContext) {
	if i.properties.Stability == nil {
		return
	}

	if proptools.Bool(i.properties.Unstable) {
		mctx.PropertyErrorf("stability", "must be empty when \"unstable\" is true")
	}

	// TODO(b/136027762): should we allow more types of stability (e.g. for APEX) or
	// should we switch this flag to be something like "vintf { enabled: true }"
	isVintf := "vintf" == proptools.String(i.properties.Stability)
	if !isVintf {
		mctx.PropertyErrorf("stability", "must be empty or \"vintf\"")
	}
}
func (i *aidlInterface) checkVersions(mctx android.LoadHookContext) {
	versions := make(map[string]bool)
	intVersions := make([]int, 0, len(i.properties.Versions))
	for _, ver := range i.properties.Versions {
		if _, dup := versions[ver]; dup {
			mctx.PropertyErrorf("versions", "duplicate found", ver)
			continue
		}
		versions[ver] = true
		n, err := strconv.Atoi(ver)
		if err != nil {
			mctx.PropertyErrorf("versions", "%q is not an integer", ver)
			continue
		}
		if n <= 0 {
			mctx.PropertyErrorf("versions", "should be > 0, but is %v", ver)
			continue
		}
		intVersions = append(intVersions, n)

	}
	if !mctx.Failed() && !sort.IntsAreSorted(intVersions) {
		mctx.PropertyErrorf("versions", "should be sorted, but is %v", i.properties.Versions)
	}
}
func (i *aidlInterface) checkVndkUseVersion(mctx android.LoadHookContext) {
	if i.properties.Vndk_use_version == nil {
		return
	}
	if !i.hasVersion() {
		mctx.PropertyErrorf("vndk_use_version", "This does not make sense when no 'versions' are specified.")

	}
	if *i.properties.Vndk_use_version == i.nextVersion() {
		return
	}
	for _, ver := range i.properties.Versions {
		if *i.properties.Vndk_use_version == ver {
			return
		}
	}
	mctx.PropertyErrorf("vndk_use_version", "Specified version %q does not exist", *i.properties.Vndk_use_version)
}

func (i *aidlInterface) nextVersion() string {
	if proptools.Bool(i.properties.Unstable) {
		return ""
	}
	return nextVersion(i.properties.Versions)
}

func nextVersion(versions []string) string {
	if len(versions) == 0 {
		return "1"
	}
	ver := versions[len(versions)-1]
	i, err := strconv.Atoi(ver)
	if err != nil {
		panic(err)
	}
	return strconv.Itoa(i + 1)
}

func (i *aidlInterface) latestVersion() string {
	if !i.hasVersion() {
		return "0"
	}
	return i.properties.Versions[len(i.properties.Versions)-1]
}

func (i *aidlInterface) hasVersion() bool {
	return len(i.properties.Versions) > 0
}

func hasVersionSuffix(moduleName string) bool {
	hasVersionSuffix, _ := regexp.MatchString("-V\\d+$", moduleName)
	return hasVersionSuffix
}

func parseModuleWithVersion(moduleName string) (string, string) {
	if hasVersionSuffix(moduleName) {
		versionIdx := strings.LastIndex(moduleName, "-V")
		if versionIdx == -1 {
			panic("-V must exist in this context")
		}
		return moduleName[:versionIdx], moduleName[versionIdx+len("-V"):]
	}
	return moduleName, ""
}

func trimVersionSuffixInList(moduleNames []string) []string {
	return wrapFunc("", moduleNames, "", func(moduleName string) string {
		moduleNameWithoutVersion, _ := parseModuleWithVersion(moduleName)
		return moduleNameWithoutVersion
	})
}

func aidlInterfaceHook(mctx android.LoadHookContext, i *aidlInterface) {
	if hasVersionSuffix(i.ModuleBase.Name()) {
		mctx.PropertyErrorf("name", "aidl_interface should not have '-V<number> suffix")
	}
	i.properties.ImportsWithoutVersion = trimVersionSuffixInList(i.properties.Imports)
	if !isRelativePath(i.properties.Local_include_dir) {
		mctx.PropertyErrorf("local_include_dir", "must be relative path: "+i.properties.Local_include_dir)
	}
	var importPaths []string
	importPaths = append(importPaths, filepath.Join(mctx.ModuleDir(), i.properties.Local_include_dir))
	importPaths = append(importPaths, i.properties.Include_dirs...)

	i.properties.Full_import_paths = importPaths

	i.gatherInterface(mctx)
	i.checkStability(mctx)
	i.checkVersions(mctx)
	i.checkVndkUseVersion(mctx)
	i.checkGenTrace(mctx)

	if mctx.Failed() {
		return
	}

	var libs []string
	sdkIsFinal := !mctx.Config().DefaultAppTargetSdk(mctx).IsPreview()

	unstable := proptools.Bool(i.properties.Unstable)

	if unstable {
		if i.hasVersion() {
			mctx.PropertyErrorf("versions", "cannot have versions for an unstable interface")
			return
		}
		if i.properties.Stability != nil {
			mctx.ModuleErrorf("unstable:true and stability:%q cannot happen at the same time", i.properties.Stability)
			return
		}
	}

	// Two different types of 'unstable' here
	// - 'unstable: true' meaning the module is never stable
	// - current unfrozen ToT version
	//
	// OEM branches may remove 'i.Owner()' here to apply the check to all interfaces, in
	// addition to core platform interfaces. Otherwise, we rely on vts_treble_vintf_vendor_test.
	requireFrozenVersion := !unstable && sdkIsFinal && i.Owner() == ""

	// surface error early, main check is via checkUnstableModuleMutator
	if requireFrozenVersion && !i.hasVersion() {
		mctx.PropertyErrorf("versions", "must be set (need to be frozen) when \"unstable\" is false, PLATFORM_VERSION_CODENAME is REL, and \"owner\" property is missing.")
	}

	versions := i.properties.Versions
	nextVersion := i.nextVersion()
	shouldGenerateLangBackendMap := map[string]bool{
		langCpp:         i.shouldGenerateCppBackend(),
		langNdk:         i.shouldGenerateNdkBackend(),
		langNdkPlatform: i.shouldGenerateNdkBackend(),
		langJava:        i.shouldGenerateJavaBackend(),
		langRust:        i.shouldGenerateRustBackend()}
	for lang, shouldGenerate := range shouldGenerateLangBackendMap {
		if !shouldGenerate {
			continue
		}
		libs = append(libs, addLibrary(mctx, i, nextVersion, lang))
		if requireFrozenVersion {
			addUnstableModule(mctx, libs[len(libs)-1])
		}
		for _, version := range versions {
			libs = append(libs, addLibrary(mctx, i, version, lang))
		}
	}

	if unstable {
		apiDirRoot := filepath.Join(aidlApiDir, i.ModuleBase.Name())
		aidlDumps, _ := mctx.GlobWithDeps(filepath.Join(mctx.ModuleDir(), apiDirRoot, "**/*.aidl"), nil)
		if len(aidlDumps) != 0 {
			mctx.PropertyErrorf("unstable", "The interface is configured as unstable, "+
				"but API dumps exist under %q. Unstable interface cannot have dumps.", apiDirRoot)
		}
	} else {
		addApiModule(mctx, i)
	}

	if proptools.Bool(i.properties.VndkProperties.Vndk.Enabled) {
		if "vintf" != proptools.String(i.properties.Stability) {
			mctx.PropertyErrorf("stability", "must be \"vintf\" if the module is for VNDK.")
		}
	}

	// Reserve this module name for future use
	mctx.CreateModule(phony.PhonyFactory, &phonyProperties{
		Name: proptools.StringPtr(i.ModuleBase.Name()),
	})

	i.internalModuleNames = libs
}

func (i *aidlInterface) commonBackendProperties(lang string) CommonBackendProperties {
	switch lang {
	case langCpp:
		return i.properties.Backend.Cpp.CommonBackendProperties
	case langJava:
		return i.properties.Backend.Java.CommonBackendProperties
	case langNdk, langNdkPlatform:
		return i.properties.Backend.Ndk.CommonBackendProperties
	case langRust:
		return i.properties.Backend.Rust.CommonBackendProperties
	default:
		panic(fmt.Errorf("unsupported language backend %q\n", lang))
	}
}

// srcsVisibility gives the value for the `visibility` property of the source gen module for the
// language backend `lang`. By default, the source gen module is not visible to the clients of
// aidl_interface (because it's an impl detail), but when `backend.<backend>.srcs_available` is set
// to true, the source gen module follows the visibility of the aidl_interface module.
func srcsVisibility(mctx android.LoadHookContext, lang string) []string {
	if a, ok := mctx.Module().(*aidlInterface); !ok {
		panic(fmt.Errorf("%q is not aidl_interface", mctx.Module().String()))
	} else {
		if proptools.Bool(a.commonBackendProperties(lang).Srcs_available) {
			// Returning nil so that the visibility of the source module defaults to the
			// the package-level default visibility. This way, the source module gets
			// the same visibility as the library modules.
			return nil
		}
	}
	return []string{
		"//" + mctx.ModuleDir(),
		// system/tools/aidl/build is always added because aidl_metadata_json in the
		// directory has dependencies to all aidl_interface modules.
		"//system/tools/aidl/build",
	}
}

func (i *aidlInterface) Name() string {
	return i.ModuleBase.Name() + aidlInterfaceSuffix
}
func (i *aidlInterface) GenerateAndroidBuildActions(ctx android.ModuleContext) {
	aidlRoot := android.PathForModuleSrc(ctx, i.properties.Local_include_dir)
	for _, src := range android.PathsForModuleSrc(ctx, i.properties.Srcs) {
		baseDir := getBaseDir(ctx, src, aidlRoot)
		relPath, _ := filepath.Rel(baseDir, src.String())
		computedType := strings.TrimSuffix(strings.ReplaceAll(relPath, "/", "."), ".aidl")
		i.computedTypes = append(i.computedTypes, computedType)
	}
}
func (i *aidlInterface) DepsMutator(ctx android.BottomUpMutatorContext) {
	ctx.AddReverseDependency(ctx.Module(), nil, aidlMetadataSingletonName)
}

var (
	aidlInterfacesKey   = android.NewOnceKey("aidlInterfaces")
	unstableModulesKey  = android.NewOnceKey("unstableModules")
	aidlDepsKey         = android.NewOnceKey("aidlDeps")
	aidlInterfaceMutex  sync.Mutex
	unstableModuleMutex sync.Mutex
	aidlDepsMutex       sync.RWMutex
)

func aidlInterfaces(config android.Config) *[]*aidlInterface {
	return config.Once(aidlInterfacesKey, func() interface{} {
		return &[]*aidlInterface{}
	}).(*[]*aidlInterface)
}

func unstableModules(config android.Config) *[]string {
	return config.Once(unstableModulesKey, func() interface{} {
		return &[]string{}
	}).(*[]string)
}

type DepInfo struct {
	ifaceName string
	verLang   string
	isSource  bool
}

func (d DepInfo) moduleName() string {
	name := d.ifaceName + d.verLang
	if d.isSource {
		name += "-source"
	}
	return name
}

func aidlDeps(config android.Config) map[android.Module][]DepInfo {
	return config.Once(aidlDepsKey, func() interface{} {
		return make(map[android.Module][]DepInfo)
	}).(map[android.Module][]DepInfo)
}

func aidlInterfaceFactory() android.Module {
	i := &aidlInterface{}
	i.AddProperties(&i.properties)
	android.InitAndroidModule(i)
	android.AddLoadHook(i, func(ctx android.LoadHookContext) { aidlInterfaceHook(ctx, i) })
	return i
}

func lookupInterface(name string, config android.Config) *aidlInterface {
	for _, i := range *aidlInterfaces(config) {
		if i.ModuleBase.Name() == name {
			return i
		}
	}
	return nil
}
