Merge "Create public stub for platform's sysprop_library"

This commit is contained in:
Treehugger Robot 2019-12-19 03:23:01 +00:00 committed by Gerrit Code Review
commit 0cbb31e9e7
6 changed files with 227 additions and 75 deletions

View File

@ -298,6 +298,7 @@ bootstrap_go_package {
"java/sdk.go",
"java/sdk_library.go",
"java/support_libraries.go",
"java/sysprop.go",
"java/system_modules.go",
"java/testing.go",
"java/tradefed.go",

View File

@ -42,7 +42,7 @@ func init() {
ctx.BottomUp("test_per_src", TestPerSrcMutator).Parallel()
ctx.BottomUp("version", VersionMutator).Parallel()
ctx.BottomUp("begin", BeginMutator).Parallel()
ctx.BottomUp("sysprop", SyspropMutator).Parallel()
ctx.BottomUp("sysprop_cc", SyspropMutator).Parallel()
})
android.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {

View File

@ -594,8 +594,36 @@ func (j *Module) deps(ctx android.BottomUpMutatorContext) {
}
}
ctx.AddVariationDependencies(nil, libTag, j.properties.Libs...)
ctx.AddVariationDependencies(nil, staticLibTag, j.properties.Static_libs...)
syspropPublicStubs := syspropPublicStubs(ctx.Config())
// rewriteSyspropLibs validates if a java module can link against platform's sysprop_library,
// and redirects dependency to public stub depending on the link type.
rewriteSyspropLibs := func(libs []string, prop string) []string {
// make a copy
ret := android.CopyOf(libs)
for idx, lib := range libs {
stub, ok := syspropPublicStubs[lib]
if !ok {
continue
}
linkType, _ := j.getLinkType(ctx.ModuleName())
if linkType == javaSystem {
ret[idx] = stub
} else if linkType != javaPlatform {
ctx.PropertyErrorf("sdk_version",
"can't link against sysprop_library %q from a module using public or core API",
lib)
}
}
return ret
}
ctx.AddVariationDependencies(nil, libTag, rewriteSyspropLibs(j.properties.Libs, "libs")...)
ctx.AddVariationDependencies(nil, staticLibTag, rewriteSyspropLibs(j.properties.Static_libs, "static_libs")...)
ctx.AddFarVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(), pluginTag, j.properties.Plugins...)
ctx.AddFarVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(), exportedPluginTag, j.properties.Exported_plugins...)

60
java/sysprop.go Normal file
View File

@ -0,0 +1,60 @@
// Copyright (C) 2019 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.
package java
import (
"sync"
"android/soong/android"
)
type syspropLibraryInterface interface {
BaseModuleName() string
Owner() string
HasPublicStub() bool
JavaPublicStubName() string
}
var (
syspropPublicStubsKey = android.NewOnceKey("syspropPublicStubsJava")
syspropPublicStubsLock sync.Mutex
)
func init() {
android.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
ctx.BottomUp("sysprop_java", SyspropMutator).Parallel()
})
}
func syspropPublicStubs(config android.Config) map[string]string {
return config.Once(syspropPublicStubsKey, func() interface{} {
return make(map[string]string)
}).(map[string]string)
}
// gather list of sysprop libraries owned by platform.
func SyspropMutator(mctx android.BottomUpMutatorContext) {
if m, ok := mctx.Module().(syspropLibraryInterface); ok {
if m.Owner() != "Platform" || !m.HasPublicStub() {
return
}
syspropPublicStubs := syspropPublicStubs(mctx.Config())
syspropPublicStubsLock.Lock()
defer syspropPublicStubsLock.Unlock()
syspropPublicStubs[m.BaseModuleName()] = m.JavaPublicStubName()
}
}

View File

