// Copyright 2016 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 (
	"fmt"
	"reflect"
	"strings"

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

// This file implements common functionality for handling modules that may exist as prebuilts,
// source, or both.

func RegisterPrebuiltMutators(ctx RegistrationContext) {
	ctx.PreArchMutators(RegisterPrebuiltsPreArchMutators)
	ctx.PreDepsMutators(RegisterPrebuiltsPreDepsMutators)
	ctx.PostDepsMutators(RegisterPrebuiltsPostDepsMutators)
}

// Marks a dependency tag as possibly preventing a reference to a source from being
// replaced with the prebuilt.
type ReplaceSourceWithPrebuilt interface {
	blueprint.DependencyTag

	// Return true if the dependency defined by this tag should be replaced with the
	// prebuilt.
	ReplaceSourceWithPrebuilt() bool
}

type prebuiltDependencyTag struct {
	blueprint.BaseDependencyTag
}

var PrebuiltDepTag prebuiltDependencyTag

// Mark this tag so dependencies that use it are excluded from visibility enforcement.
func (t prebuiltDependencyTag) ExcludeFromVisibilityEnforcement() {}

// Mark this tag so dependencies that use it are excluded from APEX contents.
func (t prebuiltDependencyTag) ExcludeFromApexContents() {}

var _ ExcludeFromVisibilityEnforcementTag = PrebuiltDepTag
var _ ExcludeFromApexContentsTag = PrebuiltDepTag

// UserSuppliedPrebuiltProperties contains the prebuilt properties that can be specified in an
// Android.bp file.
type UserSuppliedPrebuiltProperties struct {
	// When prefer is set to true the prebuilt will be used instead of any source module with
	// a matching name.
	Prefer proptools.Configurable[bool] `android:"arch_variant,replace_instead_of_append"`

	// When specified this names a Soong config variable that controls the prefer property.
	//
	// If the value of the named Soong config variable is true then prefer is set to false and vice
	// versa. If the Soong config variable is not set then it defaults to false, so prefer defaults
	// to true.
	//
	// If specified then the prefer property is ignored in favor of the value of the Soong config
	// variable.
	//
	// DEPRECATED: This property is being deprecated b/308188211.
	// Use RELEASE_APEX_CONTRIBUTIONS build flags to select prebuilts of mainline modules.
	Use_source_config_var *ConfigVarProperties
}

// CopyUserSuppliedPropertiesFromPrebuilt copies the user supplied prebuilt properties from the
// prebuilt properties.
func (u *UserSuppliedPrebuiltProperties) CopyUserSuppliedPropertiesFromPrebuilt(p *Prebuilt) {
	*u = p.properties.UserSuppliedPrebuiltProperties
}

type PrebuiltProperties struct {
	UserSuppliedPrebuiltProperties

	SourceExists bool `blueprint:"mutated"`
	UsePrebuilt  bool `blueprint:"mutated"`

	// Set if the module has been renamed to remove the "prebuilt_" prefix.
	PrebuiltRenamedToSource bool `blueprint:"mutated"`
}

// Properties that can be used to select a Soong config variable.
type ConfigVarProperties struct {
	// Allow instances of this struct to be used as a property value in a BpPropertySet.
	BpPrintableBase

	// The name of the configuration namespace.
	//
	// As passed to add_soong_config_namespace in Make.
	Config_namespace *string

	// The name of the configuration variable.
	//
	// As passed to add_soong_config_var_value in Make.
	Var_name *string
}

type Prebuilt struct {
	properties PrebuiltProperties

	// nil if the prebuilt has no srcs property at all. See InitPrebuiltModuleWithoutSrcs.
	srcsSupplier PrebuiltSrcsSupplier

	// "-" if the prebuilt has no srcs property at all. See InitPrebuiltModuleWithoutSrcs.
	srcsPropertyName string
}

// RemoveOptionalPrebuiltPrefix returns the result of removing the "prebuilt_" prefix from the
// supplied name if it has one, or returns the name unmodified if it does not.
func RemoveOptionalPrebuiltPrefix(name string) string {
	return strings.TrimPrefix(name, "prebuilt_")
}

