Build framework.aidl in Soong

Move the rules to build framework.aidl into Soong, and use it
when compiling aidl files with sdk_version: "current".

Also fixes incorrectly using the aidl includes exported by the
"framework" module when the proguardRaiseDep dependency was
added.

Bug: 130798034
Test: sdk_test.go
Change-Id: I126adf1d9e7b6acb528875ff62b974ba7ad9a337
diff --git a/java/builder.go b/java/builder.go
index 338cd52..d257d1d 100644
--- a/java/builder.go
+++ b/java/builder.go
@@ -154,6 +154,7 @@
 	processor     string
 	systemModules classpath
 	aidlFlags     string
+	aidlDeps      android.Paths
 	javaVersion   string
 
 	errorProneExtraJavacFlags string
diff --git a/java/droiddoc.go b/java/droiddoc.go
index e163617..fd7e2a4 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -404,6 +404,7 @@
 	sourcepathArgs     string
 	dokkaClasspathArgs string
 	aidlFlags          string
+	aidlDeps           android.Paths
 
 	doclavaStubsFlags string
 	doclavaDocsFlags  string
@@ -574,26 +575,23 @@
 func (j *Javadoc) collectAidlFlags(ctx android.ModuleContext, deps deps) droiddocBuilderFlags {
 	var flags droiddocBuilderFlags
 
-	// aidl flags.
-	aidlFlags := j.aidlFlags(ctx, deps.aidlPreprocess, deps.aidlIncludeDirs)
-	if len(aidlFlags) > 0 {
-		// optimization.
-		ctx.Variable(pctx, "aidlFlags", strings.Join(aidlFlags, " "))
-		flags.aidlFlags = "$aidlFlags"
-	}
+	flags.aidlFlags, flags.aidlDeps = j.aidlFlags(ctx, deps.aidlPreprocess, deps.aidlIncludeDirs)
 
 	return flags
 }
 
 func (j *Javadoc) aidlFlags(ctx android.ModuleContext, aidlPreprocess android.OptionalPath,
-	aidlIncludeDirs android.Paths) []string {
+	aidlIncludeDirs android.Paths) (string, android.Paths) {
 
 	aidlIncludes := android.PathsForModuleSrc(ctx, j.properties.Aidl.Local_include_dirs)
 	aidlIncludes = append(aidlIncludes, android.PathsForSource(ctx, j.properties.Aidl.Include_dirs)...)
 
 	var flags []string
+	var deps android.Paths
+
 	if aidlPreprocess.Valid() {
 		flags = append(flags, "-p"+aidlPreprocess.String())
+		deps = append(deps, aidlPreprocess.Path())
 	} else {
 		flags = append(flags, android.JoinWithPrefix(aidlIncludeDirs.Strings(), "-I"))
 	}
@@ -604,7 +602,7 @@
 		flags = append(flags, "-I"+src.String())
 	}
 
-	return flags
+	return strings.Join(flags, " "), deps
 }
 
 func (j *Javadoc) genSources(ctx android.ModuleContext, srcFiles android.Paths,
@@ -615,7 +613,7 @@
 	for _, srcFile := range srcFiles {
 		switch srcFile.Ext() {
 		case ".aidl":
-			javaFile := genAidl(ctx, srcFile, flags.aidlFlags)
+			javaFile := genAidl(ctx, srcFile, flags.aidlFlags, flags.aidlDeps)
 			outSrcFiles = append(outSrcFiles, javaFile)
 		case ".sysprop":
 			javaFile := genSysprop(ctx, srcFile)
diff --git a/java/gen.go b/java/gen.go
index 7c57a46..b1c028d 100644
--- a/java/gen.go
+++ b/java/gen.go
@@ -60,7 +60,7 @@
 		})
 )
 
