// Copyright 2017 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 cc

import (
	"encoding/json"
	"errors"
	"fmt"
	"path/filepath"
	"sort"
	"strings"

	"android/soong/android"
	"android/soong/cc/config"
	"android/soong/etc"
	"android/soong/snapshot"

	"github.com/google/blueprint"
)

const (
	llndkLibrariesTxt                = "llndk.libraries.txt"
	vndkCoreLibrariesTxt             = "vndkcore.libraries.txt"
	vndkSpLibrariesTxt               = "vndksp.libraries.txt"
	vndkPrivateLibrariesTxt          = "vndkprivate.libraries.txt"
	vndkProductLibrariesTxt          = "vndkproduct.libraries.txt"
	vndkUsingCoreVariantLibrariesTxt = "vndkcorevariant.libraries.txt"
)

func VndkLibrariesTxtModules(vndkVersion string) []string {
	if vndkVersion == "current" {
		return []string{
			llndkLibrariesTxt,
			vndkCoreLibrariesTxt,
			vndkSpLibrariesTxt,
			vndkPrivateLibrariesTxt,
			vndkProductLibrariesTxt,
		}
	}
	// Snapshot vndks have their own *.libraries.VER.txt files.
	// Note that snapshots don't have "vndkcorevariant.libraries.VER.txt"
	return []string{
		insertVndkVersion(llndkLibrariesTxt, vndkVersion),
		insertVndkVersion(vndkCoreLibrariesTxt, vndkVersion),
		insertVndkVersion(vndkSpLibrariesTxt, vndkVersion),
		insertVndkVersion(vndkPrivateLibrariesTxt, vndkVersion),
		insertVndkVersion(vndkProductLibrariesTxt, vndkVersion),
	}
}

type VndkProperties struct {
	Vndk struct {
		// declared as a VNDK or VNDK-SP module. The vendor variant
		// will be installed in /system instead of /vendor partition.
		//
		// `vendor_available` and `product_available` must be explicitly
		// set to either true or false together with `vndk: {enabled: true}`.
		Enabled *bool

		// declared as a VNDK-SP module, which is a subset of VNDK.
		//
		// `vndk: { enabled: true }` must set together.
		//
		// All these modules are allowed to link to VNDK-SP or LL-NDK
		// modules only. Other dependency will cause link-type errors.
		//
		// If `support_system_process` is not set or set to false,
		// the module is VNDK-core and can link to other VNDK-core,
		// VNDK-SP or LL-NDK modules only.
		Support_system_process *bool

		// declared as a VNDK-private module.
		// This module still creates the vendor and product variants refering
		// to the `vendor_available: true` and `product_available: true`
		// properties. However, it is only available to the other VNDK modules
		// but not to the non-VNDK vendor or product modules.
		Private *bool

		// Extending another module
		Extends *string
	}
}

type vndkdep struct {
	Properties VndkProperties
}

func (vndk *vndkdep) props() []interface{} {
	return []interface{}{&vndk.Properties}
}

func (vndk *vndkdep) isVndk() bool {
	return Bool(vndk.Properties.Vndk.Enabled)
}

func (vndk *vndkdep) isVndkSp() bool {
	return Bool(vndk.Properties.Vndk.Support_system_process)
}

func (vndk *vndkdep) isVndkExt() bool {
	return vndk.Properties.Vndk.Extends != nil
}

func (vndk *vndkdep) getVndkExtendsModuleName() string {
	return String(vndk.Properties.Vndk.Extends)
}

func (vndk *vndkdep) typeName() string {
	if !vndk.isVndk() {
		return "native:vendor"
	}
	if !vndk.isVndkExt() {
		if !vndk.isVndkSp() {
			return "native:vendor:vndk"
		}
		return "native:vendor:vndksp"
	}
	if !vndk.isVndkSp() {
		return "native:vendor:vndkext"
	}
	return "native:vendor:vndkspext"
}

