// 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/bazel"
	"android/soong/cc"
	"android/soong/java"
	"android/soong/phony"
	"android/soong/rust"

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

	"github.com/google/blueprint"
	"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"
	langCppAnalyzer           = "cpp-analyzer"
	// 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.HostBinToolVariable("aidlHashGen", "aidl_hash_gen")
	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(registerPreArchMutators)
	android.PreArchBp2BuildMutators(registerPreArchMutators)
	android.PostDepsMutators(registerPostDepsMutators)
}

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

func registerPostDepsMutators(ctx android.RegisterMutatorsContext) {
	ctx.BottomUp("checkAidlGeneratedModules", checkAidlGeneratedModules).Parallel()
}

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

// A marker struct for AIDL-generated library modules
type AidlGeneratedModuleProperties struct{}

func wrapLibraryFactory(factory func() android.Module) func() android.Module {
	return func() android.Module {
		m := factory()
		// put a marker struct for AIDL-generated modules
		m.AddProperties(&AidlGeneratedModuleProperties{})
		return m
	}
}

func isAidlGeneratedModule(module android.Module) bool {
	for _, props := range module.GetProperties() {
		// check if there's a marker struct
		if _, ok := props.(*AidlGeneratedModuleProperties); ok {
			return true
		}
	}
	return false
}

// AidlVersionInfo keeps the *-source module for each (aidl_interface & lang) and the list of
// not-frozen versions (which shouldn't be used by other modules)
type AidlVersionInfo struct {
	notFrozen            []string
	requireFrozenReasons []string
	sourceMap            map[string]string
}

var AidlVersionInfoProvider = blueprint.NewMutatorProvider(AidlVersionInfo{}, "checkAidlGeneratedModules")

// Merges `other` version info into this one.
// Returns the pair of mismatching versions when there's conflict. Otherwise returns nil.
// For example, when a module depends on 'foo-V2-ndk', the map contains an entry of (foo, foo-V2-ndk-source).
// Merging (foo, foo-V1-ndk-source) and (foo, foo-V2-ndk-source) will fail and returns
// {foo-V1-ndk-source, foo-V2-ndk-source}.
func (info *AidlVersionInfo) merge(other AidlVersionInfo) []string {
	info.notFrozen = append(info.notFrozen, other.notFrozen...)
	info.requireFrozenReasons = append(info.requireFrozenReasons, other.requireFrozenReasons...)

	if other.sourceMap == nil {
		return nil
	}
	if info.sourceMap == nil {
		info.sourceMap = make(map[string]string)
	}
	for ifaceName, otherSourceName := range other.sourceMap {
		if sourceName, ok := info.sourceMap[ifaceName]; ok {
			if sourceName != otherSourceName {
				return []string{sourceName, otherSourceName}
			}
		} else {
			info.sourceMap[ifaceName] = otherSourceName
		}
	}
	return nil
}

func reportUsingNotFrozenError(ctx android.BaseModuleContext, notFrozen []string, requireFrozenReason []string) {
	// TODO(b/154066686): Replace it with a common method instead of listing up module types.
	// Test libraries are exempted.
	if android.InList(ctx.ModuleType(), []string{"cc_test_library", "android_test", "cc_benchmark", "cc_test"}) {
		return
	}
	for i, name := range notFrozen {
		reason := requireFrozenReason[i]
		ctx.ModuleErrorf("%v is an unfrozen development version, and it can't be used because %q", name, reason)
	}
}

func reportMultipleVersionError(ctx android.BaseModuleContext, violators []string) {
	sort.Strings(violators)
	ctx.ModuleErrorf("depends on multiple versions of the same aidl_interface: %s", strings.Join(violators, ", "))
	ctx.WalkDeps(func(child android.Module, parent android.Module) bool {
		if android.InList(child.Name(), violators) {
			ctx.ModuleErrorf("Dependency path: %s", ctx.GetPathString(true))
			return false
		}
		return true
	})
}