// RemoveOptionalPrebuiltPrefixFromBazelLabel removes the "prebuilt_" prefix from the *target name* of a Bazel label.
// This differs from RemoveOptionalPrebuiltPrefix in that it does not remove it from the start of the string, but
// instead removes it from the target name itself.
func RemoveOptionalPrebuiltPrefixFromBazelLabel(label string) string {
	splitLabel := strings.Split(label, ":")
	bazelModuleNameNoPrebuilt := RemoveOptionalPrebuiltPrefix(splitLabel[1])
	return strings.Join([]string{
		splitLabel[0],
		bazelModuleNameNoPrebuilt,
	}, ":")
}

func (p *Prebuilt) Name(name string) string {
	return PrebuiltNameFromSource(name)
}

// PrebuiltNameFromSource returns the result of prepending the "prebuilt_" prefix to the supplied
// name.
func PrebuiltNameFromSource(name string) string {
	return "prebuilt_" + name
}

func (p *Prebuilt) ForcePrefer() {
	p.properties.Prefer = NewSimpleConfigurable(true)
}

// SingleSourcePathFromSupplier invokes the supplied supplier for the current module in the
// supplied context to retrieve a list of file paths, ensures that the returned list of file paths
// contains a single value and then assumes that is a module relative file path and converts it to
// a Path accordingly.
//
// Any issues, such as nil supplier or not exactly one file path will be reported as errors on the
// supplied context and this will return nil.
func SingleSourcePathFromSupplier(ctx ModuleContext, srcsSupplier PrebuiltSrcsSupplier, srcsPropertyName string) Path {
	if srcsSupplier != nil {
		srcs := srcsSupplier(ctx, ctx.Module())

		if len(srcs) == 0 {
			ctx.PropertyErrorf(srcsPropertyName, "missing prebuilt source file")
			return nil
		}

		if len(srcs) > 1 {
			ctx.PropertyErrorf(srcsPropertyName, "multiple prebuilt source files")
			return nil
		}

		// Return the singleton source after expanding any filegroup in the
		// sources.
		src := srcs[0]
		return PathForModuleSrc(ctx, src)
	} else {
		ctx.ModuleErrorf("prebuilt source was not set")
		return nil
	}
}

// The below source-related functions and the srcs, src fields are based on an assumption that
// prebuilt modules have a static source property at the moment. Currently there is only one
// exception, android_app_import, which chooses a source file depending on the product's DPI
// preference configs. We'll want to add native support for dynamic source cases if we end up having
// more modules like this.
func (p *Prebuilt) SingleSourcePath(ctx ModuleContext) Path {
	return SingleSourcePathFromSupplier(ctx, p.srcsSupplier, p.srcsPropertyName)
}

func (p *Prebuilt) UsePrebuilt() bool {
	return p.properties.UsePrebuilt
}

func (p *Prebuilt) SetUsePrebuilt(use bool) {
	p.properties.UsePrebuilt = use
}

// Called to provide the srcs value for the prebuilt module.
//
// This can be called with a context for any module not just the prebuilt one itself. It can also be
// called concurrently.
//
// Return the src value or nil if it is not available.
type PrebuiltSrcsSupplier func(ctx BaseModuleContext, prebuilt Module) []string

func initPrebuiltModuleCommon(module PrebuiltInterface) *Prebuilt {
	p := module.Prebuilt()
	module.AddProperties(&p.properties)
	return p
}

// Initialize the module as a prebuilt module that has no dedicated property that lists its
// sources. SingleSourcePathFromSupplier should not be called for this module.
//
// This is the case e.g. for header modules, which provides the headers in source form
// regardless whether they are prebuilt or not.
func InitPrebuiltModuleWithoutSrcs(module PrebuiltInterface) {
	p := initPrebuiltModuleCommon(module)
	p.srcsPropertyName = "-"
}

