Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 58f26aba authored by Jooyung Han's avatar Jooyung Han
Browse files

Support java_sdk_library as java_libs of apex

When a java_sdk_library module is added, both impl jar and permission
xml files are packaged together.

For example, when a java_sdk_library "foo" is listed, following two
entries will be in an APEX package.

/javalibs/foo.jar
/etc/permissions/foo.xml

Bug: 145474221
Test: m com.android.cronet
      deapexer list com.android.cronet.apex

Change-Id: If5883c02255e9309f20810b1532d3fbe73bf4e95
parent 6b295312
Loading
Loading
Loading
Loading
+1 −2
Original line number Original line Diff line number Diff line
@@ -22,7 +22,6 @@ import (


	"android/soong/android"
	"android/soong/android"
	"android/soong/cc"
	"android/soong/cc"
	"android/soong/java"


	"github.com/google/blueprint/proptools"
	"github.com/google/blueprint/proptools"
)
)
@@ -119,7 +118,7 @@ func (a *apexBundle) androidMkForFiles(w io.Writer, apexName, moduleDir string)
			}
			}
		}
		}
		if fi.class == javaSharedLib {
		if fi.class == javaSharedLib {
			javaModule := fi.module.(*java.Library)
			javaModule := fi.module.(javaLibrary)
			// soong_java_prebuilt.mk sets LOCAL_MODULE_SUFFIX := .jar  Therefore
			// soong_java_prebuilt.mk sets LOCAL_MODULE_SUFFIX := .jar  Therefore
			// we need to remove the suffix from LOCAL_MODULE_STEM, otherwise
			// we need to remove the suffix from LOCAL_MODULE_STEM, otherwise
			// we will have foo.jar.jar
			// we will have foo.jar.jar
+24 −3
Original line number Original line Diff line number Diff line
@@ -872,10 +872,16 @@ func apexFileForShBinary(ctx android.BaseModuleContext, sh *android.ShBinary) ap
	return af
	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"
	dirInApex := "javalib"
	fileToCopy := java.DexJarFile()
	fileToCopy := lib.DexJar()
	return newApexFile(ctx, fileToCopy, java.Name(), dirInApex, javaSharedLib, java)
	return newApexFile(ctx, fileToCopy, lib.Name(), dirInApex, javaSharedLib, lib)
}
}