func checkAidlGeneratedModules(mctx android.BottomUpMutatorContext) {
	switch mctx.Module().(type) {
	case *java.Library:
	case *cc.Module:
	case *rust.Module:
	case *aidlGenRule:
	default:
		return
	}
	if gen, ok := mctx.Module().(*aidlGenRule); ok {
		var notFrozen []string
		var requireFrozenReasons []string
		if gen.properties.NotFrozen {
			notFrozen = []string{strings.TrimSuffix(mctx.ModuleName(), "-source")}
			requireFrozenReasons = []string{gen.properties.RequireFrozenReason}
		}
		mctx.SetProvider(AidlVersionInfoProvider, AidlVersionInfo{
			notFrozen:            notFrozen,
			requireFrozenReasons: requireFrozenReasons,
			sourceMap: map[string]string{
				gen.properties.BaseName + "-" + gen.properties.Lang: gen.Name(),
			},
		})
		return
	}
	// Collect/merge AidlVersionInfos from direct dependencies
	var info AidlVersionInfo
	mctx.VisitDirectDeps(func(dep android.Module) {
		if mctx.OtherModuleHasProvider(dep, AidlVersionInfoProvider) {
			otherInfo := mctx.OtherModuleProvider(dep, AidlVersionInfoProvider).(AidlVersionInfo)
			if violators := info.merge(otherInfo); violators != nil {
				reportMultipleVersionError(mctx, violators)
			}
		}
	})
	if !isAidlGeneratedModule(mctx.Module()) && len(info.notFrozen) > 0 {
		reportUsingNotFrozenError(mctx, info.notFrozen, info.requireFrozenReasons)
	}
	if mctx.Failed() {
		return
	}
	if info.sourceMap != nil || len(info.notFrozen) > 0 {
		mctx.SetProvider(AidlVersionInfoProvider, info)
	}
}

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 in %v", root)
	}

	// 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:
	//   - for Java/NDK/CPP backends - True
	//   - for Rust backend - False
	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

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

type CommonNativeBackendProperties struct {
	CommonBackendProperties

	// Must be NDK libraries, for stable types.
	Additional_shared_libraries []string

	// cflags to forward to native compilation. This is expected to be
	// used more for AIDL compiler developers than being actually
	// practical.
	Cflags []string

	// 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 installed on the recovery image.
	Recovery_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

	// 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

	// If true, this interface is frozen and does not have any changes since the last
	// frozen version.
	// If false, there are changes to this interface between the last frozen version (N) and
	// the current version (N + 1).
	Frozen *bool

	// Deprecated: Use `versions_with_info` instead. Don't use `versions` property directly.
	Versions []string

	// Previous API versions that are now frozen. The version that is last in
	// the list is considered as the most recent version.
	// The struct contains both version and imports information per a version.
	// Until versions property is removed, don't use `versions_with_info` directly.
	Versions_with_info []struct {
		Version string
		Imports []string
	}

	// Use aidlInterface.getVersions()
	VersionsInternal []string `blueprint:"mutated"`

	// 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. This can be overridden by
	// backend.<name>.min_sdk_version.
	Min_sdk_version *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
			// Whether RPC features are enabled (requires API level 32)
			// TODO(b/175819535): enable this automatically?
			Gen_rpc *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

			// Set to the version of the sdk to compile against, for the NDK
			// variant.
			// Default: current
			Sdk_version *string

			// 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

	// List of aidl_interface_headers modules that provide include dependencies
	// for the AIDL tool.
	Headers []string
}

type aidlInterface struct {
	android.ModuleBase
	android.BazelModuleBase
	android.DefaultableModuleBase

	properties aidlInterfaceProperties

	computedTypes []string

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

	// map for version to preprocessed.aidl file.
	// There's two additional alias for versions:
	// - ""(empty) is for ToT
	// - "latest" is for i.latestVersion()
	preprocessed map[string]android.WritablePath
}

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)
}

// Returns whether the ndk backend supports applications or not. Default is `true`. `false` is
// returned when `apps_enabled` is explicitly set to false or the interface is exclusive to vendor
// (i.e. `vendor: true`). 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) &&
		!i.SocSpecific()
}

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

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

