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
6 changed files with 227 additions and 75 deletions

View File

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

View File

@@ -42,7 +42,7 @@ func init() {
ctx.BottomUp("test_per_src", TestPerSrcMutator).Parallel() ctx.BottomUp("test_per_src", TestPerSrcMutator).Parallel()
ctx.BottomUp("version", VersionMutator).Parallel() ctx.BottomUp("version", VersionMutator).Parallel()
ctx.BottomUp("begin", BeginMutator).Parallel() ctx.BottomUp("begin", BeginMutator).Parallel()
ctx.BottomUp("sysprop", SyspropMutator).Parallel() ctx.BottomUp("sysprop_cc", SyspropMutator).Parallel()
}) })
android.PostDepsMutators(func(ctx android.RegisterMutatorsContext) { 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...) syspropPublicStubs := syspropPublicStubs(ctx.Config())
ctx.AddVariationDependencies(nil, staticLibTag, j.properties.Static_libs...)
// 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(), pluginTag, j.properties.Plugins...)
ctx.AddFarVariationDependencies(ctx.Config().BuildOSCommonTarget.Variations(), exportedPluginTag, j.properties.Exported_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 { type syspropGenProperties struct {
Srcs []string `android:"path"` Srcs []string `android:"path"`
Scope string Scope string
Name *string
} }
type syspropJavaGenRule struct { type syspropJavaGenRule struct {
@@ -142,6 +143,9 @@ type syspropLibraryProperties struct {
// list of .sysprop files which defines the properties. // list of .sysprop files which defines the properties.
Srcs []string `android:"path"` Srcs []string `android:"path"`
// Whether public stub exists or not.
Public_stub *bool `blueprint:"mutated"`
} }
var ( var (
@@ -157,18 +161,37 @@ func (m *syspropLibrary) Name() string {
return m.BaseModuleName() + "_sysprop_library" return m.BaseModuleName() + "_sysprop_library"
} }
func (m *syspropLibrary) Owner() string {
return m.properties.Property_owner
}
func (m *syspropLibrary) CcModuleName() string { func (m *syspropLibrary) CcModuleName() string {
return "lib" + m.BaseModuleName() 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 { func (m *syspropLibrary) javaGenModuleName() string {
return m.BaseModuleName() + "_java_gen" return m.BaseModuleName() + "_java_gen"
} }
func (m *syspropLibrary) javaGenPublicStubName() string {
return m.BaseModuleName() + "_java_gen_public"
}
func (m *syspropLibrary) BaseModuleName() string { func (m *syspropLibrary) BaseModuleName() string {
return m.ModuleBase.Name() return m.ModuleBase.Name()
} }
func (m *syspropLibrary) HasPublicStub() bool {
return proptools.Bool(m.properties.Public_stub)
}
func (m *syspropLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) { func (m *syspropLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
baseModuleName := m.BaseModuleName() baseModuleName := m.BaseModuleName()
@@ -274,6 +297,36 @@ func syspropLibraryFactory() android.Module {
return m 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) { func syspropLibraryHook(ctx android.LoadHookContext, m *syspropLibrary) {
if len(m.properties.Srcs) == 0 { if len(m.properties.Srcs) == 0 {
ctx.PropertyErrorf("srcs", "sysprop_library must specify srcs") ctx.PropertyErrorf("srcs", "sysprop_library must specify srcs")
@@ -304,120 +357,107 @@ func syspropLibraryHook(ctx android.LoadHookContext, m *syspropLibrary) {
return return
} }
socSpecific := ctx.SocSpecific() // ctx's Platform or Specific functions represent where this sysprop_library installed.
deviceSpecific := ctx.DeviceSpecific() installedInSystem := ctx.Platform() || ctx.SystemExtSpecific()
productSpecific := ctx.ProductSpecific() installedInVendorOrOdm := ctx.SocSpecific() || ctx.DeviceSpecific()
isOwnerPlatform := false
owner := m.properties.Property_owner
stub := "sysprop-library-stub-" stub := "sysprop-library-stub-"
switch owner { switch m.Owner() {
case "Platform": case "Platform":
// Every partition can access platform-defined properties // Every partition can access platform-defined properties
stub += "platform" stub += "platform"
isOwnerPlatform = true
case "Vendor": case "Vendor":
// System can't access vendor's properties // 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. " + ctx.ModuleErrorf("None of soc_specific, device_specific, product_specific is true. " +
"System can't access sysprop_library owned by Vendor") "System can't access sysprop_library owned by Vendor")
} }
stub += "vendor" stub += "vendor"
case "Odm": case "Odm":
// Only vendor can access Odm-defined properties // Only vendor can access Odm-defined properties
if !socSpecific && !deviceSpecific { if !installedInVendorOrOdm {
ctx.ModuleErrorf("Neither soc_speicifc nor device_specific is true. " + ctx.ModuleErrorf("Neither soc_speicifc nor device_specific is true. " +
"Odm-defined properties should be accessed only in Vendor or Odm") "Odm-defined properties should be accessed only in Vendor or Odm")
} }
stub += "vendor" stub += "vendor"
default: default:
ctx.PropertyErrorf("property_owner", 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 { ccProps := ccLibraryProperties{}
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.Name = proptools.StringPtr(m.CcModuleName()) ccProps.Name = proptools.StringPtr(m.CcModuleName())
ccProps.Srcs = m.properties.Srcs ccProps.Srcs = m.properties.Srcs
ccProps.Soc_specific = proptools.BoolPtr(socSpecific) ccProps.Soc_specific = proptools.BoolPtr(ctx.SocSpecific())
ccProps.Device_specific = proptools.BoolPtr(deviceSpecific) ccProps.Device_specific = proptools.BoolPtr(ctx.DeviceSpecific())
ccProps.Product_specific = proptools.BoolPtr(productSpecific) ccProps.Product_specific = proptools.BoolPtr(ctx.ProductSpecific())
ccProps.Sysprop.Platform = proptools.BoolPtr(owner == "Platform") ccProps.Sysprop.Platform = proptools.BoolPtr(isOwnerPlatform)
ccProps.Header_libs = []string{"libbase_headers"} ccProps.Header_libs = []string{"libbase_headers"}
ccProps.Shared_libs = []string{"liblog"} ccProps.Shared_libs = []string{"liblog"}
ccProps.Recovery_available = m.properties.Recovery_available ccProps.Recovery_available = m.properties.Recovery_available
ccProps.Vendor_available = m.properties.Vendor_available ccProps.Vendor_available = m.properties.Vendor_available
ctx.CreateModule(cc.LibraryFactory, &ccProps) 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" scope := "internal"
isProduct := ctx.ProductSpecific()
isVendor := ctx.SocSpecific()
isOwnerPlatform := owner == "Platform"
if isProduct { // We need to only use public version, if the partition where sysprop_library will be installed
// product can't own any sysprop_library now, so product must use public scope // is different from owner.
if ctx.ProductSpecific() {
// Currently product partition can't own any sysprop_library.
scope = "public" scope = "public"
} else if isVendor && isOwnerPlatform { } else if isOwnerPlatform && installedInVendorOrOdm {
// vendor and odm can only use the public properties from the platform // Vendor or Odm should use public version of Platform's sysprop_library.
scope = "public" scope = "public"
} }
javaGenProps := struct { ctx.CreateModule(syspropJavaGenFactory, &syspropGenProperties{
Srcs []string
Scope string
Name *string
}{
Srcs: m.properties.Srcs, Srcs: m.properties.Srcs,
Scope: scope, Scope: scope,
Name: proptools.StringPtr(m.javaGenModuleName()), 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) { func syspropDepsMutator(ctx android.BottomUpMutatorContext) {
if m, ok := ctx.Module().(*syspropLibrary); ok { if m, ok := ctx.Module().(*syspropLibrary); ok {
ctx.AddReverseDependency(m, nil, m.javaGenModuleName()) 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" "strings"
"testing" "testing"
"github.com/google/blueprint"
"github.com/google/blueprint/proptools" "github.com/google/blueprint/proptools"
) )
@@ -76,7 +77,8 @@ func testContext(config android.Config) *android.TestContext {
ctx.BottomUp("vndk", cc.VndkMutator).Parallel() ctx.BottomUp("vndk", cc.VndkMutator).Parallel()
ctx.BottomUp("version", cc.VersionMutator).Parallel() ctx.BottomUp("version", cc.VersionMutator).Parallel()
ctx.BottomUp("begin", cc.BeginMutator).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) ctx.RegisterModuleType("sysprop_library", syspropLibraryFactory)
@@ -204,6 +206,13 @@ func TestSyspropLibrary(t *testing.T) {
libs: ["sysprop-platform"], libs: ["sysprop-platform"],
} }
java_library {
name: "java-platform-private",
srcs: ["c.java"],
platform_apis: true,
libs: ["sysprop-platform"],
}
java_library { java_library {
name: "java-product", name: "java-product",
srcs: ["c.java"], srcs: ["c.java"],
@@ -302,6 +311,7 @@ func TestSyspropLibrary(t *testing.T) {
} }
ctx.ModuleForTests("sysprop-platform", "android_common") ctx.ModuleForTests("sysprop-platform", "android_common")
ctx.ModuleForTests("sysprop-platform_public", "android_common")
ctx.ModuleForTests("sysprop-vendor", "android_common") ctx.ModuleForTests("sysprop-vendor", "android_common")
// Check for exported includes // 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.", t.Errorf("flags for vendor must contain %#v and %#v, but was %#v.",
platformPublicVendorPath, vendorInternalPath, vendorFlags) 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")
}
} }