Merge "bp2build: add support for cc_object's objs and exclude_srcs properties."
diff --git a/android/register.go b/android/register.go
index 18c743f..47df972 100644
--- a/android/register.go
+++ b/android/register.go
@@ -168,6 +168,7 @@
 type RegistrationContext interface {
 	RegisterModuleType(name string, factory ModuleFactory)
 	RegisterSingletonModuleType(name string, factory SingletonModuleFactory)
+	RegisterPreSingletonType(name string, factory SingletonFactory)
 	RegisterSingletonType(name string, factory SingletonFactory)
 	PreArchMutators(f RegisterMutatorFunc)
 
@@ -208,6 +209,7 @@
 type initRegistrationContext struct {
 	moduleTypes        map[string]ModuleFactory
 	singletonTypes     map[string]SingletonFactory
+	preSingletonTypes  map[string]SingletonFactory
 	moduleTypesForDocs map[string]reflect.Value
 }
 
@@ -238,6 +240,14 @@
 	RegisterSingletonType(name, factory)
 }
 
+func (ctx *initRegistrationContext) RegisterPreSingletonType(name string, factory SingletonFactory) {
+	if _, present := ctx.preSingletonTypes[name]; present {
+		panic(fmt.Sprintf("pre singleton type %q is already registered", name))
+	}
+	ctx.preSingletonTypes[name] = factory
+	RegisterPreSingletonType(name, factory)
+}
+
 func (ctx *initRegistrationContext) PreArchMutators(f RegisterMutatorFunc) {
 	PreArchMutators(f)
 }
diff --git a/android/testing.go b/android/testing.go
index 7852b60..1b1feb7 100644
--- a/android/testing.go
+++ b/android/testing.go
@@ -140,6 +140,10 @@
 	ctx.Context.RegisterSingletonType(name, SingletonFactoryAdaptor(ctx.Context, factory))
 }
 