// VNDK link type check from a module with UseVndk() == true.
func (vndk *vndkdep) vndkCheckLinkType(ctx android.BaseModuleContext, to *Module, tag blueprint.DependencyTag) {
	if to.linker == nil {
		return
	}
	if !vndk.isVndk() {
		// Non-VNDK modules those installed to /vendor, /system/vendor,
		// /product or /system/product cannot depend on VNDK-private modules
		// that include VNDK-core-private, VNDK-SP-private and LLNDK-private.
		if to.IsVndkPrivate() {
			ctx.ModuleErrorf("non-VNDK module should not link to %q which has `private: true`", to.Name())
		}
	}
	if lib, ok := to.linker.(*libraryDecorator); !ok || !lib.shared() {
		// Check only shared libraries.
		// Other (static) libraries are allowed to link.
		return
	}

	if to.IsLlndk() {
		// LL-NDK libraries are allowed to link
		return
	}

	if !to.UseVndk() {
		ctx.ModuleErrorf("(%s) should not link to %q which is not a vendor-available library",
			vndk.typeName(), to.Name())
		return
	}
	if tag == vndkExtDepTag {
		// Ensure `extends: "name"` property refers a vndk module that has vendor_available
		// and has identical vndk properties.
		if to.vndkdep == nil || !to.vndkdep.isVndk() {
			ctx.ModuleErrorf("`extends` refers a non-vndk module %q", to.Name())
			return
		}
		if vndk.isVndkSp() != to.vndkdep.isVndkSp() {
			ctx.ModuleErrorf(
				"`extends` refers a module %q with mismatched support_system_process",
				to.Name())
			return
		}
		if to.IsVndkPrivate() {
			ctx.ModuleErrorf(
				"`extends` refers module %q which has `private: true`",
				to.Name())
			return
		}
	}
	if to.vndkdep == nil {
		return
	}

	// Check the dependencies of VNDK shared libraries.
	if err := vndkIsVndkDepAllowed(vndk, to.vndkdep); err != nil {
		ctx.ModuleErrorf("(%s) should not link to %q (%s): %v",
			vndk.typeName(), to.Name(), to.vndkdep.typeName(), err)
		return
	}
}

func vndkIsVndkDepAllowed(from *vndkdep, to *vndkdep) error {
	// Check the dependencies of VNDK, VNDK-Ext, VNDK-SP, VNDK-SP-Ext and vendor modules.
	if from.isVndkExt() {
		if from.isVndkSp() {
			if to.isVndk() && !to.isVndkSp() {
				return errors.New("VNDK-SP extensions must not depend on VNDK or VNDK extensions")
			}
			return nil
		}
		// VNDK-Ext may depend on VNDK, VNDK-Ext, VNDK-SP, VNDK-SP-Ext, or vendor libs.
		return nil
	}
	if from.isVndk() {
		if to.isVndkExt() {
			return errors.New("VNDK-core and VNDK-SP must not depend on VNDK extensions")
		}
		if from.isVndkSp() {
			if !to.isVndkSp() {
				return errors.New("VNDK-SP must only depend on VNDK-SP")
			}
			return nil
		}
		if !to.isVndk() {
			return errors.New("VNDK-core must only depend on VNDK-core or VNDK-SP")
		}
		return nil
	}
	// Vendor modules may depend on VNDK, VNDK-Ext, VNDK-SP, VNDK-SP-Ext, or vendor libs.
	return nil
}

type moduleListerFunc func(ctx android.SingletonContext) (moduleNames, fileNames []string)

var (
	llndkLibraries                = vndkModuleLister(func(m *Module) bool { return m.VendorProperties.IsLLNDK && !m.Header() })
	vndkSPLibraries               = vndkModuleLister(func(m *Module) bool { return m.VendorProperties.IsVNDKSP })
	vndkCoreLibraries             = vndkModuleLister(func(m *Module) bool { return m.VendorProperties.IsVNDKCore })
	vndkPrivateLibraries          = vndkModuleLister(func(m *Module) bool { return m.VendorProperties.IsVNDKPrivate })
	vndkProductLibraries          = vndkModuleLister(func(m *Module) bool { return m.VendorProperties.IsVNDKProduct })
	vndkUsingCoreVariantLibraries = vndkModuleLister(func(m *Module) bool { return m.VendorProperties.IsVNDKUsingCoreVariant })
)

// vndkModuleLister takes a predicate that operates on a Module and returns a moduleListerFunc
// that produces a list of module names and output file names for which the predicate returns true.
func vndkModuleLister(predicate func(*Module) bool) moduleListerFunc {
	return func(ctx android.SingletonContext) (moduleNames, fileNames []string) {
		ctx.VisitAllModules(func(m android.Module) {
			if c, ok := m.(*Module); ok && predicate(c) {
				filename, err := getVndkFileName(c)
				if err != nil {
					ctx.ModuleErrorf(m, "%s", err)
				}
				moduleNames = append(moduleNames, ctx.ModuleName(m))
				fileNames = append(fileNames, filename)
			}
		})
		moduleNames = android.SortedUniqueStrings(moduleNames)
		fileNames = android.SortedUniqueStrings(fileNames)
		return
	}
}