// Initialize the module as a prebuilt module that uses the provided supplier to access the
// prebuilt sources of the module.
//
// The supplier will be called multiple times and must return the same values each time it
// is called. If it returns an empty array (or nil) then the prebuilt module will not be used
// as a replacement for a source module with the same name even if prefer = true.
//
// If the Prebuilt.SingleSourcePath() is called on the module then this must return an array
// containing exactly one source file.
//
// The provided property name is used to provide helpful error messages in the event that
// a problem arises, e.g. calling SingleSourcePath() when more than one source is provided.
func InitPrebuiltModuleWithSrcSupplier(module PrebuiltInterface, srcsSupplier PrebuiltSrcsSupplier, srcsPropertyName string) {
	if srcsSupplier == nil {
		panic(fmt.Errorf("srcsSupplier must not be nil"))
	}
	if srcsPropertyName == "" {
		panic(fmt.Errorf("srcsPropertyName must not be empty"))
	}

	p := initPrebuiltModuleCommon(module)
	p.srcsSupplier = srcsSupplier
	p.srcsPropertyName = srcsPropertyName
}

// InitPrebuiltModule is the same as InitPrebuiltModuleWithSrcSupplier, but uses the
// provided list of strings property as the source provider.
func InitPrebuiltModule(module PrebuiltInterface, srcs *[]string) {
	if srcs == nil {
		panic(fmt.Errorf("srcs must not be nil"))
	}

	srcsSupplier := func(ctx BaseModuleContext, _ Module) []string {
		return *srcs
	}

	InitPrebuiltModuleWithSrcSupplier(module, srcsSupplier, "srcs")
}

// InitConfigurablePrebuiltModule is the same as InitPrebuiltModule, but uses a
// Configurable list of strings property instead of a regular list of strings.
func InitConfigurablePrebuiltModule(module PrebuiltInterface, srcs *proptools.Configurable[[]string]) {
	if srcs == nil {
		panic(fmt.Errorf("srcs must not be nil"))
	}

	srcsSupplier := func(ctx BaseModuleContext, _ Module) []string {
		return srcs.GetOrDefault(ctx, nil)
	}

	InitPrebuiltModuleWithSrcSupplier(module, srcsSupplier, "srcs")
}

// InitConfigurablePrebuiltModuleString is the same as InitPrebuiltModule, but uses a
// Configurable string property instead of a regular list of strings. It only produces a single
// source file.
func InitConfigurablePrebuiltModuleString(module PrebuiltInterface, srcs *proptools.Configurable[string], propertyName string) {
	if srcs == nil {
		panic(fmt.Errorf("%s must not be nil", propertyName))
	}

	srcsSupplier := func(ctx BaseModuleContext, _ Module) []string {
		src := srcs.GetOrDefault(ctx, "")
		if src == "" {
			return nil
		}
		return []string{src}
	}

	InitPrebuiltModuleWithSrcSupplier(module, srcsSupplier, propertyName)
}

func InitSingleSourcePrebuiltModule(module PrebuiltInterface, srcProps interface{}, srcField string) {
	srcPropsValue := reflect.ValueOf(srcProps).Elem()
	srcStructField, _ := srcPropsValue.Type().FieldByName(srcField)
	if !srcPropsValue.IsValid() || srcStructField.Name == "" {
		panic(fmt.Errorf("invalid single source prebuilt %+v", module))
	}

	if srcPropsValue.Kind() != reflect.Struct && srcPropsValue.Kind() != reflect.Interface {
		panic(fmt.Errorf("invalid single source prebuilt %+v", srcProps))
	}

	srcFieldIndex := srcStructField.Index
	srcPropertyName := proptools.PropertyNameForField(srcField)

	srcsSupplier := func(ctx BaseModuleContext, _ Module) []string {
		if !module.Enabled(ctx) {
			return nil
		}
		value := srcPropsValue.FieldByIndex(srcFieldIndex)
		if value.Kind() == reflect.Ptr {
			if value.IsNil() {
				return nil
			}
			value = value.Elem()
		}
		if value.Kind() != reflect.String {
			panic(fmt.Errorf("prebuilt src field %q in %T in module %s should be a string or a pointer to one but was %v", srcField, srcProps, module, value))
		}
		src := value.String()
		if src == "" {
			return nil
		}
		return []string{src}
	}

	InitPrebuiltModuleWithSrcSupplier(module, srcsSupplier, srcPropertyName)
}