+func (ctx *TestContext) RegisterPreSingletonType(name string, factory SingletonFactory) {
+	ctx.Context.RegisterPreSingletonType(name, SingletonFactoryAdaptor(ctx.Context, factory))
+}
+
 func (ctx *TestContext) ModuleForTests(name, variant string) TestingModule {
 	var module Module
 	ctx.VisitAllModules(func(m blueprint.Module) {
diff --git a/apex/allowed_deps.txt b/apex/allowed_deps.txt
index 72394db..47ea239 100644
--- a/apex/allowed_deps.txt
+++ b/apex/allowed_deps.txt
@@ -507,9 +507,13 @@
 networkstack-aidl-interfaces-unstable-java(minSdkVersion:29)
 networkstack-aidl-interfaces-V10-java(minSdkVersion:29)
 networkstack-client(minSdkVersion:29)
+NetworkStackApi29Shims(minSdkVersion:29)
+NetworkStackApi30Shims(minSdkVersion:29)
 NetworkStackApiStableDependencies(minSdkVersion:29)
 NetworkStackApiStableLib(minSdkVersion:29)
+NetworkStackApiStableShims(minSdkVersion:29)
 networkstackprotos(minSdkVersion:29)
+NetworkStackShimsCommon(minSdkVersion:29)
 neuralnetworks_types(minSdkVersion:30)
 neuralnetworks_utils_hal_1_0(minSdkVersion:30)
 neuralnetworks_utils_hal_1_1(minSdkVersion:30)
diff --git a/bp2build/conversion.go b/bp2build/conversion.go
index 081e082..1225f2b 100644
--- a/bp2build/conversion.go
+++ b/bp2build/conversion.go
@@ -93,6 +93,7 @@
 		"name":       true, // redundant, since this is explicitly generated for every target
 		"from":       true, // reserved keyword
 		"in":         true, // reserved keyword
+		"size":       true, // reserved for tests
 		"arch":       true, // interface prop type is not supported yet.
 		"multilib":   true, // interface prop type is not supported yet.
 		"target":     true, // interface prop type is not supported yet.
diff --git a/cc/compiler.go b/cc/compiler.go
index e96295c..2e71922 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -442,7 +442,7 @@
 		fmt.Sprintf("${config.%sClangGlobalCflags}", hod))
 
 	if isThirdParty(modulePath) {
-		flags.Global.CommonFlags = append([]string{"${config.ClangExternalCflags}"}, flags.Global.CommonFlags...)
+		flags.Global.CommonFlags = append(flags.Global.CommonFlags, "${config.ClangExternalCflags}")
 	}
 
 	if tc.Bionic() {
diff --git a/cc/library_sdk_member.go b/cc/library_sdk_member.go
index 1402991..d5f2adf 100644
--- a/cc/library_sdk_member.go
+++ b/cc/library_sdk_member.go
@@ -206,22 +206,22 @@
 		dirs:         true,
 	},
 	{
-		// exportedGeneratedIncludeDirs lists directories that contains some header files
-		// that are explicitly listed in the exportedGeneratedHeaders property. So, the contents
+		// ExportedGeneratedIncludeDirs lists directories that contains some header files
+		// that are explicitly listed in the ExportedGeneratedHeaders property. So, the contents
 		// of these directories do not need to be copied, but these directories do need adding to
 		// the export_include_dirs property in the prebuilt module in the snapshot.
-		pathsGetter:  func(libInfo *nativeLibInfoProperties) android.Paths { return libInfo.exportedGeneratedIncludeDirs },
+		pathsGetter:  func(libInfo *nativeLibInfoProperties) android.Paths { return libInfo.ExportedGeneratedIncludeDirs },
 		propertyName: "export_include_dirs",
 		snapshotDir:  nativeGeneratedIncludeDir,
 		copy:         false,
 		dirs:         true,
 	},
 	{
-		// exportedGeneratedHeaders lists header files that are in one of the directories
-		// specified in exportedGeneratedIncludeDirs must be copied into the snapshot.
-		// As they are in a directory in exportedGeneratedIncludeDirs they do not need adding to a
+		// ExportedGeneratedHeaders lists header files that are in one of the directories
+		// specified in ExportedGeneratedIncludeDirs must be copied into the snapshot.
+		// As they are in a directory in ExportedGeneratedIncludeDirs they do not need adding to a
 		// property in the prebuilt module in the snapshot.
-		pathsGetter:  func(libInfo *nativeLibInfoProperties) android.Paths { return libInfo.exportedGeneratedHeaders },
+		pathsGetter:  func(libInfo *nativeLibInfoProperties) android.Paths { return libInfo.ExportedGeneratedHeaders },
 		propertyName: "",
 		snapshotDir:  nativeGeneratedIncludeDir,
 		copy:         true,
@@ -258,42 +258,52 @@
 	// values where necessary.
 	for _, propertyInfo := range includeDirProperties {
 		// Calculate the base directory in the snapshot into which the files will be copied.
-		// lib.ArchType is "" for common properties.
+		// lib.archType is "" for common properties.
 		targetDir := filepath.Join(libInfo.OsPrefix(), libInfo.archType, propertyInfo.snapshotDir)
 
 		propertyName := propertyInfo.propertyName
 
 		// Iterate over each path in one of the include directory properties.
 		for _, path := range propertyInfo.pathsGetter(libInfo) {
+			inputPath := path.String()
+
+			// Map the input path to a snapshot relative path. The mapping is independent of the module
+			// that references them so that if multiple modules within the same snapshot export the same
+			// header files they end up in the same place in the snapshot and so do not get duplicated.
+			targetRelativePath := inputPath
+			if isGeneratedHeaderDirectory(path) {
+				// Remove everything up to the .intermediates/ from the generated output directory to
+				// leave a module relative path.
+				base := android.PathForIntermediates(sdkModuleContext, "")
+				targetRelativePath = android.Rel(sdkModuleContext, base.String(), inputPath)
+			}
+
+			snapshotRelativePath := filepath.Join(targetDir, targetRelativePath)
 
 			// Copy the files/directories when necessary.
 			if propertyInfo.copy {
 				if propertyInfo.dirs {
 					// When copying a directory glob and copy all the headers within it.
 					// TODO(jiyong) copy headers having other suffixes
-					headers, _ := sdkModuleContext.GlobWithDeps(path.String()+"/**/*.h", nil)
+					headers, _ := sdkModuleContext.GlobWithDeps(inputPath+"/**/*.h", nil)
 					for _, file := range headers {
 						src := android.PathForSource(sdkModuleContext, file)
-						dest := filepath.Join(targetDir, file)
+
+						// The destination path in the snapshot is constructed from the snapshot relative path
+						// of the input directory and the input directory relative path of the header file.
+						inputRelativePath := android.Rel(sdkModuleContext, inputPath, file)
+						dest := filepath.Join(snapshotRelativePath, inputRelativePath)
 						builder.CopyToSnapshot(src, dest)
 					}
 				} else {
-					// Otherwise, just copy the files.
-					dest := filepath.Join(targetDir, libInfo.name, path.Rel())
-					builder.CopyToSnapshot(path, dest)
+					// Otherwise, just copy the file to its snapshot relative path.
+					builder.CopyToSnapshot(path, snapshotRelativePath)
 				}
 			}
 
 			// Only directories are added to a property.
 			if propertyInfo.dirs {
-				var snapshotPath string
-				if isGeneratedHeaderDirectory(path) {
-					snapshotPath = filepath.Join(targetDir, libInfo.name)
-				} else {
-					snapshotPath = filepath.Join(targetDir, path.String())
-				}
-
-				includeDirs[propertyName] = append(includeDirs[propertyName], snapshotPath)
+				includeDirs[propertyName] = append(includeDirs[propertyName], snapshotRelativePath)
 			}
 		}
 	}
@@ -330,9 +340,6 @@
 
 	memberType *librarySdkMemberType
 
-	// The name of the library, is not exported as this must not be changed during optimization.
-	name string
-
 	// archType is not exported as if set (to a non default value) it is always arch specific.
 	// This is "" for common properties.
 	archType string
@@ -344,13 +351,13 @@
 
 	// The list of arch specific exported generated include dirs.
 	//
-	// This field is not exported as its contents are always arch specific.
-	exportedGeneratedIncludeDirs android.Paths
+	// This field is exported as its contents may not be arch specific, e.g. protos.
+	ExportedGeneratedIncludeDirs android.Paths `android:"arch_variant"`
 
 	// The list of arch specific exported generated header files.
 	//
-	// This field is not exported as its contents are is always arch specific.
-	exportedGeneratedHeaders android.Paths
+	// This field is exported as its contents may not be arch specific, e.g. protos.
+	ExportedGeneratedHeaders android.Paths `android:"arch_variant"`
 
 	// The list of possibly common exported system include dirs.
 	//
@@ -419,12 +426,11 @@
 	exportedIncludeDirs, exportedGeneratedIncludeDirs := android.FilterPathListPredicate(
 		exportedInfo.IncludeDirs, isGeneratedHeaderDirectory)
 
-	p.name = variant.Name()
 	p.archType = ccModule.Target().Arch.ArchType.String()
 
 	// Make sure that the include directories are unique.
 	p.ExportedIncludeDirs = android.FirstUniquePaths(exportedIncludeDirs)
-	p.exportedGeneratedIncludeDirs = android.FirstUniquePaths(exportedGeneratedIncludeDirs)
+	p.ExportedGeneratedIncludeDirs = android.FirstUniquePaths(exportedGeneratedIncludeDirs)
 
 	// Take a copy before filtering out duplicates to avoid changing the slice owned by the
 	// ccModule.
@@ -450,7 +456,7 @@
 		}
 		p.SystemSharedLibs = specifiedDeps.systemSharedLibs
 	}
-	p.exportedGeneratedHeaders = exportedInfo.GeneratedHeaders
+	p.ExportedGeneratedHeaders = exportedInfo.GeneratedHeaders
 
 	if !p.memberType.noOutputFiles && addOutputFile {
 		p.outputFile = getRequiredMemberOutputFile(ctx, ccModule)
diff --git a/filesystem/Android.bp b/filesystem/Android.bp
index 42a4c88..dcdbdcf 100644
--- a/filesystem/Android.bp
+++ b/filesystem/Android.bp
@@ -13,6 +13,7 @@
     srcs: [
         "bootimg.go",
         "filesystem.go",
+        "logical_partition.go",
     ],
     testSrcs: [
     ],
diff --git a/filesystem/logical_partition.go b/filesystem/logical_partition.go
new file mode 100644
index 0000000..e547203
--- /dev/null
+++ b/filesystem/logical_partition.go
@@ -0,0 +1,210 @@
+// Copyright (C) 2021 The Android Open Source Project
+//
+// 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 filesystem
+
+import (
+	"fmt"
+	"strconv"
+
+	"github.com/google/blueprint/proptools"
+
+	"android/soong/android"
+)
+
+func init() {
+	android.RegisterModuleType("logical_partition", logicalPartitionFactory)
+}
+
+type logicalPartition struct {
+	android.ModuleBase
+
+	properties logicalPartitionProperties
+
+	output     android.OutputPath
+	installDir android.InstallPath
+}
+
+type logicalPartitionProperties struct {
+	// Set the name of the output. Defaults to <module_name>.img.
+	Stem *string
+
+	// Total size of the logical partition
+	Size *string
+
+	// List of groups. A group defines a fixed sized region. It can host one or more logical
+	// partitions and their total size is limited by the size of the group they are in.
+	Groups []groupProperties
+
+	// Whether the output is a sparse image or not. Default is false.
+	Sparse *bool
+}
+
+type groupProperties struct {
+	// Name of the partition group
+	Name *string
+
+	// Size of the partition group
+	Size *string
+
+	// List of logical partitions in this group
+	Partitions []partitionProperties
+}
+
+type partitionProperties struct {
+	// Name of the partition
+	Name *string
+
+	// Filesystem that is placed on the partition
+	Filesystem *string `android:"path"`
+}
+
+// logical_partition is a partition image which has one or more logical partitions in it.
+func logicalPartitionFactory() android.Module {
+	module := &logicalPartition{}
+	module.AddProperties(&module.properties)
+	android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst)
+	return module
+}
+
+func (l *logicalPartition) DepsMutator(ctx android.BottomUpMutatorContext) {
+	// do nothing
+}
+
+func (l *logicalPartition) installFileName() string {
+	return proptools.StringDefault(l.properties.Stem, l.BaseModuleName()+".img")
+}
+
+func (l *logicalPartition) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+	builder := android.NewRuleBuilder(pctx, ctx)
+
+	// Sparse the filesystem images and calculate their sizes
+	sparseImages := make(map[string]android.OutputPath)
+	sparseImageSizes := make(map[string]android.OutputPath)
+	for _, group := range l.properties.Groups {
+		for _, part := range group.Partitions {
+			sparseImg, sizeTxt := sparseFilesystem(ctx, part, builder)
+			pName := proptools.String(part.Name)
+			sparseImages[pName] = sparseImg
+			sparseImageSizes[pName] = sizeTxt
+		}
+	}
+
+	cmd := builder.Command().BuiltTool("lpmake")
+
+	size := proptools.String(l.properties.Size)
+	if size == "" {
+		ctx.PropertyErrorf("size", "must be set")
+	}
+	if _, err := strconv.Atoi(size); err != nil {
+		ctx.PropertyErrorf("size", "must be a number")
+	}
+	cmd.FlagWithArg("--device-size=", size)
+
+	// TODO(jiyong): consider supporting A/B devices. Then we need to adjust num of slots.
+	cmd.FlagWithArg("--metadata-slots=", "2")
+	cmd.FlagWithArg("--metadata-size=", "65536")
+
+	if proptools.Bool(l.properties.Sparse) {
+		cmd.Flag("--sparse")
+	}
+
+	groupNames := make(map[string]bool)
+	partitionNames := make(map[string]bool)
+
+	for _, group := range l.properties.Groups {
+		gName := proptools.String(group.Name)
+		if gName == "" {
+			ctx.PropertyErrorf("groups.name", "must be set")
+		}
+		if _, ok := groupNames[gName]; ok {
+			ctx.PropertyErrorf("group.name", "already exists")
+		} else {
+			groupNames[gName] = true
+		}
+		gSize := proptools.String(group.Size)
+		if gSize == "" {
+			ctx.PropertyErrorf("groups.size", "must be set")
+		}
+		if _, err := strconv.Atoi(gSize); err != nil {
+			ctx.PropertyErrorf("groups.size", "must be a number")
+		}
+		cmd.FlagWithArg("--group=", gName+":"+gSize)
+
+		for _, part := range group.Partitions {
+			pName := proptools.String(part.Name)
+			if pName == "" {
+				ctx.PropertyErrorf("groups.partitions.name", "must be set")
+			}
+			if _, ok := partitionNames[pName]; ok {
+				ctx.PropertyErrorf("groups.partitions.name", "already exists")
+			} else {
+				partitionNames[pName] = true
+			}
+			// Get size of the partition by reading the -size.txt file
+			pSize := fmt.Sprintf("$(cat %s)", sparseImageSizes[pName])
+			cmd.FlagWithArg("--partition=", fmt.Sprintf("%s:readonly:%s:%s", pName, pSize, gName))
+			cmd.FlagWithInput("--image="+pName+"=", sparseImages[pName])
+		}
+	}
+
+	l.output = android.PathForModuleOut(ctx, l.installFileName()).OutputPath
+	cmd.FlagWithOutput("--output=", l.output)
+
+	builder.Build("build_logical_partition", fmt.Sprintf("Creating %s", l.BaseModuleName()))
+
+	l.installDir = android.PathForModuleInstall(ctx, "etc")
+	ctx.InstallFile(l.installDir, l.installFileName(), l.output)
+}
+
+// Add a rule that converts the filesystem for the given partition to the given rule builder. The
+// path to the sparse file and the text file having the size of the partition are returned.
+func sparseFilesystem(ctx android.ModuleContext, p partitionProperties, builder *android.RuleBuilder) (sparseImg android.OutputPath, sizeTxt android.OutputPath) {
+	img := android.PathForModuleSrc(ctx, proptools.String(p.Filesystem))
+	name := proptools.String(p.Name)
+	sparseImg = android.PathForModuleOut(ctx, name+".img").OutputPath
+
+	builder.Temporary(sparseImg)
+	builder.Command().BuiltTool("img2simg").Input(img).Output(sparseImg)
+
+	sizeTxt = android.PathForModuleOut(ctx, name+"-size.txt").OutputPath
+	builder.Temporary(sizeTxt)
+	builder.Command().BuiltTool("sparse_img").Flag("--get_partition_size").Input(sparseImg).
+		Text("| ").Text("tr").FlagWithArg("-d ", "'\n'").
+		Text("> ").Output(sizeTxt)
+
+	return sparseImg, sizeTxt
+}
+
+var _ android.AndroidMkEntriesProvider = (*logicalPartition)(nil)
+
+// Implements android.AndroidMkEntriesProvider
+func (l *logicalPartition) AndroidMkEntries() []android.AndroidMkEntries {
+	return []android.AndroidMkEntries{android.AndroidMkEntries{
+		Class:      "ETC",
+		OutputFile: android.OptionalPathForPath(l.output),
+		ExtraEntries: []android.AndroidMkExtraEntriesFunc{
+			func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
+				entries.SetString("LOCAL_MODULE_PATH", l.installDir.ToMakePath().String())
+				entries.SetString("LOCAL_INSTALLED_MODULE_STEM", l.installFileName())
+			},
+		},
+	}}
+}
+
+var _ Filesystem = (*logicalPartition)(nil)
+
+func (l *logicalPartition) OutputPath() android.Path {
+	return l.output
+}
diff --git a/java/dex.go b/java/dex.go
index e52fdb5..b2a998f 100644
--- a/java/dex.go
+++ b/java/dex.go
@@ -260,6 +260,9 @@
 		r8Flags = append(r8Flags, "--debug")
 	}
 