// vndkModuleListRemover takes a moduleListerFunc and a prefix and returns a moduleListerFunc
// that returns the same lists as the input moduleListerFunc, but with  modules with the
// given prefix removed.
func vndkModuleListRemover(lister moduleListerFunc, prefix string) moduleListerFunc {
	return func(ctx android.SingletonContext) (moduleNames, fileNames []string) {
		moduleNames, fileNames = lister(ctx)
		filter := func(in []string) []string {
			out := make([]string, 0, len(in))
			for _, lib := range in {
				if strings.HasPrefix(lib, prefix) {
					continue
				}
				out = append(out, lib)
			}
			return out
		}
		return filter(moduleNames), filter(fileNames)
	}
}

var vndkMustUseVendorVariantListKey = android.NewOnceKey("vndkMustUseVendorVariantListKey")

func vndkMustUseVendorVariantList(cfg android.Config) []string {
	return cfg.Once(vndkMustUseVendorVariantListKey, func() interface{} {
		return config.VndkMustUseVendorVariantList
	}).([]string)
}

// test may call this to override global configuration(config.VndkMustUseVendorVariantList)
// when it is called, it must be before the first call to vndkMustUseVendorVariantList()
func setVndkMustUseVendorVariantListForTest(config android.Config, mustUseVendorVariantList []string) {
	config.Once(vndkMustUseVendorVariantListKey, func() interface{} {
		return mustUseVendorVariantList
	})
}

func processVndkLibrary(mctx android.BottomUpMutatorContext, m *Module) {
	if m.InProduct() {
		// We may skip the steps for the product variants because they
		// are already covered by the vendor variants.
		return
	}

	name := m.BaseModuleName()

	if lib := m.library; lib != nil && lib.hasStubsVariants() && name != "libz" {
		// b/155456180 libz is the ONLY exception here. We don't want to make
		// libz an LLNDK library because we in general can't guarantee that
		// libz will behave consistently especially about the compression.
		// i.e. the compressed output might be different across releases.
		// As the library is an external one, it's risky to keep the compatibility
		// promise if it becomes an LLNDK.
		mctx.PropertyErrorf("vndk.enabled", "This library provides stubs. Shouldn't be VNDK. Consider making it as LLNDK")
	}

	if inList(name, vndkMustUseVendorVariantList(mctx.Config())) {
		m.Properties.MustUseVendorVariant = true
	}
	if mctx.DeviceConfig().VndkUseCoreVariant() && !m.Properties.MustUseVendorVariant {
		m.VendorProperties.IsVNDKUsingCoreVariant = true
	}

	if m.vndkdep.isVndkSp() {
		m.VendorProperties.IsVNDKSP = true
	} else {
		m.VendorProperties.IsVNDKCore = true
	}
	if m.IsVndkPrivate() {
		m.VendorProperties.IsVNDKPrivate = true
	}
	if Bool(m.VendorProperties.Product_available) {
		m.VendorProperties.IsVNDKProduct = true
	}
}

// Check for modules that mustn't be VNDK
func shouldSkipVndkMutator(m *Module) bool {
	if !m.Enabled() {
		return true
	}
	if !m.Device() {
		// Skip non-device modules
		return true
	}
	if m.Target().NativeBridge == android.NativeBridgeEnabled {
		// Skip native_bridge modules
		return true
	}
	return false
}

func IsForVndkApex(mctx android.BottomUpMutatorContext, m *Module) bool {
	if shouldSkipVndkMutator(m) {
		return false
	}

	// prebuilt vndk modules should match with device
	// TODO(b/142675459): Use enabled: to select target device in vndk_prebuilt_shared
	// When b/142675459 is landed, remove following check
	if p, ok := m.linker.(*vndkPrebuiltLibraryDecorator); ok && !p.MatchesWithDevice(mctx.DeviceConfig()) {
		return false
	}

	if lib, ok := m.linker.(libraryInterface); ok {
		// VNDK APEX for VNDK-Lite devices will have VNDK-SP libraries from core variants
		if mctx.DeviceConfig().VndkVersion() == "" {
			// b/73296261: filter out libz.so because it is considered as LLNDK for VNDK-lite devices
			if mctx.ModuleName() == "libz" {
				return false
			}
			return m.ImageVariation().Variation == android.CoreVariation && lib.shared() && m.IsVndkSp() && !m.IsVndkExt()
		}

		useCoreVariant := m.VndkVersion() == mctx.DeviceConfig().PlatformVndkVersion() &&
			mctx.DeviceConfig().VndkUseCoreVariant() && !m.MustUseVendorVariant()
		return lib.shared() && m.InVendor() && m.IsVndk() && !m.IsVndkExt() && !useCoreVariant
	}
	return false
}

