diff --git a/java/droidstubs.go b/java/droidstubs.go index 7fd88fceb..0c66ccf40 100644 --- a/java/droidstubs.go +++ b/java/droidstubs.go @@ -25,6 +25,9 @@ import ( "android/soong/remoteexec" ) +// The values allowed for Droidstubs' Api_levels_sdk_type +var allowedApiLevelSdkTypes = []string{"public", "system", "module-lib"} + func init() { RegisterStubsBuildComponents(android.InitRegistrationContext) } @@ -134,7 +137,7 @@ type DroidstubsProperties struct { // the dirs which Metalava extracts API levels annotations from. Api_levels_annotations_dirs []string - // the sdk kind which Metalava extracts API levels annotations from. Supports 'public' and 'system' for now; defaults to public. + // the sdk kind which Metalava extracts API levels annotations from. Supports 'public', 'system' and 'module-lib' for now; defaults to public. Api_levels_sdk_type *string // the filename which Metalava extracts API levels annotations from. Defaults to android.jar. @@ -404,19 +407,24 @@ func (d *Droidstubs) apiLevelsAnnotationsFlags(ctx android.ModuleContext, cmd *a // When parsing a stub jar for a specific version, Metalava picks the first pattern that defines // an actual file present on disk (in the order the patterns were passed). For system APIs for // privileged apps that are only defined since API level 21 (Lollipop), fallback to public stubs - // for older releases. - if sdkType := proptools.StringDefault(d.properties.Api_levels_sdk_type, "public"); sdkType != "public" { - if sdkType != "system" { - ctx.PropertyErrorf("api_levels_sdk_type", "only 'public' and 'system' are supported") - } - // If building non public stubs, add all sdkType patterns first... - for _, dir := range dirs { - cmd.FlagWithArg("--android-jar-pattern ", fmt.Sprintf("%s/%%/%s/%s", dir, sdkType, filename)) - } + // for older releases. Similarly, module-lib falls back to system API. + var sdkDirs []string + switch proptools.StringDefault(d.properties.Api_levels_sdk_type, "public") { + case "module-lib": + sdkDirs = []string{"module-lib", "system", "public"} + case "system": + sdkDirs = []string{"system", "public"} + case "public": + sdkDirs = []string{"public"} + default: + ctx.PropertyErrorf("api_levels_sdk_type", "needs to be one of %v", allowedApiLevelSdkTypes) + return } - for _, dir := range dirs { - // ... and fallback to public ones, for Metalava to use if needed. - cmd.FlagWithArg("--android-jar-pattern ", fmt.Sprintf("%s/%%/%s/%s", dir, "public", filename)) + + for _, sdkDir := range sdkDirs { + for _, dir := range dirs { + cmd.FlagWithArg("--android-jar-pattern ", fmt.Sprintf("%s/%%/%s/%s", dir, sdkDir, filename)) + } } } diff --git a/java/droidstubs_test.go b/java/droidstubs_test.go index 60d0bea5d..10d99f3a5 100644 --- a/java/droidstubs_test.go +++ b/java/droidstubs_test.go @@ -15,6 +15,7 @@ package java import ( + "fmt" "reflect" "regexp" "strings" @@ -82,8 +83,10 @@ func TestDroidstubs(t *testing.T) { } } -func TestSystemDroidstubs(t *testing.T) { - ctx, _ := testJavaWithFS(t, ` +// runs a test for droidstubs with a customizable sdkType argument and returns +// the list of jar patterns that is passed as `--android-jar-pattern` +func getAndroidJarPatternsForDroidstubs(t *testing.T, sdkType string) []string { + ctx, _ := testJavaWithFS(t, fmt.Sprintf(` droiddoc_exported_dir { name: "some-exported-dir", path: "somedir", @@ -102,9 +105,9 @@ func TestSystemDroidstubs(t *testing.T) { "some-other-exported-dir", ], api_levels_annotations_enabled: true, - api_levels_sdk_type: "system", + api_levels_sdk_type: "%s", } - `, + `, sdkType), map[string][]byte{ "foo-doc/a.java": nil, }) @@ -113,13 +116,40 @@ func TestSystemDroidstubs(t *testing.T) { manifest := m.Output("metalava.sbox.textproto") cmd := String(android.RuleBuilderSboxProtoForTests(t, manifest).Commands[0].Command) r := regexp.MustCompile(`--android-jar-pattern [^ ]+/android.jar`) - matches := r.FindAllString(cmd, -1) + return r.FindAllString(cmd, -1) +} + +func TestPublicDroidstubs(t *testing.T) { + patterns := getAndroidJarPatternsForDroidstubs(t, "public") + + android.AssertArrayString(t, "order of patterns", []string{ + "--android-jar-pattern somedir/%/public/android.jar", + "--android-jar-pattern someotherdir/%/public/android.jar", + }, patterns) +} + +func TestSystemDroidstubs(t *testing.T) { + patterns := getAndroidJarPatternsForDroidstubs(t, "system") + android.AssertArrayString(t, "order of patterns", []string{ "--android-jar-pattern somedir/%/system/android.jar", "--android-jar-pattern someotherdir/%/system/android.jar", "--android-jar-pattern somedir/%/public/android.jar", "--android-jar-pattern someotherdir/%/public/android.jar", - }, matches) + }, patterns) +} + +func TestModuleLibDroidstubs(t *testing.T) { + patterns := getAndroidJarPatternsForDroidstubs(t, "module-lib") + + android.AssertArrayString(t, "order of patterns", []string{ + "--android-jar-pattern somedir/%/module-lib/android.jar", + "--android-jar-pattern someotherdir/%/module-lib/android.jar", + "--android-jar-pattern somedir/%/system/android.jar", + "--android-jar-pattern someotherdir/%/system/android.jar", + "--android-jar-pattern somedir/%/public/android.jar", + "--android-jar-pattern someotherdir/%/public/android.jar", + }, patterns) } func TestDroidstubsSandbox(t *testing.T) {