+	// TODO(b/180878971): missing classes should be added to the relevant builds.
+	r8Flags = append(r8Flags, "-ignorewarnings")
+
 	return r8Flags, r8Deps
 }
 
diff --git a/java/java_test.go b/java/java_test.go
index 11f6a7c..8407f24 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -74,8 +74,8 @@
 
 	ctx.PreDepsMutators(python.RegisterPythonPreDepsMutators)
 	ctx.PostDepsMutators(android.RegisterOverridePostDepsMutators)
-	ctx.RegisterPreSingletonType("overlay", android.SingletonFactoryAdaptor(ctx.Context, OverlaySingletonFactory))
-	ctx.RegisterPreSingletonType("sdk_versions", android.SingletonFactoryAdaptor(ctx.Context, sdkPreSingletonFactory))
+	ctx.RegisterPreSingletonType("overlay", OverlaySingletonFactory)
+	ctx.RegisterPreSingletonType("sdk_versions", sdkPreSingletonFactory)
 
 	android.RegisterPrebuiltMutators(ctx)
 
diff --git a/sdk/cc_sdk_test.go b/sdk/cc_sdk_test.go
index 6fd6b09..997d2f6 100644
--- a/sdk/cc_sdk_test.go
+++ b/sdk/cc_sdk_test.go
@@ -494,31 +494,26 @@
     apex_available: ["//apex_available:platform"],
     stl: "none",
     compile_multilib: "both",