func (i *aidlInterface) genTrace(lang string) bool {
	var ver *bool
	switch lang {
	case langCpp:
		ver = i.properties.Backend.Cpp.Gen_trace
		if ver == nil {
			// Enable tracing for all cpp backends by default
			ver = proptools.BoolPtr(true)
		}
	case langJava:
		ver = i.properties.Backend.Java.Gen_trace
		if ver == nil && proptools.Bool(i.properties.Backend.Java.Platform_apis) {
			// Enable tracing for all Java backends using platform APIs
			// TODO(161393989) Once we generate ATRACE_TAG_APP instead of ATRACE_TAG_AIDL,
			// this can be removed and we can start generating traces in all apps.
			ver = proptools.BoolPtr(true)
		}
	case langNdk, langNdkPlatform:
		ver = i.properties.Backend.Ndk.Gen_trace
	case langRust: // unsupported b/236880829
		ver = i.properties.Backend.Rust.Gen_trace
	case langCppAnalyzer:
		*ver = false
	default:
		panic(fmt.Errorf("unsupported language backend %q\n", lang))
	}
	if ver == nil {
		ver = i.properties.Gen_trace
	}
	return proptools.Bool(ver)
}

// Dep to *-api module(aidlApi)
type apiDepTag struct {
	blueprint.BaseDependencyTag
	name string
}

type importInterfaceDepTag struct {
	blueprint.BaseDependencyTag
	anImport string
}

type interfaceDepTag struct {
	blueprint.BaseDependencyTag
}

type interfaceHeadersDepTag struct {
	blueprint.BaseDependencyTag
}

var (
	// Dep from *-source (aidlGenRule) to *-api (aidlApi)
	apiDep = apiDepTag{name: "api"}
	// Dep from *-api (aidlApi) to *-api (aidlApi), representing imported interfaces
	importApiDep = apiDepTag{name: "imported-api"}
	// Dep to original *-interface (aidlInterface)
	interfaceDep = interfaceDepTag{}
	// Dep for a header interface
	interfaceHeadersDep = interfaceHeadersDepTag{}
)

func addImportedInterfaceDeps(ctx android.BottomUpMutatorContext, imports []string) {
	for _, anImport := range imports {
		name, _ := parseModuleWithVersion(anImport)
		ctx.AddDependency(ctx.Module(), importInterfaceDepTag{anImport: anImport}, name+aidlInterfaceSuffix)
	}
}

// Run custom "Deps" mutator between AIDL modules created at LoadHook stage.
// We can't use the "DepsMutator" for these dependencies because
// - We need to create library modules (cc/java/...) before "arch" mutator. Note that cc_library
//
//	should be mutated by os/image/arch mutators as well.
//
// - When creating library modules, we need to access the original interface and its imported
//
//	interfaces to determine which version to use. See aidlInterface.getImportWithVersion.
func addInterfaceDeps(mctx android.BottomUpMutatorContext) {
	switch i := mctx.Module().(type) {
	case *aidlInterface:
		// In fact this isn't necessary because soong checks dependencies on undefined modules.
		// But since aidl_interface overrides its name internally, this provides better error message.
		for _, anImportWithVersion := range i.properties.Imports {
			anImport, _ := parseModuleWithVersion(anImportWithVersion)
			if !mctx.OtherModuleExists(anImport + aidlInterfaceSuffix) {
				if !mctx.Config().AllowMissingDependencies() {
					mctx.PropertyErrorf("imports", "Import does not exist: "+anImport)
				}
			}
		}
		if mctx.Failed() {
			return
		}
		addImportedInterfaceDeps(mctx, i.properties.Imports)

		for _, header := range i.properties.Headers {
			mctx.AddDependency(i, interfaceHeadersDep, header)
		}
	case *aidlImplementationGenerator:
		mctx.AddDependency(i, interfaceDep, i.properties.AidlInterfaceName+aidlInterfaceSuffix)
		addImportedInterfaceDeps(mctx, i.properties.Imports)
	case *rust.Module:
		for _, props := range i.GetProperties() {
			if sp, ok := props.(*aidlRustSourceProviderProperties); ok {
				mctx.AddDependency(i, interfaceDep, sp.AidlInterfaceName+aidlInterfaceSuffix)
				addImportedInterfaceDeps(mctx, sp.Imports)
				break
			}
		}
	case *aidlApi:
		mctx.AddDependency(i, interfaceDep, i.properties.BaseName+aidlInterfaceSuffix)
		addImportedInterfaceDeps(mctx, i.properties.Imports)
		for _, anImport := range i.properties.Imports {
			name, _ := parseModuleWithVersion(anImport)
			mctx.AddDependency(i, importApiDep, name+aidlApiSuffix)
		}
		for _, header := range i.properties.Headers {
			mctx.AddDependency(i, interfaceHeadersDep, header)
		}
	case *aidlGenRule:
		mctx.AddDependency(i, interfaceDep, i.properties.BaseName+aidlInterfaceSuffix)
		addImportedInterfaceDeps(mctx, i.properties.Imports)
		if !proptools.Bool(i.properties.Unstable) {
			// for checkapi timestamps
			mctx.AddDependency(i, apiDep, i.properties.BaseName+aidlApiSuffix)
		}
		for _, header := range i.properties.Headers {
			mctx.AddDependency(i, interfaceHeadersDep, header)
		}
	}
}