// gather list of vndk-core, vndk-sp, and ll-ndk libs
func VndkMutator(mctx android.BottomUpMutatorContext) {
	m, ok := mctx.Module().(*Module)
	if !ok {
		return
	}

	if shouldSkipVndkMutator(m) {
		return
	}

	lib, isLib := m.linker.(*libraryDecorator)
	prebuiltLib, isPrebuiltLib := m.linker.(*prebuiltLibraryLinker)

	if m.UseVndk() && isLib && lib.hasLLNDKStubs() {
		m.VendorProperties.IsLLNDK = true
		m.VendorProperties.IsVNDKPrivate = Bool(lib.Properties.Llndk.Private)
	}
	if m.UseVndk() && isPrebuiltLib && prebuiltLib.hasLLNDKStubs() {
		m.VendorProperties.IsLLNDK = true
		m.VendorProperties.IsVNDKPrivate = Bool(prebuiltLib.Properties.Llndk.Private)
	}

	if (isLib && lib.buildShared()) || (isPrebuiltLib && prebuiltLib.buildShared()) {
		if m.vndkdep != nil && m.vndkdep.isVndk() && !m.vndkdep.isVndkExt() {
			processVndkLibrary(mctx, m)
			return
		}
	}
}

func init() {
	RegisterVndkLibraryTxtTypes(android.InitRegistrationContext)
	android.RegisterSingletonType("vndk-snapshot", VndkSnapshotSingleton)
}

func RegisterVndkLibraryTxtTypes(ctx android.RegistrationContext) {
	ctx.RegisterSingletonModuleType("llndk_libraries_txt", llndkLibrariesTxtFactory)
	ctx.RegisterSingletonModuleType("vndksp_libraries_txt", vndkSPLibrariesTxtFactory)
	ctx.RegisterSingletonModuleType("vndkcore_libraries_txt", vndkCoreLibrariesTxtFactory)
	ctx.RegisterSingletonModuleType("vndkprivate_libraries_txt", vndkPrivateLibrariesTxtFactory)
	ctx.RegisterSingletonModuleType("vndkproduct_libraries_txt", vndkProductLibrariesTxtFactory)
	ctx.RegisterSingletonModuleType("vndkcorevariant_libraries_txt", vndkUsingCoreVariantLibrariesTxtFactory)
}

type vndkLibrariesTxt struct {
	android.SingletonModuleBase

	lister               moduleListerFunc
	makeVarName          string
	filterOutFromMakeVar string

	properties VndkLibrariesTxtProperties

	outputFile  android.OutputPath
	moduleNames []string
	fileNames   []string
}

type VndkLibrariesTxtProperties struct {
	Insert_vndk_version *bool
}

var _ etc.PrebuiltEtcModule = &vndkLibrariesTxt{}
var _ android.OutputFileProducer = &vndkLibrariesTxt{}

// llndk_libraries_txt is a singleton module whose content is a list of LLNDK libraries
// generated by Soong but can be referenced by other modules.
// For example, apex_vndk can depend on these files as prebuilt.
// Make uses LLNDK_LIBRARIES to determine which libraries to install.
// HWASAN is only part of the LL-NDK in builds in which libc depends on HWASAN.
// Therefore, by removing the library here, we cause it to only be installed if libc
// depends on it.
func llndkLibrariesTxtFactory() android.SingletonModule {
	return newVndkLibrariesWithMakeVarFilter(llndkLibraries, "LLNDK_LIBRARIES", "libclang_rt.hwasan")
}

// vndksp_libraries_txt is a singleton module whose content is a list of VNDKSP libraries
// generated by Soong but can be referenced by other modules.
// For example, apex_vndk can depend on these files as prebuilt.
func vndkSPLibrariesTxtFactory() android.SingletonModule {
	return newVndkLibrariesTxt(vndkSPLibraries, "VNDK_SAMEPROCESS_LIBRARIES")
}

// vndkcore_libraries_txt is a singleton module whose content is a list of VNDK core libraries
// generated by Soong but can be referenced by other modules.
// For example, apex_vndk can depend on these files as prebuilt.
func vndkCoreLibrariesTxtFactory() android.SingletonModule {
	return newVndkLibrariesTxt(vndkCoreLibraries, "VNDK_CORE_LIBRARIES")
}

// vndkprivate_libraries_txt is a singleton module whose content is a list of VNDK private libraries
// generated by Soong but can be referenced by other modules.
// For example, apex_vndk can depend on these files as prebuilt.
func vndkPrivateLibrariesTxtFactory() android.SingletonModule {
	return newVndkLibrariesTxt(vndkPrivateLibraries, "VNDK_PRIVATE_LIBRARIES")
}

