fix: LOCAL_PATH for modules included in APEX is wrong

This change fixes a bug that LOCAL_PATH for modules included in an APEX
is set to the path of the APEX bundle, not to the path of the embedded
module. For example, LOCAL_PATH of libconscrypt included in
com.android.adbd was set to /system/core/adb instead of
/external/boringssl. This caused a problem that NOTICE file in
/external/boringssl is not tagged to libconscrypt, but the NOTICE file
for adbd is.

Fixing the problem by recording the module directories of the included
modules and emitting it in LOCAL_PATH.

Bug: 145347092
Test: Settings -> About Phone -> Legal Information -> Third-party
license. The license for /apex/com.android.adbd/lib64/libconscrypt.so is
OpenSSL.

Change-Id: I76f1830d5a10af63fa74dcc2a42730ffabb8c4ed
diff --git a/apex/apex.go b/apex/apex.go
index be86d80..aedd122 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -459,16 +459,21 @@
 	// list of symlinks that will be created in installDir that point to this apexFile
 	symlinks      []string
 	transitiveDep bool
+	moduleDir     string
 }
 
-func newApexFile(builtFile android.Path, moduleName string, installDir string, class apexFileClass, module android.Module) apexFile {
-	return apexFile{
+func newApexFile(ctx android.BaseModuleContext, builtFile android.Path, moduleName string, installDir string, class apexFileClass, module android.Module) apexFile {
+	ret := apexFile{
 		builtFile:  builtFile,
 		moduleName: moduleName,
 		installDir: installDir,
 		class:      class,
 		module:     module,
 	}
+	if module != nil {
+		ret.moduleDir = ctx.OtherModuleDir(module)
+	}
+	return ret
 }
 
 func (af *apexFile) Ok() bool {
@@ -789,7 +794,7 @@
 }
 
 // TODO(jiyong) move apexFileFor* close to the apexFile type definition
-func apexFileForNativeLibrary(ccMod *cc.Module, config android.Config, handleSpecialLibs bool) apexFile {
+func apexFileForNativeLibrary(ctx android.BaseModuleContext, ccMod *cc.Module, handleSpecialLibs bool) apexFile {
 	// Decide the APEX-local directory by the multilib of the library
 	// In the future, we may query this to the module.
 	var dirInApex string
@@ -803,7 +808,7 @@
 	if ccMod.Target().NativeBridge == android.NativeBridgeEnabled {
 		dirInApex = filepath.Join(dirInApex, ccMod.Target().NativeBridgeRelativePath)
 	}
-	if handleSpecialLibs && cc.InstallToBootstrap(ccMod.BaseModuleName(), config) {
+	if handleSpecialLibs && cc.InstallToBootstrap(ccMod.BaseModuleName(), ctx.Config()) {
 		// Special case for Bionic libs and other libs installed with them. This is
 		// to prevent those libs from being included in the search path
 		// /apex/com.android.runtime/${LIB}. This exclusion is required because
@@ -818,26 +823,26 @@
 	}
 
 	fileToCopy := ccMod.OutputFile().Path()
-	return newApexFile(fileToCopy, ccMod.Name(), dirInApex, nativeSharedLib, ccMod)
+	return newApexFile(ctx, fileToCopy, ccMod.Name(), dirInApex, nativeSharedLib, ccMod)
 }
 
-func apexFileForExecutable(cc *cc.Module) apexFile {
+func apexFileForExecutable(ctx android.BaseModuleContext, cc *cc.Module) apexFile {
 	dirInApex := filepath.Join("bin", cc.RelativeInstallPath())
 	if cc.Target().NativeBridge == android.NativeBridgeEnabled {
 		dirInApex = filepath.Join(dirInApex, cc.Target().NativeBridgeRelativePath)
 	}
 	fileToCopy := cc.OutputFile().Path()
-	af := newApexFile(fileToCopy, cc.Name(), dirInApex, nativeExecutable, cc)
+	af := newApexFile(ctx, fileToCopy, cc.Name(), dirInApex, nativeExecutable, cc)
 	af.symlinks = cc.Symlinks()
 	return af
 }
 
-func apexFileForPyBinary(py *python.Module) apexFile {
+func apexFileForPyBinary(ctx android.BaseModuleContext, py *python.Module) apexFile {
 	dirInApex := "bin"
 	fileToCopy := py.HostToolPath().Path()
-	return newApexFile(fileToCopy, py.Name(), dirInApex, pyBinary, py)
+	return newApexFile(ctx, fileToCopy, py.Name(), dirInApex, pyBinary, py)
 }
-func apexFileForGoBinary(ctx android.ModuleContext, depName string, gb bootstrap.GoBinaryTool) apexFile {
+func apexFileForGoBinary(ctx android.BaseModuleContext, depName string, gb bootstrap.GoBinaryTool) apexFile {
 	dirInApex := "bin"
 	s, err := filepath.Rel(android.PathForOutput(ctx).String(), gb.InstallPath())
 	if err != nil {
@@ -848,24 +853,24 @@
 	// NB: Since go binaries are static we don't need the module for anything here, which is
 	// good since the go tool is a blueprint.Module not an android.Module like we would
 	// normally use.
-	return newApexFile(fileToCopy, depName, dirInApex, goBinary, nil)
+	return newApexFile(ctx, fileToCopy, depName, dirInApex, goBinary, nil)
 }
 
-func apexFileForShBinary(sh *android.ShBinary) apexFile {
+func apexFileForShBinary(ctx android.BaseModuleContext, sh *android.ShBinary) apexFile {
 	dirInApex := filepath.Join("bin", sh.SubDir())
 	fileToCopy := sh.OutputFile()
-	af := newApexFile(fileToCopy, sh.Name(), dirInApex, shBinary, sh)
+	af := newApexFile(ctx, fileToCopy, sh.Name(), dirInApex, shBinary, sh)
 	af.symlinks = sh.Symlinks()
 	return af
 }
 
-func apexFileForJavaLibrary(java *java.Library) apexFile {
+func apexFileForJavaLibrary(ctx android.BaseModuleContext, java *java.Library) apexFile {
 	dirInApex := "javalib"
 	fileToCopy := java.DexJarFile()
-	return newApexFile(fileToCopy, java.Name(), dirInApex, javaSharedLib, java)
+	return newApexFile(ctx, fileToCopy, java.Name(), dirInApex, javaSharedLib, java)
 }
 
-func apexFileForPrebuiltJavaLibrary(java *java.Import) apexFile {
+func apexFileForPrebuiltJavaLibrary(ctx android.BaseModuleContext, java *java.Import) apexFile {
 	dirInApex := "javalib"
 	// The output is only one, but for some reason, ImplementationJars returns Paths, not Path
 	implJars := java.ImplementationJars()
@@ -874,16 +879,16 @@
 			strings.Join(implJars.Strings(), ", ")))
 	}
 	fileToCopy := implJars[0]
-	return newApexFile(fileToCopy, java.Name(), dirInApex, javaSharedLib, java)
+	return newApexFile(ctx, fileToCopy, java.Name(), dirInApex, javaSharedLib, java)
 }
 
-func apexFileForPrebuiltEtc(prebuilt android.PrebuiltEtcModule, depName string) apexFile {
+func apexFileForPrebuiltEtc(ctx android.BaseModuleContext, prebuilt android.PrebuiltEtcModule, depName string) apexFile {
 	dirInApex := filepath.Join("etc", prebuilt.SubDir())
 	fileToCopy := prebuilt.OutputFile()
-	return newApexFile(fileToCopy, depName, dirInApex, etc, prebuilt)
+	return newApexFile(ctx, fileToCopy, depName, dirInApex, etc, prebuilt)
 }
 
-func apexFileForAndroidApp(aapp interface {
+func apexFileForAndroidApp(ctx android.BaseModuleContext, aapp interface {
 	android.Module
 	Privileged() bool
 	OutputFile() android.Path
@@ -894,7 +899,7 @@
 	}
 	dirInApex := filepath.Join(appDir, pkgName)
 	fileToCopy := aapp.OutputFile()
-	return newApexFile(fileToCopy, aapp.Name(), dirInApex, app, aapp)
+	return newApexFile(ctx, fileToCopy, aapp.Name(), dirInApex, app, aapp)
 }
 
 // Context "decorator", overriding the InstallBypassMake method to always reply `true`.
@@ -982,19 +987,19 @@
 					if cc.HasStubsVariants() {
 						provideNativeLibs = append(provideNativeLibs, cc.OutputFile().Path().Base())
 					}
-					filesInfo = append(filesInfo, apexFileForNativeLibrary(cc, ctx.Config(), handleSpecialLibs))
+					filesInfo = append(filesInfo, apexFileForNativeLibrary(ctx, cc, handleSpecialLibs))
 					return true // track transitive dependencies
 				} else {
 					ctx.PropertyErrorf("native_shared_libs", "%q is not a cc_library or cc_library_shared module", depName)
 				}
 			case executableTag:
 				if cc, ok := child.(*cc.Module); ok {
-					filesInfo = append(filesInfo, apexFileForExecutable(cc))
+					filesInfo = append(filesInfo, apexFileForExecutable(ctx, cc))
 					return true // track transitive dependencies
 				} else if sh, ok := child.(*android.ShBinary); ok {
-					filesInfo = append(filesInfo, apexFileForShBinary(sh))
+					filesInfo = append(filesInfo, apexFileForShBinary(ctx, sh))
 				} else if py, ok := child.(*python.Module); ok && py.HostToolPath().Valid() {
-					filesInfo = append(filesInfo, apexFileForPyBinary(py))
+					filesInfo = append(filesInfo, apexFileForPyBinary(ctx, py))
 				} else if gb, ok := child.(bootstrap.GoBinaryTool); ok && a.Host() {
 					filesInfo = append(filesInfo, apexFileForGoBinary(ctx, depName, gb))
 				} else {
@@ -1002,7 +1007,7 @@
 				}
 			case javaLibTag:
 				if javaLib, ok := child.(*java.Library); ok {
-					af := apexFileForJavaLibrary(javaLib)
+					af := apexFileForJavaLibrary(ctx, javaLib)
 					if !af.Ok() {
 						ctx.PropertyErrorf("java_libs", "%q is not configured to be compiled into dex", depName)
 					} else {
@@ -1010,7 +1015,7 @@
 						return true // track transitive dependencies
 					}
 				} else if javaLib, ok := child.(*java.Import); ok {
-					af := apexFileForPrebuiltJavaLibrary(javaLib)
+					af := apexFileForPrebuiltJavaLibrary(ctx, javaLib)
 					if !af.Ok() {
 						ctx.PropertyErrorf("java_libs", "%q does not have a jar output", depName)
 					} else {
@@ -1022,16 +1027,16 @@
 			case androidAppTag:
 				pkgName := ctx.DeviceConfig().OverridePackageNameFor(depName)
 				if ap, ok := child.(*java.AndroidApp); ok {
-					filesInfo = append(filesInfo, apexFileForAndroidApp(ap, pkgName))
+					filesInfo = append(filesInfo, apexFileForAndroidApp(ctx, ap, pkgName))
 					return true // track transitive dependencies
 				} else if ap, ok := child.(*java.AndroidAppImport); ok {
-					filesInfo = append(filesInfo, apexFileForAndroidApp(ap, pkgName))
+					filesInfo = append(filesInfo, apexFileForAndroidApp(ctx, ap, pkgName))
 				} else {
 					ctx.PropertyErrorf("apps", "%q is not an android_app module", depName)
 				}
 			case prebuiltTag:
 				if prebuilt, ok := child.(android.PrebuiltEtcModule); ok {
-					filesInfo = append(filesInfo, apexFileForPrebuiltEtc(prebuilt, depName))
+					filesInfo = append(filesInfo, apexFileForPrebuiltEtc(ctx, prebuilt, depName))
 				} else {
 					ctx.PropertyErrorf("prebuilts", "%q is not a prebuilt_etc module", depName)
 				}
@@ -1047,7 +1052,7 @@
 						return true
 					} else {
 						// Single-output test module (where `test_per_src: false`).
-						af := apexFileForExecutable(ccTest)
+						af := apexFileForExecutable(ctx, ccTest)
 						af.class = nativeTest
 						filesInfo = append(filesInfo, af)
 					}
@@ -1103,14 +1108,14 @@
 							// Don't track further
 							return false
 						}
-						af := apexFileForNativeLibrary(cc, ctx.Config(), handleSpecialLibs)
+						af := apexFileForNativeLibrary(ctx, cc, handleSpecialLibs)
 						af.transitiveDep = true
 						filesInfo = append(filesInfo, af)
 						return true // track transitive dependencies
 					}
 				} else if cc.IsTestPerSrcDepTag(depTag) {
 					if cc, ok := child.(*cc.Module); ok {
-						af := apexFileForExecutable(cc)
+						af := apexFileForExecutable(ctx, cc)
 						// Handle modules created as `test_per_src` variations of a single test module:
 						// use the name of the generated test binary (`fileToCopy`) instead of the name
 						// of the original test module (`depName`, shared by all `test_per_src`
@@ -1139,7 +1144,7 @@
 			dirInApex := filepath.Join("javalib", arch.String())
 			for _, f := range files {
 				localModule := "javalib_" + arch.String() + "_" + filepath.Base(f.String())
-				af := newApexFile(f, localModule, dirInApex, etc, nil)
+				af := newApexFile(ctx, f, localModule, dirInApex, etc, nil)
 				filesInfo = append(filesInfo, af)
 			}
 		}