type PrebuiltInterface interface {
	Module
	Prebuilt() *Prebuilt
}

// IsModulePreferred returns true if the given module is preferred.
//
// A source module is preferred if there is no corresponding prebuilt module or the prebuilt module
// does not have "prefer: true".
//
// A prebuilt module is preferred if there is no corresponding source module or the prebuilt module
// has "prefer: true".
func IsModulePreferred(module Module) bool {
	if module.IsReplacedByPrebuilt() {
		// A source module that has been replaced by a prebuilt counterpart.
		return false
	}
	if p := GetEmbeddedPrebuilt(module); p != nil {
		return p.UsePrebuilt()
	}
	return true
}

// IsModulePrebuilt returns true if the module implements PrebuiltInterface and
// has been initialized as a prebuilt and so returns a non-nil value from the
// PrebuiltInterface.Prebuilt() method.
func IsModulePrebuilt(module Module) bool {
	return GetEmbeddedPrebuilt(module) != nil
}

// GetEmbeddedPrebuilt returns a pointer to the embedded Prebuilt structure or
// nil if the module does not implement PrebuiltInterface or has not been
// initialized as a prebuilt module.
func GetEmbeddedPrebuilt(module Module) *Prebuilt {
	if p, ok := module.(PrebuiltInterface); ok {
		return p.Prebuilt()
	}

	return nil
}

// PrebuiltGetPreferred returns the module that is preferred for the given
// module. That is either the module itself or the prebuilt counterpart that has
// taken its place. The given module must be a direct dependency of the current
// context module, and it must be the source module if both source and prebuilt
// exist.
//
// This function is for use on dependencies after PrebuiltPostDepsMutator has
// run - any dependency that is registered before that will already reference
// the right module. This function is only safe to call after all TransitionMutators
// have run, e.g. in GenerateAndroidBuildActions.
func PrebuiltGetPreferred(ctx BaseModuleContext, module Module) Module {
	if !OtherModuleProviderOrDefault(ctx, module, CommonModuleInfoKey).ReplacedByPrebuilt {
		return module
	}
	if _, ok := OtherModuleProvider(ctx, module, PrebuiltModuleInfoProvider); ok {
		// If we're given a prebuilt then assume there's no source module around.
		return module
	}

	sourceModDepFound := false
	var prebuiltMod Module

	ctx.WalkDepsProxy(func(child, parent ModuleProxy) bool {
		if prebuiltMod != nil {
			return false
		}
		if ctx.EqualModules(parent, ctx.Module()) {
			// First level: Only recurse if the module is found as a direct dependency.
			sourceModDepFound = child == module
			return sourceModDepFound
		}
		// Second level: Follow PrebuiltDepTag to the prebuilt.
		if t := ctx.OtherModuleDependencyTag(child); t == PrebuiltDepTag {
			prebuiltMod = child
		}
		return false
	})

	if prebuiltMod == nil {
		if !sourceModDepFound {
			panic(fmt.Errorf("Failed to find source module as a direct dependency: %s", module))
		} else {
			panic(fmt.Errorf("Failed to find prebuilt for source module: %s", module))
		}
	}
	return prebuiltMod
}

func RegisterPrebuiltsPreArchMutators(ctx RegisterMutatorsContext) {
	ctx.BottomUp("prebuilt_rename", PrebuiltRenameMutator).UsesRename()
}

func RegisterPrebuiltsPreDepsMutators(ctx RegisterMutatorsContext) {
	ctx.BottomUp("prebuilt_source", PrebuiltSourceDepsMutator).UsesReverseDependencies()
	ctx.BottomUp("prebuilt_select", PrebuiltSelectModuleMutator)
}

func RegisterPrebuiltsPostDepsMutators(ctx RegisterMutatorsContext) {
	ctx.BottomUp("prebuilt_postdeps", PrebuiltPostDepsMutator).UsesReplaceDependencies()
}

// Returns the name of the source module corresponding to a prebuilt module
// For source modules, it returns its own name
type baseModuleName interface {
	BaseModuleName() string
}