// vndkproduct_libraries_txt is a singleton module whose content is a list of VNDK product libraries
// generated by Soong but can be referenced by other modules.
// For example, apex_vndk can depend on these files as prebuilt.
func vndkProductLibrariesTxtFactory() android.SingletonModule {
	return newVndkLibrariesTxt(vndkProductLibraries, "VNDK_PRODUCT_LIBRARIES")
}

// vndkcorevariant_libraries_txt is a singleton module whose content is a list of VNDK libraries
// that are using the core variant, generated by Soong but can be referenced by other modules.
// For example, apex_vndk can depend on these files as prebuilt.
func vndkUsingCoreVariantLibrariesTxtFactory() android.SingletonModule {
	return newVndkLibrariesTxt(vndkUsingCoreVariantLibraries, "VNDK_USING_CORE_VARIANT_LIBRARIES")
}

func newVndkLibrariesWithMakeVarFilter(lister moduleListerFunc, makeVarName string, filter string) android.SingletonModule {
	m := &vndkLibrariesTxt{
		lister:               lister,
		makeVarName:          makeVarName,
		filterOutFromMakeVar: filter,
	}
	m.AddProperties(&m.properties)
	android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
	return m
}

func newVndkLibrariesTxt(lister moduleListerFunc, makeVarName string) android.SingletonModule {
	return newVndkLibrariesWithMakeVarFilter(lister, makeVarName, "")
}

func insertVndkVersion(filename string, vndkVersion string) string {
	if index := strings.LastIndex(filename, "."); index != -1 {
		return filename[:index] + "." + vndkVersion + filename[index:]
	}
	return filename
}

func (txt *vndkLibrariesTxt) GenerateAndroidBuildActions(ctx android.ModuleContext) {
	var filename string
	if BoolDefault(txt.properties.Insert_vndk_version, true) {
		filename = insertVndkVersion(txt.Name(), ctx.DeviceConfig().PlatformVndkVersion())
	} else {
		filename = txt.Name()
	}

	txt.outputFile = android.PathForModuleOut(ctx, filename).OutputPath

	installPath := android.PathForModuleInstall(ctx, "etc")
	ctx.InstallFile(installPath, filename, txt.outputFile)
}

func (txt *vndkLibrariesTxt) GenerateSingletonBuildActions(ctx android.SingletonContext) {
	txt.moduleNames, txt.fileNames = txt.lister(ctx)
	android.WriteFileRule(ctx, txt.outputFile, strings.Join(txt.fileNames, "\n"))
}

func (txt *vndkLibrariesTxt) AndroidMkEntries() []android.AndroidMkEntries {
	return []android.AndroidMkEntries{android.AndroidMkEntries{
		Class:      "ETC",
		OutputFile: android.OptionalPathForPath(txt.outputFile),
		ExtraEntries: []android.AndroidMkExtraEntriesFunc{
			func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
				entries.SetString("LOCAL_MODULE_STEM", txt.outputFile.Base())
			},
		},
	}}
}

func (txt *vndkLibrariesTxt) MakeVars(ctx android.MakeVarsContext) {
	filter := func(modules []string, prefix string) []string {
		if prefix == "" {
			return modules
		}
		var result []string
		for _, module := range modules {
			if strings.HasPrefix(module, prefix) {
				continue
			} else {
				result = append(result, module)
			}
		}
		return result
	}
	ctx.Strict(txt.makeVarName, strings.Join(filter(txt.moduleNames, txt.filterOutFromMakeVar), " "))
}

// PrebuiltEtcModule interface
func (txt *vndkLibrariesTxt) OutputFile() android.OutputPath {
	return txt.outputFile
}

// PrebuiltEtcModule interface
func (txt *vndkLibrariesTxt) BaseDir() string {
	return "etc"
}

// PrebuiltEtcModule interface
func (txt *vndkLibrariesTxt) SubDir() string {
	return ""
}

func (txt *vndkLibrariesTxt) OutputFiles(tag string) (android.Paths, error) {
	return android.Paths{txt.outputFile}, nil
}

func VndkSnapshotSingleton() android.Singleton {
	return &vndkSnapshotSingleton{}
}

type vndkSnapshotSingleton struct {
	vndkLibrariesFile   android.OutputPath
	vndkSnapshotZipFile android.OptionalPath
}