-    export_include_dirs: ["include/myinclude"],
+    export_include_dirs: [
+        "include/myinclude",
+        "include_gen/generated_foo/gen",
+        "include_gen/generated_foo/gen/protos",
+    ],
     arch: {
         arm64: {
             srcs: ["arm64/lib/mynativelib.so"],
-            export_include_dirs: [
-                "arm64/include_gen/mynativelib",
-                "arm64/include_gen/mynativelib",
-            ],
         },
         arm: {
             srcs: ["arm/lib/mynativelib.so"],
-            export_include_dirs: [
-                "arm/include_gen/mynativelib",
-                "arm/include_gen/mynativelib",
-            ],
         },
     },
 }
 `),
 		checkAllCopyRules(`
 myinclude/Test.h -> include/myinclude/Test.h
+.intermediates/generated_foo/gen/generated_foo/protos/foo/bar.h -> include_gen/generated_foo/gen/generated_foo/protos/foo/bar.h
 .intermediates/mynativelib/android_arm64_armv8-a_shared/mynativelib.so -> arm64/lib/mynativelib.so
-.intermediates/generated_foo/gen/generated_foo/protos/foo/bar.h -> arm64/include_gen/mynativelib/generated_foo/protos/foo/bar.h
 .intermediates/mynativelib/android_arm_armv7-a-neon_shared/mynativelib.so -> arm/lib/mynativelib.so
