Split out sdk.go from java.go

Split out SDK handling functions from java.go to sdk.go and tests
from java_test.go to sdk.go.

Test: sdk_test.go
Change-Id: I83ef48cbe5230572c1d4ecc0e89021d2f7c71b76
diff --git a/java/java.go b/java/java.go
index 8b8e4ba..9955be9 100644
--- a/java/java.go
+++ b/java/java.go
@@ -430,154 +430,6 @@
 	return j.sdkVersion()
 }
 
-type sdkContext interface {
-	// sdkVersion eturns the sdk_version property of the current module, or an empty string if it is not set.
-	sdkVersion() string
-	// minSdkVersion returns the min_sdk_version property of the current module, or sdkVersion() if it is not set.
-	minSdkVersion() string
-	// targetSdkVersion returns the target_sdk_version property of the current module, or sdkVersion() if it is not set.
-	targetSdkVersion() string
-}
-
-func sdkVersionOrDefault(ctx android.BaseContext, v string) string {
-	switch v {
-	case "", "current", "system_current", "test_current", "core_current":
-		return ctx.Config().DefaultAppTargetSdk()
-	default:
-		return v
-	}
-}
-
-// Returns a sdk version as a number.  For modules targeting an unreleased SDK (meaning it does not yet have a number)
-// it returns android.FutureApiLevel (10000).
-func sdkVersionToNumber(ctx android.BaseContext, v string) (int, error) {
-	switch v {
-	case "", "current", "test_current", "system_current", "core_current":
-		return ctx.Config().DefaultAppTargetSdkInt(), nil
-	default:
-		n := android.GetNumericSdkVersion(v)
-		if i, err := strconv.Atoi(n); err != nil {
-			return -1, fmt.Errorf("invalid sdk version %q", n)
-		} else {
-			return i, nil
-		}
-	}
-}
-
-func sdkVersionToNumberAsString(ctx android.BaseContext, v string) (string, error) {
-	n, err := sdkVersionToNumber(ctx, v)
-	if err != nil {
-		return "", err
-	}
-	return strconv.Itoa(n), nil
-}
-
-func decodeSdkDep(ctx android.BaseContext, sdkContext sdkContext) sdkDep {
-	v := sdkContext.sdkVersion()
-	i, err := sdkVersionToNumber(ctx, v)
-	if err != nil {
-		ctx.PropertyErrorf("sdk_version", "%s", err)
-		return sdkDep{}
-	}
-
-	// Ensures that the specificed system SDK version is one of BOARD_SYSTEMSDK_VERSIONS (for vendor apks)
-	// or PRODUCT_SYSTEMSDK_VERSIONS (for other apks or when BOARD_SYSTEMSDK_VERSIONS is not set)
-	if strings.HasPrefix(v, "system_") && i != android.FutureApiLevel {
-		allowed_versions := ctx.DeviceConfig().PlatformSystemSdkVersions()
-		if ctx.DeviceSpecific() || ctx.SocSpecific() {
-			if len(ctx.DeviceConfig().SystemSdkVersions()) > 0 {
-				allowed_versions = ctx.DeviceConfig().SystemSdkVersions()
-			}
-		}
-		version := strings.TrimPrefix(v, "system_")
-		if len(allowed_versions) > 0 && !android.InList(version, allowed_versions) {
-			ctx.PropertyErrorf("sdk_version", "incompatible sdk version %q. System SDK version should be one of %q",
-				v, allowed_versions)
-		}
-	}
-
-	toPrebuilt := func(sdk string) sdkDep {
-		var api, v string
-		if strings.Contains(sdk, "_") {
-			t := strings.Split(sdk, "_")
-			api = t[0]
-			v = t[1]
-		} else {
-			api = "public"
-			v = sdk
-		}
-		dir := filepath.Join("prebuilts", "sdk", v, api)
-		jar := filepath.Join(dir, "android.jar")
-		// There's no aidl for other SDKs yet.
-		// TODO(77525052): Add aidl files for other SDKs too.
-		public_dir := filepath.Join("prebuilts", "sdk", v, "public")
-		aidl := filepath.Join(public_dir, "framework.aidl")
-		jarPath := android.ExistentPathForSource(ctx, jar)
-		aidlPath := android.ExistentPathForSource(ctx, aidl)
-		lambdaStubsPath := android.PathForSource(ctx, config.SdkLambdaStubsPath)
-
-		if (!jarPath.Valid() || !aidlPath.Valid()) && ctx.Config().AllowMissingDependencies() {
-			return sdkDep{
-				invalidVersion: true,
-				modules:        []string{fmt.Sprintf("sdk_%s_%s_android", api, v)},
-			}
-		}
-
-		if !jarPath.Valid() {
-			ctx.PropertyErrorf("sdk_version", "invalid sdk version %q, %q does not exist", v, jar)
-			return sdkDep{}
-		}
-
-		if !aidlPath.Valid() {
-			ctx.PropertyErrorf("sdk_version", "invalid sdk version %q, %q does not exist", v, aidl)
-			return sdkDep{}
-		}
-
-		return sdkDep{
-			useFiles: true,
-			jars:     android.Paths{jarPath.Path(), lambdaStubsPath},
-			aidl:     aidlPath.Path(),
-		}
-	}
-
-	toModule := func(m, r string) sdkDep {
-		ret := sdkDep{
-			useModule:          true,
-			modules:            []string{m, config.DefaultLambdaStubsLibrary},
-			systemModules:      m + "_system_modules",
-			frameworkResModule: r,
-		}
-		if m == "core.current.stubs" {
-			ret.systemModules = "core-system-modules"
-		} else if m == "core.platform.api.stubs" {
-			ret.systemModules = "core-platform-api-stubs-system-modules"
-		}
-		return ret
-	}
-
-	if ctx.Config().UnbundledBuildPrebuiltSdks() && v != "" {
-		return toPrebuilt(v)
-	}
-
-	switch v {
-	case "":
-		return sdkDep{
-			useDefaultLibs:     true,
-			frameworkResModule: "framework-res",
-		}
-	case "current":
-		return toModule("android_stubs_current", "framework-res")
-	case "system_current":
-		return toModule("android_system_stubs_current", "framework-res")
-	case "test_current":
-		return toModule("android_test_stubs_current", "framework-res")
-	case "core_current":
-		return toModule("core.current.stubs", "")
-	default:
-		return toPrebuilt(v)
-	}
-}
-
 func (j *Module) deps(ctx android.BottomUpMutatorContext) {
 	if ctx.Device() {
 		if !Bool(j.properties.No_standard_libs) {
diff --git a/java/java_test.go b/java/java_test.go
index c4cf905..889cae7 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -19,13 +19,10 @@
 	"io/ioutil"
 	"os"
 	"path/filepath"
-	"reflect"
 	"strconv"
 	"strings"
 	"testing"
 
-	"github.com/google/blueprint/proptools"
-
 	"android/soong/android"
 	"android/soong/cc"
 	"android/soong/genrule"
@@ -354,241 +351,6 @@
 
 }
 
-var classpathTestcases = []struct {
-	name          string
-	unbundled     bool
-	moduleType    string
-	host          android.OsClass
-	properties    string
-	bootclasspath []string
-	system        string
-	classpath     []string
-}{
-	{
-		name:          "default",
-		bootclasspath: []string{"core.platform.api.stubs", "core-lambda-stubs"},
-		system:        "core-platform-api-stubs-system-modules",
-		classpath:     []string{"ext", "framework"},
-	},
-	{
-		name:          "blank sdk version",
-		properties:    `sdk_version: "",`,
-		bootclasspath: []string{"core.platform.api.stubs", "core-lambda-stubs"},
-		system:        "core-platform-api-stubs-system-modules",
-		classpath:     []string{"ext", "framework"},
-	},
-	{
-
-		name:          "sdk v14",
-		properties:    `sdk_version: "14",`,
-		bootclasspath: []string{`""`},
-		system:        "bootclasspath", // special value to tell 1.9 test to expect bootclasspath
-		classpath:     []string{"prebuilts/sdk/14/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_14",
-		properties:    `sdk_version: "system_14",`,
-		bootclasspath: []string{`""`},
-		system:        "bootclasspath", // special value to tell 1.9 test to expect bootclasspath
-		classpath:     []string{"prebuilts/sdk/14/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 v14",
-		unbundled:     true,
-		properties:    `sdk_version: "14",`,
-		bootclasspath: []string{`""`},
-		system:        "bootclasspath", // special value to tell 1.9 test to expect bootclasspath
-		classpath:     []string{"prebuilts/sdk/14/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"},
-	},
-}
-
-func TestClasspath(t *testing.T) {
-	for _, testcase := range classpathTestcases {
-		t.Run(testcase.name, func(t *testing.T) {
-			moduleType := "java_library"
-			if testcase.moduleType != "" {
-				moduleType = testcase.moduleType
-			}
-
-			bp := moduleType + ` {
-				name: "foo",
-				srcs: ["a.java"],
-				` + testcase.properties + `
-			}`
-
-			variant := "android_common"
-			if testcase.host == android.Host {
-				variant = android.BuildOs.String() + "_common"
-			}
-
-			convertModulesToPaths := func(cp []string) []string {
-				ret := make([]string, len(cp))
-				for i, e := range cp {
-					ret[i] = moduleToPath(e)
-				}
-				return ret
-			}
-
-			bootclasspath := convertModulesToPaths(testcase.bootclasspath)
-			classpath := convertModulesToPaths(testcase.classpath)
-
-			bc := strings.Join(bootclasspath, ":")
-			if bc != "" {
-				bc = "-bootclasspath " + bc
-			}
-
-			c := strings.Join(classpath, ":")
-			if c != "" {
-				c = "-classpath " + c
-			}
-			system := ""
-			if testcase.system == "none" {
-				system = "--system=none"
-			} else if testcase.system != "" {
-				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)
-				}
-				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())
-				}
-			})
-
-			// Test again with javac 1.9
-			t.Run("1.9", func(t *testing.T) {
-				config := testConfig(map[string]string{"EXPERIMENTAL_USE_OPENJDK9": "true"})
-				if testcase.unbundled {
-					config.TestProductVariables.Unbundled_build = proptools.BoolPtr(true)
-				}
-				ctx := testContext(config, bp, nil)
-				run(t, ctx, config)
-
-				javac := ctx.ModuleForTests("foo", variant).Rule("javac")
-				got := javac.Args["bootClasspath"]
-				expected := system
-				if testcase.system == "bootclasspath" {
-					expected = bc
-				}
-				if got != expected {
-					t.Errorf("bootclasspath expected %q != got %q", expected, got)
-				}
-			})
-		})
-	}
-
-}
-
 func TestPrebuilts(t *testing.T) {
 	ctx := testJava(t, `
 		java_library {
diff --git a/java/sdk.go b/java/sdk.go
new file mode 100644
index 0000000..cd128d1
--- /dev/null
+++ b/java/sdk.go
@@ -0,0 +1,172 @@
+// Copyright 2019 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 java
+
+import (
+	"android/soong/android"
+	"android/soong/java/config"
+	"fmt"
+	"path/filepath"
+	"strconv"
+	"strings"
+)
+
+type sdkContext interface {
+	// sdkVersion eturns the sdk_version property of the current module, or an empty string if it is not set.
+	sdkVersion() string
+	// minSdkVersion returns the min_sdk_version property of the current module, or sdkVersion() if it is not set.
+	minSdkVersion() string
+	// targetSdkVersion returns the target_sdk_version property of the current module, or sdkVersion() if it is not set.
+	targetSdkVersion() string
+}
+
+func sdkVersionOrDefault(ctx android.BaseContext, v string) string {
+	switch v {
+	case "", "current", "system_current", "test_current", "core_current":
+		return ctx.Config().DefaultAppTargetSdk()
+	default:
+		return v
+	}
+}
+
+// Returns a sdk version as a number.  For modules targeting an unreleased SDK (meaning it does not yet have a number)
+// it returns android.FutureApiLevel (10000).
+func sdkVersionToNumber(ctx android.BaseContext, v string) (int, error) {
+	switch v {
+	case "", "current", "test_current", "system_current", "core_current":
+		return ctx.Config().DefaultAppTargetSdkInt(), nil
+	default:
+		n := android.GetNumericSdkVersion(v)
+		if i, err := strconv.Atoi(n); err != nil {
+			return -1, fmt.Errorf("invalid sdk version %q", n)
+		} else {
+			return i, nil
+		}
+	}
+}
+
+func sdkVersionToNumberAsString(ctx android.BaseContext, v string) (string, error) {
+	n, err := sdkVersionToNumber(ctx, v)
+	if err != nil {
+		return "", err
+	}
+	return strconv.Itoa(n), nil
+}
+
+func decodeSdkDep(ctx android.BaseContext, sdkContext sdkContext) sdkDep {
+	v := sdkContext.sdkVersion()
+	i, err := sdkVersionToNumber(ctx, v)
+	if err != nil {
+		ctx.PropertyErrorf("sdk_version", "%s", err)
+		return sdkDep{}
+	}
+
+	// Ensures that the specificed system SDK version is one of BOARD_SYSTEMSDK_VERSIONS (for vendor apks)
+	// or PRODUCT_SYSTEMSDK_VERSIONS (for other apks or when BOARD_SYSTEMSDK_VERSIONS is not set)
+	if strings.HasPrefix(v, "system_") && i != android.FutureApiLevel {
+		allowed_versions := ctx.DeviceConfig().PlatformSystemSdkVersions()
+		if ctx.DeviceSpecific() || ctx.SocSpecific() {
+			if len(ctx.DeviceConfig().SystemSdkVersions()) > 0 {
+				allowed_versions = ctx.DeviceConfig().SystemSdkVersions()
+			}
+		}
+		version := strings.TrimPrefix(v, "system_")
+		if len(allowed_versions) > 0 && !android.InList(version, allowed_versions) {
+			ctx.PropertyErrorf("sdk_version", "incompatible sdk version %q. System SDK version should be one of %q",
+				v, allowed_versions)
+		}
+	}
+
+	toPrebuilt := func(sdk string) sdkDep {
+		var api, v string
+		if strings.Contains(sdk, "_") {
+			t := strings.Split(sdk, "_")
+			api = t[0]
+			v = t[1]
+		} else {
+			api = "public"
+			v = sdk
+		}
+		dir := filepath.Join("prebuilts", "sdk", v, api)
+		jar := filepath.Join(dir, "android.jar")
+		// There's no aidl for other SDKs yet.
+		// TODO(77525052): Add aidl files for other SDKs too.
+		public_dir := filepath.Join("prebuilts", "sdk", v, "public")
+		aidl := filepath.Join(public_dir, "framework.aidl")
+		jarPath := android.ExistentPathForSource(ctx, jar)
+		aidlPath := android.ExistentPathForSource(ctx, aidl)
+		lambdaStubsPath := android.PathForSource(ctx, config.SdkLambdaStubsPath)
+
+		if (!jarPath.Valid() || !aidlPath.Valid()) && ctx.Config().AllowMissingDependencies() {
+			return sdkDep{
+				invalidVersion: true,
+				modules:        []string{fmt.Sprintf("sdk_%s_%s_android", api, v)},
+			}
+		}
+
+		if !jarPath.Valid() {
+			ctx.PropertyErrorf("sdk_version", "invalid sdk version %q, %q does not exist", v, jar)
+			return sdkDep{}
+		}
+
+		if !aidlPath.Valid() {
+			ctx.PropertyErrorf("sdk_version", "invalid sdk version %q, %q does not exist", v, aidl)
+			return sdkDep{}
+		}
+
+		return sdkDep{
+			useFiles: true,
+			jars:     android.Paths{jarPath.Path(), lambdaStubsPath},
+			aidl:     aidlPath.Path(),
+		}
+	}
+
+	toModule := func(m, r string) sdkDep {
+		ret := sdkDep{
+			useModule:          true,
+			modules:            []string{m, config.DefaultLambdaStubsLibrary},
+			systemModules:      m + "_system_modules",
+			frameworkResModule: r,
+		}
+		if m == "core.current.stubs" {
+			ret.systemModules = "core-system-modules"
+		} else if m == "core.platform.api.stubs" {
+			ret.systemModules = "core-platform-api-stubs-system-modules"
+		}
+		return ret
+	}
+
+	if ctx.Config().UnbundledBuildPrebuiltSdks() && v != "" {
+		return toPrebuilt(v)
+	}
+
+	switch v {
+	case "":
+		return sdkDep{
+			useDefaultLibs:     true,
+			frameworkResModule: "framework-res",
+		}
+	case "current":
+		return toModule("android_stubs_current", "framework-res")
+	case "system_current":
+		return toModule("android_system_stubs_current", "framework-res")
+	case "test_current":
+		return toModule("android_test_stubs_current", "framework-res")
+	case "core_current":
+		return toModule("core.current.stubs", "")
+	default:
+		return toPrebuilt(v)
+	}
+}
diff --git a/java/sdk_test.go b/java/sdk_test.go
new file mode 100644
index 0000000..ced7729
--- /dev/null
+++ b/java/sdk_test.go
@@ -0,0 +1,260 @@
+// Copyright 2019 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 java
+
+import (
+	"android/soong/android"
+	"path/filepath"
+	"reflect"
+	"strings"
+	"testing"
+
+	"github.com/google/blueprint/proptools"
+)
+
+var classpathTestcases = []struct {
+	name          string
+	unbundled     bool
+	moduleType    string
+	host          android.OsClass
+	properties    string
+	bootclasspath []string
+	system        string
+	classpath     []string
+}{
+	{
+		name:          "default",
+		bootclasspath: []string{"core.platform.api.stubs", "core-lambda-stubs"},
+		system:        "core-platform-api-stubs-system-modules",
+		classpath:     []string{"ext", "framework"},
+	},
+	{
+		name:          "blank sdk version",
+		properties:    `sdk_version: "",`,
+		bootclasspath: []string{"core.platform.api.stubs", "core-lambda-stubs"},
+		system:        "core-platform-api-stubs-system-modules",
+		classpath:     []string{"ext", "framework"},
+	},
+	{
+
+		name:          "sdk v14",
+		properties:    `sdk_version: "14",`,
+		bootclasspath: []string{`""`},
+		system:        "bootclasspath", // special value to tell 1.9 test to expect bootclasspath
+		classpath:     []string{"prebuilts/sdk/14/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_14",
+		properties:    `sdk_version: "system_14",`,
+		bootclasspath: []string{`""`},
+		system:        "bootclasspath", // special value to tell 1.9 test to expect bootclasspath
+		classpath:     []string{"prebuilts/sdk/14/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 v14",
+		unbundled:     true,
+		properties:    `sdk_version: "14",`,
+		bootclasspath: []string{`""`},
+		system:        "bootclasspath", // special value to tell 1.9 test to expect bootclasspath
+		classpath:     []string{"prebuilts/sdk/14/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"},
+	},
+}
+
+func TestClasspath(t *testing.T) {
+	for _, testcase := range classpathTestcases {
+		t.Run(testcase.name, func(t *testing.T) {
+			moduleType := "java_library"
+			if testcase.moduleType != "" {
+				moduleType = testcase.moduleType
+			}
+
+			bp := moduleType + ` {
+				name: "foo",
+				srcs: ["a.java"],
+				` + testcase.properties + `
+			}`
+
+			variant := "android_common"
+			if testcase.host == android.Host {
+				variant = android.BuildOs.String() + "_common"
+			}
+
+			convertModulesToPaths := func(cp []string) []string {
+				ret := make([]string, len(cp))
+				for i, e := range cp {
+					ret[i] = moduleToPath(e)
+				}
+				return ret
+			}
+
+			bootclasspath := convertModulesToPaths(testcase.bootclasspath)
+			classpath := convertModulesToPaths(testcase.classpath)
+
+			bc := strings.Join(bootclasspath, ":")
+			if bc != "" {
+				bc = "-bootclasspath " + bc
+			}
+
+			c := strings.Join(classpath, ":")
+			if c != "" {
+				c = "-classpath " + c
+			}
+			system := ""
+			if testcase.system == "none" {
+				system = "--system=none"
+			} else if testcase.system != "" {
+				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)
+				}
+				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())
+				}
+			})
+
+			// Test again with javac 1.9
+			t.Run("1.9", func(t *testing.T) {
+				config := testConfig(map[string]string{"EXPERIMENTAL_USE_OPENJDK9": "true"})
+				if testcase.unbundled {
+					config.TestProductVariables.Unbundled_build = proptools.BoolPtr(true)
+				}
+				ctx := testContext(config, bp, nil)
+				run(t, ctx, config)
+
+				javac := ctx.ModuleForTests("foo", variant).Rule("javac")
+				got := javac.Args["bootClasspath"]
+				expected := system
+				if testcase.system == "bootclasspath" {
+					expected = bc
+				}
+				if got != expected {
+					t.Errorf("bootclasspath expected %q != got %q", expected, got)
+				}
+			})
+		})
+	}
+
+}