// PrebuiltRenameMutator ensures that there always is a module with an
// undecorated name.
func PrebuiltRenameMutator(ctx BottomUpMutatorContext) {
	m := ctx.Module()
	if p := GetEmbeddedPrebuilt(m); p != nil {
		bmn, _ := m.(baseModuleName)
		name := bmn.BaseModuleName()
		if !ctx.OtherModuleExists(name) {
			ctx.Rename(name)
			p.properties.PrebuiltRenamedToSource = true
		}
	}
}

// PrebuiltSourceDepsMutator adds dependencies to the prebuilt module from the
// corresponding source module, if one exists for the same variant.
// Add a dependency from the prebuilt to `all_apex_contributions`
// The metadata will be used for source vs prebuilts selection
func PrebuiltSourceDepsMutator(ctx BottomUpMutatorContext) {
	m := ctx.Module()
	if p := GetEmbeddedPrebuilt(m); p != nil {
		// Add a dependency from the prebuilt to the `all_apex_contributions`
		// metadata module
		// TODO: When all branches contain this singleton module, make this strict
		// TODO: Add this dependency only for mainline prebuilts and not every prebuilt module
		if ctx.OtherModuleExists("all_apex_contributions") {
			ctx.AddDependency(m, AcDepTag, "all_apex_contributions")
		}
		if m.Enabled(ctx) && !p.properties.PrebuiltRenamedToSource {
			// If this module is a prebuilt, is enabled and has not been renamed to source then add a
			// dependency onto the source if it is present.
			bmn, _ := m.(baseModuleName)
			name := bmn.BaseModuleName()
			if ctx.OtherModuleReverseDependencyVariantExists(name) {
				ctx.AddReverseVariationDependency(nil, PrebuiltDepTag, name)
				p.properties.SourceExists = true
			}
		}
	}
}

// checkInvariantsForSourceAndPrebuilt checks if invariants are kept when replacing
// source with prebuilt. Note that the current module for the context is the source module.
func checkInvariantsForSourceAndPrebuilt(ctx BaseModuleContext, s, p Module) {
	if _, ok := s.(OverrideModule); ok {
		// skip the check when the source module is `override_X` because it's only a placeholder
		// for the actual source module. The check will be invoked for the actual module.
		return
	}
	if sourcePartition, prebuiltPartition := s.PartitionTag(ctx.DeviceConfig()), p.PartitionTag(ctx.DeviceConfig()); sourcePartition != prebuiltPartition {
		ctx.OtherModuleErrorf(p, "partition is different: %s(%s) != %s(%s)",
			sourcePartition, ctx.ModuleName(), prebuiltPartition, ctx.OtherModuleName(p))
	}
}