-.intermediates/generated_foo/gen/generated_foo/protos/foo/bar.h -> arm/include_gen/mynativelib/generated_foo/protos/foo/bar.h
 `),
 	)
 }
@@ -1119,11 +1114,11 @@
     arch: {
         arm64: {
             srcs: ["arm64/lib/mynativelib.so"],
-            export_include_dirs: ["arm64/include_gen/mynativelib"],
+            export_include_dirs: ["arm64/include_gen/mynativelib/android_arm64_armv8-a_shared/gen/aidl"],
         },
         arm: {
             srcs: ["arm/lib/mynativelib.so"],
-            export_include_dirs: ["arm/include_gen/mynativelib"],
+            export_include_dirs: ["arm/include_gen/mynativelib/android_arm_armv7-a-neon_shared/gen/aidl"],
         },
     },
 }
@@ -1131,13 +1126,13 @@
 		checkAllCopyRules(`
 myinclude/Test.h -> include/myinclude/Test.h
 .intermediates/mynativelib/android_arm64_armv8-a_shared/mynativelib.so -> arm64/lib/mynativelib.so
-.intermediates/mynativelib/android_arm64_armv8-a_shared/gen/aidl/aidl/foo/bar/Test.h -> arm64/include_gen/mynativelib/aidl/foo/bar/Test.h
-.intermediates/mynativelib/android_arm64_armv8-a_shared/gen/aidl/aidl/foo/bar/BnTest.h -> arm64/include_gen/mynativelib/aidl/foo/bar/BnTest.h
-.intermediates/mynativelib/android_arm64_armv8-a_shared/gen/aidl/aidl/foo/bar/BpTest.h -> arm64/include_gen/mynativelib/aidl/foo/bar/BpTest.h
+.intermediates/mynativelib/android_arm64_armv8-a_shared/gen/aidl/aidl/foo/bar/Test.h -> arm64/include_gen/mynativelib/android_arm64_armv8-a_shared/gen/aidl/aidl/foo/bar/Test.h
+.intermediates/mynativelib/android_arm64_armv8-a_shared/gen/aidl/aidl/foo/bar/BnTest.h -> arm64/include_gen/mynativelib/android_arm64_armv8-a_shared/gen/aidl/aidl/foo/bar/BnTest.h
+.intermediates/mynativelib/android_arm64_armv8-a_shared/gen/aidl/aidl/foo/bar/BpTest.h -> arm64/include_gen/mynativelib/android_arm64_armv8-a_shared/gen/aidl/aidl/foo/bar/BpTest.h
 .intermediates/mynativelib/android_arm_armv7-a-neon_shared/mynativelib.so -> arm/lib/mynativelib.so
-.intermediates/mynativelib/android_arm_armv7-a-neon_shared/gen/aidl/aidl/foo/bar/Test.h -> arm/include_gen/mynativelib/aidl/foo/bar/Test.h
-.intermediates/mynativelib/android_arm_armv7-a-neon_shared/gen/aidl/aidl/foo/bar/BnTest.h -> arm/include_gen/mynativelib/aidl/foo/bar/BnTest.h
-.intermediates/mynativelib/android_arm_armv7-a-neon_shared/gen/aidl/aidl/foo/bar/BpTest.h -> arm/include_gen/mynativelib/aidl/foo/bar/BpTest.h
+.intermediates/mynativelib/android_arm_armv7-a-neon_shared/gen/aidl/aidl/foo/bar/Test.h -> arm/include_gen/mynativelib/android_arm_armv7-a-neon_shared/gen/aidl/aidl/foo/bar/Test.h
+.intermediates/mynativelib/android_arm_armv7-a-neon_shared/gen/aidl/aidl/foo/bar/BnTest.h -> arm/include_gen/mynativelib/android_arm_armv7-a-neon_shared/gen/aidl/aidl/foo/bar/BnTest.h
+.intermediates/mynativelib/android_arm_armv7-a-neon_shared/gen/aidl/aidl/foo/bar/BpTest.h -> arm/include_gen/mynativelib/android_arm_armv7-a-neon_shared/gen/aidl/aidl/foo/bar/BpTest.h
 `),
 	)
 }
@@ -1321,12 +1316,12 @@
         linux_glibc_x86_64: {
             enabled: true,
             srcs: ["x86_64/lib/mynativelib.so"],
-            export_include_dirs: ["x86_64/include_gen/mynativelib"],
+            export_include_dirs: ["x86_64/include_gen/mynativelib/linux_glibc_x86_64_shared/gen/aidl"],
         },
         linux_glibc_x86: {
             enabled: true,
             srcs: ["x86/lib/mynativelib.so"],
-            export_include_dirs: ["x86/include_gen/mynativelib"],
+            export_include_dirs: ["x86/include_gen/mynativelib/linux_glibc_x86_shared/gen/aidl"],
         },
     },
 }
@@ -1353,12 +1348,12 @@
         linux_glibc_x86_64: {
             enabled: true,
             srcs: ["x86_64/lib/mynativelib.so"],
-            export_include_dirs: ["x86_64/include_gen/mynativelib"],
+            export_include_dirs: ["x86_64/include_gen/mynativelib/linux_glibc_x86_64_shared/gen/aidl"],
         },
         linux_glibc_x86: {
             enabled: true,
             srcs: ["x86/lib/mynativelib.so"],
-            export_include_dirs: ["x86/include_gen/mynativelib"],
+            export_include_dirs: ["x86/include_gen/mynativelib/linux_glibc_x86_shared/gen/aidl"],
         },
     },
 }
@@ -1385,13 +1380,13 @@
 		checkAllCopyRules(`
 myinclude/Test.h -> include/myinclude/Test.h
 .intermediates/mynativelib/linux_glibc_x86_64_shared/mynativelib.so -> x86_64/lib/mynativelib.so