-func genAidl(ctx android.ModuleContext, aidlFile android.Path, aidlFlags string) android.Path {
+func genAidl(ctx android.ModuleContext, aidlFile android.Path, aidlFlags string, deps android.Paths) android.Path {
 	javaFile := android.GenPathWithExt(ctx, "aidl", aidlFile, "java")
 	depFile := javaFile.String() + ".d"
 
@@ -69,6 +69,7 @@
 		Description: "aidl " + aidlFile.Rel(),
 		Output:      javaFile,
 		Input:       aidlFile,
+		Implicits:   deps,
 		Args: map[string]string{
 			"depFile":   depFile,
 			"aidlFlags": aidlFlags,
@@ -112,7 +113,7 @@
 	for _, srcFile := range srcFiles {
 		switch srcFile.Ext() {
 		case ".aidl":
-			javaFile := genAidl(ctx, srcFile, flags.aidlFlags)
+			javaFile := genAidl(ctx, srcFile, flags.aidlFlags, flags.aidlDeps)
 			outSrcFiles = append(outSrcFiles, javaFile)
 		case ".logtags":
 			j.logtagsSrcs = append(j.logtagsSrcs, srcFile)
diff --git a/java/java.go b/java/java.go
index 7768756..7c5d841 100644
--- a/java/java.go
+++ b/java/java.go
@@ -410,7 +410,7 @@
 	frameworkResModule string
 
 	jars android.Paths
-	aidl android.Path
+	aidl android.OptionalPath
 }
 
 type jniLib struct {
@@ -534,7 +534,7 @@
 }
 
 func (j *Module) aidlFlags(ctx android.ModuleContext, aidlPreprocess android.OptionalPath,
-	aidlIncludeDirs android.Paths) []string {
+	aidlIncludeDirs android.Paths) (string, android.Paths) {
 
 	aidlIncludes := android.PathsForModuleSrc(ctx, j.deviceProperties.Aidl.Local_include_dirs)
 	aidlIncludes = append(aidlIncludes,
@@ -542,16 +542,24 @@
 	aidlIncludes = append(aidlIncludes,
 		android.PathsForSource(ctx, j.deviceProperties.Aidl.Include_dirs)...)
 
-	flags := []string{}
+	var flags []string
+	var deps android.Paths
 
 	if aidlPreprocess.Valid() {
 		flags = append(flags, "-p"+aidlPreprocess.String())
-	} else {
+		deps = append(deps, aidlPreprocess.Path())
+	} else if len(aidlIncludeDirs) > 0 {
 		flags = append(flags, android.JoinWithPrefix(aidlIncludeDirs.Strings(), "-I"))
 	}
 
-	flags = append(flags, android.JoinWithPrefix(j.exportAidlIncludeDirs.Strings(), "-I"))
-	flags = append(flags, android.JoinWithPrefix(aidlIncludes.Strings(), "-I"))
+	if len(j.exportAidlIncludeDirs) > 0 {
+		flags = append(flags, android.JoinWithPrefix(j.exportAidlIncludeDirs.Strings(), "-I"))
+	}
+
+	if len(aidlIncludes) > 0 {
+		flags = append(flags, android.JoinWithPrefix(aidlIncludes.Strings(), "-I"))
+	}
+
 	flags = append(flags, "-I"+android.PathForModuleSrc(ctx).String())
 	if src := android.ExistentPathForSource(ctx, ctx.ModuleDir(), "src"); src.Valid() {
 		flags = append(flags, "-I"+src.String())
@@ -565,7 +573,7 @@
 		flags = append(flags, "--transaction_names")
 	}
 
-	return flags
+	return strings.Join(flags, " "), deps
 }
 
 type deps struct {
@@ -683,7 +691,9 @@
 		} else if sdkDep.useFiles {
 			// sdkDep.jar is actually equivalent to turbine header.jar.
 			deps.classpath = append(deps.classpath, sdkDep.jars...)
-			deps.aidlIncludeDirs = append(deps.aidlIncludeDirs, sdkDep.aidl)
+			deps.aidlPreprocess = sdkDep.aidl
+		} else {
+			deps.aidlPreprocess = sdkDep.aidl
 		}
 	}
 
@@ -724,6 +734,7 @@
 				deps.classpath = append(deps.classpath, dep.HeaderJars()...)
 				// sdk lib names from dependencies are re-exported
 				j.exportedSdkLibs = append(j.exportedSdkLibs, dep.ExportedSdkLibs()...)
+				deps.aidlIncludeDirs = append(deps.aidlIncludeDirs, dep.AidlIncludeDirs()...)
 			case staticLibTag:
 				deps.classpath = append(deps.classpath, dep.HeaderJars()...)
 				deps.staticJars = append(deps.staticJars, dep.ImplementationJars()...)
@@ -731,6 +742,7 @@
 				deps.staticResourceJars = append(deps.staticResourceJars, dep.ResourceJars()...)
 				// sdk lib names from dependencies are re-exported
 				j.exportedSdkLibs = append(j.exportedSdkLibs, dep.ExportedSdkLibs()...)
+				deps.aidlIncludeDirs = append(deps.aidlIncludeDirs, dep.AidlIncludeDirs()...)
 			case pluginTag:
 				if plugin, ok := dep.(*Plugin); ok {
 					deps.processorPath = append(deps.processorPath, dep.ImplementationAndResourcesJars()...)
@@ -765,7 +777,6 @@
 				deps.kotlinAnnotations = dep.HeaderJars()
 			}
 
-			deps.aidlIncludeDirs = append(deps.aidlIncludeDirs, dep.AidlIncludeDirs()...)
 		case android.SourceFileProducer:
 			switch tag {
 			case libTag:
@@ -806,7 +817,7 @@
 	v := sdkContext.sdkVersion()
 	// For PDK builds, use the latest SDK version instead of "current"
 	if ctx.Config().IsPdkBuild() && (v == "" || v == "current") {
-		sdkVersions := ctx.Config().Get(sdkSingletonKey).([]int)
+		sdkVersions := ctx.Config().Get(sdkVersionsKey).([]int)
 		latestSdkVersion := 0
 		if len(sdkVersions) > 0 {
 			latestSdkVersion = sdkVersions[len(sdkVersions)-1]
@@ -919,12 +930,7 @@
 	}
 
 	// aidl flags.
-	aidlFlags := j.aidlFlags(ctx, deps.aidlPreprocess, deps.aidlIncludeDirs)
-	if len(aidlFlags) > 0 {
-		// optimization.
-		ctx.Variable(pctx, "aidlFlags", strings.Join(aidlFlags, " "))
-		flags.aidlFlags = "$aidlFlags"
-	}
+	flags.aidlFlags, flags.aidlDeps = j.aidlFlags(ctx, deps.aidlPreprocess, deps.aidlIncludeDirs)
 
 	if len(javacFlags) > 0 {
 		// optimization.
diff --git a/java/java_test.go b/java/java_test.go
index 0a1c17c..1a4db21 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -97,7 +97,7 @@
 		ctx.TopDown("prebuilt_apis", PrebuiltApisMutator).Parallel()
 	})
 	ctx.RegisterPreSingletonType("overlay", android.SingletonFactoryAdaptor(OverlaySingletonFactory))
-	ctx.RegisterPreSingletonType("sdk", android.SingletonFactoryAdaptor(sdkSingletonFactory))
+	ctx.RegisterPreSingletonType("sdk_versions", android.SingletonFactoryAdaptor(sdkPreSingletonFactory))
 
 	// Register module types and mutators from cc needed for JNI testing
 	ctx.RegisterModuleType("cc_library", android.ModuleFactoryAdaptor(cc.LibraryFactory))
@@ -131,6 +131,7 @@
 		"api/system-removed.txt": nil,
 		"api/test-current.txt":   nil,
 		"api/test-removed.txt":   nil,
+		"framework/aidl/a.aidl":  nil,
 
 		"prebuilts/sdk/14/public/android.jar":         nil,
 		"prebuilts/sdk/14/public/framework.aidl":      nil,
diff --git a/java/sdk.go b/java/sdk.go
index 48e7746..d50bcae 100644
--- a/java/sdk.go
+++ b/java/sdk.go
@@ -22,13 +22,18 @@
 	"sort"
 	"strconv"
 	"strings"
+
+	"github.com/google/blueprint/pathtools"
 )
 
 func init() {
-	android.RegisterPreSingletonType("sdk", sdkSingletonFactory)
+	android.RegisterPreSingletonType("sdk_versions", sdkPreSingletonFactory)
+	android.RegisterSingletonType("sdk", sdkSingletonFactory)
+	android.RegisterMakeVarsProvider(pctx, sdkFrameworkAidlMakeVars)
 }
 
-var sdkSingletonKey = android.NewOnceKey("sdkSingletonKey")
+var sdkVersionsKey = android.NewOnceKey("sdkVersionsKey")
+var sdkFrameworkAidlPathKey = android.NewOnceKey("sdkFrameworkAidlPathKey")
 
 type sdkContext interface {
 	// sdkVersion eturns the sdk_version property of the current module, or an empty string if it is not set.
@@ -76,7 +81,7 @@
 	v := sdkContext.sdkVersion()
 	// For PDK builds, use the latest SDK version instead of "current"
 	if ctx.Config().IsPdkBuild() && (v == "" || v == "current") {
-		sdkVersions := ctx.Config().Get(sdkSingletonKey).([]int)
+		sdkVersions := ctx.Config().Get(sdkVersionsKey).([]int)
 		latestSdkVersion := 0
 		if len(sdkVersions) > 0 {
 			latestSdkVersion = sdkVersions[len(sdkVersions)-1]
@@ -130,17 +135,19 @@
 		return sdkDep{
 			useFiles: true,
 			jars:     android.Paths{jarPath.Path(), lambdaStubsPath},
-			aidl:     aidlPath.Path(),
+			aidl:     android.OptionalPathForPath(aidlPath.Path()),
 		}
 	}
 
-	toModule := func(m, r string) sdkDep {
+	toModule := func(m, r string, aidl android.Path) sdkDep {
 		ret := sdkDep{
 			useModule:          true,
 			modules:            []string{m, config.DefaultLambdaStubsLibrary},
 			systemModules:      m + "_system_modules",
 			frameworkResModule: r,
+			aidl:               android.OptionalPathForPath(aidl),
 		}
+
 		if m == "core.current.stubs" {
 			ret.systemModules = "core-system-modules"
 		} else if m == "core.platform.api.stubs" {
@@ -175,25 +182,25 @@
 			frameworkResModule: "framework-res",
 		}
 	case "current":
-		return toModule("android_stubs_current", "framework-res")
+		return toModule("android_stubs_current", "framework-res", sdkFrameworkAidlPath(ctx))
 	case "system_current":
-		return toModule("android_system_stubs_current", "framework-res")
+		return toModule("android_system_stubs_current", "framework-res", sdkFrameworkAidlPath(ctx))
 	case "test_current":
-		return toModule("android_test_stubs_current", "framework-res")
+		return toModule("android_test_stubs_current", "framework-res", sdkFrameworkAidlPath(ctx))
 	case "core_current":
-		return toModule("core.current.stubs", "")
+		return toModule("core.current.stubs", "", nil)
 	default:
 		return toPrebuilt(v)
 	}
 }
 
-func sdkSingletonFactory() android.Singleton {
-	return sdkSingleton{}
+func sdkPreSingletonFactory() android.Singleton {
+	return sdkPreSingleton{}
 }
 
-type sdkSingleton struct{}
+type sdkPreSingleton struct{}
 
-func (sdkSingleton) GenerateBuildActions(ctx android.SingletonContext) {
+func (sdkPreSingleton) GenerateBuildActions(ctx android.SingletonContext) {
 	sdkJars, err := ctx.GlobWithDeps("prebuilts/sdk/*/public/android.jar", nil)
 	if err != nil {
 		ctx.Errorf("failed to glob prebuilts/sdk/*/public/android.jar: %s", err.Error())
@@ -213,5 +220,98 @@
 
 	sort.Ints(sdkVersions)
 
-	ctx.Config().Once(sdkSingletonKey, func() interface{} { return sdkVersions })
+	ctx.Config().Once(sdkVersionsKey, func() interface{} { return sdkVersions })
+}
+
+func sdkSingletonFactory() android.Singleton {
+	return sdkSingleton{}
+}
+
+type sdkSingleton struct{}
+
+func (sdkSingleton) GenerateBuildActions(ctx android.SingletonContext) {
+	if ctx.Config().UnbundledBuildPrebuiltSdks() || ctx.Config().IsPdkBuild() {
+		return
+	}
+
+	// Create framework.aidl by extracting anything that implements android.os.Parcelable from the SDK stubs modules.
+
+	stubsModules := []string{
+		"android_stubs_current",
+		"android_test_stubs_current",
+		"android_system_stubs_current",
+	}
+
+	stubsJars := make([]android.Paths, len(stubsModules))
+
+	ctx.VisitAllModules(func(module android.Module) {
+		// Collect dex jar paths for the modules listed above.
+		if j, ok := module.(Dependency); ok {
+			name := ctx.ModuleName(module)
+			if i := android.IndexList(name, stubsModules); i != -1 {
+				stubsJars[i] = j.HeaderJars()
+			}
+		}
+	})
+
+	var missingDeps []string
+
+	for i := range stubsJars {
+		if stubsJars[i] == nil {
+			if ctx.Config().AllowMissingDependencies() {
+				missingDeps = append(missingDeps, stubsModules[i])
+			} else {
+				ctx.Errorf("failed to find dex jar path for module %q",
+					stubsModules[i])
+			}
+		}
+	}
+
+	rule := android.NewRuleBuilder()
+	rule.MissingDeps(missingDeps)
+
+	var aidls android.Paths
+	for _, jars := range stubsJars {
+		for _, jar := range jars {
+			aidl := android.PathForOutput(ctx, "aidl", pathtools.ReplaceExtension(jar.Base(), "aidl"))
+
+			rule.Command().
+				Text("rm -f").Output(aidl)
+			rule.Command().
+				Tool(ctx.Config().HostToolPath(ctx, "sdkparcelables")).
+				Input(jar).
+				Output(aidl)
+
+			aidls = append(aidls, aidl)
+		}
+	}
+
+	combinedAidl := sdkFrameworkAidlPath(ctx)
+	tempPath := combinedAidl.ReplaceExtension(ctx, "aidl.tmp")
+
+	rule.Command().
+		Text("rm -f").Output(tempPath)
+	rule.Command().
+		Text("cat").
+		Inputs(aidls).
+		Text("| sort -u >").
+		Output(tempPath)
+
+	commitChangeForRestat(rule, tempPath, combinedAidl)
+
+	rule.Build(pctx, ctx, "framework_aidl", "generate framework.aidl")
+}
+
+func sdkFrameworkAidlPath(ctx android.PathContext) android.OutputPath {
+	return ctx.Config().Once(sdkFrameworkAidlPathKey, func() interface{} {
+		return android.PathForOutput(ctx, "framework.aidl")
+	}).(android.OutputPath)
+}
+
+func sdkFrameworkAidlMakeVars(ctx android.MakeVarsContext) {
+	if ctx.Config().UnbundledBuildPrebuiltSdks() || ctx.Config().IsPdkBuild() {
+		return
+	}
+
+	ctx.Strict("FRAMEWORK_AIDL", sdkFrameworkAidlPath(ctx).String())
 }
diff --git a/java/sdk_test.go b/java/sdk_test.go
index a20e15f..e446129 100644
--- a/java/sdk_test.go
+++ b/java/sdk_test.go
@@ -26,165 +26,178 @@
 	"android/soong/java/config"
 )
 
-var classpathTestcases = []struct {
-	name          string
-	unbundled     bool
-	pdk           bool
-	moduleType    string
-	host          android.OsClass
-	properties    string
-	bootclasspath []string
-	system        string
-	classpath     []string
-}{
-	{
-		name:          "default",
-		bootclasspath: config.DefaultBootclasspathLibraries,
-		system:        config.DefaultSystemModules,
-		classpath:     config.DefaultLibraries,
-	},
-	{
-		name:          "blank sdk version",
-		properties:    `sdk_version: "",`,
-		bootclasspath: config.DefaultBootclasspathLibraries,
-		system:        config.DefaultSystemModules,
-		classpath:     config.DefaultLibraries,
-	},
-	{
-
-		name:          "sdk v25",
-		properties:    `sdk_version: "25",`,
-		bootclasspath: []string{`""`},
-		system:        "bootclasspath", // special value to tell 1.9 test to expect bootclasspath
-		classpath:     []string{"prebuilts/sdk/25/public/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"},
-	},
-	{
-
-		name:          "current",
-		properties:    `sdk_version: "current",`,
-		bootclasspath: []string{"android_stubs_current", "core-lambda-stubs"},
-		system:        "bootclasspath", // special value to tell 1.9 test to expect bootclasspath
-	},
-	{
-
-		name:          "system_current",
-		properties:    `sdk_version: "system_current",`,
-		bootclasspath: []string{"android_system_stubs_current", "core-lambda-stubs"},
-		system:        "bootclasspath", // special value to tell 1.9 test to expect bootclasspath
-	},
-	{
-
-		name:          "system_25",
-		properties:    `sdk_version: "system_25",`,
-		bootclasspath: []string{`""`},
-		system:        "bootclasspath", // special value to tell 1.9 test to expect bootclasspath
-		classpath:     []string{"prebuilts/sdk/25/system/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"},
-	},
-	{
-
-		name:          "test_current",
-		properties:    `sdk_version: "test_current",`,
-		bootclasspath: []string{"android_test_stubs_current", "core-lambda-stubs"},
-		system:        "bootclasspath", // special value to tell 1.9 test to expect bootclasspath
-	},
-	{
-
-		name:          "core_current",
-		properties:    `sdk_version: "core_current",`,
-		bootclasspath: []string{"core.current.stubs", "core-lambda-stubs"},
-		system:        "bootclasspath", // special value to tell 1.9 test to expect bootclasspath
-	},
-	{
-
-		name:          "nostdlib",
-		properties:    `no_standard_libs: true, system_modules: "none"`,
-		system:        "none",
-		bootclasspath: []string{`""`},
-		classpath:     []string{},
-	},
-	{
-
-		name:          "nostdlib system_modules",
-		properties:    `no_standard_libs: true, system_modules: "core-platform-api-stubs-system-modules"`,
-		system:        "core-platform-api-stubs-system-modules",
-		bootclasspath: []string{`""`},
-		classpath:     []string{},
-	},
-	{
-
-		name:          "host default",
-		moduleType:    "java_library_host",
-		properties:    ``,
-		host:          android.Host,
-		bootclasspath: []string{"jdk8/jre/lib/jce.jar", "jdk8/jre/lib/rt.jar"},
-		classpath:     []string{},
-	},
-	{
-		name:       "host nostdlib",
-		moduleType: "java_library_host",
-		host:       android.Host,
-		properties: `no_standard_libs: true`,
-		classpath:  []string{},
-	},
-	{
-
-		name:          "host supported default",
-		host:          android.Host,
-		properties:    `host_supported: true,`,
-		classpath:     []string{},
-		bootclasspath: []string{"jdk8/jre/lib/jce.jar", "jdk8/jre/lib/rt.jar"},
-	},
-	{
-		name:       "host supported nostdlib",
-		host:       android.Host,
-		properties: `host_supported: true, no_standard_libs: true, system_modules: "none"`,
-		classpath:  []string{},
-	},
-	{
-
-		name:          "unbundled sdk v25",
-		unbundled:     true,
-		properties:    `sdk_version: "25",`,
-		bootclasspath: []string{`""`},
-		system:        "bootclasspath", // special value to tell 1.9 test to expect bootclasspath
-		classpath:     []string{"prebuilts/sdk/25/public/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"},
-	},
-	{
-
-		name:          "unbundled current",
-		unbundled:     true,
-		properties:    `sdk_version: "current",`,
-		bootclasspath: []string{`""`},
-		system:        "bootclasspath", // special value to tell 1.9 test to expect bootclasspath
-		classpath:     []string{"prebuilts/sdk/current/public/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"},
-	},
-
-	{
-		name:          "pdk default",
-		pdk:           true,
-		bootclasspath: []string{`""`},
-		system:        "bootclasspath", // special value to tell 1.9 test to expect bootclasspath
-		classpath:     []string{"prebuilts/sdk/25/public/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"},
-	},
-	{
-		name:          "pdk current",
-		pdk:           true,
-		properties:    `sdk_version: "current",`,
-		bootclasspath: []string{`""`},
-		system:        "bootclasspath", // special value to tell 1.9 test to expect bootclasspath
-		classpath:     []string{"prebuilts/sdk/25/public/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"},
-	},
-	{
-		name:          "pdk 25",
-		pdk:           true,
-		properties:    `sdk_version: "25",`,
-		bootclasspath: []string{`""`},
-		system:        "bootclasspath", // special value to tell 1.9 test to expect bootclasspath
-		classpath:     []string{"prebuilts/sdk/25/public/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"},
-	},
-}
-
 func TestClasspath(t *testing.T) {
+	var classpathTestcases = []struct {
+		name          string
+		unbundled     bool
+		pdk           bool
+		moduleType    string
+		host          android.OsClass
+		properties    string
+		bootclasspath []string
+		system        string
+		classpath     []string
+		aidl          string
+	}{
+		{
+			name:          "default",
+			bootclasspath: config.DefaultBootclasspathLibraries,
+			system:        config.DefaultSystemModules,
+			classpath:     config.DefaultLibraries,
+			aidl:          "-Iframework/aidl",
+		},
+		{
+			name:          "blank sdk version",
+			properties:    `sdk_version: "",`,
+			bootclasspath: config.DefaultBootclasspathLibraries,
+			system:        config.DefaultSystemModules,
+			classpath:     config.DefaultLibraries,
+			aidl:          "-Iframework/aidl",
+		},
+		{
+
+			name:          "sdk v25",
+			properties:    `sdk_version: "25",`,
+			bootclasspath: []string{`""`},
+			system:        "bootclasspath", // special value to tell 1.9 test to expect bootclasspath
+			classpath:     []string{"prebuilts/sdk/25/public/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"},
+			aidl:          "-pprebuilts/sdk/25/public/framework.aidl",
+		},
+		{
+
+			name:          "current",
+			properties:    `sdk_version: "current",`,
+			bootclasspath: []string{"android_stubs_current", "core-lambda-stubs"},
+			system:        "bootclasspath", // special value to tell 1.9 test to expect bootclasspath
+			aidl:          "-p" + buildDir + "/framework.aidl",
+		},
+		{
+
+			name:          "system_current",
+			properties:    `sdk_version: "system_current",`,
+			bootclasspath: []string{"android_system_stubs_current", "core-lambda-stubs"},
+			system:        "bootclasspath", // special value to tell 1.9 test to expect bootclasspath
+			aidl:          "-p" + buildDir + "/framework.aidl",
+		},
+		{
+
+			name:          "system_25",
+			properties:    `sdk_version: "system_25",`,
+			bootclasspath: []string{`""`},
+			system:        "bootclasspath", // special value to tell 1.9 test to expect bootclasspath
+			classpath:     []string{"prebuilts/sdk/25/system/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"},
+			aidl:          "-pprebuilts/sdk/25/public/framework.aidl",
+		},
+		{
+
+			name:          "test_current",
+			properties:    `sdk_version: "test_current",`,
+			bootclasspath: []string{"android_test_stubs_current", "core-lambda-stubs"},
+			system:        "bootclasspath", // special value to tell 1.9 test to expect bootclasspath
+			aidl:          "-p" + buildDir + "/framework.aidl",
+		},
+		{
+
+			name:          "core_current",
+			properties:    `sdk_version: "core_current",`,
+			bootclasspath: []string{"core.current.stubs", "core-lambda-stubs"},
+			system:        "bootclasspath", // special value to tell 1.9 test to expect bootclasspath
+		},
+		{
+
+			name:          "nostdlib",
+			properties:    `no_standard_libs: true, system_modules: "none"`,
+			system:        "none",
+			bootclasspath: []string{`""`},
+			classpath:     []string{},
+		},
+		{
+
+			name:          "nostdlib system_modules",
+			properties:    `no_standard_libs: true, system_modules: "core-platform-api-stubs-system-modules"`,
+			system:        "core-platform-api-stubs-system-modules",
+			bootclasspath: []string{`""`},
+			classpath:     []string{},
+		},
+		{
+
+			name:          "host default",
+			moduleType:    "java_library_host",
+			properties:    ``,
+			host:          android.Host,
+			bootclasspath: []string{"jdk8/jre/lib/jce.jar", "jdk8/jre/lib/rt.jar"},
+			classpath:     []string{},
+		},
+		{
+			name:       "host nostdlib",
+			moduleType: "java_library_host",
+			host:       android.Host,
+			properties: `no_standard_libs: true`,
+			classpath:  []string{},
+		},
+		{
+
+			name:          "host supported default",
+			host:          android.Host,
+			properties:    `host_supported: true,`,
+			classpath:     []string{},
+			bootclasspath: []string{"jdk8/jre/lib/jce.jar", "jdk8/jre/lib/rt.jar"},
+		},
+		{
+			name:       "host supported nostdlib",
+			host:       android.Host,
+			properties: `host_supported: true, no_standard_libs: true, system_modules: "none"`,
+			classpath:  []string{},
+		},
+		{
+
+			name:          "unbundled sdk v25",
+			unbundled:     true,
+			properties:    `sdk_version: "25",`,
+			bootclasspath: []string{`""`},
+			system:        "bootclasspath", // special value to tell 1.9 test to expect bootclasspath
+			classpath:     []string{"prebuilts/sdk/25/public/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"},
+			aidl:          "-pprebuilts/sdk/25/public/framework.aidl",
+		},
+		{
+
+			name:          "unbundled current",
+			unbundled:     true,
+			properties:    `sdk_version: "current",`,
+			bootclasspath: []string{`""`},
+			system:        "bootclasspath", // special value to tell 1.9 test to expect bootclasspath
+			classpath:     []string{"prebuilts/sdk/current/public/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"},
+			aidl:          "-pprebuilts/sdk/current/public/framework.aidl",
+		},
+
+		{
+			name:          "pdk default",
+			pdk:           true,
+			bootclasspath: []string{`""`},
+			system:        "bootclasspath", // special value to tell 1.9 test to expect bootclasspath
+			classpath:     []string{"prebuilts/sdk/25/public/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"},
+			aidl:          "-pprebuilts/sdk/25/public/framework.aidl",
+		},
+		{
+			name:          "pdk current",
+			pdk:           true,
+			properties:    `sdk_version: "current",`,
+			bootclasspath: []string{`""`},
+			system:        "bootclasspath", // special value to tell 1.9 test to expect bootclasspath
+			classpath:     []string{"prebuilts/sdk/25/public/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"},
+			aidl:          "-pprebuilts/sdk/25/public/framework.aidl",
+		},
+		{
+			name:          "pdk 25",
+			pdk:           true,
+			properties:    `sdk_version: "25",`,
+			bootclasspath: []string{`""`},
+			system:        "bootclasspath", // special value to tell 1.9 test to expect bootclasspath
+			classpath:     []string{"prebuilts/sdk/25/public/android.jar", "prebuilts/sdk/tools/core-lambda-stubs.jar"},
+			aidl:          "-pprebuilts/sdk/25/public/framework.aidl",
+		},
+	}
+
 	for _, testcase := range classpathTestcases {
 		t.Run(testcase.name, func(t *testing.T) {
 			moduleType := "java_library"
@@ -195,6 +208,11 @@
 			bp := moduleType + ` {
 				name: "foo",
 				srcs: ["a.java"],
+				target: {
+					android: {
+						srcs: ["bar-doc/IFoo.aidl"],
+					},
+				},
 				` + testcase.properties + `
 			}`
 
@@ -230,18 +248,7 @@
 				system = "--system=" + filepath.Join(buildDir, ".intermediates", testcase.system, "android_common", "system") + "/"
 			}
 
-			t.Run("1.8", func(t *testing.T) {
-				// Test default javac 1.8
-				config := testConfig(nil)
-				if testcase.unbundled {
-					config.TestProductVariables.Unbundled_build = proptools.BoolPtr(true)
-				}
-				if testcase.pdk {
-					config.TestProductVariables.Pdk = proptools.BoolPtr(true)
-				}
-				ctx := testContext(config, bp, nil)
-				run(t, ctx, config)
-
+			checkClasspath := func(t *testing.T, ctx *android.TestContext) {
 				javac := ctx.ModuleForTests("foo", variant).Rule("javac")
 
 				got := javac.Args["bootClasspath"]
@@ -263,6 +270,33 @@
 				if !reflect.DeepEqual(javac.Implicits.Strings(), deps) {
 					t.Errorf("implicits expected %q != got %q", deps, javac.Implicits.Strings())
 				}
+			}
+
+			t.Run("1.8", func(t *testing.T) {
+				// Test default javac 1.8
+				config := testConfig(nil)
+				if testcase.unbundled {
+					config.TestProductVariables.Unbundled_build = proptools.BoolPtr(true)
+				}
+				if testcase.pdk {
+					config.TestProductVariables.Pdk = proptools.BoolPtr(true)
+				}
+				ctx := testContext(config, bp, nil)
+				run(t, ctx, config)
+
+				checkClasspath(t, ctx)
+
+				if testcase.host != android.Host {
+					aidl := ctx.ModuleForTests("foo", variant).Rule("aidl")
+
+					aidlFlags := aidl.Args["aidlFlags"]
+					// Trim trailing "-I." to avoid having to specify it in every test
+					aidlFlags = strings.TrimSpace(strings.TrimSuffix(aidlFlags, "-I."))
+
+					if g, w := aidlFlags, testcase.aidl; g != w {
+						t.Errorf("want aidl flags %q, got %q", w, g)
+					}
+				}
 			})
 
 			// Test again with javac 1.9
@@ -303,27 +337,7 @@
 				ctx := testContext(config, bp, nil)
 				run(t, ctx, config)
 
-				javac := ctx.ModuleForTests("foo", variant).Rule("javac")
-
-				got := javac.Args["bootClasspath"]
-				if got != bc {
-					t.Errorf("bootclasspath expected %q != got %q", bc, got)
-				}
-
-				got = javac.Args["classpath"]
-				if got != c {
-					t.Errorf("classpath expected %q != got %q", c, got)
-				}
-
-				var deps []string
-				if len(bootclasspath) > 0 && bootclasspath[0] != `""` {
-					deps = append(deps, bootclasspath...)
-				}
-				deps = append(deps, classpath...)
-
-				if !reflect.DeepEqual(javac.Implicits.Strings(), deps) {
-					t.Errorf("implicits expected %q != got %q", deps, javac.Implicits.Strings())
-				}
+				checkClasspath(t, ctx)
 			})
 		})
 	}
diff --git a/java/testing.go b/java/testing.go
index 7d23d8f..1be3768 100644
--- a/java/testing.go
+++ b/java/testing.go
@@ -37,7 +37,6 @@
 
 	extraModules := []string{
 		"core-lambda-stubs",
-		"framework",
 		"ext",
 		"android_stubs_current",
 		"android_system_stubs_current",
@@ -61,6 +60,17 @@
 	}
 
 	bp += `
+		java_library {
+			name: "framework",
+			srcs: ["a.java"],
+			no_standard_libs: true,
+			sdk_version: "core_current",
+			system_modules: "core-platform-api-stubs-system-modules",
+			aidl: {
+				export_include_dirs: ["framework/aidl"],
+			},
+		}
+
 		android_app {
 			name: "framework-res",
 			no_framework_libs: true,