// PrebuiltSelectModuleMutator marks prebuilts that are used, either overriding source modules or
// because the source module doesn't exist.  It also disables installing overridden source modules.
//
// If the visited module is the metadata module `all_apex_contributions`, it sets a
// provider containing metadata about whether source or prebuilt of mainline modules should be used.
// This logic was added here to prevent the overhead of creating a new mutator.
func PrebuiltSelectModuleMutator(ctx BottomUpMutatorContext) {
	m := ctx.Module()
	if p := GetEmbeddedPrebuilt(m); p != nil {
		if p.srcsSupplier == nil && p.srcsPropertyName == "" {
			panic(fmt.Errorf("prebuilt module did not have InitPrebuiltModule called on it"))
		}
		if !p.properties.SourceExists {
			p.properties.UsePrebuilt = p.usePrebuilt(ctx, nil, m)
		}
		// Propagate the provider received from `all_apex_contributions`
		// to the source module
		ctx.VisitDirectDepsWithTag(AcDepTag, func(am Module) {
			psi, _ := OtherModuleProvider(ctx, am, PrebuiltSelectionInfoProvider)
			SetProvider(ctx, PrebuiltSelectionInfoProvider, psi)
		})

	} else if s, ok := ctx.Module().(Module); ok {
		// Use `all_apex_contributions` for source vs prebuilt selection.
		psi := PrebuiltSelectionInfoMap{}
		ctx.VisitDirectDepsWithTag(PrebuiltDepTag, func(am Module) {
			// The value of psi gets overwritten with the provider from the last visited prebuilt.
			// But all prebuilts have the same value of the provider, so this should be idempontent.
			psi, _ = OtherModuleProvider(ctx, am, PrebuiltSelectionInfoProvider)
		})
		ctx.VisitDirectDepsWithTag(PrebuiltDepTag, func(prebuiltModule Module) {
			p := GetEmbeddedPrebuilt(prebuiltModule)
			if p.usePrebuilt(ctx, s, prebuiltModule) {
				checkInvariantsForSourceAndPrebuilt(ctx, s, prebuiltModule)

				p.properties.UsePrebuilt = true
				s.ReplacedByPrebuilt()
			}
		})

		// If any module in this mainline module family has been flagged using apex_contributions, disable every other module in that family
		// Add source
		allModules := []Module{s}
		// Add each prebuilt
		ctx.VisitDirectDepsWithTag(PrebuiltDepTag, func(prebuiltModule Module) {
			allModules = append(allModules, prebuiltModule)
		})
		hideUnflaggedModules(ctx, psi, allModules)

	}

	// If this is `all_apex_contributions`, set a provider containing
	// metadata about source vs prebuilts selection
	if am, ok := m.(*allApexContributions); ok {
		am.SetPrebuiltSelectionInfoProvider(ctx)
	}
}

// If any module in this mainline module family has been flagged using apex_contributions, disable every other module in that family
func hideUnflaggedModules(ctx BottomUpMutatorContext, psi PrebuiltSelectionInfoMap, allModulesInFamily []Module) {
	var selectedModuleInFamily Module
	// query all_apex_contributions to see if any module in this family has been selected
	for _, moduleInFamily := range allModulesInFamily {
		// validate that are no duplicates
		if isSelected(psi, moduleInFamily) {
			if selectedModuleInFamily == nil {
				// Store this so we can validate that there are no duplicates
				selectedModuleInFamily = moduleInFamily
			} else {
				// There are duplicate modules from the same mainline module family
				ctx.ModuleErrorf("Found duplicate variations of the same module in apex_contributions: %s and %s. Please remove one of these.\n", selectedModuleInFamily.Name(), moduleInFamily.Name())
			}
		}
	}

	// If a module has been selected, hide all other modules
	if selectedModuleInFamily != nil {
		for _, moduleInFamily := range allModulesInFamily {
			if moduleInFamily.Name() != selectedModuleInFamily.Name() {
				moduleInFamily.HideFromMake()
				moduleInFamily.SkipInstall()
				// If this is a prebuilt module, unset properties.UsePrebuilt
				// properties.UsePrebuilt might evaluate to true via soong config var fallback mechanism
				// Set it to false explicitly so that the following mutator does not replace rdeps to this unselected prebuilt
				if p := GetEmbeddedPrebuilt(moduleInFamily); p != nil {
					p.properties.UsePrebuilt = false
				}
			}
		}
	}
	// Do a validation pass to make sure that multiple prebuilts of a specific module are not selected.
	// This might happen if the prebuilts share the same soong config var namespace.
	// This should be an error, unless one of the prebuilts has been explicitly declared in apex_contributions
	var selectedPrebuilt Module
	for _, moduleInFamily := range allModulesInFamily {
		// Skip if this module is in a different namespace
		if !moduleInFamily.ExportedToMake() {
			continue
		}
		// Skip for the top-level java_sdk_library_(_import). This has some special cases that need to be addressed first.
		// This does not run into non-determinism because PrebuiltPostDepsMutator also has the special case
		if sdkLibrary, ok := moduleInFamily.(interface{ SdkLibraryName() *string }); ok && sdkLibrary.SdkLibraryName() != nil {
			continue
		}
		if p := GetEmbeddedPrebuilt(moduleInFamily); p != nil && p.properties.UsePrebuilt {
			if selectedPrebuilt == nil {
				selectedPrebuilt = moduleInFamily
			} else {
				ctx.ModuleErrorf("Multiple prebuilt modules %v and %v have been marked as preferred for this source module. "+
					"Please add the appropriate prebuilt module to apex_contributions for this release config.", selectedPrebuilt.Name(), moduleInFamily.Name())
			}
		}
	}
}