-.intermediates/mynativelib/linux_glibc_x86_64_shared/gen/aidl/aidl/foo/bar/Test.h -> x86_64/include_gen/mynativelib/aidl/foo/bar/Test.h
-.intermediates/mynativelib/linux_glibc_x86_64_shared/gen/aidl/aidl/foo/bar/BnTest.h -> x86_64/include_gen/mynativelib/aidl/foo/bar/BnTest.h
-.intermediates/mynativelib/linux_glibc_x86_64_shared/gen/aidl/aidl/foo/bar/BpTest.h -> x86_64/include_gen/mynativelib/aidl/foo/bar/BpTest.h
+.intermediates/mynativelib/linux_glibc_x86_64_shared/gen/aidl/aidl/foo/bar/Test.h -> x86_64/include_gen/mynativelib/linux_glibc_x86_64_shared/gen/aidl/aidl/foo/bar/Test.h
+.intermediates/mynativelib/linux_glibc_x86_64_shared/gen/aidl/aidl/foo/bar/BnTest.h -> x86_64/include_gen/mynativelib/linux_glibc_x86_64_shared/gen/aidl/aidl/foo/bar/BnTest.h
+.intermediates/mynativelib/linux_glibc_x86_64_shared/gen/aidl/aidl/foo/bar/BpTest.h -> x86_64/include_gen/mynativelib/linux_glibc_x86_64_shared/gen/aidl/aidl/foo/bar/BpTest.h
 .intermediates/mynativelib/linux_glibc_x86_shared/mynativelib.so -> x86/lib/mynativelib.so
-.intermediates/mynativelib/linux_glibc_x86_shared/gen/aidl/aidl/foo/bar/Test.h -> x86/include_gen/mynativelib/aidl/foo/bar/Test.h
-.intermediates/mynativelib/linux_glibc_x86_shared/gen/aidl/aidl/foo/bar/BnTest.h -> x86/include_gen/mynativelib/aidl/foo/bar/BnTest.h
-.intermediates/mynativelib/linux_glibc_x86_shared/gen/aidl/aidl/foo/bar/BpTest.h -> x86/include_gen/mynativelib/aidl/foo/bar/BpTest.h
+.intermediates/mynativelib/linux_glibc_x86_shared/gen/aidl/aidl/foo/bar/Test.h -> x86/include_gen/mynativelib/linux_glibc_x86_shared/gen/aidl/aidl/foo/bar/Test.h
+.intermediates/mynativelib/linux_glibc_x86_shared/gen/aidl/aidl/foo/bar/BnTest.h -> x86/include_gen/mynativelib/linux_glibc_x86_shared/gen/aidl/aidl/foo/bar/BnTest.h
+.intermediates/mynativelib/linux_glibc_x86_shared/gen/aidl/aidl/foo/bar/BpTest.h -> x86/include_gen/mynativelib/linux_glibc_x86_shared/gen/aidl/aidl/foo/bar/BpTest.h
 `),
 	)
 }
@@ -1569,11 +1564,11 @@
     arch: {
         arm64: {
             srcs: ["arm64/lib/mynativelib.a"],
-            export_include_dirs: ["arm64/include_gen/mynativelib"],
+            export_include_dirs: ["arm64/include_gen/mynativelib/android_arm64_armv8-a_static/gen/aidl"],
         },
         arm: {
             srcs: ["arm/lib/mynativelib.a"],
-            export_include_dirs: ["arm/include_gen/mynativelib"],
+            export_include_dirs: ["arm/include_gen/mynativelib/android_arm_armv7-a-neon_static/gen/aidl"],
         },
     },
 }
@@ -1581,13 +1576,13 @@
 		checkAllCopyRules(`
 myinclude/Test.h -> include/myinclude/Test.h
 .intermediates/mynativelib/android_arm64_armv8-a_static/mynativelib.a -> arm64/lib/mynativelib.a