// checkImports checks if "import:" property is valid.
// In fact, this isn't necessary because Soong can check/report when we add a dependency to
// undefined/unknown module. But module names are very implementation specific and may not be easy
// to understand. For example, when foo (with java enabled) depends on bar (with java disabled), the
// error message would look like "foo-V2-java depends on unknown module `bar-V3-java`", which isn't
// clear that backend.java.enabled should be turned on.
func checkImports(mctx android.BottomUpMutatorContext) {
	if i, ok := mctx.Module().(*aidlInterface); ok {
		mctx.VisitDirectDeps(func(dep android.Module) {
			tag, ok := mctx.OtherModuleDependencyTag(dep).(importInterfaceDepTag)
			if !ok {
				return
			}
			other := dep.(*aidlInterface)
			anImport := other.ModuleBase.Name()
			anImportWithVersion := tag.anImport
			_, version := parseModuleWithVersion(tag.anImport)

			candidateVersions := other.getVersions()
			if !proptools.Bool(other.properties.Frozen) {
				candidateVersions = concat(candidateVersions, []string{other.nextVersion()})
			}

			if version == "" {
				if !proptools.Bool(other.properties.Unstable) {
					mctx.PropertyErrorf("imports", "%q depends on %q but does not specify a version (must be one of %q)", i.ModuleBase.Name(), anImport, candidateVersions)
				}
			} else {
				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)
			}

			if i.isFrozen() && other.isExplicitlyUnFrozen() && version == "" {
				mctx.PropertyErrorf("frozen",
					"%q imports %q which is not frozen. Either %q must set 'frozen: false' or must explicitly import %q where * is one of %q",
					i.ModuleBase.Name(), anImport, i.ModuleBase.Name(), anImport+"-V*", candidateVersions)
			}
		})
	}
}

func (i *aidlInterface) checkGenTrace(mctx android.DefaultableHookContext) {
	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.DefaultableHookContext) {
	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.DefaultableHookContext) {
	if len(i.properties.Versions) > 0 && len(i.properties.Versions_with_info) > 0 {
		mctx.ModuleErrorf("versions:%q and versions_with_info:%q cannot be used at the same time. Use versions_with_info instead of versions.", i.properties.Versions, i.properties.Versions_with_info)
	}

	if len(i.properties.Versions) > 0 {
		i.properties.VersionsInternal = make([]string, len(i.properties.Versions))
		copy(i.properties.VersionsInternal, i.properties.Versions)
	} else if len(i.properties.Versions_with_info) > 0 {
		i.properties.VersionsInternal = make([]string, len(i.properties.Versions_with_info))
		for idx, value := range i.properties.Versions_with_info {
			i.properties.VersionsInternal[idx] = value.Version
			for _, im := range value.Imports {
				if !hasVersionSuffix(im) {
					mctx.ModuleErrorf("imports in versions_with_info must specify its version, but %s. Add a version suffix(such as %s-V1).", im, im)
					return
				}
			}
		}
	}

	versions := make(map[string]bool)
	intVersions := make([]int, 0, len(i.getVersions()))
	for _, ver := range i.getVersions() {
		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.getVersions())
	}
}
func (i *aidlInterface) checkVndkUseVersion(mctx android.DefaultableHookContext) {
	if i.properties.Vndk_use_version == nil {
		return
	}
	if *i.properties.Vndk_use_version == i.nextVersion() {
		return
	}
	for _, ver := range i.getVersions() {
		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.getVersions())
}

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.getVersions()[len(i.getVersions())-1]
}

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