func IsDontReplaceSourceWithPrebuiltTag(tag blueprint.DependencyTag) bool {
	if t, ok := tag.(ReplaceSourceWithPrebuilt); ok {
		return !t.ReplaceSourceWithPrebuilt()
	}
	return false
}

// PrebuiltPostDepsMutator replaces dependencies on the source module with dependencies on the
// prebuilt when both modules exist and the prebuilt should be used.  When the prebuilt should not
// be used, disable installing it.
func PrebuiltPostDepsMutator(ctx BottomUpMutatorContext) {
	m := ctx.Module()
	if p := GetEmbeddedPrebuilt(m); p != nil {
		bmn, _ := m.(baseModuleName)
		name := bmn.BaseModuleName()
		psi := PrebuiltSelectionInfoMap{}
		ctx.VisitDirectDepsWithTag(AcDepTag, func(am Module) {
			psi, _ = OtherModuleProvider(ctx, am, PrebuiltSelectionInfoProvider)
		})

		if p.properties.UsePrebuilt {
			if p.properties.SourceExists {
				ctx.ReplaceDependenciesIf(name, func(from blueprint.Module, tag blueprint.DependencyTag, to blueprint.Module) bool {
					if sdkLibrary, ok := m.(interface{ SdkLibraryName() *string }); ok && sdkLibrary.SdkLibraryName() != nil {
						// Do not replace deps to the top-level prebuilt java_sdk_library hook.
						// This hook has been special-cased in #isSelected to be _always_ active, even in next builds
						// for dexpreopt and hiddenapi processing.
						// If we do not special-case this here, rdeps referring to a java_sdk_library in next builds via libs
						// will get prebuilt stubs
						// TODO (b/308187268): Remove this after the apexes have been added to apex_contributions
						if psi.IsSelected(name) {
							return false
						}
					}

					if t, ok := tag.(ReplaceSourceWithPrebuilt); ok {
						return t.ReplaceSourceWithPrebuilt()
					}
					return true
				})
			}
		} else {
			m.HideFromMake()
			m.SkipInstall()
		}
	}
}

// A wrapper around PrebuiltSelectionInfoMap.IsSelected with special handling for java_sdk_library
// java_sdk_library is a macro that creates
// 1. top-level impl library
// 2. stub libraries (suffixed with .stubs...)
//
// java_sdk_library_import is a macro that creates
// 1. top-level "impl" library
// 2. stub libraries (suffixed with .stubs...)
//
// the impl of java_sdk_library_import is a "hook" for hiddenapi and dexpreopt processing. It does not have an impl jar, but acts as a shim
// to provide the jar deapxed from the prebuilt apex
//
// isSelected uses `all_apex_contributions` to supersede source vs prebuilts selection of the stub libraries. It does not supersede the
// selection of the top-level "impl" library so that this hook can work
//
// TODO (b/308174306) - Fix this when we need to support multiple prebuilts in main
func isSelected(psi PrebuiltSelectionInfoMap, m Module) bool {
	if sdkLibrary, ok := m.(interface{ SdkLibraryName() *string }); ok && sdkLibrary.SdkLibraryName() != nil {
		sln := proptools.String(sdkLibrary.SdkLibraryName())

		// This is the top-level library
		// Do not supersede the existing prebuilts vs source selection mechanisms
		// TODO (b/308187268): Remove this after the apexes have been added to apex_contributions
		if bmn, ok := m.(baseModuleName); ok && sln == bmn.BaseModuleName() {
			return false
		}

		// Stub library created by java_sdk_library_import
		// java_sdk_library creates several child modules (java_import + prebuilt_stubs_sources) dynamically.
		// This code block ensures that these child modules are selected if the top-level java_sdk_library_import is listed
		// in the selected apex_contributions.
		if javaImport, ok := m.(createdByJavaSdkLibraryName); ok && javaImport.CreatedByJavaSdkLibraryName() != nil {
			return psi.IsSelected(PrebuiltNameFromSource(proptools.String(javaImport.CreatedByJavaSdkLibraryName())))
		}

		// Stub library created by java_sdk_library
		return psi.IsSelected(sln)
	}
	return psi.IsSelected(m.Name())
}

