// Copyright 2020 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 dexpreopt

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

	"android/soong/android"
)

// These libs are added as <uses-library> dependencies for apps if the targetSdkVersion in the
// app manifest is less than the specified version. This is needed because these libraries haven't
// existed prior to certain SDK version, but classes in them were in bootclasspath jars, etc.
// Some of the compatibility libraries are optional (their <uses-library> tag has "required=false"),
// so that if this library is missing this in not a build or run-time error.
var OrgApacheHttpLegacy = "org.apache.http.legacy"
var AndroidTestBase = "android.test.base"
var AndroidTestMock = "android.test.mock"
var AndroidHidlBase = "android.hidl.base-V1.0-java"
var AndroidHidlManager = "android.hidl.manager-V1.0-java"

var OptionalCompatUsesLibs28 = []string{
	OrgApacheHttpLegacy,
}
var OptionalCompatUsesLibs30 = []string{
	AndroidTestBase,
	AndroidTestMock,
}
var CompatUsesLibs29 = []string{
	AndroidHidlBase,
	AndroidHidlManager,
}
var OptionalCompatUsesLibs = append(android.CopyOf(OptionalCompatUsesLibs28), OptionalCompatUsesLibs30...)
var CompatUsesLibs = android.CopyOf(CompatUsesLibs29)

const UnknownInstallLibraryPath = "error"

const AnySdkVersion int = 9999 // should go last in class loader context

// LibraryPath contains paths to the library DEX jar on host and on device.
type LibraryPath struct {
	Host   android.Path
	Device string
}

// LibraryPaths is a map from library name to on-host and on-device paths to its DEX jar.
type LibraryPaths map[string]*LibraryPath

type classLoaderContext struct {
	// Library names
	Names []string

	// The class loader context using paths in the build.
	Host android.Paths

	// The class loader context using paths as they will be on the device.
	Target []string
}

// A map of class loader contexts for each SDK version.
// A map entry for "any" version contains libraries that are unconditionally added to class loader
// context. Map entries for existing versions contains libraries that were in the default classpath
// until that API version, and should be added to class loader context if and only if the
// targetSdkVersion in the manifest or APK is less than that API version.
type classLoaderContextMap map[int]*classLoaderContext

// Add a new library path to the map, unless a path for this library already exists.
// If necessary, check that the build and install paths exist.
func (libPaths LibraryPaths) addLibraryPath(ctx android.ModuleContext, lib string,
	hostPath, installPath android.Path, strict bool) {

	// If missing dependencies are allowed, the build shouldn't fail when a <uses-library> is
	// not found. However, this is likely to result is disabling dexpreopt, as it won't be
	// possible to construct class loader context without on-host and on-device library paths.
	strict = strict && !ctx.Config().AllowMissingDependencies()

	if hostPath == nil && strict {
		android.ReportPathErrorf(ctx, "unknown build path to <uses-library> '%s'", lib)
	}

	if installPath == nil {
		if android.InList(lib, CompatUsesLibs) || android.InList(lib, OptionalCompatUsesLibs) {
			// Assume that compatibility libraries are installed in /system/framework.
			installPath = android.PathForModuleInstall(ctx, "framework", lib+".jar")
		} else if strict {
			android.ReportPathErrorf(ctx, "unknown install path to <uses-library> '%s'", lib)
		}
	}

	// Add a library only if the build and install path to it is known.
	if _, present := libPaths[lib]; !present {
		var devicePath string
		if installPath != nil {
			devicePath = android.InstallPathToOnDevicePath(ctx, installPath.(android.InstallPath))
		} else {
			// For some stub libraries the only known thing is the name of their implementation
			// library, but the library itself is unavailable (missing or part of a prebuilt). In
			// such cases we still need to add the library to <uses-library> tags in the manifest,
			// but we cannot use if for dexpreopt.
			devicePath = UnknownInstallLibraryPath
		}
		libPaths[lib] = &LibraryPath{hostPath, devicePath}
	}
}

// Add a new library path to the map. Enforce checks that the library paths exist.
func (libPaths LibraryPaths) AddLibraryPath(ctx android.ModuleContext, lib string, hostPath, installPath android.Path) {
	libPaths.addLibraryPath(ctx, lib, hostPath, installPath, true)
}