@ -35,6 +35,7 @@ type dependencyTag struct {
type syspropGenProperties struct {
Srcs []string `android:"path"`
Scope string
Name *string
}
type syspropJavaGenRule struct {
@ -142,6 +143,9 @@ type syspropLibraryProperties struct {
// list of .sysprop files which defines the properties.
Srcs []string `android:"path"`
// Whether public stub exists or not.
Public_stub *bool `blueprint:"mutated"`
}
var (
@ -157,18 +161,37 @@ func (m *syspropLibrary) Name() string {
return m.BaseModuleName() + "_sysprop_library"
}
func (m *syspropLibrary) Owner() string {
return m.properties.Property_owner
}
func (m *syspropLibrary) CcModuleName() string {
return "lib" + m.BaseModuleName()
}
func (m *syspropLibrary) JavaPublicStubName() string {
if proptools.Bool(m.properties.Public_stub) {
return m.BaseModuleName() + "_public"
}
return ""
}
func (m *syspropLibrary) javaGenModuleName() string {
return m.BaseModuleName() + "_java_gen"
}
func (m *syspropLibrary) javaGenPublicStubName() string {
return m.BaseModuleName() + "_java_gen_public"
}
func (m *syspropLibrary) BaseModuleName() string {
return m.ModuleBase.Name()
}
func (m *syspropLibrary) HasPublicStub() bool {
return proptools.Bool(m.properties.Public_stub)
}
func (m *syspropLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
baseModuleName := m.BaseModuleName()
@ -274,6 +297,36 @@ func syspropLibraryFactory() android.Module {
return m
}
type ccLibraryProperties struct {
Name *string
Srcs []string
Soc_specific *bool
Device_specific *bool
Product_specific *bool
Sysprop struct {
Platform *bool
}
Header_libs []string
Shared_libs []string
Required []string
Recovery *bool
Recovery_available *bool
Vendor_available *bool
}
type javaLibraryProperties struct {
Name *string
Srcs []string
Soc_specific *bool
Device_specific *bool
Product_specific *bool
Required []string
Sdk_version *string
Installable *bool
Libs []string
Stem *string
}
func syspropLibraryHook(ctx android.LoadHookContext, m *syspropLibrary) {
if len(m.properties.Srcs) == 0 {
ctx.PropertyErrorf("srcs", "sysprop_library must specify srcs")
@ -304,120 +357,107 @@ func syspropLibraryHook(ctx android.LoadHookContext, m *syspropLibrary) {
return
}
socSpecific := ctx.SocSpecific()
deviceSpecific := ctx.DeviceSpecific()
productSpecific := ctx.ProductSpecific()
owner := m.properties.Property_owner
// ctx's Platform or Specific functions represent where this sysprop_library installed.
installedInSystem := ctx.Platform() || ctx.SystemExtSpecific()
installedInVendorOrOdm := ctx.SocSpecific() || ctx.DeviceSpecific()
isOwnerPlatform := false
stub := "sysprop-library-stub-"
switch owner {
switch m.Owner() {
case "Platform":
// Every partition can access platform-defined properties
stub += "platform"
isOwnerPlatform = true
case "Vendor":
// System can't access vendor's properties
if !socSpecific && !deviceSpecific && !productSpecific {
if installedInSystem {
ctx.ModuleErrorf("None of soc_specific, device_specific, product_specific is true. " +
"System can't access sysprop_library owned by Vendor")
}
stub += "vendor"
case "Odm":
// Only vendor can access Odm-defined properties
if !socSpecific && !deviceSpecific {
if !installedInVendorOrOdm {
ctx.ModuleErrorf("Neither soc_speicifc nor device_specific is true. " +
"Odm-defined properties should be accessed only in Vendor or Odm")
}
stub += "vendor"
default:
ctx.PropertyErrorf("property_owner",
"Unknown value %s: must be one of Platform, Vendor or Odm", owner)
"Unknown value %s: must be one of Platform, Vendor or Odm", m.Owner())
}
ccProps := struct {
Name *string
Srcs []string
Soc_specific *bool
Device_specific *bool
Product_specific *bool
Sysprop struct {
Platform *bool
}
Header_libs []string
Shared_libs []string
Required []string
Recovery *bool
Recovery_available *bool
Vendor_available *bool
}{}
ccProps := ccLibraryProperties{}
ccProps.Name = proptools.StringPtr(m.CcModuleName())
ccProps.Srcs = m.properties.Srcs
ccProps.Soc_specific = proptools.BoolPtr(socSpecific)
ccProps.Device_specific = proptools.BoolPtr(deviceSpecific)
ccProps.Product_specific = proptools.BoolPtr(productSpecific)
ccProps.Sysprop.Platform = proptools.BoolPtr(owner == "Platform")
ccProps.Soc_specific = proptools.BoolPtr(ctx.SocSpecific())
ccProps.Device_specific = proptools.BoolPtr(ctx.DeviceSpecific())
ccProps.Product_specific = proptools.BoolPtr(ctx.ProductSpecific())
ccProps.Sysprop.Platform = proptools.BoolPtr(isOwnerPlatform)
ccProps.Header_libs = []string{"libbase_headers"}
ccProps.Shared_libs = []string{"liblog"}
ccProps.Recovery_available = m.properties.Recovery_available
ccProps.Vendor_available = m.properties.Vendor_available
ctx.CreateModule(cc.LibraryFactory, &ccProps)
// internal scope contains all properties
// public scope only contains public properties
// use public if the owner is different from client
scope := "internal"
isProduct := ctx.ProductSpecific()
isVendor := ctx.SocSpecific()
isOwnerPlatform := owner == "Platform"
if isProduct {
// product can't own any sysprop_library now, so product must use public scope
// We need to only use public version, if the partition where sysprop_library will be installed
// is different from owner.
if ctx.ProductSpecific() {
// Currently product partition can't own any sysprop_library.
scope = "public"
} else if isVendor && isOwnerPlatform {
// vendor and odm can only use the public properties from the platform
} else if isOwnerPlatform && installedInVendorOrOdm {
// Vendor or Odm should use public version of Platform's sysprop_library.
scope = "public"
}
javaGenProps := struct {
Srcs []string
Scope string
Name *string
}{
ctx.CreateModule(syspropJavaGenFactory, &syspropGenProperties{
Srcs: m.properties.Srcs,
Scope: scope,
Name: proptools.StringPtr(m.javaGenModuleName()),
})
ctx.CreateModule(java.LibraryFactory, &javaLibraryProperties{
Name: proptools.StringPtr(m.BaseModuleName()),
Srcs: []string{":" + m.javaGenModuleName()},
Soc_specific: proptools.BoolPtr(ctx.SocSpecific()),
Device_specific: proptools.BoolPtr(ctx.DeviceSpecific()),
Product_specific: proptools.BoolPtr(ctx.ProductSpecific()),
Installable: m.properties.Installable,
Sdk_version: proptools.StringPtr("core_current"),
Libs: []string{stub},
})
// if platform sysprop_library is installed in /system or /system-ext, we regard it as an API
// and allow any modules (even from different partition) to link against the sysprop_library.
// To do that, we create a public stub and expose it to modules with sdk_version: system_*.
if isOwnerPlatform && installedInSystem {
m.properties.Public_stub = proptools.BoolPtr(true)
ctx.CreateModule(syspropJavaGenFactory, &syspropGenProperties{
Srcs: m.properties.Srcs,
Scope: "public",
Name: proptools.StringPtr(m.javaGenPublicStubName()),
})
ctx.CreateModule(java.LibraryFactory, &javaLibraryProperties{
Name: proptools.StringPtr(m.JavaPublicStubName()),
Srcs: []string{":" + m.javaGenPublicStubName()},
Installable: proptools.BoolPtr(false),
Sdk_version: proptools.StringPtr("core_current"),
Libs: []string{stub},
Stem: proptools.StringPtr(m.BaseModuleName()),
})
}
ctx.CreateModule(syspropJavaGenFactory, &javaGenProps)
javaProps := struct {
Name *string
Srcs []string
Soc_specific *bool
Device_specific *bool
Product_specific *bool
Required []string
Sdk_version *string
Installable *bool
Libs []string
}{}
javaProps.Name = proptools.StringPtr(m.BaseModuleName())
javaProps.Srcs = []string{":" + *javaGenProps.Name}
javaProps.Soc_specific = proptools.BoolPtr(socSpecific)
javaProps.Device_specific = proptools.BoolPtr(deviceSpecific)
javaProps.Product_specific = proptools.BoolPtr(productSpecific)
javaProps.Installable = m.properties.Installable
javaProps.Sdk_version = proptools.StringPtr("core_current")
javaProps.Libs = []string{stub}
ctx.CreateModule(java.LibraryFactory, &javaProps)
}
func syspropDepsMutator(ctx android.BottomUpMutatorContext) {
if m, ok := ctx.Module().(*syspropLibrary); ok {
ctx.AddReverseDependency(m, nil, m.javaGenModuleName())
if proptools.Bool(m.properties.Public_stub) {
ctx.AddReverseDependency(m, nil, m.javaGenPublicStubName())
}
}
}

View File

@ -24,6 +24,7 @@ import (
"strings"
"testing"
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
)
@ -76,7 +77,8 @@ func testContext(config android.Config) *android.TestContext {
ctx.BottomUp("vndk", cc.VndkMutator).Parallel()
ctx.BottomUp("version", cc.VersionMutator).Parallel()
ctx.BottomUp("begin", cc.BeginMutator).Parallel()
ctx.BottomUp("sysprop", cc.SyspropMutator).Parallel()
ctx.BottomUp("sysprop_cc", cc.SyspropMutator).Parallel()
ctx.BottomUp("sysprop_java", java.SyspropMutator).Parallel()
})
ctx.RegisterModuleType("sysprop_library", syspropLibraryFactory)
@ -204,6 +206,13 @@ func TestSyspropLibrary(t *testing.T) {
libs: ["sysprop-platform"],
}
java_library {
name: "java-platform-private",
srcs: ["c.java"],
platform_apis: true,
libs: ["sysprop-platform"],
}
java_library {
name: "java-product",
srcs: ["c.java"],
@ -302,6 +311,7 @@ func TestSyspropLibrary(t *testing.T) {
}
ctx.ModuleForTests("sysprop-platform", "android_common")
ctx.ModuleForTests("sysprop-platform_public", "android_common")
ctx.ModuleForTests("sysprop-vendor", "android_common")
// Check for exported includes
@ -354,4 +364,17 @@ func TestSyspropLibrary(t *testing.T) {
t.Errorf("flags for vendor must contain %#v and %#v, but was %#v.",
platformPublicVendorPath, vendorInternalPath, vendorFlags)
}
// Java modules linking against system API should use public stub
javaSystemApiClient := ctx.ModuleForTests("java-platform", "android_common")
publicStubFound := false
ctx.VisitDirectDeps(javaSystemApiClient.Module(), func(dep blueprint.Module) {
if dep.Name() == "sysprop-platform_public" {
publicStubFound = true
}
})
if !publicStubFound {
t.Errorf("system api client should use public stub")
}
}