// implemented by child modules of java_sdk_library_import
type createdByJavaSdkLibraryName interface {
	CreatedByJavaSdkLibraryName() *string
}

// Returns true if the prebuilt variant is disabled
// e.g. for a cc_prebuilt_library_shared, this will return
// - true for the static variant of the module
// - false for the shared variant of the module
//
// Even though this is a cc_prebuilt_library_shared, we create both the variants today
// https://source.corp.google.com/h/googleplex-android/platform/build/soong/+/e08e32b45a18a77bc3c3e751f730539b1b374f1b:cc/library.go;l=2113-2116;drc=2c4a9779cd1921d0397a12b3d3521f4c9b30d747;bpv=1;bpt=0
func (p *Prebuilt) variantIsDisabled(ctx BaseModuleContext, prebuilt Module) bool {
	return p.srcsSupplier != nil && len(p.srcsSupplier(ctx, prebuilt)) == 0
}

type apexVariationName interface {
	ApexVariationName() string
}

// usePrebuilt returns true if a prebuilt should be used instead of the source module.  The prebuilt
// will be used if it is marked "prefer" or if the source module is disabled.
func (p *Prebuilt) usePrebuilt(ctx BaseModuleContext, source Module, prebuilt Module) bool {
	isMainlinePrebuilt := func(prebuilt Module) bool {
		apex, ok := prebuilt.(apexVariationName)
		if !ok {
			return false
		}
		// Prebuilts of aosp apexes in prebuilts/runtime
		// Used in minimal art branches
		if prebuilt.base().BaseModuleName() == apex.ApexVariationName() {
			return false
		}
		return InList(apex.ApexVariationName(), ctx.Config().AllMainlineApexNames())
	}

	// Use `all_apex_contributions` for source vs prebuilt selection.
	psi := PrebuiltSelectionInfoMap{}
	var psiDepTag blueprint.DependencyTag
	if p := GetEmbeddedPrebuilt(ctx.Module()); p != nil {
		// This is a prebuilt module, visit all_apex_contributions to get the info
		psiDepTag = AcDepTag
	} else {
		// This is a source module, visit any of its prebuilts to get the info
		psiDepTag = PrebuiltDepTag
	}
	ctx.VisitDirectDepsWithTag(psiDepTag, func(am Module) {
		psi, _ = OtherModuleProvider(ctx, am, PrebuiltSelectionInfoProvider)
	})

	// If the source module is explicitly listed in the metadata module, use that
	if source != nil && isSelected(psi, source) {
		return false
	}
	// If the prebuilt module is explicitly listed in the metadata module, use that
	if isSelected(psi, prebuilt) && !p.variantIsDisabled(ctx, prebuilt) {
		return true
	}

	// If this is a mainline prebuilt, but has not been flagged, hide it.
	if isMainlinePrebuilt(prebuilt) {
		return false
	}

	// If the baseModuleName could not be found in the metadata module,
	// fall back to the existing source vs prebuilt selection.
	// TODO: Drop the fallback mechanisms

	if p.variantIsDisabled(ctx, prebuilt) {
		return false
	}

	// Skip prebuilt modules under unexported namespaces so that we won't
	// end up shadowing non-prebuilt module when prebuilt module under same
	// name happens to have a `Prefer` property set to true.
	if ctx.Config().KatiEnabled() && !prebuilt.ExportedToMake() {
		return false
	}

	// If source is not available or is disabled then always use the prebuilt.
	if source == nil || !source.Enabled(ctx) {
		return true
	}

	// TODO: use p.Properties.Name and ctx.ModuleDir to override preference
	return p.properties.Prefer.GetOrDefault(ctx, false)
}

func (p *Prebuilt) SourceExists() bool {
	return p.properties.SourceExists
}