-.intermediates/mynativelib/android_arm64_armv8-a_static/gen/aidl/aidl/foo/bar/Test.h -> arm64/include_gen/mynativelib/aidl/foo/bar/Test.h
-.intermediates/mynativelib/android_arm64_armv8-a_static/gen/aidl/aidl/foo/bar/BnTest.h -> arm64/include_gen/mynativelib/aidl/foo/bar/BnTest.h
-.intermediates/mynativelib/android_arm64_armv8-a_static/gen/aidl/aidl/foo/bar/BpTest.h -> arm64/include_gen/mynativelib/aidl/foo/bar/BpTest.h
+.intermediates/mynativelib/android_arm64_armv8-a_static/gen/aidl/aidl/foo/bar/Test.h -> arm64/include_gen/mynativelib/android_arm64_armv8-a_static/gen/aidl/aidl/foo/bar/Test.h
+.intermediates/mynativelib/android_arm64_armv8-a_static/gen/aidl/aidl/foo/bar/BnTest.h -> arm64/include_gen/mynativelib/android_arm64_armv8-a_static/gen/aidl/aidl/foo/bar/BnTest.h
+.intermediates/mynativelib/android_arm64_armv8-a_static/gen/aidl/aidl/foo/bar/BpTest.h -> arm64/include_gen/mynativelib/android_arm64_armv8-a_static/gen/aidl/aidl/foo/bar/BpTest.h
 .intermediates/mynativelib/android_arm_armv7-a-neon_static/mynativelib.a -> arm/lib/mynativelib.a
-.intermediates/mynativelib/android_arm_armv7-a-neon_static/gen/aidl/aidl/foo/bar/Test.h -> arm/include_gen/mynativelib/aidl/foo/bar/Test.h
-.intermediates/mynativelib/android_arm_armv7-a-neon_static/gen/aidl/aidl/foo/bar/BnTest.h -> arm/include_gen/mynativelib/aidl/foo/bar/BnTest.h
-.intermediates/mynativelib/android_arm_armv7-a-neon_static/gen/aidl/aidl/foo/bar/BpTest.h -> arm/include_gen/mynativelib/aidl/foo/bar/BpTest.h
+.intermediates/mynativelib/android_arm_armv7-a-neon_static/gen/aidl/aidl/foo/bar/Test.h -> arm/include_gen/mynativelib/android_arm_armv7-a-neon_static/gen/aidl/aidl/foo/bar/Test.h
+.intermediates/mynativelib/android_arm_armv7-a-neon_static/gen/aidl/aidl/foo/bar/BnTest.h -> arm/include_gen/mynativelib/android_arm_armv7-a-neon_static/gen/aidl/aidl/foo/bar/BnTest.h
+.intermediates/mynativelib/android_arm_armv7-a-neon_static/gen/aidl/aidl/foo/bar/BpTest.h -> arm/include_gen/mynativelib/android_arm_armv7-a-neon_static/gen/aidl/aidl/foo/bar/BpTest.h
 `),
 	)
 }
@@ -1638,12 +1633,12 @@
         linux_glibc_x86_64: {
             enabled: true,
             srcs: ["x86_64/lib/mynativelib.a"],
-            export_include_dirs: ["x86_64/include_gen/mynativelib"],
+            export_include_dirs: ["x86_64/include_gen/mynativelib/linux_glibc_x86_64_static/gen/aidl"],
         },
         linux_glibc_x86: {
             enabled: true,
             srcs: ["x86/lib/mynativelib.a"],
-            export_include_dirs: ["x86/include_gen/mynativelib"],
+            export_include_dirs: ["x86/include_gen/mynativelib/linux_glibc_x86_static/gen/aidl"],
         },
     },
 }
@@ -1669,12 +1664,12 @@
         linux_glibc_x86_64: {
             enabled: true,
             srcs: ["x86_64/lib/mynativelib.a"],
-            export_include_dirs: ["x86_64/include_gen/mynativelib"],
+            export_include_dirs: ["x86_64/include_gen/mynativelib/linux_glibc_x86_64_static/gen/aidl"],
         },
         linux_glibc_x86: {
             enabled: true,
             srcs: ["x86/lib/mynativelib.a"],
-            export_include_dirs: ["x86/include_gen/mynativelib"],
+            export_include_dirs: ["x86/include_gen/mynativelib/linux_glibc_x86_static/gen/aidl"],
         },
     },
 }
@@ -1701,13 +1696,13 @@
 		checkAllCopyRules(`
 myinclude/Test.h -> include/myinclude/Test.h
 .intermediates/mynativelib/linux_glibc_x86_64_static/mynativelib.a -> x86_64/lib/mynativelib.a
-.intermediates/mynativelib/linux_glibc_x86_64_static/gen/aidl/aidl/foo/bar/Test.h -> x86_64/include_gen/mynativelib/aidl/foo/bar/Test.h
-.intermediates/mynativelib/linux_glibc_x86_64_static/gen/aidl/aidl/foo/bar/BnTest.h -> x86_64/include_gen/mynativelib/aidl/foo/bar/BnTest.h
-.intermediates/mynativelib/linux_glibc_x86_64_static/gen/aidl/aidl/foo/bar/BpTest.h -> x86_64/include_gen/mynativelib/aidl/foo/bar/BpTest.h
+.intermediates/mynativelib/linux_glibc_x86_64_static/gen/aidl/aidl/foo/bar/Test.h -> x86_64/include_gen/mynativelib/linux_glibc_x86_64_static/gen/aidl/aidl/foo/bar/Test.h
+.intermediates/mynativelib/linux_glibc_x86_64_static/gen/aidl/aidl/foo/bar/BnTest.h -> x86_64/include_gen/mynativelib/linux_glibc_x86_64_static/gen/aidl/aidl/foo/bar/BnTest.h
+.intermediates/mynativelib/linux_glibc_x86_64_static/gen/aidl/aidl/foo/bar/BpTest.h -> x86_64/include_gen/mynativelib/linux_glibc_x86_64_static/gen/aidl/aidl/foo/bar/BpTest.h
 .intermediates/mynativelib/linux_glibc_x86_static/mynativelib.a -> x86/lib/mynativelib.a