func isVndkSnapshotAware(config android.DeviceConfig, m LinkableInterface,
	apexInfo android.ApexInfo) (vndkType string, isVndkSnapshotLib bool) {

	if m.Target().NativeBridge == android.NativeBridgeEnabled {
		return "", false
	}
	// !inVendor: There's product/vendor variants for VNDK libs. We only care about vendor variants.
	// !installable: Snapshot only cares about "installable" modules.
	// !m.IsLlndk: llndk stubs are required for building against snapshots.
	// IsSnapshotPrebuilt: Snapshotting a snapshot doesn't make sense.
	// !outputFile.Valid: Snapshot requires valid output file.
	if !m.InVendor() || (!installable(m, apexInfo) && !m.IsLlndk()) || m.IsSnapshotPrebuilt() || !m.OutputFile().Valid() {
		return "", false
	}
	if !m.IsSnapshotLibrary() || !m.Shared() {
		return "", false
	}
	if m.VndkVersion() == config.PlatformVndkVersion() {
		if m.IsVndk() && !m.IsVndkExt() {
			if m.IsVndkSp() {
				return "vndk-sp", true
			} else {
				return "vndk-core", true
			}
		} else if m.HasLlndkStubs() && m.StubsVersion() == "" {
			// Use default version for the snapshot.
			return "llndk-stub", true
		}
	}

	return "", false
}