func (i *aidlInterface) getVersions() []string {
	return i.properties.VersionsInternal
}

func (i *aidlInterface) isFrozen() bool {
	return proptools.Bool(i.properties.Frozen)
}

// in order to keep original behavior for certain operations, we may want to
// check if frozen is set.
func (i *aidlInterface) isExplicitlyUnFrozen() bool {
	return i.properties.Frozen != nil && !proptools.Bool(i.properties.Frozen)
}

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 (i *aidlInterface) checkRequireFrozenAndReason(mctx android.EarlyModuleContext) (bool, string) {
	if proptools.Bool(i.properties.Unstable) {
		return false, "it's an unstable interface"
	}

	if proptools.Bool(i.properties.Frozen) {
		return true, "it's explicitly marked as `frozen: true`"
	}

	if i.Owner() == "" {
		if !mctx.Config().DefaultAppTargetSdk(mctx).IsPreview() {
			return true, "this is a release branch - freeze it or set 'owners:'"
		} else if mctx.Config().IsEnvTrue("AIDL_FROZEN_REL") {
			return true, "this is a release branch (simulated by setting AIDL_FROZEN_REL) - freeze it or set 'owners:'"
		}
	} else {
		// has an OWNER
		// REL branches don't enforce downstream interfaces or owned interfaces
		// to be frozen. Instead, these interfaces are verified by other tests
		// like vts_treble_vintf_vendor_test
		if android.InList(i.Owner(), strings.Fields(mctx.Config().Getenv("AIDL_FROZEN_OWNERS"))) {
			return true, "the owner field is in environment variable AIDL_FROZEN_OWNERS"
		}
	}

	return false, "by default, we don't require the interface to be frozen"
}

