// Copyright 2015 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package android

import (
	"fmt"
	"path"
	"path/filepath"
	"slices"
	"strings"

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

// BuildParameters describes the set of potential parameters to build a Ninja rule.
// In general, these correspond to a Ninja concept.
type BuildParams struct {
	// A Ninja Rule that will be written to the Ninja file. This allows factoring out common code
	// among multiple modules to reduce repetition in the Ninja file of action requirements. A rule
	// can contain variables that should be provided in Args.
	Rule blueprint.Rule
	// Deps represents the depfile format. When using RuleBuilder, this defaults to GCC when depfiles
	// are used.
	Deps blueprint.Deps
	// Depfile is a writeable path that allows correct incremental builds when the inputs have not
	// been fully specified by the Ninja rule. Ninja supports a subset of the Makefile depfile syntax.
	Depfile WritablePath
	// A description of the build action.
	Description string
	// Output is an output file of the action. When using this field, references to $out in the Ninja
	// command will refer to this file.
	Output WritablePath
	// Outputs is a slice of output file of the action. When using this field, references to $out in
	// the Ninja command will refer to these files.
	Outputs WritablePaths
	// ImplicitOutput is an output file generated by the action. Note: references to `$out` in the
	// Ninja command will NOT include references to this file.
	ImplicitOutput WritablePath
	// ImplicitOutputs is a slice of output files generated by the action. Note: references to `$out`
	// in the Ninja command will NOT include references to these files.
	ImplicitOutputs WritablePaths
	// Input is an input file to the Ninja action. When using this field, references to $in in the
	// Ninja command will refer to this file.
	Input Path
	// Inputs is a slice of input files to the Ninja action. When using this field, references to $in
	// in the Ninja command will refer to these files.
	Inputs Paths
	// Implicit is an input file to the Ninja action. Note: references to `$in` in the Ninja command
	// will NOT include references to this file.
	Implicit Path
	// Implicits is a slice of input files to the Ninja action. Note: references to `$in` in the Ninja
	// command will NOT include references to these files.
	Implicits Paths
	// OrderOnly are Ninja order-only inputs to the action. When these are out of date, the output is
	// not rebuilt until they are built, but changes in order-only dependencies alone do not cause the
	// output to be rebuilt.
	OrderOnly Paths
	// Validation is an output path for a validation action. Validation outputs imply lower
	// non-blocking priority to building non-validation outputs.
	Validation Path
	// Validations is a slice of output path for a validation action. Validation outputs imply lower
	// non-blocking priority to building non-validation outputs.
	Validations Paths
	// Whether to output a default target statement which will be built by Ninja when no
	// targets are specified on Ninja's command line.
	Default bool
	// Args is a key value mapping for replacements of variables within the Rule
	Args map[string]string
}

type ModuleBuildParams BuildParams

type ModuleContext interface {
	BaseModuleContext

	// BlueprintModuleContext returns the blueprint.ModuleContext that the ModuleContext wraps.  It may only be
	// used by the golang module types that need to call into the bootstrap module types.
	BlueprintModuleContext() blueprint.ModuleContext

	// Deprecated: use ModuleContext.Build instead.
	ModuleBuild(pctx PackageContext, params ModuleBuildParams)

	// Returns a list of paths expanded from globs and modules referenced using ":module" syntax.  The property must
	// be tagged with `android:"path" to support automatic source module dependency resolution.
	//
	// Deprecated: use PathsForModuleSrc or PathsForModuleSrcExcludes instead.
	ExpandSources(srcFiles, excludes []string) Paths

	// Returns a single path expanded from globs and modules referenced using ":module" syntax.  The property must
	// be tagged with `android:"path" to support automatic source module dependency resolution.
	//
	// Deprecated: use PathForModuleSrc instead.
	ExpandSource(srcFile, prop string) Path

	ExpandOptionalSource(srcFile *string, prop string) OptionalPath

	// InstallExecutable creates a rule to copy srcPath to name in the installPath directory,
	// with the given additional dependencies.  The file is marked executable after copying.
	//
	// The installed file can be accessed by InstallFilesInfo.InstallFiles, and the PackagingSpec
	// for the installed file can be accessed by InstallFilesInfo.PackagingSpecs on this module
	// or by InstallFilesInfo.TransitivePackagingSpecs on modules that depend on this module through
	// dependency tags for which IsInstallDepNeeded returns true.
	InstallExecutable(installPath InstallPath, name string, srcPath Path, deps ...InstallPath) InstallPath

	// InstallFile creates a rule to copy srcPath to name in the installPath directory,
	// with the given additional dependencies.
	//
	// The installed file can be accessed by InstallFilesInfo.InstallFiles, and the PackagingSpec
	// for the installed file can be accessed by InstallFilesInfo.PackagingSpecs on this module
	// or by InstallFilesInfo.TransitivePackagingSpecs on modules that depend on this module through
	// dependency tags for which IsInstallDepNeeded returns true.
	InstallFile(installPath InstallPath, name string, srcPath Path, deps ...InstallPath) InstallPath

	// InstallFileWithoutCheckbuild creates a rule to copy srcPath to name in the installPath directory,
	// with the given additional dependencies, but does not add the file to the list of files to build
	// during `m checkbuild`.
	//
	// The installed file will be returned by FilesToInstall(), and the PackagingSpec for the
	// installed file will be returned by PackagingSpecs() on this module or by
	// TransitivePackagingSpecs() on modules that depend on this module through dependency tags
	// for which IsInstallDepNeeded returns true.
	InstallFileWithoutCheckbuild(installPath InstallPath, name string, srcPath Path, deps ...InstallPath) InstallPath

	// InstallFileWithExtraFilesZip creates a rule to copy srcPath to name in the installPath
	// directory, and also unzip a zip file containing extra files to install into the same
	// directory.
	//
	// The installed file can be accessed by InstallFilesInfo.InstallFiles, and the PackagingSpec
	// for the installed file can be accessed by InstallFilesInfo.PackagingSpecs on this module
	// or by InstallFilesInfo.TransitivePackagingSpecs on modules that depend on this module through
	// dependency tags for which IsInstallDepNeeded returns true.
	InstallFileWithExtraFilesZip(installPath InstallPath, name string, srcPath Path, extraZip Path, deps ...InstallPath) InstallPath

	// InstallSymlink creates a rule to create a symlink from src srcPath to name in the installPath
	// directory.
	//
	// The installed symlink can be accessed by InstallFilesInfo.InstallFiles, and the PackagingSpec
	// for the installed file can be accessed by InstallFilesInfo.PackagingSpecs on this module
	// or by InstallFilesInfo.TransitivePackagingSpecs on modules that depend on this module through
	// dependency tags for which IsInstallDepNeeded returns true.
	InstallSymlink(installPath InstallPath, name string, srcPath InstallPath) InstallPath

	// InstallAbsoluteSymlink creates a rule to create an absolute symlink from src srcPath to name
	// in the installPath directory.
	//
	// The installed symlink can be accessed by InstallFilesInfo.InstallFiles, and the PackagingSpec
	// for the installed file can be accessed by InstallFilesInfo.PackagingSpecs on this module
	// or by InstallFilesInfo.TransitivePackagingSpecs on modules that depend on this module through
	// dependency tags for which IsInstallDepNeeded returns true.
	InstallAbsoluteSymlink(installPath InstallPath, name string, absPath string) InstallPath

	// InstallTestData creates rules to install test data (e.g. data files used during a test) into
	// the installPath directory.
	//
	// The installed files can be accessed by InstallFilesInfo.InstallFiles, and the PackagingSpec
	// for the installed files can be accessed by InstallFilesInfo.PackagingSpecs on this module
	// or by InstallFilesInfo.TransitivePackagingSpecs on modules that depend on this module through
	// dependency tags for which IsInstallDepNeeded returns true.
	InstallTestData(installPath InstallPath, data []DataPath) InstallPaths

	// PackageFile creates a PackagingSpec as if InstallFile was called, but without creating
	// the rule to copy the file.  This is useful to define how a module would be packaged
	// without installing it into the global installation directories.
	//
	// The created PackagingSpec can be accessed by InstallFilesInfo.PackagingSpecs on this module
	// or by InstallFilesInfo.TransitivePackagingSpecs on modules that depend on this module through
	// dependency tags for which IsInstallDepNeeded returns true.
	PackageFile(installPath InstallPath, name string, srcPath Path) PackagingSpec

	CheckbuildFile(srcPaths ...Path)
	UncheckedModule()

	InstallInData() bool
	InstallInTestcases() bool
	InstallInSanitizerDir() bool
	InstallInRamdisk() bool
	InstallInVendorRamdisk() bool
	InstallInDebugRamdisk() bool
	InstallInRecovery() bool
	InstallInRoot() bool
	InstallInOdm() bool
	InstallInProduct() bool
	InstallInVendor() bool
	InstallInSystemDlkm() bool
	InstallInVendorDlkm() bool
	InstallInOdmDlkm() bool
	InstallForceOS() (*OsType, *ArchType)

	RequiredModuleNames(ctx ConfigurableEvaluatorContext) []string
	HostRequiredModuleNames() []string
	TargetRequiredModuleNames() []string

	ModuleSubDir() string

	Variable(pctx PackageContext, name, value string)
	Rule(pctx PackageContext, name string, params blueprint.RuleParams, argNames ...string) blueprint.Rule
	// Similar to blueprint.ModuleContext.Build, but takes Paths instead of []string,
	// and performs more verification.
	Build(pctx PackageContext, params BuildParams)
	// Phony creates a Make-style phony rule, a rule with no commands that can depend on other
	// phony rules or real files.  Phony can be called on the same name multiple times to add
	// additional dependencies.
	Phony(phony string, deps ...Path)

	// GetMissingDependencies returns the list of dependencies that were passed to AddDependencies or related methods,
	// but do not exist.
	GetMissingDependencies() []string

	// LicenseMetadataFile returns the path where the license metadata for this module will be
	// generated.
	LicenseMetadataFile() Path

	// ModuleInfoJSON returns a pointer to the ModuleInfoJSON struct that can be filled out by
	// GenerateAndroidBuildActions.  If it is called then the struct will be written out and included in
	// the module-info.json generated by Make, and Make will not generate its own data for this module.
	ModuleInfoJSON() *ModuleInfoJSON

	// Simiar to ModuleInfoJSON, ExtraModuleInfoJSON also returns a pointer to the ModuleInfoJSON struct.
	// This should only be called by a module that generates multiple AndroidMkEntries struct.
	ExtraModuleInfoJSON() *ModuleInfoJSON

	// SetOutputFiles stores the outputFiles to outputFiles property, which is used
	// to set the OutputFilesProvider later.
	SetOutputFiles(outputFiles Paths, tag string)

	GetOutputFiles() OutputFilesInfo

	// SetLicenseInstallMap stores the set of dependency module:location mappings for files in an
	// apex container for use when generation the license metadata file.
	SetLicenseInstallMap(installMap []string)

	// ComplianceMetadataInfo returns a ComplianceMetadataInfo instance for different module types to dump metadata,
	// which usually happens in GenerateAndroidBuildActions() of a module type.
	// See android.ModuleBase.complianceMetadataInfo
	ComplianceMetadataInfo() *ComplianceMetadataInfo

	// Get the information about the containers this module belongs to.
	getContainersInfo() ContainersInfo
	setContainersInfo(info ContainersInfo)

	setAconfigPaths(paths Paths)
}

type moduleContext struct {
	bp blueprint.ModuleContext
	baseModuleContext
	packagingSpecs   []PackagingSpec
	installFiles     InstallPaths
	checkbuildFiles  Paths
	checkbuildTarget Path
	uncheckedModule  bool
	module           Module
	phonies          map[string]Paths
	// outputFiles stores the output of a module by tag and is used to set
	// the OutputFilesProvider in GenerateBuildActions
	outputFiles OutputFilesInfo

	TransitiveInstallFiles depset.DepSet[InstallPath]

	// set of dependency module:location mappings used to populate the license metadata for
	// apex containers.
	licenseInstallMap []string

	// The path to the generated license metadata file for the module.
	licenseMetadataFile WritablePath

	katiInstalls katiInstalls
	katiSymlinks katiInstalls
	// katiInitRcInstalls and katiVintfInstalls track the install rules created by Soong that are
	// allowed to have duplicates across modules and variants.
	katiInitRcInstalls           katiInstalls
	katiVintfInstalls            katiInstalls
	initRcPaths                  Paths
	vintfFragmentsPaths          Paths
	installedInitRcPaths         InstallPaths
	installedVintfFragmentsPaths InstallPaths

	testData []DataPath

	// For tests
	buildParams []BuildParams
	ruleParams  map[blueprint.Rule]blueprint.RuleParams
	variables   map[string]string

	// moduleInfoJSON can be filled out by GenerateAndroidBuildActions to write a JSON file that will
	// be included in the final module-info.json produced by Make.
	moduleInfoJSON []*ModuleInfoJSON

	// containersInfo stores the information about the containers and the information of the
	// apexes the module belongs to.
	containersInfo ContainersInfo

	// Merged Aconfig files for all transitive deps.
	aconfigFilePaths Paths

	// complianceMetadataInfo is for different module types to dump metadata.
	// See android.ModuleContext interface.
	complianceMetadataInfo *ComplianceMetadataInfo
}

var _ ModuleContext = &moduleContext{}

func (m *moduleContext) ninjaError(params BuildParams, err error) (PackageContext, BuildParams) {
	return pctx, BuildParams{
		Rule:            ErrorRule,
		Description:     params.Description,
		Output:          params.Output,
		Outputs:         params.Outputs,
		ImplicitOutput:  params.ImplicitOutput,
		ImplicitOutputs: params.ImplicitOutputs,
		Args: map[string]string{
			"error": err.Error(),
		},
	}
}

func (m *moduleContext) ModuleBuild(pctx PackageContext, params ModuleBuildParams) {
	m.Build(pctx, BuildParams(params))
}

// Convert build parameters from their concrete Android types into their string representations,
// and combine the singular and plural fields of the same type (e.g. Output and Outputs).
func convertBuildParams(params BuildParams) blueprint.BuildParams {
	bparams := blueprint.BuildParams{
		Rule:            params.Rule,
		Description:     params.Description,
		Deps:            params.Deps,
		Outputs:         params.Outputs.Strings(),
		ImplicitOutputs: params.ImplicitOutputs.Strings(),
		Inputs:          params.Inputs.Strings(),
		Implicits:       params.Implicits.Strings(),
		OrderOnly:       params.OrderOnly.Strings(),
		Validations:     params.Validations.Strings(),
		Args:            params.Args,
		Default:         params.Default,
	}

	if params.Depfile != nil {
		bparams.Depfile = params.Depfile.String()
	}
	if params.Output != nil {
		bparams.Outputs = append(bparams.Outputs, params.Output.String())
	}
	if params.ImplicitOutput != nil {
		bparams.ImplicitOutputs = append(bparams.ImplicitOutputs, params.ImplicitOutput.String())
	}
	if params.Input != nil {
		bparams.Inputs = append(bparams.Inputs, params.Input.String())
	}
	if params.Implicit != nil {
		bparams.Implicits = append(bparams.Implicits, params.Implicit.String())
	}
	if params.Validation != nil {
		bparams.Validations = append(bparams.Validations, params.Validation.String())
	}

	bparams.Outputs = proptools.NinjaEscapeList(bparams.Outputs)
	bparams.ImplicitOutputs = proptools.NinjaEscapeList(bparams.ImplicitOutputs)
	bparams.Inputs = proptools.NinjaEscapeList(bparams.Inputs)
	bparams.Implicits = proptools.NinjaEscapeList(bparams.Implicits)
	bparams.OrderOnly = proptools.NinjaEscapeList(bparams.OrderOnly)
	bparams.Validations = proptools.NinjaEscapeList(bparams.Validations)
	bparams.Depfile = proptools.NinjaEscape(bparams.Depfile)

	return bparams
}

func (m *moduleContext) Variable(pctx PackageContext, name, value string) {
	if m.config.captureBuild {
		m.variables[name] = value
	}

	m.bp.Variable(pctx.PackageContext, name, value)
}

func (m *moduleContext) Rule(pctx PackageContext, name string, params blueprint.RuleParams,
	argNames ...string) blueprint.Rule {

	if m.config.UseRemoteBuild() {
		if params.Pool == nil {
			// When USE_GOMA=true or USE_RBE=true are set and the rule is not supported by goma/RBE, restrict
			// jobs to the local parallelism value
			params.Pool = localPool
		} else if params.Pool == remotePool {
			// remotePool is a fake pool used to identify rule that are supported for remoting. If the rule's
			// pool is the remotePool, replace with nil so that ninja runs it at NINJA_REMOTE_NUM_JOBS
			// parallelism.
			params.Pool = nil
		}
	}

	rule := m.bp.Rule(pctx.PackageContext, name, params, argNames...)

	if m.config.captureBuild {
		m.ruleParams[rule] = params
	}

	return rule
}

func (m *moduleContext) Build(pctx PackageContext, params BuildParams) {
	if params.Description != "" {
		params.Description = "${moduleDesc}" + params.Description + "${moduleDescSuffix}"
	}

	if missingDeps := m.GetMissingDependencies(); len(missingDeps) > 0 {
		pctx, params = m.ninjaError(params, fmt.Errorf("module %s missing dependencies: %s\n",
			m.ModuleName(), strings.Join(missingDeps, ", ")))
	}

	if m.config.captureBuild {
		m.buildParams = append(m.buildParams, params)
	}

	bparams := convertBuildParams(params)
	m.bp.Build(pctx.PackageContext, bparams)
}

func (m *moduleContext) Phony(name string, deps ...Path) {
	m.phonies[name] = append(m.phonies[name], deps...)
}

func (m *moduleContext) GetMissingDependencies() []string {
	var missingDeps []string
	missingDeps = append(missingDeps, m.Module().base().commonProperties.MissingDeps...)
	missingDeps = append(missingDeps, m.bp.GetMissingDependencies()...)
	missingDeps = FirstUniqueStrings(missingDeps)
	return missingDeps
}

func (m *moduleContext) GetDirectDepWithTag(name string, tag blueprint.DependencyTag) Module {
	deps := m.getDirectDepsInternal(name, tag)
	if len(deps) == 1 {
		return deps[0]
	} else if len(deps) >= 2 {
		panic(fmt.Errorf("Multiple dependencies having same BaseModuleName() %q found from %q",
			name, m.ModuleName()))
	} else {
		return nil
	}
}

func (m *moduleContext) GetDirectDepProxyWithTag(name string, tag blueprint.DependencyTag) *ModuleProxy {
	deps := m.getDirectDepsProxyInternal(name, tag)
	if len(deps) == 1 {
		return &deps[0]
	} else if len(deps) >= 2 {
		panic(fmt.Errorf("Multiple dependencies having same BaseModuleName() %q found from %q",
			name, m.ModuleName()))
	} else {
		return nil
	}
}

func (m *moduleContext) ModuleSubDir() string {
	return m.bp.ModuleSubDir()
}

func (m *moduleContext) InstallInData() bool {
	return m.module.InstallInData()
}

func (m *moduleContext) InstallInTestcases() bool {
	return m.module.InstallInTestcases()
}

func (m *moduleContext) InstallInSanitizerDir() bool {
	return m.module.InstallInSanitizerDir()
}

func (m *moduleContext) InstallInRamdisk() bool {
	return m.module.InstallInRamdisk()
}

func (m *moduleContext) InstallInVendorRamdisk() bool {
	return m.module.InstallInVendorRamdisk()
}

func (m *moduleContext) InstallInDebugRamdisk() bool {
	return m.module.InstallInDebugRamdisk()
}

func (m *moduleContext) InstallInRecovery() bool {
	return m.module.InstallInRecovery()
}

func (m *moduleContext) InstallInRoot() bool {
	return m.module.InstallInRoot()
}

func (m *moduleContext) InstallForceOS() (*OsType, *ArchType) {
	return m.module.InstallForceOS()
}

func (m *moduleContext) InstallInOdm() bool {
	return m.module.InstallInOdm()
}

func (m *moduleContext) InstallInProduct() bool {
	return m.module.InstallInProduct()
}

func (m *moduleContext) InstallInVendor() bool {
	return m.module.InstallInVendor()
}

func (m *moduleContext) InstallInSystemDlkm() bool {
	return m.module.InstallInSystemDlkm()
}

func (m *moduleContext) InstallInVendorDlkm() bool {
	return m.module.InstallInVendorDlkm()
}

func (m *moduleContext) InstallInOdmDlkm() bool {
	return m.module.InstallInOdmDlkm()
}

func (m *moduleContext) skipInstall() bool {
	if m.module.base().commonProperties.SkipInstall {
		return true
	}

	// We'll need a solution for choosing which of modules with the same name in different
	// namespaces to install.  For now, reuse the list of namespaces exported to Make as the
	// list of namespaces to install in a Soong-only build.
	if !m.module.base().commonProperties.NamespaceExportedToMake {
		return true
	}

	return false
}

// Tells whether this module is installed to the full install path (ex:
// out/target/product/<name>/<partition>) or not. If this returns false, the install build rule is
// not created and this module can only be installed to packaging modules like android_filesystem.
func (m *moduleContext) requiresFullInstall() bool {
	if m.skipInstall() {
		return false
	}

	if m.module.base().commonProperties.HideFromMake {
		return false
	}

	if proptools.Bool(m.module.base().commonProperties.No_full_install) {
		return false
	}

	return true
}

func (m *moduleContext) InstallFile(installPath InstallPath, name string, srcPath Path,
	deps ...InstallPath) InstallPath {
	return m.installFile(installPath, name, srcPath, deps, false, true, true, nil)
}

func (m *moduleContext) InstallFileWithoutCheckbuild(installPath InstallPath, name string, srcPath Path,
	deps ...InstallPath) InstallPath {
	return m.installFile(installPath, name, srcPath, deps, false, true, false, nil)
}

func (m *moduleContext) InstallExecutable(installPath InstallPath, name string, srcPath Path,
	deps ...InstallPath) InstallPath {
	return m.installFile(installPath, name, srcPath, deps, true, true, true, nil)
}

func (m *moduleContext) InstallFileWithExtraFilesZip(installPath InstallPath, name string, srcPath Path,
	extraZip Path, deps ...InstallPath) InstallPath {
	return m.installFile(installPath, name, srcPath, deps, false, true, true, &extraFilesZip{
		zip: extraZip,
		dir: installPath,
	})
}

func (m *moduleContext) PackageFile(installPath InstallPath, name string, srcPath Path) PackagingSpec {
	fullInstallPath := installPath.Join(m, name)
	return m.packageFile(fullInstallPath, srcPath, false)
}

func (m *moduleContext) getAconfigPaths() Paths {
	return m.aconfigFilePaths
}

func (m *moduleContext) setAconfigPaths(paths Paths) {
	m.aconfigFilePaths = paths
}

func (m *moduleContext) getOwnerAndOverrides() (string, []string) {
	owner := m.ModuleName()
	overrides := slices.Clone(m.Module().base().commonProperties.Overrides)
	if b, ok := m.Module().(OverridableModule); ok {
		if b.GetOverriddenBy() != "" {
			// overriding variant of base module
			overrides = append(overrides, m.ModuleName()) // com.android.foo
			owner = m.Module().Name()                     // com.company.android.foo
		}
	}
	return owner, overrides
}

func (m *moduleContext) packageFile(fullInstallPath InstallPath, srcPath Path, executable bool) PackagingSpec {
	licenseFiles := m.Module().EffectiveLicenseFiles()
	owner, overrides := m.getOwnerAndOverrides()
	spec := PackagingSpec{
		relPathInPackage:      Rel(m, fullInstallPath.PartitionDir(), fullInstallPath.String()),
		srcPath:               srcPath,
		symlinkTarget:         "",
		executable:            executable,
		effectiveLicenseFiles: uniquelist.Make(licenseFiles),
		partition:             fullInstallPath.partition,
		skipInstall:           m.skipInstall(),
		aconfigPaths:          uniquelist.Make(m.getAconfigPaths()),
		archType:              m.target.Arch.ArchType,
		overrides:             uniquelist.Make(overrides),
		owner:                 owner,
	}
	m.packagingSpecs = append(m.packagingSpecs, spec)
	return spec
}

func (m *moduleContext) installFile(installPath InstallPath, name string, srcPath Path, deps []InstallPath,
	executable bool, hooks bool, checkbuild bool, extraZip *extraFilesZip) InstallPath {

	fullInstallPath := installPath.Join(m, name)
	if hooks {
		m.module.base().hooks.runInstallHooks(m, srcPath, fullInstallPath, false)
	}

	if m.requiresFullInstall() {
		deps = append(deps, InstallPaths(m.TransitiveInstallFiles.ToList())...)
		if m.config.KatiEnabled() {
			deps = append(deps, m.installedInitRcPaths...)
			deps = append(deps, m.installedVintfFragmentsPaths...)
		}

		var implicitDeps, orderOnlyDeps Paths

		if m.Host() {
			// Installed host modules might be used during the build, depend directly on their
			// dependencies so their timestamp is updated whenever their dependency is updated
			implicitDeps = InstallPaths(deps).Paths()
		} else {
			orderOnlyDeps = InstallPaths(deps).Paths()
		}

		// When creating the install rule in Soong but embedding in Make, write the rule to a
		// makefile instead of directly to the ninja file so that main.mk can add the
		// dependencies from the `required` property that are hard to resolve in Soong.
		// In soong-only builds, the katiInstall will still be created for semi-legacy code paths
		// such as module-info.json or compliance, but it will not be used for actually installing
		// the file.
		m.katiInstalls = append(m.katiInstalls, katiInstall{
			from:          srcPath,
			to:            fullInstallPath,
			implicitDeps:  implicitDeps,
			orderOnlyDeps: orderOnlyDeps,
			executable:    executable,
			extraFiles:    extraZip,
		})
		if !m.Config().KatiEnabled() {
			rule := CpWithBash
			if executable {
				rule = CpExecutableWithBash
			}

			extraCmds := ""
			if extraZip != nil {
				extraCmds += fmt.Sprintf(" && ( unzip -qDD -d '%s' '%s' 2>&1 | grep -v \"zipfile is empty\"; exit $${PIPESTATUS[0]} )",
					extraZip.dir.String(), extraZip.zip.String())
				extraCmds += " || ( code=$$?; if [ $$code -ne 0 -a $$code -ne 1 ]; then exit $$code; fi )"
				implicitDeps = append(implicitDeps, extraZip.zip)
			}

			m.Build(pctx, BuildParams{
				Rule:        rule,
				Description: "install " + fullInstallPath.Base(),
				Output:      fullInstallPath,
				Input:       srcPath,
				Implicits:   implicitDeps,
				OrderOnly:   orderOnlyDeps,
				Args: map[string]string{
					"extraCmds": extraCmds,
					"cpFlags":   "-f",
				},
			})
		}

		m.installFiles = append(m.installFiles, fullInstallPath)
	}

	m.packageFile(fullInstallPath, srcPath, executable)

	if checkbuild {
		m.checkbuildFiles = append(m.checkbuildFiles, srcPath)
	}

	return fullInstallPath
}

func (m *moduleContext) InstallSymlink(installPath InstallPath, name string, srcPath InstallPath) InstallPath {
	fullInstallPath := installPath.Join(m, name)
	m.module.base().hooks.runInstallHooks(m, srcPath, fullInstallPath, true)

	relPath, err := filepath.Rel(path.Dir(fullInstallPath.String()), srcPath.String())
	if err != nil {
		panic(fmt.Sprintf("Unable to generate symlink between %q and %q: %s", fullInstallPath.Base(), srcPath.Base(), err))
	}
	if m.requiresFullInstall() {

		// When creating the symlink rule in Soong but embedding in Make, write the rule to a
		// makefile instead of directly to the ninja file so that main.mk can add the
		// dependencies from the `required` property that are hard to resolve in Soong.
		// In soong-only builds, the katiInstall will still be created for semi-legacy code paths
		// such as module-info.json or compliance, but it will not be used for actually installing
		// the file.
		m.katiSymlinks = append(m.katiSymlinks, katiInstall{
			from: srcPath,
			to:   fullInstallPath,
		})
		if !m.Config().KatiEnabled() {
			// The symlink doesn't need updating when the target is modified, but we sometimes
			// have a dependency on a symlink to a binary instead of to the binary directly, and
			// the mtime of the symlink must be updated when the binary is modified, so use a
			// normal dependency here instead of an order-only dependency.
			m.Build(pctx, BuildParams{
				Rule:        SymlinkWithBash,
				Description: "install symlink " + fullInstallPath.Base(),
				Output:      fullInstallPath,
				Input:       srcPath,
				Args: map[string]string{
					"fromPath": relPath,
				},
			})
		}

		m.installFiles = append(m.installFiles, fullInstallPath)
	}

	owner, overrides := m.getOwnerAndOverrides()
	m.packagingSpecs = append(m.packagingSpecs, PackagingSpec{
		relPathInPackage: Rel(m, fullInstallPath.PartitionDir(), fullInstallPath.String()),
		srcPath:          nil,
		symlinkTarget:    relPath,
		executable:       false,
		partition:        fullInstallPath.partition,
		skipInstall:      m.skipInstall(),
		aconfigPaths:     uniquelist.Make(m.getAconfigPaths()),
		archType:         m.target.Arch.ArchType,
		overrides:        uniquelist.Make(overrides),
		owner:            owner,
	})

	return fullInstallPath
}

// installPath/name -> absPath where absPath might be a path that is available only at runtime
// (e.g. /apex/...)
func (m *moduleContext) InstallAbsoluteSymlink(installPath InstallPath, name string, absPath string) InstallPath {
	fullInstallPath := installPath.Join(m, name)
	m.module.base().hooks.runInstallHooks(m, nil, fullInstallPath, true)

	if m.requiresFullInstall() {
		// When creating the symlink rule in Soong but embedding in Make, write the rule to a
		// makefile instead of directly to the ninja file so that main.mk can add the
		// dependencies from the `required` property that are hard to resolve in Soong.
		// In soong-only builds, the katiInstall will still be created for semi-legacy code paths
		// such as module-info.json or compliance, but it will not be used for actually installing
		// the file.
		m.katiSymlinks = append(m.katiSymlinks, katiInstall{
			absFrom: absPath,
			to:      fullInstallPath,
		})
		if !m.Config().KatiEnabled() {
			m.Build(pctx, BuildParams{
				Rule:        Symlink,
				Description: "install symlink " + fullInstallPath.Base() + " -> " + absPath,
				Output:      fullInstallPath,
				Args: map[string]string{
					"fromPath": absPath,
				},
			})
		}

		m.installFiles = append(m.installFiles, fullInstallPath)
	}

	owner, overrides := m.getOwnerAndOverrides()
	m.packagingSpecs = append(m.packagingSpecs, PackagingSpec{
		relPathInPackage: Rel(m, fullInstallPath.PartitionDir(), fullInstallPath.String()),
		srcPath:          nil,
		symlinkTarget:    absPath,
		executable:       false,
		partition:        fullInstallPath.partition,
		skipInstall:      m.skipInstall(),
		aconfigPaths:     uniquelist.Make(m.getAconfigPaths()),
		archType:         m.target.Arch.ArchType,
		overrides:        uniquelist.Make(overrides),
		owner:            owner,
	})

	return fullInstallPath
}

func (m *moduleContext) InstallTestData(installPath InstallPath, data []DataPath) InstallPaths {
	m.testData = append(m.testData, data...)

	ret := make(InstallPaths, 0, len(data))
	for _, d := range data {
		relPath := d.ToRelativeInstallPath()
		installed := m.installFile(installPath, relPath, d.SrcPath, nil, false, false, true, nil)
		ret = append(ret, installed)
	}

	return ret
}

// CheckbuildFile specifies the output files that should be built by checkbuild.
func (m *moduleContext) CheckbuildFile(srcPaths ...Path) {
	m.checkbuildFiles = append(m.checkbuildFiles, srcPaths...)
}

// UncheckedModule marks the current module has having no files that should be built by checkbuild.
func (m *moduleContext) UncheckedModule() {
	m.uncheckedModule = true
}

func (m *moduleContext) BlueprintModuleContext() blueprint.ModuleContext {
	return m.bp
}

func (m *moduleContext) LicenseMetadataFile() Path {
	return m.licenseMetadataFile
}

func (m *moduleContext) ModuleInfoJSON() *ModuleInfoJSON {
	if len(m.moduleInfoJSON) == 0 {
		moduleInfoJSON := &ModuleInfoJSON{}
		m.moduleInfoJSON = append(m.moduleInfoJSON, moduleInfoJSON)
	}
	return m.moduleInfoJSON[0]
}

func (m *moduleContext) ExtraModuleInfoJSON() *ModuleInfoJSON {
	if len(m.moduleInfoJSON) == 0 {
		panic("call ModuleInfoJSON() instead")
	}

	moduleInfoJSON := &ModuleInfoJSON{}
	m.moduleInfoJSON = append(m.moduleInfoJSON, moduleInfoJSON)
	return moduleInfoJSON
}

func (m *moduleContext) SetOutputFiles(outputFiles Paths, tag string) {
	for _, outputFile := range outputFiles {
		if outputFile == nil {
			panic("outputfiles cannot be nil")
		}
	}
	if tag == "" {
		if len(m.outputFiles.DefaultOutputFiles) > 0 {
			m.ModuleErrorf("Module %s default OutputFiles cannot be overwritten", m.ModuleName())
		}
		m.outputFiles.DefaultOutputFiles = outputFiles
	} else {
		if m.outputFiles.TaggedOutputFiles == nil {
			m.outputFiles.TaggedOutputFiles = make(map[string]Paths)
		}
		if _, exists := m.outputFiles.TaggedOutputFiles[tag]; exists {
			m.ModuleErrorf("Module %s OutputFiles at tag %s cannot be overwritten", m.ModuleName(), tag)
		} else {
			m.outputFiles.TaggedOutputFiles[tag] = outputFiles
		}
	}
}

func (m *moduleContext) GetOutputFiles() OutputFilesInfo {
	return m.outputFiles
}

func (m *moduleContext) SetLicenseInstallMap(installMap []string) {
	m.licenseInstallMap = append(m.licenseInstallMap, installMap...)
}

func (m *moduleContext) ComplianceMetadataInfo() *ComplianceMetadataInfo {
	if m.complianceMetadataInfo == nil {
		m.complianceMetadataInfo = NewComplianceMetadataInfo()
	}
	return m.complianceMetadataInfo
}

// Returns a list of paths expanded from globs and modules referenced using ":module" syntax.  The property must
// be tagged with `android:"path" to support automatic source module dependency resolution.
//
// Deprecated: use PathsForModuleSrc or PathsForModuleSrcExcludes instead.
func (m *moduleContext) ExpandSources(srcFiles, excludes []string) Paths {
	return PathsForModuleSrcExcludes(m, srcFiles, excludes)
}

// Returns a single path expanded from globs and modules referenced using ":module" syntax.  The property must
// be tagged with `android:"path" to support automatic source module dependency resolution.
//
// Deprecated: use PathForModuleSrc instead.
func (m *moduleContext) ExpandSource(srcFile, _ string) Path {
	return PathForModuleSrc(m, srcFile)
}

// Returns an optional single path expanded from globs and modules referenced using ":module" syntax if
// the srcFile is non-nil.  The property must be tagged with `android:"path" to support automatic source module
// dependency resolution.
func (m *moduleContext) ExpandOptionalSource(srcFile *string, _ string) OptionalPath {
	if srcFile != nil {
		return OptionalPathForPath(PathForModuleSrc(m, *srcFile))
	}
	return OptionalPath{}
}

func (m *moduleContext) RequiredModuleNames(ctx ConfigurableEvaluatorContext) []string {
	return m.module.RequiredModuleNames(ctx)
}

func (m *moduleContext) HostRequiredModuleNames() []string {
	return m.module.HostRequiredModuleNames()
}

func (m *moduleContext) TargetRequiredModuleNames() []string {
	return m.module.TargetRequiredModuleNames()
}

func (m *moduleContext) getContainersInfo() ContainersInfo {
	return m.containersInfo
}

func (m *moduleContext) setContainersInfo(info ContainersInfo) {
	m.containersInfo = info
}