func (c *vndkSnapshotSingleton) GenerateBuildActions(ctx android.SingletonContext) {
	// build these files even if PlatformVndkVersion or BoardVndkVersion is not set
	c.buildVndkLibrariesTxtFiles(ctx)

	// BOARD_VNDK_VERSION must be set to 'current' in order to generate a VNDK snapshot.
	if ctx.DeviceConfig().VndkVersion() != "current" {
		return
	}

	if ctx.DeviceConfig().PlatformVndkVersion() == "" {
		return
	}

	var snapshotOutputs android.Paths

	/*
		VNDK snapshot zipped artifacts directory structure:
		{SNAPSHOT_ARCH}/
			arch-{TARGET_ARCH}-{TARGET_ARCH_VARIANT}/
				shared/
					vndk-core/
						(VNDK-core libraries, e.g. libbinder.so)
					vndk-sp/
						(VNDK-SP libraries, e.g. libc++.so)
					llndk-stub/
						(LLNDK stub libraries)
			arch-{TARGET_2ND_ARCH}-{TARGET_2ND_ARCH_VARIANT}/
				shared/
					vndk-core/
						(VNDK-core libraries, e.g. libbinder.so)
					vndk-sp/
						(VNDK-SP libraries, e.g. libc++.so)
					llndk-stub/
						(LLNDK stub libraries)
			binder32/
				(This directory is newly introduced in v28 (Android P) to hold
				prebuilts built for 32-bit binder interface.)
				arch-{TARGET_ARCH}-{TARGE_ARCH_VARIANT}/
					...
			configs/
				(various *.txt configuration files)
			include/
				(header files of same directory structure with source tree)
			NOTICE_FILES/
				(notice files of libraries, e.g. libcutils.so.txt)
	*/

	snapshotDir := "vndk-snapshot"
	snapshotArchDir := filepath.Join(snapshotDir, ctx.DeviceConfig().DeviceArch())

	configsDir := filepath.Join(snapshotArchDir, "configs")
	noticeDir := filepath.Join(snapshotArchDir, "NOTICE_FILES")
	includeDir := filepath.Join(snapshotArchDir, "include")

	// set of notice files copied.
	noticeBuilt := make(map[string]bool)

	// paths of VNDK modules for GPL license checking
	modulePaths := make(map[string]string)

	// actual module names of .so files
	// e.g. moduleNames["libprotobuf-cpp-full-3.9.1.so"] = "libprotobuf-cpp-full"
	moduleNames := make(map[string]string)

	var headers android.Paths

	// installVndkSnapshotLib copies built .so file from the module.
	// Also, if the build artifacts is on, write a json file which contains all exported flags
	// with FlagExporterInfo.
	installVndkSnapshotLib := func(m *Module, vndkType string) (android.Paths, bool) {
		var ret android.Paths

		targetArch := "arch-" + m.Target().Arch.ArchType.String()
		if m.Target().Arch.ArchVariant != "" {
			targetArch += "-" + m.Target().Arch.ArchVariant
		}

		libPath := m.outputFile.Path()
		snapshotLibOut := filepath.Join(snapshotArchDir, targetArch, "shared", vndkType, libPath.Base())
		ret = append(ret, snapshot.CopyFileRule(pctx, ctx, libPath, snapshotLibOut))

		if ctx.Config().VndkSnapshotBuildArtifacts() {
			prop := struct {
				ExportedDirs        []string `json:",omitempty"`
				ExportedSystemDirs  []string `json:",omitempty"`
				ExportedFlags       []string `json:",omitempty"`
				RelativeInstallPath string   `json:",omitempty"`
			}{}
			exportedInfo := ctx.ModuleProvider(m, FlagExporterInfoProvider).(FlagExporterInfo)
			prop.ExportedFlags = exportedInfo.Flags
			prop.ExportedDirs = exportedInfo.IncludeDirs.Strings()
			prop.ExportedSystemDirs = exportedInfo.SystemIncludeDirs.Strings()
			prop.RelativeInstallPath = m.RelativeInstallPath()

			propOut := snapshotLibOut + ".json"

			j, err := json.Marshal(prop)
			if err != nil {
				ctx.Errorf("json marshal to %q failed: %#v", propOut, err)
				return nil, false
			}
			ret = append(ret, snapshot.WriteStringToFileRule(ctx, string(j), propOut))
		}
		return ret, true
	}

	ctx.VisitAllModules(func(module android.Module) {
		m, ok := module.(*Module)
		if !ok || !m.Enabled() {
			return
		}

		apexInfo := ctx.ModuleProvider(module, android.ApexInfoProvider).(android.ApexInfo)

		vndkType, ok := isVndkSnapshotAware(ctx.DeviceConfig(), m, apexInfo)
		if !ok {
			return
		}

		// For all snapshot candidates, the followings are captured.
		//   - .so files
		//   - notice files
		//
		// The followings are also captured if VNDK_SNAPSHOT_BUILD_ARTIFACTS.
		//   - .json files containing exported flags
		//   - exported headers from collectHeadersForSnapshot()
		//
		// Headers are deduplicated after visiting all modules.

		// install .so files for appropriate modules.
		// Also install .json files if VNDK_SNAPSHOT_BUILD_ARTIFACTS
		libs, ok := installVndkSnapshotLib(m, vndkType)
		if !ok {
			return
		}
		snapshotOutputs = append(snapshotOutputs, libs...)

		// These are for generating module_names.txt and module_paths.txt
		stem := m.outputFile.Path().Base()
		moduleNames[stem] = ctx.ModuleName(m)
		modulePaths[stem] = ctx.ModuleDir(m)

		if len(m.NoticeFiles()) > 0 {
			noticeName := stem + ".txt"
			// skip already copied notice file
			if _, ok := noticeBuilt[noticeName]; !ok {
				noticeBuilt[noticeName] = true
				snapshotOutputs = append(snapshotOutputs, combineNoticesRule(
					ctx, m.NoticeFiles(), filepath.Join(noticeDir, noticeName)))
			}
		}

		if ctx.Config().VndkSnapshotBuildArtifacts() {
			headers = append(headers, m.SnapshotHeaders()...)
		}
	})

	// install all headers after removing duplicates
	for _, header := range android.FirstUniquePaths(headers) {
		snapshotOutputs = append(snapshotOutputs, snapshot.CopyFileRule(
			pctx, ctx, header, filepath.Join(includeDir, header.String())))
	}

	// install *.libraries.txt except vndkcorevariant.libraries.txt
	ctx.VisitAllModules(func(module android.Module) {
		m, ok := module.(*vndkLibrariesTxt)
		if !ok || !m.Enabled() || m.Name() == vndkUsingCoreVariantLibrariesTxt {
			return
		}
		snapshotOutputs = append(snapshotOutputs, snapshot.CopyFileRule(
			pctx, ctx, m.OutputFile(), filepath.Join(configsDir, m.Name())))
	})

	/*
		module_paths.txt contains paths on which VNDK modules are defined.
		e.g.,
			libbase.so system/libbase
			libc.so bionic/libc
			...
	*/
	snapshotOutputs = append(snapshotOutputs, installMapListFileRule(ctx, modulePaths, filepath.Join(configsDir, "module_paths.txt")))

	/*
		module_names.txt contains names as which VNDK modules are defined,
		because output filename and module name can be different with stem and suffix properties.

		e.g.,
			libcutils.so libcutils
			libprotobuf-cpp-full-3.9.2.so libprotobuf-cpp-full
			...
	*/
	snapshotOutputs = append(snapshotOutputs, installMapListFileRule(ctx, moduleNames, filepath.Join(configsDir, "module_names.txt")))

	// All artifacts are ready. Sort them to normalize ninja and then zip.
	sort.Slice(snapshotOutputs, func(i, j int) bool {
		return snapshotOutputs[i].String() < snapshotOutputs[j].String()
	})

	zipPath := android.PathForOutput(ctx, snapshotDir, "android-vndk-"+ctx.DeviceConfig().DeviceArch()+".zip")
	zipRule := android.NewRuleBuilder(pctx, ctx)

	// filenames in rspfile from FlagWithRspFileInputList might be single-quoted. Remove it with tr
	snapshotOutputList := android.PathForOutput(ctx, snapshotDir, "android-vndk-"+ctx.DeviceConfig().DeviceArch()+"_list")
	rspFile := snapshotOutputList.ReplaceExtension(ctx, "rsp")
	zipRule.Command().
		Text("tr").
		FlagWithArg("-d ", "\\'").
		FlagWithRspFileInputList("< ", rspFile, snapshotOutputs).
		FlagWithOutput("> ", snapshotOutputList)

	zipRule.Temporary(snapshotOutputList)

	zipRule.Command().
		BuiltTool("soong_zip").
		FlagWithOutput("-o ", zipPath).
		FlagWithArg("-C ", android.PathForOutput(ctx, snapshotDir).String()).
		FlagWithInput("-l ", snapshotOutputList)

	zipRule.Build(zipPath.String(), "vndk snapshot "+zipPath.String())
	zipRule.DeleteTemporaryFiles()
	c.vndkSnapshotZipFile = android.OptionalPathForPath(zipPath)
}