-.intermediates/mynativelib/linux_glibc_x86_static/gen/aidl/aidl/foo/bar/Test.h -> x86/include_gen/mynativelib/aidl/foo/bar/Test.h
-.intermediates/mynativelib/linux_glibc_x86_static/gen/aidl/aidl/foo/bar/BnTest.h -> x86/include_gen/mynativelib/aidl/foo/bar/BnTest.h
-.intermediates/mynativelib/linux_glibc_x86_static/gen/aidl/aidl/foo/bar/BpTest.h -> x86/include_gen/mynativelib/aidl/foo/bar/BpTest.h
+.intermediates/mynativelib/linux_glibc_x86_static/gen/aidl/aidl/foo/bar/Test.h -> x86/include_gen/mynativelib/linux_glibc_x86_static/gen/aidl/aidl/foo/bar/Test.h
+.intermediates/mynativelib/linux_glibc_x86_static/gen/aidl/aidl/foo/bar/BnTest.h -> x86/include_gen/mynativelib/linux_glibc_x86_static/gen/aidl/aidl/foo/bar/BnTest.h
+.intermediates/mynativelib/linux_glibc_x86_static/gen/aidl/aidl/foo/bar/BpTest.h -> x86/include_gen/mynativelib/linux_glibc_x86_static/gen/aidl/aidl/foo/bar/BpTest.h
 `),
 	)
 }
@@ -1858,7 +1853,10 @@
     host_supported: true,
     stl: "none",
     compile_multilib: "64",
-    export_include_dirs: ["include/myinclude"],
+    export_include_dirs: [
+        "include/myinclude",
+        "include_gen/mynativelib/linux_glibc_x86_64_static/gen/aidl",
+    ],
     target: {
         host: {
             enabled: false,
@@ -1866,7 +1864,6 @@
         linux_glibc_x86_64: {
             enabled: true,
             srcs: ["x86_64/lib/mynativelib.a"],
-            export_include_dirs: ["x86_64/include_gen/mynativelib"],
         },
     },
 }
@@ -1884,7 +1881,10 @@
     installable: false,
     stl: "none",
     compile_multilib: "64",
-    export_include_dirs: ["include/myinclude"],
+    export_include_dirs: [
+        "include/myinclude",
+        "include_gen/mynativelib/linux_glibc_x86_64_static/gen/aidl",
+    ],
     target: {
         host: {
             enabled: false,
@@ -1892,7 +1892,6 @@
         linux_glibc_x86_64: {
             enabled: true,
             srcs: ["x86_64/lib/mynativelib.a"],
-            export_include_dirs: ["x86_64/include_gen/mynativelib"],
         },
     },
 }
@@ -1916,10 +1915,10 @@
 `),
 		checkAllCopyRules(`
 myinclude/Test.h -> include/myinclude/Test.h
+.intermediates/mynativelib/linux_glibc_x86_64_static/gen/aidl/aidl/foo/bar/Test.h -> include_gen/mynativelib/linux_glibc_x86_64_static/gen/aidl/aidl/foo/bar/Test.h
+.intermediates/mynativelib/linux_glibc_x86_64_static/gen/aidl/aidl/foo/bar/BnTest.h -> include_gen/mynativelib/linux_glibc_x86_64_static/gen/aidl/aidl/foo/bar/BnTest.h
+.intermediates/mynativelib/linux_glibc_x86_64_static/gen/aidl/aidl/foo/bar/BpTest.h -> include_gen/mynativelib/linux_glibc_x86_64_static/gen/aidl/aidl/foo/bar/BpTest.h
 .intermediates/mynativelib/linux_glibc_x86_64_static/mynativelib.a -> x86_64/lib/mynativelib.a
-.intermediates/mynativelib/linux_glibc_x86_64_static/gen/aidl/aidl/foo/bar/Test.h -> x86_64/include_gen/mynativelib/aidl/foo/bar/Test.h
-.intermediates/mynativelib/linux_glibc_x86_64_static/gen/aidl/aidl/foo/bar/BnTest.h -> x86_64/include_gen/mynativelib/aidl/foo/bar/BnTest.h
-.intermediates/mynativelib/linux_glibc_x86_64_static/gen/aidl/aidl/foo/bar/BpTest.h -> x86_64/include_gen/mynativelib/aidl/foo/bar/BpTest.h
 `),
 	)
 }
diff --git a/sdk/testing.go b/sdk/testing.go
index 3910e6a..0bbf7f4 100644
--- a/sdk/testing.go
+++ b/sdk/testing.go
@@ -204,7 +204,11 @@
 
 func (h *TestHelper) AssertTrimmedStringEquals(message string, expected string, actual string) {
 	h.t.Helper()
-	h.AssertStringEquals(message, strings.TrimSpace(expected), strings.TrimSpace(actual))
+	expected = strings.TrimSpace(expected)
+	actual = strings.TrimSpace(actual)
+	if actual != expected {
+		h.t.Errorf("%s: expected:\n%s\nactual:\n%s\n", message, expected, actual)
+	}
 }
 
 func (h *TestHelper) AssertDeepEquals(message string, expected interface{}, actual interface{}) {