func aidlInterfaceHook(mctx android.DefaultableHookContext, i *aidlInterface) {
	if hasVersionSuffix(i.ModuleBase.Name()) {
		mctx.PropertyErrorf("name", "aidl_interface should not have '-V<number> suffix")
	}
	if !isRelativePath(i.properties.Local_include_dir) {
		mctx.PropertyErrorf("local_include_dir", "must be relative path: "+i.properties.Local_include_dir)
	}

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

	if mctx.Failed() {
		return
	}

	var libs []string

	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
		}
	}

	if i.isFrozen() {
		if !i.hasVersion() {
			mctx.PropertyErrorf("frozen", "cannot be frozen without versions")
			return
		}
	}

	if !unstable && mctx.Namespace().Path != "." && i.Owner() == "" {
		mctx.PropertyErrorf("owner", "aidl_interface in a soong_namespace must have the 'owner' property set.")
	}

	requireFrozenVersion, requireFrozenReason := i.checkRequireFrozenAndReason(mctx)

	// surface error early, main check is via checkUnstableModuleMutator
	if requireFrozenVersion && !i.hasVersion() {
		mctx.PropertyErrorf("versions", "must be set (need to be frozen) because: %q", requireFrozenReason)
	}

	vndkEnabled := proptools.Bool(i.properties.VndkProperties.Vndk.Enabled) ||
		proptools.Bool(i.properties.Backend.Cpp.CommonNativeBackendProperties.VndkProperties.Vndk.Enabled) ||
		proptools.Bool(i.properties.Backend.Ndk.CommonNativeBackendProperties.VndkProperties.Vndk.Enabled)

	if vndkEnabled && !proptools.Bool(i.properties.Unstable) {
		if i.properties.Frozen == nil {
			mctx.PropertyErrorf("frozen", "true or false must be specified when the VNDK is enabled on a versioned interface (not `unstable: true`)")
		}
		if !proptools.Bool(i.properties.Frozen) && i.properties.Vndk_use_version == nil {
			mctx.PropertyErrorf("vndk_use_version", "must be specified if interface is unfrozen (or specify 'frozen: false')")
		}
	}

	versions := i.getVersions()
	nextVersion := i.nextVersion()
	shouldGenerateLangBackendMap := map[string]bool{
		langCpp:  i.shouldGenerateCppBackend(),
		langNdk:  i.shouldGenerateNdkBackend(),
		langJava: i.shouldGenerateJavaBackend(),
		langRust: i.shouldGenerateRustBackend()}

	// The ndk_platform backend is generated only when explicitly requested. This will
	// eventually be completely removed the devices in the long tail are gone.
	if mctx.DeviceConfig().GenerateAidlNdkPlatformBackend() {
		shouldGenerateLangBackendMap[langNdkPlatform] = i.shouldGenerateNdkBackend()
	}

	for lang, shouldGenerate := range shouldGenerateLangBackendMap {
		if !shouldGenerate {
			continue
		}
		libs = append(libs, addLibrary(mctx, i, nextVersion, lang, requireFrozenVersion, requireFrozenReason))
		for _, version := range versions {
			libs = append(libs, addLibrary(mctx, i, version, lang, false, "this is a known frozen version"))
		}
	}

	// In the future, we may want to force the -cpp backend to be on host,
	// and limit its visibility, even if it's not created normally
	if i.shouldGenerateCppBackend() && len(i.properties.Imports) == 0 {
		libs = append(libs, addLibrary(mctx, i, nextVersion, langCppAnalyzer, false, "analysis always uses latest version even if frozen"))
	}

	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)
	}

	// 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))
	}
}

func (i *aidlInterface) Name() string {
	return i.ModuleBase.Name() + aidlInterfaceSuffix
}

func (i *aidlInterface) GenerateAndroidBuildActions(ctx android.ModuleContext) {
	srcs, _ := getPaths(ctx, i.properties.Srcs, i.properties.Local_include_dir)
	for _, src := range srcs {
		computedType := strings.TrimSuffix(strings.ReplaceAll(src.Rel(), "/", "."), ".aidl")
		i.computedTypes = append(i.computedTypes, computedType)
	}

	i.preprocessed = make(map[string]android.WritablePath)
	// generate (len(versions) + 1) preprocessed.aidl files
	for _, version := range concat(i.getVersions(), []string{i.nextVersion()}) {
		i.preprocessed[version] = i.buildPreprocessed(ctx, version)
	}
	// helpful aliases
	if !proptools.Bool(i.properties.Unstable) {
		if i.hasVersion() {
			i.preprocessed["latest"] = i.preprocessed[i.latestVersion()]
		} else {
			// when we have no frozen versions yet, use "next version" as latest
			i.preprocessed["latest"] = i.preprocessed[i.nextVersion()]
		}
		i.preprocessed[""] = i.preprocessed[i.nextVersion()]
	}
}

func (i *aidlInterface) getImportsForVersion(version string) []string {
	// `Imports` is used when version == i.nextVersion() or`versions` is defined instead of `versions_with_info`
	importsSrc := i.properties.Imports
	for _, v := range i.properties.Versions_with_info {
		if v.Version == version {
			importsSrc = v.Imports
			break
		}
	}
	imports := make([]string, len(importsSrc))
	copy(imports, importsSrc)

	return imports
}

func (i *aidlInterface) getImports(version string) map[string]string {
	imports := make(map[string]string)
	imports_src := i.getImportsForVersion(version)

	useLatestStable := !proptools.Bool(i.properties.Unstable) && version != "" && version != i.nextVersion()
	for _, importString := range imports_src {
		name, targetVersion := parseModuleWithVersion(importString)
		if targetVersion == "" && useLatestStable {
			targetVersion = "latest"
		}
		imports[name] = targetVersion
	}
	return imports
}