func getVndkFileName(m *Module) (string, error) {
	if library, ok := m.linker.(*libraryDecorator); ok {
		return library.getLibNameHelper(m.BaseModuleName(), true, false) + ".so", nil
	}
	if prebuilt, ok := m.linker.(*prebuiltLibraryLinker); ok {
		return prebuilt.libraryDecorator.getLibNameHelper(m.BaseModuleName(), true, false) + ".so", nil
	}
	return "", fmt.Errorf("VNDK library should have libraryDecorator or prebuiltLibraryLinker as linker: %T", m.linker)
}

func (c *vndkSnapshotSingleton) buildVndkLibrariesTxtFiles(ctx android.SingletonContext) {
	// Build list of vndk libs as merged & tagged & filter-out(libclang_rt):
	// Since each target have different set of libclang_rt.* files,
	// keep the common set of files in vndk.libraries.txt
	_, llndk := vndkModuleListRemover(llndkLibraries, "libclang_rt.")(ctx)
	_, vndkcore := vndkModuleListRemover(vndkCoreLibraries, "libclang_rt.")(ctx)
	_, vndksp := vndkSPLibraries(ctx)
	_, vndkprivate := vndkPrivateLibraries(ctx)
	_, vndkproduct := vndkModuleListRemover(vndkProductLibraries, "libclang_rt.")(ctx)
	var merged []string
	merged = append(merged, addPrefix(llndk, "LLNDK: ")...)
	merged = append(merged, addPrefix(vndksp, "VNDK-SP: ")...)
	merged = append(merged, addPrefix(vndkcore, "VNDK-core: ")...)
	merged = append(merged, addPrefix(vndkprivate, "VNDK-private: ")...)
	merged = append(merged, addPrefix(vndkproduct, "VNDK-product: ")...)
	c.vndkLibrariesFile = android.PathForOutput(ctx, "vndk", "vndk.libraries.txt")
	android.WriteFileRule(ctx, c.vndkLibrariesFile, strings.Join(merged, "\n"))
}

func (c *vndkSnapshotSingleton) MakeVars(ctx android.MakeVarsContext) {
	// Make uses LLNDK_MOVED_TO_APEX_LIBRARIES to avoid installing libraries on /system if
	// they been moved to an apex.
	movedToApexLlndkLibraries := make(map[string]bool)
	ctx.VisitAllModules(func(module android.Module) {
		if library := moduleLibraryInterface(module); library != nil && library.hasLLNDKStubs() {
			// Skip bionic libs, they are handled in different manner
			name := library.implementationModuleName(module.(*Module).BaseModuleName())
			if module.(android.ApexModule).DirectlyInAnyApex() && !isBionic(name) {
				movedToApexLlndkLibraries[name] = true
			}
		}
	})

	ctx.Strict("LLNDK_MOVED_TO_APEX_LIBRARIES",
		strings.Join(android.SortedStringKeys(movedToApexLlndkLibraries), " "))

	ctx.Strict("VNDK_LIBRARIES_FILE", c.vndkLibrariesFile.String())
	ctx.Strict("SOONG_VNDK_SNAPSHOT_ZIP", c.vndkSnapshotZipFile.String())
}