// Add a new library path to the map, if the library exists (name is not nil).
// Don't enforce checks that the library paths exist. Some libraries may be missing from the build,
// but their names still need to be added to <uses-library> tags in the manifest.
func (libPaths LibraryPaths) MaybeAddLibraryPath(ctx android.ModuleContext, lib *string, hostPath, installPath android.Path) {
	if lib != nil {
		libPaths.addLibraryPath(ctx, *lib, hostPath, installPath, false)
	}
}

// Add library paths from the second map to the first map (do not override existing entries).
func (libPaths LibraryPaths) AddLibraryPaths(otherPaths LibraryPaths) {
	for lib, path := range otherPaths {
		if _, present := libPaths[lib]; !present {
			libPaths[lib] = path
		}
	}
}

func (m classLoaderContextMap) getValue(sdkVer int) *classLoaderContext {
	if _, ok := m[sdkVer]; !ok {
		m[sdkVer] = &classLoaderContext{}
	}
	return m[sdkVer]
}

func (clc *classLoaderContext) addLib(lib string, hostPath android.Path, targetPath string) {
	clc.Names = append(clc.Names, lib)
	clc.Host = append(clc.Host, hostPath)
	clc.Target = append(clc.Target, targetPath)
}

func (m classLoaderContextMap) addLibs(ctx android.PathContext, sdkVer int, module *ModuleConfig, libs ...string) bool {
	clc := m.getValue(sdkVer)
	for _, lib := range libs {
		if p, ok := module.LibraryPaths[lib]; ok && p.Host != nil && p.Device != UnknownInstallLibraryPath {
			clc.addLib(lib, p.Host, p.Device)
		} else {
			if sdkVer == AnySdkVersion {
				// Fail the build if dexpreopt doesn't know paths to one of the <uses-library>
				// dependencies. In the future we may need to relax this and just disable dexpreopt.
				android.ReportPathErrorf(ctx, "dexpreopt cannot find path for <uses-library> '%s'", lib)
			} else {
				// No error for compatibility libraries, as Soong doesn't know if they are needed
				// (this depends on the targetSdkVersion in the manifest).
			}
			return false
		}
	}
	return true
}

func (m classLoaderContextMap) addSystemServerLibs(sdkVer int, ctx android.PathContext, module *ModuleConfig, libs ...string) {
	clc := m.getValue(sdkVer)
	for _, lib := range libs {
		clc.addLib(lib, SystemServerDexJarHostPath(ctx, lib), filepath.Join("/system/framework", lib+".jar"))
	}
}

func (m classLoaderContextMap) usesLibs() []string {
	if clc, ok := m[AnySdkVersion]; ok {
		return clc.Names
	}
	return nil
}

// genClassLoaderContext generates host and target class loader context to be passed to the dex2oat
// command for the dexpreopted module. There are three possible cases:
//
// 1. System server jars. They have a special class loader context that includes other system
//    server jars.
//
// 2. Library jars or APKs which have precise list of their <uses-library> libs. Their class loader
//    context includes build and on-device paths to these libs. In some cases it may happen that
//    the path to a <uses-library> is unknown (e.g. the dexpreopted module may depend on stubs
//    library, whose implementation library is missing from the build altogether). In such case
//    dexpreopting with the <uses-library> is impossible, and dexpreopting without it is pointless,
//    as the runtime classpath won't match and the dexpreopted code will be discarded. Therefore in
//    such cases the function returns nil, which disables dexpreopt.
//
// 3. All other library jars or APKs for which the exact <uses-library> list is unknown. They use
//    the unsafe &-classpath workaround that means empty class loader context and absence of runtime
//    check that the class loader context provided by the PackageManager agrees with the stored
//    class loader context recorded in the .odex file.
//
func genClassLoaderContext(ctx android.PathContext, global *GlobalConfig, module *ModuleConfig) *classLoaderContextMap {
	classLoaderContexts := make(classLoaderContextMap)
	systemServerJars := NonUpdatableSystemServerJars(ctx, global)

	if jarIndex := android.IndexList(module.Name, systemServerJars); jarIndex >= 0 {
		// System server jars should be dexpreopted together: class loader context of each jar
		// should include all preceding jars on the system server classpath.
		classLoaderContexts.addSystemServerLibs(AnySdkVersion, ctx, module, systemServerJars[:jarIndex]...)

	} else if module.EnforceUsesLibraries {
		// Unconditional class loader context.
		usesLibs := append(copyOf(module.UsesLibraries), module.OptionalUsesLibraries...)
		if !classLoaderContexts.addLibs(ctx, AnySdkVersion, module, usesLibs...) {
			return nil
		}

		// Conditional class loader context for API version < 28.
		const httpLegacy = "org.apache.http.legacy"
		if !classLoaderContexts.addLibs(ctx, 28, module, httpLegacy) {
			return nil
		}

		// Conditional class loader context for API version < 29.
		usesLibs29 := []string{
			"android.hidl.base-V1.0-java",
			"android.hidl.manager-V1.0-java",
		}
		if !classLoaderContexts.addLibs(ctx, 29, module, usesLibs29...) {
			return nil
		}

		// Conditional class loader context for API version < 30.
		if !classLoaderContexts.addLibs(ctx, 30, module, OptionalCompatUsesLibs30...) {
			return nil
		}

	} else {
		// Pass special class loader context to skip the classpath and collision check.
		// This will get removed once LOCAL_USES_LIBRARIES is enforced.
		// Right now LOCAL_USES_LIBRARIES is opt in, for the case where it's not specified we still default
		// to the &.
	}

	fixConditionalClassLoaderContext(classLoaderContexts)

	return &classLoaderContexts
}