// generate preprocessed.aidl which contains only types with evaluated constants.
// "imports" will use preprocessed.aidl with -p flag to avoid parsing the entire transitive list
// of dependencies.
func (i *aidlInterface) buildPreprocessed(ctx android.ModuleContext, version string) android.WritablePath {
	deps := getDeps(ctx, i.getImports(version))

	preprocessed := android.PathForModuleOut(ctx, version, "preprocessed.aidl")
	rb := android.NewRuleBuilder(pctx, ctx)
	srcs, root_dir := i.srcsForVersion(ctx, version)

	if len(srcs) == 0 {
		ctx.PropertyErrorf("srcs", "No sources for a previous version in %v. Was a version manually added to .bp file? This is added automatically by <module>-freeze-api.", root_dir)
	}

	paths, imports := getPaths(ctx, srcs, root_dir)
	imports = append(imports, deps.imports...)
	imports = append(imports, i.properties.Include_dirs...)

	preprocessCommand := rb.Command().BuiltTool("aidl").
		FlagWithOutput("--preprocess ", preprocessed).
		Flag("--structured")
	if i.properties.Stability != nil {
		preprocessCommand.FlagWithArg("--stability ", *i.properties.Stability)
	}
	preprocessCommand.FlagForEachInput("-p", deps.preprocessed)
	preprocessCommand.FlagForEachArg("-I", imports)
	preprocessCommand.Inputs(paths)
	name := i.BaseModuleName()
	if version != "" {
		name += "/" + version
	}
	rb.Build("export_"+name, "export types for "+name)
	return preprocessed
}

func (i *aidlInterface) DepsMutator(ctx android.BottomUpMutatorContext) {
	ctx.AddReverseDependency(ctx.Module(), nil, aidlMetadataSingletonName)
}

func AidlInterfaceFactory() android.Module {
	i := &aidlInterface{}
	i.AddProperties(&i.properties)
	android.InitAndroidModule(i)
	android.InitBazelModule(i)
	android.InitDefaultableModule(i)
	i.SetDefaultableHook(func(ctx android.DefaultableHookContext) { aidlInterfaceHook(ctx, i) })
	return i
}

type aidlInterfaceAttributes struct {
	aidlLibraryAttributes
	Versions           bazel.StringListAttribute
	Stability          *string
	Versions_with_info []versionWithInfoAttribute
	Java_config        *javaConfigAttributes
	Cpp_config         *cppConfigAttributes
	Ndk_config         *ndkConfigAttributes
	// Backend_Configs    backendConfigAttributes
	Unstable *bool
}

type javaConfigAttributes struct {
	commonBackendAttributes
}
type cppConfigAttributes struct {
	commonNativeBackendAttributes
}
type ndkConfigAttributes struct {
	commonNativeBackendAttributes
}

type commonBackendAttributes struct {
	Enabled         bool
	Min_sdk_version *string
}

type commonNativeBackendAttributes struct {
	commonBackendAttributes
}

type versionWithInfoAttribute struct {
	Version string
	// Versions_with_info.Deps in Bazel is analogous to Versions_with_info.Imports in Soong.
	// Deps is chosen to be consistent with other Bazel rules/macros for AIDL
	Deps bazel.LabelListAttribute
}

type aidlLibraryAttributes struct {
	Srcs                bazel.LabelListAttribute
	Hdrs                bazel.LabelListAttribute
	Deps                bazel.LabelListAttribute
	Strip_import_prefix *string
	Flags               []string
}