func apexFileForPrebuiltJavaLibrary(ctx android.BaseModuleContext, java *java.Import) apexFile {
func apexFileForPrebuiltJavaLibrary(ctx android.BaseModuleContext, java *java.Import) apexFile {
@@ -1022,6 +1028,21 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
						filesInfo = append(filesInfo, af)
						filesInfo = append(filesInfo, af)
						return true // track transitive dependencies
						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 {
				} else if javaLib, ok := child.(*java.Import); ok {
					af := apexFileForPrebuiltJavaLibrary(ctx, javaLib)
					af := apexFileForPrebuiltJavaLibrary(ctx, javaLib)
					if !af.Ok() {
					if !af.Ok() {
+39 −0
Original line number Original line Diff line number Diff line
@@ -306,6 +306,7 @@ func testApexContext(t *testing.T, bp string, handlers ...testCustomizer) (*andr
	java.RegisterJavaBuildComponents(ctx)
	java.RegisterJavaBuildComponents(ctx)
	java.RegisterSystemModulesBuildComponents(ctx)
	java.RegisterSystemModulesBuildComponents(ctx)
	java.RegisterAppBuildComponents(ctx)
	java.RegisterAppBuildComponents(ctx)
	ctx.RegisterModuleType("java_sdk_library", java.SdkLibraryFactory)


	ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
	ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
	ctx.PreArchMutators(func(ctx android.RegisterMutatorsContext) {
	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())
	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, `<library name="foo" file="/apex/myapex/javalib/foo.jar"`)
}

func TestRejectNonInstallableJavaLibrary(t *testing.T) {
func TestRejectNonInstallableJavaLibrary(t *testing.T) {
	testApexError(t, `"myjar" is not configured to be compiled into dex`, `
	testApexError(t, `"myjar" is not configured to be compiled into dex`, `
		apex {
		apex {
+0 −4
Original line number Original line Diff line number Diff line
@@ -426,10 +426,6 @@ func (j *Module) OutputFiles(tag string) (android.Paths, error) {
	}
	}
}
}


func (j *Module) DexJarFile() android.Path {
	return j.dexJarFile
}

var _ android.OutputFileProducer = (*Module)(nil)
var _ android.OutputFileProducer = (*Module)(nil)


type Dependency interface {
type Dependency interface {
+51 −22
Original line number Original line Diff line number Diff line
@@ -29,12 +29,31 @@ import (
	"github.com/google/blueprint/proptools"
	"github.com/google/blueprint/proptools"
)
)


var (
const (
	sdkStubsLibrarySuffix = ".stubs"
	sdkStubsLibrarySuffix = ".stubs"
	sdkSystemApiSuffix    = ".system"
	sdkSystemApiSuffix    = ".system"
	sdkTestApiSuffix      = ".test"
	sdkTestApiSuffix      = ".test"
	sdkDocsSuffix         = ".docs"
	sdkDocsSuffix         = ".docs"
	sdkXmlFileSuffix      = ".xml"
	sdkXmlFileSuffix      = ".xml"
	permissionTemplate    = `<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2018 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.
-->
<permissions>
	<library name="%s" file="%s"/>
</permissions>
`
)
)


type stubsLibraryDependencyTag struct {
type stubsLibraryDependencyTag struct {
@@ -134,6 +153,8 @@ type SdkLibrary struct {
	publicApiFilePath android.Path
	publicApiFilePath android.Path
	systemApiFilePath android.Path
	systemApiFilePath android.Path
	testApiFilePath   android.Path
	testApiFilePath   android.Path

	permissionFile android.Path
}
}


var _ Dependency = (*SdkLibrary)(nil)
var _ Dependency = (*SdkLibrary)(nil)
@@ -163,6 +184,10 @@ func (module *SdkLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {
func (module *SdkLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
func (module *SdkLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
	module.Library.GenerateAndroidBuildActions(ctx)
	module.Library.GenerateAndroidBuildActions(ctx)


	if module.ApexName() != "" {
		module.buildPermissionFile(ctx)
	}

	// Record the paths to the header jars of the library (stubs and impl).
	// 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,
	// 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.
	// 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 {
func (module *SdkLibrary) AndroidMkEntries() []android.AndroidMkEntries {
	entriesList := module.Library.AndroidMkEntries()
	entriesList := module.Library.AndroidMkEntries()
	entries := &entriesList[0]
	entries := &entriesList[0]
@@ -290,6 +330,12 @@ func (module *SdkLibrary) implName() string {


// File path to the runtime implementation library
// File path to the runtime implementation library
func (module *SdkLibrary) implPath() string {
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"
	partition := "system"
	if module.SocSpecific() {
	if module.SocSpecific() {
		partition = "vendor"
		partition = "vendor"
@@ -532,31 +578,11 @@ func (module *SdkLibrary) createDocs(mctx android.LoadHookContext, apiScope apiS


// Creates the xml file that publicizes the runtime library
// Creates the xml file that publicizes the runtime library
func (module *SdkLibrary) createXmlFile(mctx android.LoadHookContext) {
func (module *SdkLibrary) createXmlFile(mctx android.LoadHookContext) {
	template := `
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2018 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.
-->

<permissions>
    <library name="%s" file="%s"/>
</permissions>
`
	// genrule to generate the xml file content from the template above
	// genrule to generate the xml file content from the template above
	// TODO: preserve newlines in the generate xml file. Newlines are being squashed
	// 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?
	// 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 {
	genruleProps := struct {
		Name *string
		Name *string
		Cmd  *string
		Cmd  *string
@@ -666,10 +692,12 @@ func javaSdkLibraries(config android.Config) *[]string {
func (module *SdkLibrary) CreateInternalModules(mctx android.LoadHookContext) {
func (module *SdkLibrary) CreateInternalModules(mctx android.LoadHookContext) {
	if len(module.Library.Module.properties.Srcs) == 0 {
	if len(module.Library.Module.properties.Srcs) == 0 {
		mctx.PropertyErrorf("srcs", "java_sdk_library must specify srcs")
		mctx.PropertyErrorf("srcs", "java_sdk_library must specify srcs")
		return
	}
	}


	if len(module.sdkLibraryProperties.Api_packages) == 0 {
	if len(module.sdkLibraryProperties.Api_packages) == 0 {
		mctx.PropertyErrorf("api_packages", "java_sdk_library must specify api_packages")
		mctx.PropertyErrorf("api_packages", "java_sdk_library must specify api_packages")
		return
	}
	}


	missing_current_api := false
	missing_current_api := false
@@ -745,6 +773,7 @@ func (module *SdkLibrary) InitSdkLibraryProperties() {
func SdkLibraryFactory() android.Module {
func SdkLibraryFactory() android.Module {
	module := &SdkLibrary{}
	module := &SdkLibrary{}
	module.InitSdkLibraryProperties()
	module.InitSdkLibraryProperties()
	android.InitApexModule(module)
	InitJavaModule(module, android.HostAndDeviceSupported)
	InitJavaModule(module, android.HostAndDeviceSupported)
	android.AddLoadHook(module, func(ctx android.LoadHookContext) { module.CreateInternalModules(ctx) })
	android.AddLoadHook(module, func(ctx android.LoadHookContext) { module.CreateInternalModules(ctx) })
	return module
	return module