// Now that the full unconditional context is known, reconstruct conditional context.
// Apply filters for individual libraries, mirroring what the PackageManager does when it
// constructs class loader context on device.
//
// TODO(b/132357300):
//   - remove android.hidl.manager and android.hidl.base unless the app is a system app.
//
func fixConditionalClassLoaderContext(clcMap classLoaderContextMap) {
	usesLibs := clcMap.usesLibs()

	for sdkVer, clc := range clcMap {
		if sdkVer == AnySdkVersion {
			continue
		}
		clcMap[sdkVer] = &classLoaderContext{}
		for i, lib := range clc.Names {
			if android.InList(lib, usesLibs) {
				// skip compatibility libraries that are already included in unconditional context
			} else if lib == AndroidTestMock && !android.InList("android.test.runner", usesLibs) {
				// android.test.mock is only needed as a compatibility library (in conditional class
				// loader context) if android.test.runner is used, otherwise skip it
			} else {
				clcMap[sdkVer].addLib(lib, clc.Host[i], clc.Target[i])
			}
		}
	}
}

// Return the class loader context as a string and a slice of build paths for all dependencies.
func computeClassLoaderContext(ctx android.PathContext, clcMap classLoaderContextMap) (clcStr string, paths android.Paths) {
	for _, ver := range android.SortedIntKeys(clcMap) {
		clc := clcMap.getValue(ver)

		clcLen := len(clc.Names)
		if clcLen != len(clc.Host) || clcLen != len(clc.Target) {
			android.ReportPathErrorf(ctx, "ill-formed class loader context")
		}

		var hostClc, targetClc []string
		var hostPaths android.Paths

		for i := 0; i < clcLen; i++ {
			hostStr := "PCL[" + clc.Host[i].String() + "]"
			targetStr := "PCL[" + clc.Target[i] + "]"

			hostClc = append(hostClc, hostStr)
			targetClc = append(targetClc, targetStr)
			hostPaths = append(hostPaths, clc.Host[i])
		}

		if hostPaths != nil {
			sdkVerStr := fmt.Sprintf("%d", ver)
			if ver == AnySdkVersion {
				sdkVerStr = "any" // a special keyword that means any SDK version
			}
			clcStr += fmt.Sprintf(" --host-context-for-sdk %s %s", sdkVerStr, strings.Join(hostClc, "#"))
			clcStr += fmt.Sprintf(" --target-context-for-sdk %s %s", sdkVerStr, strings.Join(targetClc, "#"))
			paths = append(paths, hostPaths...)
		}
	}

	return clcStr, paths
}

type jsonLibraryPath struct {
	Host   string
	Device string
}

type jsonLibraryPaths map[string]jsonLibraryPath

// convert JSON map of library paths to LibraryPaths
func constructLibraryPaths(ctx android.PathContext, paths jsonLibraryPaths) LibraryPaths {
	m := LibraryPaths{}
	for lib, path := range paths {
		m[lib] = &LibraryPath{
			constructPath(ctx, path.Host),
			path.Device,
		}
	}
	return m
}
