diff --git a/apex/androidmk.go b/apex/androidmk.go index a231a907c..7d1a3015b 100644 --- a/apex/androidmk.go +++ b/apex/androidmk.go @@ -22,7 +22,6 @@ import ( "android/soong/android" "android/soong/cc" - "android/soong/java" "github.com/google/blueprint/proptools" ) @@ -119,7 +118,7 @@ func (a *apexBundle) androidMkForFiles(w io.Writer, apexName, moduleDir string) } } if fi.class == javaSharedLib { - javaModule := fi.module.(*java.Library) + javaModule := fi.module.(javaLibrary) // soong_java_prebuilt.mk sets LOCAL_MODULE_SUFFIX := .jar Therefore // we need to remove the suffix from LOCAL_MODULE_STEM, otherwise // we will have foo.jar.jar diff --git a/apex/apex.go b/apex/apex.go index 8a336ba21..f6997bf58 100644 --- a/apex/apex.go +++ b/apex/apex.go @@ -872,10 +872,16 @@ func apexFileForShBinary(ctx android.BaseModuleContext, sh *android.ShBinary) ap return af } -func apexFileForJavaLibrary(ctx android.BaseModuleContext, java *java.Library) apexFile { +// TODO(b/146586360): replace javaLibrary(in apex/apex.go) with java.Dependency +type javaLibrary interface { + android.Module + java.Dependency +} + +func apexFileForJavaLibrary(ctx android.BaseModuleContext, lib javaLibrary) apexFile { dirInApex := "javalib" - fileToCopy := java.DexJarFile() - return newApexFile(ctx, fileToCopy, java.Name(), dirInApex, javaSharedLib, java) + fileToCopy := lib.DexJar() + return newApexFile(ctx, fileToCopy, lib.Name(), dirInApex, javaSharedLib, lib) } func apexFileForPrebuiltJavaLibrary(ctx android.BaseModuleContext, java *java.Import) apexFile { @@ -1022,6 +1028,21 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) { filesInfo = append(filesInfo, af) return true // track transitive dependencies } + } else if sdkLib, ok := child.(*java.SdkLibrary); ok { + af := apexFileForJavaLibrary(ctx, sdkLib) + if !af.Ok() { + ctx.PropertyErrorf("java_libs", "%q is not configured to be compiled into dex", depName) + return false + } + filesInfo = append(filesInfo, af) + + pf := sdkLib.PermissionFile() + if pf == nil { + ctx.PropertyErrorf("java_libs", "%q failed to generate permission XML", depName) + return false + } + filesInfo = append(filesInfo, newApexFile(ctx, pf, pf.Base(), "etc/permissions", etc, nil)) + return true // track transitive dependencies } else if javaLib, ok := child.(*java.Import); ok { af := apexFileForPrebuiltJavaLibrary(ctx, javaLib) if !af.Ok() { diff --git a/apex/apex_test.go b/apex/apex_test.go index 035a553f9..bb64f801c 100644 --- a/apex/apex_test.go +++ b/apex/apex_test.go @@ -306,6 +306,7 @@ func testApexContext(t *testing.T, bp string, handlers ...testCustomizer) (*andr java.RegisterJavaBuildComponents(ctx) java.RegisterSystemModulesBuildComponents(ctx) java.RegisterAppBuildComponents(ctx) + ctx.RegisterModuleType("java_sdk_library", java.SdkLibraryFactory) ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators) ctx.PreArchMutators(func(ctx android.RegisterMutatorsContext) { @@ -3252,6 +3253,44 @@ func TestLegacyAndroid10Support(t *testing.T) { ensureContains(t, args["opt_flags"], "--manifest_json "+module.Output("apex_manifest.json").Output.String()) } +func TestJavaSDKLibrary(t *testing.T) { + ctx, _ := testApex(t, ` + apex { + name: "myapex", + key: "myapex.key", + java_libs: ["foo"], + } + + apex_key { + name: "myapex.key", + public_key: "testkey.avbpubkey", + private_key: "testkey.pem", + } + + java_sdk_library { + name: "foo", + srcs: ["a.java"], + api_packages: ["foo"], + } + `, withFiles(map[string][]byte{ + "api/current.txt": nil, + "api/removed.txt": nil, + "api/system-current.txt": nil, + "api/system-removed.txt": nil, + "api/test-current.txt": nil, + "api/test-removed.txt": nil, + })) + + // java_sdk_library installs both impl jar and permission XML + ensureExactContents(t, ctx, "myapex", []string{ + "javalib/foo.jar", + "etc/permissions/foo.xml", + }) + // Permission XML should point to the activated path of impl jar of java_sdk_library + genXMLCommand := ctx.ModuleForTests("foo", "android_common_myapex").Output("foo.xml").RuleParams.Command + ensureContains(t, genXMLCommand, ` + + + + +` ) type stubsLibraryDependencyTag struct { @@ -134,6 +153,8 @@ type SdkLibrary struct { publicApiFilePath android.Path systemApiFilePath android.Path testApiFilePath android.Path + + permissionFile android.Path } var _ Dependency = (*SdkLibrary)(nil) @@ -163,6 +184,10 @@ func (module *SdkLibrary) DepsMutator(ctx android.BottomUpMutatorContext) { func (module *SdkLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) { module.Library.GenerateAndroidBuildActions(ctx) + if module.ApexName() != "" { + module.buildPermissionFile(ctx) + } + // Record the paths to the header jars of the library (stubs and impl). // When this java_sdk_library is dependened from others via "libs" property, // the recorded paths will be returned depending on the link type of the caller. @@ -198,6 +223,21 @@ func (module *SdkLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) }) } +func (module *SdkLibrary) buildPermissionFile(ctx android.ModuleContext) { + xmlContent := strings.ReplaceAll(fmt.Sprintf(permissionTemplate, module.BaseModuleName(), module.implPath()), "\n", "\\n") + permissionFile := android.PathForModuleOut(ctx, module.xmlFileName()) + + rule := android.NewRuleBuilder() + rule.Command().Text("echo -e ").Text(proptools.ShellEscape(xmlContent)).Text(">").Output(permissionFile) + rule.Build(pctx, ctx, "gen_permission_xml", "Generate permission") + + module.permissionFile = permissionFile +} + +func (module *SdkLibrary) PermissionFile() android.Path { + return module.permissionFile +} + func (module *SdkLibrary) AndroidMkEntries() []android.AndroidMkEntries { entriesList := module.Library.AndroidMkEntries() entries := &entriesList[0] @@ -290,6 +330,12 @@ func (module *SdkLibrary) implName() string { // File path to the runtime implementation library func (module *SdkLibrary) implPath() string { + if apexName := module.ApexName(); apexName != "" { + // TODO(b/146468504): ApexName() is only a soong module name, not apex name. + // In most cases, this works fine. But when apex_name is set or override_apex is used + // this can be wrong. + return fmt.Sprintf("/apex/%s/javalib/%s.jar", apexName, module.implName()) + } partition := "system" if module.SocSpecific() { partition = "vendor" @@ -532,31 +578,11 @@ func (module *SdkLibrary) createDocs(mctx android.LoadHookContext, apiScope apiS // Creates the xml file that publicizes the runtime library func (module *SdkLibrary) createXmlFile(mctx android.LoadHookContext) { - template := ` - - - - - - -` // genrule to generate the xml file content from the template above // TODO: preserve newlines in the generate xml file. Newlines are being squashed // in the ninja file. Do we need to have an external tool for this? - xmlContent := fmt.Sprintf(template, module.BaseModuleName(), module.implPath()) + xmlContent := fmt.Sprintf(permissionTemplate, module.BaseModuleName(), module.implPath()) genruleProps := struct { Name *string Cmd *string @@ -666,10 +692,12 @@ func javaSdkLibraries(config android.Config) *[]string { func (module *SdkLibrary) CreateInternalModules(mctx android.LoadHookContext) { if len(module.Library.Module.properties.Srcs) == 0 { mctx.PropertyErrorf("srcs", "java_sdk_library must specify srcs") + return } if len(module.sdkLibraryProperties.Api_packages) == 0 { mctx.PropertyErrorf("api_packages", "java_sdk_library must specify api_packages") + return } missing_current_api := false @@ -745,6 +773,7 @@ func (module *SdkLibrary) InitSdkLibraryProperties() { func SdkLibraryFactory() android.Module { module := &SdkLibrary{} module.InitSdkLibraryProperties() + android.InitApexModule(module) InitJavaModule(module, android.HostAndDeviceSupported) android.AddLoadHook(module, func(ctx android.LoadHookContext) { module.CreateInternalModules(ctx) }) return module