// getBazelLabelListForImports returns a bazel label list converted from
// aidl_interface.imports or aidl_interface.versions_with_info.imports prop
func getBazelLabelListForImports(ctx android.BazelConversionPathContext, imports []string) bazel.LabelList {
	type nameAndVersion struct {
		name    string
		version string
	}
	// An aidl_interface with a version designation doesn't correspond to a specific
	// module, but rather just imforms Soong on which collection of sources to provide
	// from a particular interface module.
	// However in Bazel, we will be creating an aidl_library for each version, so we can
	// depend directly on a "versioned" module. But, we must look up the "unversioned"
	// module name in BazelLabelForModuleDeps and then re-attach the version information.
	namesAndVersions := make([]nameAndVersion, len(imports))
	names := make([]string, len(imports))
	for i, dep := range imports {
		// Split dep into two parts
		name, version := parseModuleWithVersion(dep)
		if version == "" {
			version = "-latest"
		} else {
			version = "-V" + version
		}
		namesAndVersions[i] = nameAndVersion{
			name:    name,
			version: version,
		}
		names[i] = name
	}
	// Look up bazel label by name without version
	bazelLabels := android.BazelLabelForModuleDeps(ctx, names)
	for i := range bazelLabels.Includes {
		// Re-attach the version to the name
		bazelLabels.Includes[i].Label = bazelLabels.Includes[i].Label + namesAndVersions[i].version
	}
	return bazelLabels
}

func (i *aidlInterface) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
	imports := getBazelLabelListForImports(ctx, i.properties.Imports)
	headers := android.BazelLabelForModuleDeps(ctx, i.properties.Headers)
	imports.Append(headers)

	var deps bazel.LabelListAttribute
	if !imports.IsEmpty() {
		deps = bazel.MakeLabelListAttribute(imports)
	}

	var versions bazel.StringListAttribute
	if len(i.properties.Versions) > 0 {
		versions = bazel.MakeStringListAttribute(append([]string{}, i.properties.Versions...))
	}

	var javaConfig *javaConfigAttributes
	var cppConfig *cppConfigAttributes
	var ndkConfig *ndkConfigAttributes
	if i.shouldGenerateJavaBackend() {
		javaConfig = &javaConfigAttributes{}
		javaConfig.Enabled = true
		javaConfig.Min_sdk_version = i.minSdkVersion(langJava)
	}
	if i.shouldGenerateCppBackend() {
		cppConfig = &cppConfigAttributes{}
		cppConfig.Enabled = true
		cppConfig.Min_sdk_version = i.minSdkVersion(langCpp)
	}
	if i.shouldGenerateNdkBackend() {
		ndkConfig = &ndkConfigAttributes{}
		ndkConfig.Enabled = true
		ndkConfig.Min_sdk_version = i.minSdkVersion(langNdk)
	}

	var versionsWithInfos []versionWithInfoAttribute
	if len(i.properties.Versions_with_info) > 0 {
		for _, versionWithInfo := range i.properties.Versions_with_info {
			imports := getBazelLabelListForImports(ctx, versionWithInfo.Imports)
			var attributes versionWithInfoAttribute
			if !imports.IsEmpty() {
				attributes = versionWithInfoAttribute{
					Version: versionWithInfo.Version,
					Deps:    bazel.MakeLabelListAttribute(imports),
				}
			} else {
				attributes = versionWithInfoAttribute{
					Version: versionWithInfo.Version,
				}
			}
			versionsWithInfos = append(versionsWithInfos, attributes)
		}
	}

	srcsAttr := bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrc(ctx, i.properties.Srcs))
	var stripImportPrefixAttr *string = nil
	if i.properties.Local_include_dir != "" && !srcsAttr.IsEmpty() {
		stripImportPrefixAttr = &i.properties.Local_include_dir
	}

	attrs := &aidlInterfaceAttributes{
		aidlLibraryAttributes: aidlLibraryAttributes{
			Srcs:                srcsAttr,
			Flags:               i.properties.Flags,
			Deps:                deps,
			Strip_import_prefix: stripImportPrefixAttr,
		},
		Versions:           versions,
		Stability:          i.properties.Stability,
		Versions_with_info: versionsWithInfos,
		Java_config:        javaConfig,
		Cpp_config:         cppConfig,
		Ndk_config:         ndkConfig,
		Unstable:           i.properties.Unstable,
	}

	interfaceName := strings.TrimSuffix(i.Name(), "_interface")

	ctx.CreateBazelTargetModule(
		bazel.BazelTargetModuleProperties{
			Rule_class:        "aidl_interface",
			Bzl_load_location: "//build/bazel/rules/aidl:interface.bzl",
		},
		android.CommonAttributes{Name: interfaceName},
		attrs,
	)
}
