aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-02-03 19:59:59 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-02-03 19:59:59 +0000
commit1a6d55f949f3599a51a1b5c253be8d143dec99fe (patch)
tree5a4175d1e905d066e2a5df8575b29d8c84607a89
parent8710ea81d6a6bfcb702519738628991216c6fa38 (diff)
parentd9100a56e64541c340ffb8c72fe04db95b6fd6a8 (diff)
downloadsoong-android12-mainline-neuralnetworks-release.tar.gz
Snap for 8146243 from d9100a56e64541c340ffb8c72fe04db95b6fd6a8 to mainline-neuralnetworks-releaseandroid-mainline-12.0.0_r92android12-mainline-neuralnetworks-release
Change-Id: Idfe291bde90fe74f17c200a54a119bd3dd037f16
-rw-r--r--android/Android.bp1
-rw-r--r--android/apex.go20
-rw-r--r--android/api_levels.go16
-rw-r--r--android/config.go10
-rw-r--r--android/neverallow.go65
-rw-r--r--android/neverallow_test.go49
-rw-r--r--android/sdk_version.go8
-rw-r--r--android/sdk_version_test.go89
-rw-r--r--apex/androidmk.go29
-rw-r--r--apex/apex.go51
-rw-r--r--apex/apex_test.go298
-rw-r--r--apex/builder.go150
-rw-r--r--apex/testing.go1
-rw-r--r--bpf/bpf.go16
-rw-r--r--dexpreopt/testing.go8
-rwxr-xr-xjava/app.go2
-rw-r--r--java/base.go15
-rw-r--r--java/classpath_fragment.go65
-rw-r--r--java/config/config.go2
-rw-r--r--java/dex.go52
-rw-r--r--java/java.go1
-rw-r--r--java/platform_bootclasspath.go1
-rw-r--r--java/sdk_library.go24
-rw-r--r--java/sdk_library_test.go93
-rw-r--r--java/systemserver_classpath_fragment.go26
-rw-r--r--java/systemserver_classpath_fragment_test.go2
-rw-r--r--rust/rust.go10
-rw-r--r--scripts/OWNERS2
-rwxr-xr-xscripts/gen_java_usedby_apex.sh48
-rw-r--r--sdk/sdk.go8
30 files changed, 945 insertions, 217 deletions
diff --git a/android/Android.bp b/android/Android.bp
index 5d0f2b941..36b2670d5 100644
--- a/android/Android.bp
+++ b/android/Android.bp
@@ -110,6 +110,7 @@ bootstrap_go_package {
"paths_test.go",
"prebuilt_test.go",
"rule_builder_test.go",
+ "sdk_version_test.go",
"singleton_module_test.go",
"soong_config_modules_test.go",
"util_test.go",
diff --git a/android/apex.go b/android/apex.go
index 4618fe97e..b5d96e4ae 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -903,16 +903,18 @@ var minSdkVersionAllowlist = func(apiMap map[string]int) map[string]ApiLevel {
//
// Return true if the `to` module should be visited, false otherwise.
type PayloadDepsCallback func(ctx ModuleContext, from blueprint.Module, to ApexModule, externalDep bool) bool
+type WalkPayloadDepsFunc func(ctx ModuleContext, do PayloadDepsCallback)
-// UpdatableModule represents updatable APEX/APK
-type UpdatableModule interface {
+// ModuleWithMinSdkVersionCheck represents a module that implements min_sdk_version checks
+type ModuleWithMinSdkVersionCheck interface {
Module
- WalkPayloadDeps(ctx ModuleContext, do PayloadDepsCallback)
+ MinSdkVersion(ctx EarlyModuleContext) SdkSpec
+ CheckMinSdkVersion(ctx ModuleContext)
}
// CheckMinSdkVersion checks if every dependency of an updatable module sets min_sdk_version
// accordingly
-func CheckMinSdkVersion(m UpdatableModule, ctx ModuleContext, minSdkVersion ApiLevel) {
+func CheckMinSdkVersion(ctx ModuleContext, minSdkVersion ApiLevel, walk WalkPayloadDepsFunc) {
// do not enforce min_sdk_version for host
if ctx.Host() {
return
@@ -928,7 +930,7 @@ func CheckMinSdkVersion(m UpdatableModule, ctx ModuleContext, minSdkVersion ApiL
return
}
- m.WalkPayloadDeps(ctx, func(ctx ModuleContext, from blueprint.Module, to ApexModule, externalDep bool) bool {
+ walk(ctx, func(ctx ModuleContext, from blueprint.Module, to ApexModule, externalDep bool) bool {
if externalDep {
// external deps are outside the payload boundary, which is "stable"
// interface. We don't have to check min_sdk_version for external
@@ -938,6 +940,14 @@ func CheckMinSdkVersion(m UpdatableModule, ctx ModuleContext, minSdkVersion ApiL
if am, ok := from.(DepIsInSameApex); ok && !am.DepIsInSameApex(ctx, to) {
return false
}
+ if m, ok := to.(ModuleWithMinSdkVersionCheck); ok {
+ // This dependency performs its own min_sdk_version check, just make sure it sets min_sdk_version
+ // to trigger the check.
+ if !m.MinSdkVersion(ctx).Specified() {
+ ctx.OtherModuleErrorf(m, "must set min_sdk_version")
+ }
+ return false
+ }
if err := to.ShouldSupportSdkVersion(ctx, minSdkVersion); err != nil {
toName := ctx.OtherModuleName(to)
if ver, ok := minSdkVersionAllowlist[toName]; !ok || ver.GreaterThan(minSdkVersion) {
diff --git a/android/api_levels.go b/android/api_levels.go
index 93583bc07..fe3f41753 100644
--- a/android/api_levels.go
+++ b/android/api_levels.go
@@ -188,8 +188,8 @@ var FirstNonLibAndroidSupportVersion = uncheckedFinalApiLevel(21)
// * "30" -> "30"
// * "R" -> "30"
// * "S" -> "S"
-func ReplaceFinalizedCodenames(ctx PathContext, raw string) string {
- num, ok := getFinalCodenamesMap(ctx.Config())[raw]
+func ReplaceFinalizedCodenames(config Config, raw string) string {
+ num, ok := getFinalCodenamesMap(config)[raw]
if !ok {
return raw
}
@@ -197,7 +197,7 @@ func ReplaceFinalizedCodenames(ctx PathContext, raw string) string {
return strconv.Itoa(num)
}
-// Converts the given string `raw` to an ApiLevel, possibly returning an error.
+// ApiLevelFromUser converts the given string `raw` to an ApiLevel, possibly returning an error.
//
// `raw` must be non-empty. Passing an empty string results in a panic.
//
@@ -212,6 +212,12 @@ func ReplaceFinalizedCodenames(ctx PathContext, raw string) string {
// Inputs that are not "current", known previews, or convertible to an integer
// will return an error.
func ApiLevelFromUser(ctx PathContext, raw string) (ApiLevel, error) {
+ return ApiLevelFromUserWithConfig(ctx.Config(), raw)
+}
+
+// ApiLevelFromUserWithConfig implements ApiLevelFromUser, see comments for
+// ApiLevelFromUser for more details.
+func ApiLevelFromUserWithConfig(config Config, raw string) (ApiLevel, error) {
if raw == "" {
panic("API level string must be non-empty")
}
@@ -220,13 +226,13 @@ func ApiLevelFromUser(ctx PathContext, raw string) (ApiLevel, error) {
return FutureApiLevel, nil
}
- for _, preview := range ctx.Config().PreviewApiLevels() {
+ for _, preview := range config.PreviewApiLevels() {
if raw == preview.String() {
return preview, nil
}
}
- canonical := ReplaceFinalizedCodenames(ctx, raw)
+ canonical := ReplaceFinalizedCodenames(config, raw)
asInt, err := strconv.Atoi(canonical)
if err != nil {
return NoneApiLevel, fmt.Errorf("%q could not be parsed as an integer and is not a recognized codename", canonical)
diff --git a/android/config.go b/android/config.go
index 61383e762..8e9a0a2e6 100644
--- a/android/config.go
+++ b/android/config.go
@@ -698,6 +698,16 @@ func (c *config) PreviewApiLevels() []ApiLevel {
return levels
}
+func (c *config) LatestPreviewApiLevel() ApiLevel {
+ level := NoneApiLevel
+ for _, l := range c.PreviewApiLevels() {
+ if l.GreaterThan(level) {
+ level = l
+ }
+ }
+ return level
+}
+
func (c *config) AllSupportedApiLevels() []ApiLevel {
var levels []ApiLevel
levels = append(levels, c.FinalApiLevels()...)
diff --git a/android/neverallow.go b/android/neverallow.go
index af072cdbb..f7827f8ef 100644
--- a/android/neverallow.go
+++ b/android/neverallow.go
@@ -238,7 +238,7 @@ func neverallowMutator(ctx BottomUpMutatorContext) {
continue
}
- if !n.appliesToProperties(properties) {
+ if !n.appliesToProperties(ctx, properties) {
continue
}
@@ -258,8 +258,12 @@ func neverallowMutator(ctx BottomUpMutatorContext) {
}
}
+type ValueMatcherContext interface {
+ Config() Config
+}
+
type ValueMatcher interface {
- Test(string) bool
+ Test(ValueMatcherContext, string) bool
String() string
}
@@ -267,7 +271,7 @@ type equalMatcher struct {
expected string
}
-func (m *equalMatcher) Test(value string) bool {
+func (m *equalMatcher) Test(ctx ValueMatcherContext, value string) bool {
return m.expected == value
}
@@ -278,7 +282,7 @@ func (m *equalMatcher) String() string {
type anyMatcher struct {
}
-func (m *anyMatcher) Test(value string) bool {
+func (m *anyMatcher) Test(ctx ValueMatcherContext, value string) bool {
return true
}
@@ -292,7 +296,7 @@ type startsWithMatcher struct {
prefix string
}
-func (m *startsWithMatcher) Test(value string) bool {
+func (m *startsWithMatcher) Test(ctx ValueMatcherContext, value string) bool {
return strings.HasPrefix(value, m.prefix)
}
@@ -304,7 +308,7 @@ type regexMatcher struct {
re *regexp.Regexp
}
-func (m *regexMatcher) Test(value string) bool {
+func (m *regexMatcher) Test(ctx ValueMatcherContext, value string) bool {
return m.re.MatchString(value)
}
@@ -316,7 +320,7 @@ type notInListMatcher struct {
allowed []string
}
-func (m *notInListMatcher) Test(value string) bool {
+func (m *notInListMatcher) Test(ctx ValueMatcherContext, value string) bool {
return !InList(value, m.allowed)
}
@@ -326,7 +330,7 @@ func (m *notInListMatcher) String() string {
type isSetMatcher struct{}
-func (m *isSetMatcher) Test(value string) bool {
+func (m *isSetMatcher) Test(ctx ValueMatcherContext, value string) bool {
return value != ""
}
@@ -336,6 +340,19 @@ func (m *isSetMatcher) String() string {
var isSetMatcherInstance = &isSetMatcher{}
+type sdkVersionMatcher struct {
+ condition func(ctx ValueMatcherContext, spec SdkSpec) bool
+ description string
+}
+
+func (m *sdkVersionMatcher) Test(ctx ValueMatcherContext, value string) bool {
+ return m.condition(ctx, SdkSpecFromWithConfig(ctx.Config(), value))
+}
+
+func (m *sdkVersionMatcher) String() string {
+ return ".sdk-version(" + m.description + ")"
+}
+
type ruleProperty struct {
fields []string // e.x.: Vndk.Enabled
matcher ValueMatcher
@@ -549,9 +566,10 @@ func (r *rule) appliesToModuleType(moduleType string) bool {
return (len(r.moduleTypes) == 0 || InList(moduleType, r.moduleTypes)) && !InList(moduleType, r.unlessModuleTypes)
}
-func (r *rule) appliesToProperties(properties []interface{}) bool {
- includeProps := hasAllProperties(properties, r.props)
- excludeProps := hasAnyProperty(properties, r.unlessProps)
+func (r *rule) appliesToProperties(ctx ValueMatcherContext,
+ properties []interface{}) bool {
+ includeProps := hasAllProperties(ctx, properties, r.props)
+ excludeProps := hasAnyProperty(ctx, properties, r.unlessProps)
return includeProps && !excludeProps
}
@@ -571,6 +589,16 @@ func NotInList(allowed []string) ValueMatcher {
return &notInListMatcher{allowed}
}
+func LessThanSdkVersion(sdk string) ValueMatcher {
+ return &sdkVersionMatcher{
+ condition: func(ctx ValueMatcherContext, spec SdkSpec) bool {
+ return spec.ApiLevel.LessThan(
+ SdkSpecFromWithConfig(ctx.Config(), sdk).ApiLevel)
+ },
+ description: "lessThan=" + sdk,
+ }
+}
+
// assorted utils
func cleanPaths(paths []string) []string {
@@ -589,25 +617,28 @@ func fieldNamesForProperties(propertyNames string) []string {
return names
}
-func hasAnyProperty(properties []interface{}, props []ruleProperty) bool {
+func hasAnyProperty(ctx ValueMatcherContext, properties []interface{},
+ props []ruleProperty) bool {
for _, v := range props {
- if hasProperty(properties, v) {
+ if hasProperty(ctx, properties, v) {
return true
}
}
return false
}
-func hasAllProperties(properties []interface{}, props []ruleProperty) bool {
+func hasAllProperties(ctx ValueMatcherContext, properties []interface{},
+ props []ruleProperty) bool {
for _, v := range props {
- if !hasProperty(properties, v) {
+ if !hasProperty(ctx, properties, v) {
return false
}
}
return true
}
-func hasProperty(properties []interface{}, prop ruleProperty) bool {
+func hasProperty(ctx ValueMatcherContext, properties []interface{},
+ prop ruleProperty) bool {
for _, propertyStruct := range properties {
propertiesValue := reflect.ValueOf(propertyStruct).Elem()
for _, v := range prop.fields {
@@ -621,7 +652,7 @@ func hasProperty(properties []interface{}, prop ruleProperty) bool {
}
check := func(value string) bool {
- return prop.matcher.Test(value)
+ return prop.matcher.Test(ctx, value)
}
if matchValue(propertiesValue, check) {
diff --git a/android/neverallow_test.go b/android/neverallow_test.go
index 35aadd8b8..0b93fcfd7 100644
--- a/android/neverallow_test.go
+++ b/android/neverallow_test.go
@@ -296,6 +296,48 @@ var neverallowTests = []struct {
"Only boot images may be imported as a makefile goal.",
},
},
+ {
+ name: "min_sdk too low",
+ fs: map[string][]byte{
+ "Android.bp": []byte(`
+ java_library {
+ name: "min_sdk_too_low",
+ min_sdk_version: "30",
+ }`),
+ },
+ rules: []Rule{
+ NeverAllow().WithMatcher("min_sdk_version", LessThanSdkVersion("31")),
+ },
+ expectedErrors: []string{
+ "module \"min_sdk_too_low\": violates neverallow",
+ },
+ },
+ {
+ name: "min_sdk high enough",
+ fs: map[string][]byte{
+ "Android.bp": []byte(`
+ java_library {
+ name: "min_sdk_high_enough",
+ min_sdk_version: "31",
+ }`),
+ },
+ rules: []Rule{
+ NeverAllow().WithMatcher("min_sdk_version", LessThanSdkVersion("31")),
+ },
+ },
+ {
+ name: "current min_sdk high enough",
+ fs: map[string][]byte{
+ "Android.bp": []byte(`
+ java_library {
+ name: "current_min_sdk_high_enough",
+ min_sdk_version: "current",
+ }`),
+ },
+ rules: []Rule{
+ NeverAllow().WithMatcher("min_sdk_version", LessThanSdkVersion("31")),
+ },
+ },
}
var prepareForNeverAllowTest = GroupFixturePreparers(
@@ -379,9 +421,10 @@ func (p *mockCcLibraryModule) GenerateAndroidBuildActions(ModuleContext) {
}
type mockJavaLibraryProperties struct {
- Libs []string
- Sdk_version *string
- Uncompress_dex *bool
+ Libs []string
+ Min_sdk_version *string
+ Sdk_version *string
+ Uncompress_dex *bool
}
type mockJavaLibraryModule struct {
diff --git a/android/sdk_version.go b/android/sdk_version.go
index c6c75a399..49e607502 100644
--- a/android/sdk_version.go
+++ b/android/sdk_version.go
@@ -117,7 +117,7 @@ func (s SdkSpec) Stable() bool {
return false
}
-// PrebuiltSdkAvailableForUnbundledBuilt tells whether this SdkSpec can have a prebuilt SDK
+// PrebuiltSdkAvailableForUnbundledBuild tells whether this SdkSpec can have a prebuilt SDK
// that can be used for unbundled builds.
func (s SdkSpec) PrebuiltSdkAvailableForUnbundledBuild() bool {
// "", "none", and "core_platform" are not available for unbundled build
@@ -212,6 +212,10 @@ var (
)
func SdkSpecFrom(ctx EarlyModuleContext, str string) SdkSpec {
+ return SdkSpecFromWithConfig(ctx.Config(), str)
+}
+
+func SdkSpecFromWithConfig(config Config, str string) SdkSpec {
switch str {
// special cases first
case "":
@@ -252,7 +256,7 @@ func SdkSpecFrom(ctx EarlyModuleContext, str string) SdkSpec {
return SdkSpec{SdkInvalid, NoneApiLevel, str}
}
- apiLevel, err := ApiLevelFromUser(ctx, versionString)
+ apiLevel, err := ApiLevelFromUserWithConfig(config, versionString)
if err != nil {
return SdkSpec{SdkInvalid, apiLevel, str}
}
diff --git a/android/sdk_version_test.go b/android/sdk_version_test.go
new file mode 100644
index 000000000..8924fd295
--- /dev/null
+++ b/android/sdk_version_test.go
@@ -0,0 +1,89 @@
+// Copyright 2015 Google Inc. All rights reserved.
+//
+// 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 android
+
+import (
+ "testing"
+)
+
+func TestSdkSpecFrom(t *testing.T) {
+ testCases := []struct {
+ input string
+ expected string
+ }{
+ {
+ input: "",
+ expected: "private_current",
+ },
+ {
+ input: "none",
+ expected: "none_(no version)",
+ },
+ {
+ input: "core_platform",
+ expected: "core_platform_current",
+ },
+ {
+ input: "_",
+ expected: "invalid_(no version)",
+ },
+ {
+ input: "_31",
+ expected: "invalid_(no version)",
+ },
+ {
+ input: "system_R",
+ expected: "system_30",
+ },
+ {
+ input: "test_31",
+ expected: "test_31",
+ },
+ {
+ input: "module_current",
+ expected: "module-lib_current",
+ },
+ {
+ input: "31",
+ expected: "public_31",
+ },
+ {
+ input: "S",
+ expected: "public_31",
+ },
+ {
+ input: "current",
+ expected: "public_current",
+ },
+ {
+ input: "Tiramisu",
+ expected: "public_Tiramisu",
+ },
+ }
+
+ config := NullConfig("")
+
+ config.productVariables = productVariables{
+ Platform_sdk_version: intPtr(31),
+ Platform_sdk_codename: stringPtr("Tiramisu"),
+ Platform_version_active_codenames: []string{"Tiramisu"},
+ }
+
+ for _, tc := range testCases {
+ if got := SdkSpecFromWithConfig(config, tc.input).String(); tc.expected != got {
+ t.Errorf("Expected %v, got %v", tc.expected, got)
+ }
+ }
+}
diff --git a/apex/androidmk.go b/apex/androidmk.go
index ebf08330b..6695a6fea 100644
--- a/apex/androidmk.go
+++ b/apex/androidmk.go
@@ -446,23 +446,18 @@ func (a *apexBundle) androidMkForType() android.AndroidMkData {
fmt.Fprintf(w, dist)
}
- if a.apisUsedByModuleFile.String() != "" {
- goal := "apps_only"
- distFile := a.apisUsedByModuleFile.String()
- fmt.Fprintf(w, "ifneq (,$(filter $(my_register_name),$(TARGET_BUILD_APPS)))\n"+
- " $(call dist-for-goals,%s,%s:ndk_apis_usedby_apex/$(notdir %s))\n"+
- "endif\n",
- goal, distFile, distFile)
- }
-
- if a.apisBackedByModuleFile.String() != "" {
- goal := "apps_only"
- distFile := a.apisBackedByModuleFile.String()
- fmt.Fprintf(w, "ifneq (,$(filter $(my_register_name),$(TARGET_BUILD_APPS)))\n"+
- " $(call dist-for-goals,%s,%s:ndk_apis_backedby_apex/$(notdir %s))\n"+
- "endif\n",
- goal, distFile, distFile)
- }
+ distCoverageFiles(w, "ndk_apis_usedby_apex", a.nativeApisUsedByModuleFile.String())
+ distCoverageFiles(w, "ndk_apis_backedby_apex", a.nativeApisBackedByModuleFile.String())
+ distCoverageFiles(w, "java_apis_used_by_apex", a.javaApisUsedByModuleFile.String())
}
}}
}
+
+func distCoverageFiles(w io.Writer, dir string, distfile string) {
+ if distfile != "" {
+ goal := "apps_only"
+ fmt.Fprintf(w, "ifneq (,$(filter $(my_register_name),$(TARGET_BUILD_APPS)))\n"+
+ " $(call dist-for-goals,%s,%s:%s/$(notdir %s))\n"+
+ "endif\n", goal, distfile, dir, distfile)
+ }
+}
diff --git a/apex/apex.go b/apex/apex.go
index a2b16f151..e1bc030c5 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -95,6 +95,14 @@ type apexBundleProperties struct {
// /system/sepolicy/apex/<module_name>_file_contexts.
File_contexts *string `android:"path"`
+ // Path to the canned fs config file for customizing file's uid/gid/mod/capabilities. The
+ // format is /<path_or_glob> <uid> <gid> <mode> [capabilities=0x<cap>], where path_or_glob is a
+ // path or glob pattern for a file or set of files, uid/gid are numerial values of user ID
+ // and group ID, mode is octal value for the file mode, and cap is hexadecimal value for the
+ // capability. If this property is not set, or a file is missing in the file, default config
+ // is used.
+ Canned_fs_config *string `android:"path"`
+
ApexNativeDependencies
Multilib apexMultilibProperties
@@ -413,8 +421,9 @@ type apexBundle struct {
isCompressed bool
// Path of API coverage generate file
- apisUsedByModuleFile android.ModuleOutPath
- apisBackedByModuleFile android.ModuleOutPath
+ nativeApisUsedByModuleFile android.ModuleOutPath
+ nativeApisBackedByModuleFile android.ModuleOutPath
+ javaApisUsedByModuleFile android.ModuleOutPath
}
// apexFileClass represents a type of file that can be included in APEX.
@@ -1563,8 +1572,8 @@ func apexFileForRuntimeResourceOverlay(ctx android.BaseModuleContext, rro java.R
return af
}
-func apexFileForBpfProgram(ctx android.BaseModuleContext, builtFile android.Path, bpfProgram bpf.BpfModule) apexFile {
- dirInApex := filepath.Join("etc", "bpf")
+func apexFileForBpfProgram(ctx android.BaseModuleContext, builtFile android.Path, apex_sub_dir string, bpfProgram bpf.BpfModule) apexFile {
+ dirInApex := filepath.Join("etc", "bpf", apex_sub_dir)
return newApexFile(ctx, builtFile, builtFile.Base(), dirInApex, etc, bpfProgram)
}
@@ -1631,7 +1640,7 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
// 1) do some validity checks such as apex_available, min_sdk_version, etc.
a.checkApexAvailability(ctx)
a.checkUpdatable(ctx)
- a.checkMinSdkVersion(ctx)
+ a.CheckMinSdkVersion(ctx)
a.checkStaticLinkingToStubLibraries(ctx)
if len(a.properties.Tests) > 0 && !a.testApex {
ctx.PropertyErrorf("tests", "property allowed only in apex_test module type")
@@ -1763,8 +1772,9 @@ func (a *apexBundle) GenerateAndroidBuildActions(ctx android.ModuleContext) {
case bpfTag:
if bpfProgram, ok := child.(bpf.BpfModule); ok {
filesToCopy, _ := bpfProgram.OutputFiles("")
+ apex_sub_dir := bpfProgram.SubDir()
for _, bpfFile := range filesToCopy {
- filesInfo = append(filesInfo, apexFileForBpfProgram(ctx, bpfFile, bpfProgram))
+ filesInfo = append(filesInfo, apexFileForBpfProgram(ctx, bpfFile, apex_sub_dir, bpfProgram))
}
} else {
ctx.PropertyErrorf("bpfs", "%q is not a bpf module", depName)
@@ -2245,18 +2255,28 @@ func overrideApexFactory() android.Module {
//
// TODO(jiyong): move these checks to a separate go file.
+var _ android.ModuleWithMinSdkVersionCheck = (*apexBundle)(nil)
+
// Entures that min_sdk_version of the included modules are equal or less than the min_sdk_version
// of this apexBundle.
-func (a *apexBundle) checkMinSdkVersion(ctx android.ModuleContext) {
+func (a *apexBundle) CheckMinSdkVersion(ctx android.ModuleContext) {
if a.testApex || a.vndkApex {
return
}
// apexBundle::minSdkVersion reports its own errors.
minSdkVersion := a.minSdkVersion(ctx)
- android.CheckMinSdkVersion(a, ctx, minSdkVersion)
+ android.CheckMinSdkVersion(ctx, minSdkVersion, a.WalkPayloadDeps)
}
-func (a *apexBundle) minSdkVersion(ctx android.BaseModuleContext) android.ApiLevel {
+func (a *apexBundle) MinSdkVersion(ctx android.EarlyModuleContext) android.SdkSpec {
+ return android.SdkSpec{
+ Kind: android.SdkNone,
+ ApiLevel: a.minSdkVersion(ctx),
+ Raw: String(a.properties.Min_sdk_version),
+ }
+}
+
+func (a *apexBundle) minSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel {
ver := proptools.String(a.properties.Min_sdk_version)
if ver == "" {
return android.NoneApiLevel
@@ -2328,6 +2348,12 @@ func (a *apexBundle) checkUpdatable(ctx android.ModuleContext) {
func (a *apexBundle) checkClasspathFragments(ctx android.ModuleContext) {
ctx.VisitDirectDeps(func(module android.Module) {
if tag := ctx.OtherModuleDependencyTag(module); tag == bcpfTag || tag == sscpfTag {
+ if tag == sscpfTag {
+ sscpf := module.(*java.SystemServerClasspathModule)
+ if sscpf.ShouldIgnore() {
+ return
+ }
+ }
info := ctx.OtherModuleProvider(module, java.ClasspathFragmentProtoContentInfoProvider).(java.ClasspathFragmentProtoContentInfo)
if !info.ClasspathFragmentProtoGenerated {
ctx.OtherModuleErrorf(module, "is included in updatable apex %v, it must not set generate_classpaths_proto to false", ctx.ModuleName())
@@ -3038,15 +3064,16 @@ func createApexPermittedPackagesRules(modules_packages map[string][]string) []an
BootclasspathJar().
With("apex_available", module_name).
WithMatcher("permitted_packages", android.NotInList(module_packages)).
+ WithMatcher("min_sdk_version", android.LessThanSdkVersion("Tiramisu")).
Because("jars that are part of the " + module_name +
" module may only allow these packages: " + strings.Join(module_packages, ",") +
- ". Please jarjar or move code around.")
+ " with min_sdk < T. Please jarjar or move code around.")
rules = append(rules, permittedPackagesRule)
}
return rules
}
-// DO NOT EDIT! These are the package prefixes that are exempted from being AOT'ed by ART.
+// DO NOT EDIT! These are the package prefixes that are exempted from being AOT'ed by ART on Q/R/S.
// Adding code to the bootclasspath in new packages will cause issues on module update.
func qModulesPackages() map[string][]string {
return map[string][]string{
@@ -3060,7 +3087,7 @@ func qModulesPackages() map[string][]string {
}
}
-// DO NOT EDIT! These are the package prefixes that are exempted from being AOT'ed by ART.
+// DO NOT EDIT! These are the package prefixes that are exempted from being AOT'ed by ART on R/S.
// Adding code to the bootclasspath in new packages will cause issues on module update.
func rModulesPackages() map[string][]string {
return map[string][]string{
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 12317a275..f3c3b44c5 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -622,7 +622,7 @@ func TestDefaults(t *testing.T) {
java_libs: ["myjar"],
apps: ["AppFoo"],
rros: ["rro"],
- bpfs: ["bpf"],
+ bpfs: ["bpf", "netd_test"],
updatable: false,
}
@@ -675,6 +675,12 @@ func TestDefaults(t *testing.T) {
srcs: ["bpf.c", "bpf2.c"],
}
+ bpf {
+ name: "netd_test",
+ srcs: ["netd_test.c"],
+ sub_dir: "netd",
+ }
+
`)
ensureExactContents(t, ctx, "myapex", "android_common_myapex_image", []string{
"etc/myetc",
@@ -684,6 +690,7 @@ func TestDefaults(t *testing.T) {
"overlay/blue/rro.apk",
"etc/bpf/bpf.o",
"etc/bpf/bpf2.o",
+ "etc/bpf/netd/netd_test.o",
})
}
@@ -2293,22 +2300,21 @@ func TestFilesInSubDir(t *testing.T) {
`)
generateFsRule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Rule("generateFsConfig")
- dirs := strings.Split(generateFsRule.Args["exec_paths"], " ")
+ cmd := generateFsRule.RuleParams.Command
// Ensure that the subdirectories are all listed
- ensureListContains(t, dirs, "etc")
- ensureListContains(t, dirs, "etc/foo")
- ensureListContains(t, dirs, "etc/foo/bar")
- ensureListContains(t, dirs, "lib64")
- ensureListContains(t, dirs, "lib64/foo")
- ensureListContains(t, dirs, "lib64/foo/bar")
- ensureListContains(t, dirs, "lib")
- ensureListContains(t, dirs, "lib/foo")
- ensureListContains(t, dirs, "lib/foo/bar")
-
- ensureListContains(t, dirs, "bin")
- ensureListContains(t, dirs, "bin/foo")
- ensureListContains(t, dirs, "bin/foo/bar")
+ ensureContains(t, cmd, "/etc ")
+ ensureContains(t, cmd, "/etc/foo ")
+ ensureContains(t, cmd, "/etc/foo/bar ")
+ ensureContains(t, cmd, "/lib64 ")
+ ensureContains(t, cmd, "/lib64/foo ")
+ ensureContains(t, cmd, "/lib64/foo/bar ")
+ ensureContains(t, cmd, "/lib ")
+ ensureContains(t, cmd, "/lib/foo ")
+ ensureContains(t, cmd, "/lib/foo/bar ")
+ ensureContains(t, cmd, "/bin ")
+ ensureContains(t, cmd, "/bin/foo ")
+ ensureContains(t, cmd, "/bin/foo/bar ")
}
func TestFilesInSubDirWhenNativeBridgeEnabled(t *testing.T) {
@@ -6897,6 +6903,7 @@ func TestApexPermittedPackagesRules(t *testing.T) {
apex_available: ["myapex"],
sdk_version: "none",
system_modules: "none",
+ min_sdk_version: "30",
}
java_library {
name: "nonbcp_lib2",
@@ -6905,9 +6912,11 @@ func TestApexPermittedPackagesRules(t *testing.T) {
permitted_packages: ["a.b"],
sdk_version: "none",
system_modules: "none",
+ min_sdk_version: "30",
}
apex {
name: "myapex",
+ min_sdk_version: "30",
key: "myapex.key",
java_libs: ["bcp_lib1", "nonbcp_lib2"],
updatable: false,
@@ -6920,8 +6929,45 @@ func TestApexPermittedPackagesRules(t *testing.T) {
},
},
{
- name: "Bootclasspath apex jar not satisfying allowed module packages.",
- expectedError: `module "bcp_lib2" .* which is restricted because jars that are part of the myapex module may only allow these packages: foo.bar. Please jarjar or move code around.`,
+ name: "Bootclasspath apex jar not satisfying allowed module packages on Q.",
+ expectedError: `module "bcp_lib2" .* which is restricted because jars that are part of the myapex module may only allow these packages: foo.bar with min_sdk < T. Please jarjar or move code around.`,
+ bp: `
+ java_library {
+ name: "bcp_lib1",
+ srcs: ["lib1/src/*.java"],
+ apex_available: ["myapex"],
+ permitted_packages: ["foo.bar"],
+ sdk_version: "none",
+ system_modules: "none",
+ min_sdk_version: "29",
+ }
+ java_library {
+ name: "bcp_lib2",
+ srcs: ["lib2/src/*.java"],
+ apex_available: ["myapex"],
+ permitted_packages: ["foo.bar", "bar.baz"],
+ sdk_version: "none",
+ system_modules: "none",
+ min_sdk_version: "29",
+ }
+ apex {
+ name: "myapex",
+ min_sdk_version: "29",
+ key: "myapex.key",
+ java_libs: ["bcp_lib1", "bcp_lib2"],
+ updatable: false,
+ }
+ `,
+ bootJars: []string{"bcp_lib1", "bcp_lib2"},
+ modulesPackages: map[string][]string{
+ "myapex": []string{
+ "foo.bar",
+ },
+ },
+ },
+ {
+ name: "Bootclasspath apex jar not satisfying allowed module packages on R.",
+ expectedError: `module "bcp_lib2" .* which is restricted because jars that are part of the myapex module may only allow these packages: foo.bar with min_sdk < T. Please jarjar or move code around.`,
bp: `
java_library {
name: "bcp_lib1",
@@ -6930,6 +6976,7 @@ func TestApexPermittedPackagesRules(t *testing.T) {
permitted_packages: ["foo.bar"],
sdk_version: "none",
system_modules: "none",
+ min_sdk_version: "30",
}
java_library {
name: "bcp_lib2",
@@ -6938,9 +6985,48 @@ func TestApexPermittedPackagesRules(t *testing.T) {
permitted_packages: ["foo.bar", "bar.baz"],
sdk_version: "none",
system_modules: "none",
+ min_sdk_version: "30",
}
apex {
name: "myapex",
+ min_sdk_version: "30",
+ key: "myapex.key",
+ java_libs: ["bcp_lib1", "bcp_lib2"],
+ updatable: false,
+ }
+ `,
+ bootJars: []string{"bcp_lib1", "bcp_lib2"},
+ modulesPackages: map[string][]string{
+ "myapex": []string{
+ "foo.bar",
+ },
+ },
+ },
+ {
+ name: "Bootclasspath apex jar >= T not satisfying Q/R/S allowed module packages.",
+ expectedError: "",
+ bp: `
+ java_library {
+ name: "bcp_lib1",
+ srcs: ["lib1/src/*.java"],
+ apex_available: ["myapex"],
+ permitted_packages: ["foo.bar"],
+ sdk_version: "none",
+ system_modules: "none",
+ min_sdk_version: "current",
+ }
+ java_library {
+ name: "bcp_lib2",
+ srcs: ["lib2/src/*.java"],
+ apex_available: ["myapex"],
+ permitted_packages: ["foo.bar", "bar.baz"],
+ sdk_version: "none",
+ system_modules: "none",
+ min_sdk_version: "current",
+ }
+ apex {
+ name: "myapex",
+ min_sdk_version: "current",
key: "myapex.key",
java_libs: ["bcp_lib1", "bcp_lib2"],
updatable: false,
@@ -7742,6 +7828,184 @@ func TestApexJavaCoverage(t *testing.T) {
}
}
+func TestSdkLibraryCanHaveHigherMinSdkVersion(t *testing.T) {
+ preparer := android.GroupFixturePreparers(
+ PrepareForTestWithApexBuildComponents,
+ prepareForTestWithMyapex,
+ java.PrepareForTestWithJavaSdkLibraryFiles,
+ java.PrepareForTestWithJavaDefaultModules,
+ android.PrepareForTestWithAndroidBuildComponents,
+ dexpreopt.FixtureSetApexBootJars("myapex:mybootclasspathlib"),
+ dexpreopt.FixtureSetApexSystemServerJars("myapex:mysystemserverclasspathlib"),
+ )
+
+ // Test java_sdk_library in bootclasspath_fragment may define higher min_sdk_version than the apex
+ t.Run("bootclasspath_fragment jar has higher min_sdk_version than apex", func(t *testing.T) {
+ preparer.RunTestWithBp(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ bootclasspath_fragments: ["mybootclasspathfragment"],
+ min_sdk_version: "30",
+ updatable: false,
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ bootclasspath_fragment {
+ name: "mybootclasspathfragment",
+ contents: ["mybootclasspathlib"],
+ apex_available: ["myapex"],
+ }
+
+ java_sdk_library {
+ name: "mybootclasspathlib",
+ srcs: ["mybootclasspathlib.java"],
+ apex_available: ["myapex"],
+ compile_dex: true,
+ unsafe_ignore_missing_latest_api: true,
+ min_sdk_version: "31",
+ static_libs: ["util"],
+ }
+
+ java_library {
+ name: "util",
+ srcs: ["a.java"],
+ apex_available: ["myapex"],
+ min_sdk_version: "31",
+ static_libs: ["another_util"],
+ }
+
+ java_library {
+ name: "another_util",
+ srcs: ["a.java"],
+ min_sdk_version: "31",
+ apex_available: ["myapex"],
+ }
+ `)
+ })
+
+ // Test java_sdk_library in systemserverclasspath_fragment may define higher min_sdk_version than the apex
+ t.Run("systemserverclasspath_fragment jar has higher min_sdk_version than apex", func(t *testing.T) {
+ preparer.RunTestWithBp(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ systemserverclasspath_fragments: ["mysystemserverclasspathfragment"],
+ min_sdk_version: "30",
+ updatable: false,
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ systemserverclasspath_fragment {
+ name: "mysystemserverclasspathfragment",
+ contents: ["mysystemserverclasspathlib"],
+ apex_available: ["myapex"],
+ }
+
+ java_sdk_library {
+ name: "mysystemserverclasspathlib",
+ srcs: ["mysystemserverclasspathlib.java"],
+ apex_available: ["myapex"],
+ compile_dex: true,
+ min_sdk_version: "32",
+ unsafe_ignore_missing_latest_api: true,
+ static_libs: ["util"],
+ }
+
+ java_library {
+ name: "util",
+ srcs: ["a.java"],
+ apex_available: ["myapex"],
+ min_sdk_version: "31",
+ static_libs: ["another_util"],
+ }
+
+ java_library {
+ name: "another_util",
+ srcs: ["a.java"],
+ min_sdk_version: "31",
+ apex_available: ["myapex"],
+ }
+ `)
+ })
+
+ t.Run("bootclasspath_fragment jar must set min_sdk_version", func(t *testing.T) {
+ preparer.ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`module "mybootclasspathlib".*must set min_sdk_version`)).
+ RunTestWithBp(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ bootclasspath_fragments: ["mybootclasspathfragment"],
+ min_sdk_version: "30",
+ updatable: false,
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ bootclasspath_fragment {
+ name: "mybootclasspathfragment",
+ contents: ["mybootclasspathlib"],
+ apex_available: ["myapex"],
+ }
+
+ java_sdk_library {
+ name: "mybootclasspathlib",
+ srcs: ["mybootclasspathlib.java"],
+ apex_available: ["myapex"],
+ compile_dex: true,
+ unsafe_ignore_missing_latest_api: true,
+ }
+ `)
+ })
+
+ t.Run("systemserverclasspath_fragment jar must set min_sdk_version", func(t *testing.T) {
+ preparer.ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`module "mysystemserverclasspathlib".*must set min_sdk_version`)).
+ RunTestWithBp(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ systemserverclasspath_fragments: ["mysystemserverclasspathfragment"],
+ min_sdk_version: "30",
+ updatable: false,
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ systemserverclasspath_fragment {
+ name: "mysystemserverclasspathfragment",
+ contents: ["mysystemserverclasspathlib"],
+ apex_available: ["myapex"],
+ }
+
+ java_sdk_library {
+ name: "mysystemserverclasspathlib",
+ srcs: ["mysystemserverclasspathlib.java"],
+ apex_available: ["myapex"],
+ compile_dex: true,
+ unsafe_ignore_missing_latest_api: true,
+ }
+ `)
+ })
+}
+
func TestMain(m *testing.M) {
os.Exit(m.Run())
}
diff --git a/apex/builder.go b/apex/builder.go
index d2e6ad8d5..8a94ad7c7 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -67,23 +67,11 @@ func init() {
pctx.HostBinToolVariable("make_f2fs", "make_f2fs")
pctx.HostBinToolVariable("sload_f2fs", "sload_f2fs")
pctx.HostBinToolVariable("apex_compression_tool", "apex_compression_tool")
+ pctx.HostBinToolVariable("dexdeps", "dexdeps")
pctx.SourcePathVariable("genNdkUsedbyApexPath", "build/soong/scripts/gen_ndk_usedby_apex.sh")
}
var (
- // Create a canned fs config file where all files and directories are
- // by default set to (uid/gid/mode) = (1000/1000/0644)
- // TODO(b/113082813) make this configurable using config.fs syntax
- generateFsConfig = pctx.StaticRule("generateFsConfig", blueprint.RuleParams{
- Command: `( echo '/ 1000 1000 0755' ` +
- `&& for i in ${ro_paths}; do echo "/$$i 1000 1000 0644"; done ` +
- `&& for i in ${exec_paths}; do echo "/$$i 0 2000 0755"; done ` +
- `&& ( tr ' ' '\n' <${out}.apklist | for i in ${apk_paths}; do read apk; echo "/$$i 0 2000 0755"; zipinfo -1 $$apk | sed "s:\(.*\):/$$i/\1 1000 1000 0644:"; done ) ) > ${out}`,
- Description: "fs_config ${out}",
- Rspfile: "$out.apklist",
- RspfileContent: "$in",
- }, "ro_paths", "exec_paths", "apk_paths")
-
apexManifestRule = pctx.StaticRule("apexManifestRule", blueprint.RuleParams{
Command: `rm -f $out && ${jsonmodify} $in ` +
`-a provideNativeLibs ${provideNativeLibs} ` +
@@ -520,55 +508,11 @@ func (a *apexBundle) buildUnflattenedApex(ctx android.ModuleContext) {
// Figure out if need to compress apex.
compressionEnabled := ctx.Config().CompressedApex() && proptools.BoolDefault(a.properties.Compressible, false) && !a.testApex && !ctx.Config().UnbundledBuildApps()
if apexType == imageApex {
+
////////////////////////////////////////////////////////////////////////////////////
// Step 2: create canned_fs_config which encodes filemode,uid,gid of each files
// in this APEX. The file will be used by apexer in later steps.
- // TODO(jiyong): make this as a function
- // TODO(jiyong): use the RuleBuilder
- var readOnlyPaths = []string{"apex_manifest.json", "apex_manifest.pb"}
- var executablePaths []string // this also includes dirs
- var extractedAppSetPaths android.Paths
- var extractedAppSetDirs []string
- for _, f := range a.filesInfo {
- pathInApex := f.path()
- if f.installDir == "bin" || strings.HasPrefix(f.installDir, "bin/") {
- executablePaths = append(executablePaths, pathInApex)
- for _, d := range f.dataPaths {
- readOnlyPaths = append(readOnlyPaths, filepath.Join(f.installDir, d.RelativeInstallPath, d.SrcPath.Rel()))
- }
- for _, s := range f.symlinks {
- executablePaths = append(executablePaths, filepath.Join(f.installDir, s))
- }
- } else if f.class == appSet {
- extractedAppSetPaths = append(extractedAppSetPaths, f.builtFile)
- extractedAppSetDirs = append(extractedAppSetDirs, f.installDir)
- } else {
- readOnlyPaths = append(readOnlyPaths, pathInApex)
- }
- dir := f.installDir
- for !android.InList(dir, executablePaths) && dir != "" {
- executablePaths = append(executablePaths, dir)
- dir, _ = filepath.Split(dir) // move up to the parent
- if len(dir) > 0 {
- // remove trailing slash
- dir = dir[:len(dir)-1]
- }
- }
- }
- sort.Strings(readOnlyPaths)
- sort.Strings(executablePaths)
- cannedFsConfig := android.PathForModuleOut(ctx, "canned_fs_config")
- ctx.Build(pctx, android.BuildParams{
- Rule: generateFsConfig,
- Output: cannedFsConfig,
- Description: "generate fs config",
- Inputs: extractedAppSetPaths,
- Args: map[string]string{
- "ro_paths": strings.Join(readOnlyPaths, " "),
- "exec_paths": strings.Join(executablePaths, " "),
- "apk_paths": strings.Join(extractedAppSetDirs, " "),
- },
- })
+ cannedFsConfig := a.buildCannedFsConfig(ctx)
implicitInputs = append(implicitInputs, cannedFsConfig)
////////////////////////////////////////////////////////////////////////////////////
@@ -696,12 +640,12 @@ func (a *apexBundle) buildUnflattenedApex(ctx android.ModuleContext) {
"readelf": "${config.ClangBin}/llvm-readelf",
},
})
- a.apisUsedByModuleFile = apisUsedbyOutputFile
+ a.nativeApisUsedByModuleFile = apisUsedbyOutputFile
- var libNames []string
+ var nativeLibNames []string
for _, f := range a.filesInfo {
if f.class == nativeSharedLib {
- libNames = append(libNames, f.stem())
+ nativeLibNames = append(nativeLibNames, f.stem())
}
}
apisBackedbyOutputFile := android.PathForModuleOut(ctx, a.Name()+"_backing.txt")
@@ -711,9 +655,25 @@ func (a *apexBundle) buildUnflattenedApex(ctx android.ModuleContext) {
Tool(android.PathForSource(ctx, "build/soong/scripts/gen_ndk_backedby_apex.sh")).
Output(apisBackedbyOutputFile).
Input(ndkLibraryList).
- Flags(libNames)
+ Flags(nativeLibNames)
rule.Build("ndk_backedby_list", "Generate API libraries backed by Apex")
- a.apisBackedByModuleFile = apisBackedbyOutputFile
+ a.nativeApisBackedByModuleFile = apisBackedbyOutputFile
+
+ var javaLibOrApkPath []android.Path
+ for _, f := range a.filesInfo {
+ if f.class == javaSharedLib || f.class == app {
+ javaLibOrApkPath = append(javaLibOrApkPath, f.builtFile)
+ }
+ }
+ javaApiUsedbyOutputFile := android.PathForModuleOut(ctx, a.Name()+"_using.xml")
+ javaUsedByRule := android.NewRuleBuilder(pctx, ctx)
+ javaUsedByRule.Command().
+ Tool(android.PathForSource(ctx, "build/soong/scripts/gen_java_usedby_apex.sh")).
+ BuiltTool("dexdeps").
+ Output(javaApiUsedbyOutputFile).
+ Inputs(javaLibOrApkPath)
+ javaUsedByRule.Build("java_usedby_list", "Generate Java APIs used by Apex")
+ a.javaApisUsedByModuleFile = javaApiUsedbyOutputFile
bundleConfig := a.buildBundleConfig(ctx)
@@ -988,3 +948,65 @@ func (a *apexBundle) buildLintReports(ctx android.ModuleContext) {
a.lintReports = java.BuildModuleLintReportZips(ctx, depSetsBuilder.Build())
}
+
+func (a *apexBundle) buildCannedFsConfig(ctx android.ModuleContext) android.OutputPath {
+ var readOnlyPaths = []string{"apex_manifest.json", "apex_manifest.pb"}
+ var executablePaths []string // this also includes dirs
+ var appSetDirs []string
+ appSetFiles := make(map[string]android.Path)
+ for _, f := range a.filesInfo {
+ pathInApex := f.path()
+ if f.installDir == "bin" || strings.HasPrefix(f.installDir, "bin/") {
+ executablePaths = append(executablePaths, pathInApex)
+ for _, d := range f.dataPaths {
+ readOnlyPaths = append(readOnlyPaths, filepath.Join(f.installDir, d.RelativeInstallPath, d.SrcPath.Rel()))
+ }
+ for _, s := range f.symlinks {
+ executablePaths = append(executablePaths, filepath.Join(f.installDir, s))
+ }
+ } else if f.class == appSet {
+ appSetDirs = append(appSetDirs, f.installDir)
+ appSetFiles[f.installDir] = f.builtFile
+ } else {
+ readOnlyPaths = append(readOnlyPaths, pathInApex)
+ }
+ dir := f.installDir
+ for !android.InList(dir, executablePaths) && dir != "" {
+ executablePaths = append(executablePaths, dir)
+ dir, _ = filepath.Split(dir) // move up to the parent
+ if len(dir) > 0 {
+ // remove trailing slash
+ dir = dir[:len(dir)-1]
+ }
+ }
+ }
+ sort.Strings(readOnlyPaths)
+ sort.Strings(executablePaths)
+ sort.Strings(appSetDirs)
+
+ cannedFsConfig := android.PathForModuleOut(ctx, "canned_fs_config")
+ builder := android.NewRuleBuilder(pctx, ctx)
+ cmd := builder.Command()
+ cmd.Text("(")
+ cmd.Text("echo '/ 1000 1000 0755';")
+ for _, p := range readOnlyPaths {
+ cmd.Textf("echo '/%s 1000 1000 0644';", p)
+ }
+ for _, p := range executablePaths {
+ cmd.Textf("echo '/%s 0 2000 0755';", p)
+ }
+ for _, dir := range appSetDirs {
+ cmd.Textf("echo '/%s 0 2000 0755';", dir)
+ file := appSetFiles[dir]
+ cmd.Text("zipinfo -1").Input(file).Textf(`| sed "s:\(.*\):/%s/\1 1000 1000 0644:";`, dir)
+ }
+ // Custom fs_config is "appended" to the last so that entries from the file are preferred
+ // over default ones set above.
+ if a.properties.Canned_fs_config != nil {
+ cmd.Text("cat").Input(android.PathForModuleSrc(ctx, *a.properties.Canned_fs_config))
+ }
+ cmd.Text(")").FlagWithOutput("> ", cannedFsConfig)
+ builder.Build("generateFsConfig", fmt.Sprintf("Generating canned fs config for %s", a.BaseModuleName()))
+
+ return cannedFsConfig.OutputPath
+}
diff --git a/apex/testing.go b/apex/testing.go
index 69bd73e5d..337c86210 100644
--- a/apex/testing.go
+++ b/apex/testing.go
@@ -24,6 +24,7 @@ var PrepareForTestWithApexBuildComponents = android.GroupFixturePreparers(
android.MockFS{
// Needed by apex.
"system/core/rootdir/etc/public.libraries.android.txt": nil,
+ "build/soong/scripts/gen_java_usedby_apex.sh": nil,
"build/soong/scripts/gen_ndk_backedby_apex.sh": nil,
// Needed by prebuilt_apex.
"build/soong/scripts/unpack-prebuilt-apex.sh": nil,
diff --git a/bpf/bpf.go b/bpf/bpf.go
index fa1a84d04..187b4db61 100644
--- a/bpf/bpf.go
+++ b/bpf/bpf.go
@@ -54,12 +54,16 @@ type BpfModule interface {
android.Module
OutputFiles(tag string) (android.Paths, error)
+
+ // Returns the sub install directory if the bpf module is included by apex.
+ SubDir() string
}
type BpfProperties struct {
Srcs []string `android:"path"`
Cflags []string
Include_dirs []string
+ Sub_dir string
}
type bpf struct {
@@ -83,9 +87,9 @@ func (bpf *bpf) GenerateAndroidBuildActions(ctx android.ModuleContext) {
// The architecture doesn't matter here, but asm/types.h is included by linux/types.h.
"-isystem bionic/libc/kernel/uapi/asm-arm64",
"-isystem bionic/libc/kernel/android/uapi",
+ "-I frameworks/libs/net/common/native/bpf_headers/include/bpf",
// TODO(b/149785767): only give access to specific file with AID_* constants
"-I system/core/libcutils/include",
- "-I system/bpf/progs/include",
"-I " + ctx.ModuleDir(),
}
@@ -121,6 +125,10 @@ func (bpf *bpf) AndroidMk() android.AndroidMkData {
fmt.Fprintln(w)
fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir)
fmt.Fprintln(w)
+ localModulePath := "LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/bpf"
+ if len(bpf.properties.Sub_dir) > 0 {
+ localModulePath += "/" + bpf.properties.Sub_dir
+ }
for _, obj := range bpf.objs {
objName := name + "_" + obj.Base()
names = append(names, objName)
@@ -130,7 +138,7 @@ func (bpf *bpf) AndroidMk() android.AndroidMkData {
fmt.Fprintln(w, "LOCAL_PREBUILT_MODULE_FILE :=", obj.String())
fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", obj.Base())
fmt.Fprintln(w, "LOCAL_MODULE_CLASS := ETC")
- fmt.Fprintln(w, "LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/bpf")
+ fmt.Fprintln(w, localModulePath)
fmt.Fprintln(w, "include $(BUILD_PREBUILT)")
fmt.Fprintln(w)
}
@@ -154,6 +162,10 @@ func (bpf *bpf) OutputFiles(tag string) (android.Paths, error) {
}
}
+func (bpf *bpf) SubDir() string {
+ return bpf.properties.Sub_dir
+}
+
var _ android.OutputFileProducer = (*bpf)(nil)
func BpfFactory() android.Module {
diff --git a/dexpreopt/testing.go b/dexpreopt/testing.go
index 2f996555f..63d5317c5 100644
--- a/dexpreopt/testing.go
+++ b/dexpreopt/testing.go
@@ -122,6 +122,14 @@ func FixtureSetBootJars(bootJars ...string) android.FixturePreparer {
func FixtureSetApexBootJars(bootJars ...string) android.FixturePreparer {
return FixtureModifyGlobalConfig(func(dexpreoptConfig *GlobalConfig) {
dexpreoptConfig.ApexBootJars = android.CreateTestConfiguredJarList(bootJars)
+
+ })
+}
+
+// FixtureSetApexSystemServerJars sets the ApexSystemServerJars property in the global config.
+func FixtureSetApexSystemServerJars(jars ...string) android.FixturePreparer {
+ return FixtureModifyGlobalConfig(func(dexpreoptConfig *GlobalConfig) {
+ dexpreoptConfig.ApexSystemServerJars = android.CreateTestConfiguredJarList(jars)
})
}
diff --git a/java/app.go b/java/app.go
index fc1ace07b..06967690b 100755
--- a/java/app.go
+++ b/java/app.go
@@ -288,7 +288,7 @@ func (a *AndroidApp) checkAppSdkVersions(ctx android.ModuleContext) {
if minSdkVersion, err := a.MinSdkVersion(ctx).EffectiveVersion(ctx); err == nil {
a.checkJniLibsSdkVersion(ctx, minSdkVersion)
- android.CheckMinSdkVersion(a, ctx, minSdkVersion)
+ android.CheckMinSdkVersion(ctx, minSdkVersion, a.WalkPayloadDeps)
} else {
ctx.PropertyErrorf("min_sdk_version", "%s", err.Error())
}
diff --git a/java/base.go b/java/base.go
index 5d2927ac9..4780cc909 100644
--- a/java/base.go
+++ b/java/base.go
@@ -185,6 +185,10 @@ type DeviceProperties struct {
// Defaults to sdk_version if not set.
Min_sdk_version *string
+ // if not blank, set the maximum version of the sdk that the compiled artifacts will run against.
+ // Defaults to empty string "". See sdk_version for possible values.
+ Max_sdk_version *string
+
// if not blank, set the targetSdkVersion in the AndroidManifest.xml.
// Defaults to sdk_version if not set.
Target_sdk_version *string
@@ -367,6 +371,7 @@ type Module struct {
sdkVersion android.SdkSpec
minSdkVersion android.SdkSpec
+ maxSdkVersion android.SdkSpec
}
func (j *Module) CheckStableSdkVersion(ctx android.BaseModuleContext) error {
@@ -524,6 +529,13 @@ func (j *Module) MinSdkVersion(ctx android.EarlyModuleContext) android.SdkSpec {
return j.SdkVersion(ctx)
}
+func (j *Module) MaxSdkVersion(ctx android.EarlyModuleContext) android.SdkSpec {
+ maxSdkVersion := proptools.StringDefault(j.deviceProperties.Max_sdk_version, "")
+ // SdkSpecFrom returns SdkSpecPrivate for this, which may be confusing.
+ // TODO(b/208456999): ideally MaxSdkVersion should be an ApiLevel and not SdkSpec.
+ return android.SdkSpecFrom(ctx, maxSdkVersion)
+}
+
func (j *Module) MinSdkVersionString() string {
return j.minSdkVersion.Raw
}
@@ -1488,8 +1500,7 @@ func (j *Module) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Modu
}
// Implements android.ApexModule
-func (j *Module) ShouldSupportSdkVersion(ctx android.BaseModuleContext,
- sdkVersion android.ApiLevel) error {
+func (j *Module) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion android.ApiLevel) error {
sdkSpec := j.MinSdkVersion(ctx)
if !sdkSpec.Specified() {
return fmt.Errorf("min_sdk_version is not specified")
diff --git a/java/classpath_fragment.go b/java/classpath_fragment.go
index f63d81d6e..7eadfe6c3 100644
--- a/java/classpath_fragment.go
+++ b/java/classpath_fragment.go
@@ -84,11 +84,10 @@ func initClasspathFragment(c classpathFragment, classpathType classpathType) {
// Matches definition of Jar in packages/modules/SdkExtensions/proto/classpaths.proto
type classpathJar struct {
- path string
- classpath classpathType
- // TODO(satayev): propagate min/max sdk versions for the jars
- minSdkVersion int32
- maxSdkVersion int32
+ path string
+ classpath classpathType
+ minSdkVersion string
+ maxSdkVersion string
}
// gatherPossibleApexModuleNamesAndStems returns a set of module and stem names from the
@@ -120,10 +119,32 @@ func configuredJarListToClasspathJars(ctx android.ModuleContext, configuredJars
jars := make([]classpathJar, 0, len(paths)*len(classpaths))
for i := 0; i < len(paths); i++ {
for _, classpathType := range classpaths {
- jars = append(jars, classpathJar{
+ jar := classpathJar{
classpath: classpathType,
path: paths[i],
+ }
+ ctx.VisitDirectDepsIf(func(m android.Module) bool {
+ return m.Name() == configuredJars.Jar(i)
+ }, func(m android.Module) {
+ if s, ok := m.(*SdkLibrary); ok {
+ // TODO(208456999): instead of mapping "current" to latest, min_sdk_version should never be set to "current"
+ if s.minSdkVersion.Specified() {
+ if s.minSdkVersion.ApiLevel.IsCurrent() {
+ jar.minSdkVersion = ctx.Config().LatestPreviewApiLevel().String()
+ } else {
+ jar.minSdkVersion = s.minSdkVersion.ApiLevel.String()
+ }
+ }
+ if s.maxSdkVersion.Specified() {
+ if s.maxSdkVersion.ApiLevel.IsCurrent() {
+ jar.maxSdkVersion = ctx.Config().LatestPreviewApiLevel().String()
+ } else {
+ jar.maxSdkVersion = s.maxSdkVersion.ApiLevel.String()
+ }
+ }
+ }
})
+ jars = append(jars, jar)
}
}
return jars
@@ -136,15 +157,15 @@ func (c *ClasspathFragmentBase) generateClasspathProtoBuildActions(ctx android.M
c.outputFilepath = android.PathForModuleOut(ctx, outputFilename).OutputPath
c.installDirPath = android.PathForModuleInstall(ctx, "etc", "classpaths")
- generatedJson := android.PathForModuleOut(ctx, outputFilename+".json")
- writeClasspathsJson(ctx, generatedJson, jars)
+ generatedTextproto := android.PathForModuleOut(ctx, outputFilename+".textproto")
+ writeClasspathsTextproto(ctx, generatedTextproto, jars)
rule := android.NewRuleBuilder(pctx, ctx)
rule.Command().
BuiltTool("conv_classpaths_proto").
Flag("encode").
- Flag("--format=json").
- FlagWithInput("--input=", generatedJson).
+ Flag("--format=textproto").
+ FlagWithInput("--input=", generatedTextproto).
FlagWithOutput("--output=", c.outputFilepath)
rule.Build("classpath_fragment", "Compiling "+c.outputFilepath.String())
@@ -159,24 +180,18 @@ func (c *ClasspathFragmentBase) generateClasspathProtoBuildActions(ctx android.M
ctx.SetProvider(ClasspathFragmentProtoContentInfoProvider, classpathProtoInfo)
}
-func writeClasspathsJson(ctx android.ModuleContext, output android.WritablePath, jars []classpathJar) {
+func writeClasspathsTextproto(ctx android.ModuleContext, output android.WritablePath, jars []classpathJar) {
var content strings.Builder
- fmt.Fprintf(&content, "{\n")
- fmt.Fprintf(&content, "\"jars\": [\n")
- for idx, jar := range jars {
- fmt.Fprintf(&content, "{\n")
- fmt.Fprintf(&content, "\"path\": \"%s\",\n", jar.path)
- fmt.Fprintf(&content, "\"classpath\": \"%s\"\n", jar.classpath)
-
- if idx < len(jars)-1 {
- fmt.Fprintf(&content, "},\n")
- } else {
- fmt.Fprintf(&content, "}\n")
- }
+ for _, jar := range jars {
+ fmt.Fprintf(&content, "jars {\n")
+ fmt.Fprintf(&content, "path: \"%s\"\n", jar.path)
+ fmt.Fprintf(&content, "classpath: %s\n", jar.classpath)
+ fmt.Fprintf(&content, "min_sdk_version: \"%s\"\n", jar.minSdkVersion)
+ fmt.Fprintf(&content, "max_sdk_version: \"%s\"\n", jar.maxSdkVersion)
+ fmt.Fprintf(&content, "}\n")
}
- fmt.Fprintf(&content, "]\n")
- fmt.Fprintf(&content, "}\n")
+
android.WriteFileRule(ctx, output, content.String())
}
diff --git a/java/config/config.go b/java/config/config.go
index 273084c85..30c6f91aa 100644
--- a/java/config/config.go
+++ b/java/config/config.go
@@ -69,8 +69,6 @@ func init() {
pctx.StaticVariable("JavacHeapSize", "2048M")
pctx.StaticVariable("JavacHeapFlags", "-J-Xmx${JavacHeapSize}")
pctx.StaticVariable("DexFlags", "-JXX:OnError='cat hs_err_pid%p.log' -JXX:CICompilerCount=6 -JXX:+UseDynamicNumberOfGCThreads")
- // TODO(b/181095653): remove duplicated flags.
- pctx.StaticVariable("DexJavaFlags", "-XX:OnError='cat hs_err_pid%p.log' -XX:CICompilerCount=6 -XX:+UseDynamicNumberOfGCThreads -Xmx2G")
pctx.StaticVariable("CommonJdkFlags", strings.Join([]string{
`-Xmaxerrs 9999999`,
diff --git a/java/dex.go b/java/dex.go
index 6bf0143b1..1acfebd51 100644
--- a/java/dex.go
+++ b/java/dex.go
@@ -69,6 +69,9 @@ type DexProperties struct {
// This defaults to reasonable value based on module and should not be set.
// It exists only to support ART tests.
Uncompress_dex *bool
+
+ // Exclude kotlinc generate files: *.kotlin_module, *.kotlin_builtins. Defaults to false.
+ Exclude_kotlinc_generated_files *bool
}
type dexer struct {
@@ -84,17 +87,12 @@ func (d *dexer) effectiveOptimizeEnabled() bool {
return BoolDefault(d.dexProperties.Optimize.Enabled, d.dexProperties.Optimize.EnabledByDefault)
}
-func init() {
- pctx.HostBinToolVariable("runWithTimeoutCmd", "run_with_timeout")
- pctx.SourcePathVariable("jstackCmd", "${config.JavaToolchain}/jstack")
-}
-
var d8, d8RE = pctx.MultiCommandRemoteStaticRules("d8",
blueprint.RuleParams{
Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` +
`$d8Template${config.D8Cmd} ${config.DexFlags} --output $outDir $d8Flags $in && ` +
`$zipTemplate${config.SoongZipCmd} $zipFlags -o $outDir/classes.dex.jar -C $outDir -f "$outDir/classes*.dex" && ` +
- `${config.MergeZipsCmd} -D -stripFile "**/*.class" $out $outDir/classes.dex.jar $in`,
+ `${config.MergeZipsCmd} -D -stripFile "**/*.class" $mergeZipsFlags $out $outDir/classes.dex.jar $in`,
CommandDeps: []string{
"${config.D8Cmd}",
"${config.SoongZipCmd}",
@@ -115,17 +113,14 @@ var d8, d8RE = pctx.MultiCommandRemoteStaticRules("d8",
ExecStrategy: "${config.RED8ExecStrategy}",
Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"},
},
- }, []string{"outDir", "d8Flags", "zipFlags"}, nil)
+ }, []string{"outDir", "d8Flags", "zipFlags", "mergeZipsFlags"}, nil)
var r8, r8RE = pctx.MultiCommandRemoteStaticRules("r8",
blueprint.RuleParams{
Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` +
`rm -f "$outDict" && rm -rf "${outUsageDir}" && ` +
`mkdir -p $$(dirname ${outUsage}) && ` +
- // TODO(b/181095653): remove R8 timeout and go back to config.R8Cmd.
- `${runWithTimeoutCmd} -timeout 30m -on_timeout '${jstackCmd} $$PID' -- ` +
- `$r8Template${config.JavaCmd} ${config.DexJavaFlags} -cp ${config.R8Jar} ` +
- `com.android.tools.r8.compatproguard.CompatProguard -injars $in --output $outDir ` +
+ `$r8Template${config.R8Cmd} ${config.DexFlags} -injars $in --output $outDir ` +
`--no-data-resources ` +
`-printmapping ${outDict} ` +
`-printusage ${outUsage} ` +
@@ -134,12 +129,11 @@ var r8, r8RE = pctx.MultiCommandRemoteStaticRules("r8",
`${config.SoongZipCmd} -o ${outUsageZip} -C ${outUsageDir} -f ${outUsage} && ` +
`rm -rf ${outUsageDir} && ` +
`$zipTemplate${config.SoongZipCmd} $zipFlags -o $outDir/classes.dex.jar -C $outDir -f "$outDir/classes*.dex" && ` +
- `${config.MergeZipsCmd} -D -stripFile "**/*.class" $out $outDir/classes.dex.jar $in`,
+ `${config.MergeZipsCmd} -D -stripFile "**/*.class" $mergeZipsFlags $out $outDir/classes.dex.jar $in`,
CommandDeps: []string{
- "${config.R8Jar}",
+ "${config.R8Cmd}",
"${config.SoongZipCmd}",
"${config.MergeZipsCmd}",
- "${runWithTimeoutCmd}",
},
}, map[string]*remoteexec.REParams{
"$r8Template": &remoteexec.REParams{
@@ -165,7 +159,7 @@ var r8, r8RE = pctx.MultiCommandRemoteStaticRules("r8",
Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"},
},
}, []string{"outDir", "outDict", "outUsage", "outUsageZip", "outUsageDir",
- "r8Flags", "zipFlags"}, []string{"implicits"})
+ "r8Flags", "zipFlags", "mergeZipsFlags"}, []string{"implicits"})
func (d *dexer) dexCommonFlags(ctx android.ModuleContext, minSdkVersion android.SdkSpec) []string {
flags := d.dexProperties.Dxflags
@@ -290,6 +284,12 @@ func (d *dexer) compileDex(ctx android.ModuleContext, flags javaBuilderFlags, mi
commonFlags := d.dexCommonFlags(ctx, minSdkVersion)
+ // Exclude kotlinc generated files when "exclude_kotlinc_generated_files" is set to true.
+ mergeZipsFlags := ""
+ if proptools.BoolDefault(d.dexProperties.Exclude_kotlinc_generated_files, false) {
+ mergeZipsFlags = "-stripFile META-INF/*.kotlin_module -stripFile **/*.kotlin_builtins"
+ }
+
useR8 := d.effectiveOptimizeEnabled()
if useR8 {
proguardDictionary := android.PathForModuleOut(ctx, "proguard_dictionary")
@@ -302,13 +302,14 @@ func (d *dexer) compileDex(ctx android.ModuleContext, flags javaBuilderFlags, mi
r8Flags, r8Deps := d.r8Flags(ctx, flags)
rule := r8
args := map[string]string{
- "r8Flags": strings.Join(append(commonFlags, r8Flags...), " "),
- "zipFlags": zipFlags,
- "outDict": proguardDictionary.String(),
- "outUsageDir": proguardUsageDir.String(),
- "outUsage": proguardUsage.String(),
- "outUsageZip": proguardUsageZip.String(),
- "outDir": outDir.String(),
+ "r8Flags": strings.Join(append(commonFlags, r8Flags...), " "),
+ "zipFlags": zipFlags,
+ "outDict": proguardDictionary.String(),
+ "outUsageDir": proguardUsageDir.String(),
+ "outUsage": proguardUsage.String(),
+ "outUsageZip": proguardUsageZip.String(),
+ "outDir": outDir.String(),
+ "mergeZipsFlags": mergeZipsFlags,
}
if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_R8") {
rule = r8RE
@@ -336,9 +337,10 @@ func (d *dexer) compileDex(ctx android.ModuleContext, flags javaBuilderFlags, mi
Input: classesJar,
Implicits: d8Deps,
Args: map[string]string{
- "d8Flags": strings.Join(append(commonFlags, d8Flags...), " "),
- "zipFlags": zipFlags,
- "outDir": outDir.String(),
+ "d8Flags": strings.Join(append(commonFlags, d8Flags...), " "),
+ "zipFlags": zipFlags,
+ "outDir": outDir.String(),
+ "mergeZipsFlags": mergeZipsFlags,
},
})
}
diff --git a/java/java.go b/java/java.go
index 02e06e0c0..a61ddf426 100644
--- a/java/java.go
+++ b/java/java.go
@@ -487,6 +487,7 @@ func shouldUncompressDex(ctx android.ModuleContext, dexpreopter *dexpreopter) bo
func (j *Library) GenerateAndroidBuildActions(ctx android.ModuleContext) {
j.sdkVersion = j.SdkVersion(ctx)
j.minSdkVersion = j.MinSdkVersion(ctx)
+ j.maxSdkVersion = j.MaxSdkVersion(ctx)
apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
if !apexInfo.IsForPlatform() {
diff --git a/java/platform_bootclasspath.go b/java/platform_bootclasspath.go
index cf266b80b..ca87f92fd 100644
--- a/java/platform_bootclasspath.go
+++ b/java/platform_bootclasspath.go
@@ -68,7 +68,6 @@ type platformBootclasspathProperties struct {
func platformBootclasspathFactory() android.SingletonModule {
m := &platformBootclasspathModule{}
m.AddProperties(&m.properties)
- // TODO(satayev): split apex jars into separate configs.
initClasspathFragment(m, BOOTCLASSPATH)
android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
return m
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 751a71d0c..c6747c730 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -1122,6 +1122,22 @@ func (module *SdkLibrary) getGeneratedApiScopes(ctx android.EarlyModuleContext)
return generatedScopes
}
+var _ android.ModuleWithMinSdkVersionCheck = (*SdkLibrary)(nil)
+
+func (module *SdkLibrary) CheckMinSdkVersion(ctx android.ModuleContext) {
+ android.CheckMinSdkVersion(ctx, module.MinSdkVersion(ctx).ApiLevel, func(c android.ModuleContext, do android.PayloadDepsCallback) {
+ ctx.WalkDeps(func(child android.Module, parent android.Module) bool {
+ isExternal := !module.depIsInSameApex(ctx, child)
+ if am, ok := child.(android.ApexModule); ok {
+ if !do(ctx, parent, am, isExternal) {
+ return false
+ }
+ }
+ return !isExternal
+ })
+ })
+}
+
type sdkLibraryComponentTag struct {
blueprint.BaseDependencyTag
name string
@@ -1207,6 +1223,10 @@ func (module *SdkLibrary) OutputFiles(tag string) (android.Paths, error) {
}
func (module *SdkLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ if proptools.String(module.deviceProperties.Min_sdk_version) != "" {
+ module.CheckMinSdkVersion(ctx)
+ }
+
module.generateCommonBuildActions(ctx)
// Only build an implementation library if required.
@@ -2466,12 +2486,12 @@ func (module *sdkLibraryXml) GenerateAndroidBuildActions(ctx android.ModuleConte
func (module *sdkLibraryXml) AndroidMkEntries() []android.AndroidMkEntries {
if module.hideApexVariantFromMake {
- return []android.AndroidMkEntries{android.AndroidMkEntries{
+ return []android.AndroidMkEntries{{
Disabled: true,
}}
}
- return []android.AndroidMkEntries{android.AndroidMkEntries{
+ return []android.AndroidMkEntries{{
Class: "ETC",
OutputFile: android.OptionalPathForPath(module.outputFilePath),
ExtraEntries: []android.AndroidMkExtraEntriesFunc{
diff --git a/java/sdk_library_test.go b/java/sdk_library_test.go
index 3cf4987e1..f8717c066 100644
--- a/java/sdk_library_test.go
+++ b/java/sdk_library_test.go
@@ -47,6 +47,7 @@ func TestJavaSdkLibrary(t *testing.T) {
name: "bar",
srcs: ["a.java", "b.java"],
api_packages: ["bar"],
+ exclude_kotlinc_generated_files: true,
}
java_library {
name: "baz",
@@ -159,6 +160,14 @@ func TestJavaSdkLibrary(t *testing.T) {
sdkLibs := quxLib.ClassLoaderContexts().UsesLibs()
android.AssertDeepEquals(t, "qux exports", []string{"foo", "bar", "fred", "quuz"}, sdkLibs)
}
+
+ fooDexJar := result.ModuleForTests("foo", "android_common").Rule("d8")
+ // tests if kotlinc generated files are NOT excluded from output of foo.
+ android.AssertStringDoesNotContain(t, "foo dex", fooDexJar.BuildParams.Args["mergeZipsFlags"], "-stripFile META-INF/*.kotlin_module")
+
+ barDexJar := result.ModuleForTests("bar", "android_common").Rule("d8")
+ // tests if kotlinc generated files are excluded from output of bar.
+ android.AssertStringDoesContain(t, "bar dex", barDexJar.BuildParams.Args["mergeZipsFlags"], "-stripFile META-INF/*.kotlin_module")
}
func TestJavaSdkLibrary_StubOrImplOnlyLibs(t *testing.T) {
@@ -958,3 +967,87 @@ func TestJavaSdkLibraryDist(t *testing.T) {
})
}
}
+
+func TestSdkLibrary_CheckMinSdkVersion(t *testing.T) {
+ preparer := android.GroupFixturePreparers(
+ PrepareForTestWithJavaBuildComponents,
+ PrepareForTestWithJavaDefaultModules,
+ PrepareForTestWithJavaSdkLibraryFiles,
+ )
+
+ preparer.RunTestWithBp(t, `
+ java_sdk_library {
+ name: "sdklib",
+ srcs: ["a.java"],
+ static_libs: ["util"],
+ min_sdk_version: "30",
+ unsafe_ignore_missing_latest_api: true,
+ }
+
+ java_library {
+ name: "util",
+ srcs: ["a.java"],
+ min_sdk_version: "30",
+ }
+ `)
+
+ preparer.
+ RunTestWithBp(t, `
+ java_sdk_library {
+ name: "sdklib",
+ srcs: ["a.java"],
+ libs: ["util"],
+ impl_only_libs: ["util"],
+ stub_only_libs: ["util"],
+ stub_only_static_libs: ["util"],
+ min_sdk_version: "30",
+ unsafe_ignore_missing_latest_api: true,
+ }
+
+ java_library {
+ name: "util",
+ srcs: ["a.java"],
+ }
+ `)
+
+ preparer.ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`module "util".*should support min_sdk_version\(30\)`)).
+ RunTestWithBp(t, `
+ java_sdk_library {
+ name: "sdklib",
+ srcs: ["a.java"],
+ static_libs: ["util"],
+ min_sdk_version: "30",
+ unsafe_ignore_missing_latest_api: true,
+ }
+
+ java_library {
+ name: "util",
+ srcs: ["a.java"],
+ min_sdk_version: "31",
+ }
+ `)
+
+ preparer.ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(`module "another_util".*should support min_sdk_version\(30\)`)).
+ RunTestWithBp(t, `
+ java_sdk_library {
+ name: "sdklib",
+ srcs: ["a.java"],
+ static_libs: ["util"],
+ min_sdk_version: "30",
+ unsafe_ignore_missing_latest_api: true,
+ }
+
+ java_library {
+ name: "util",
+ srcs: ["a.java"],
+ static_libs: ["another_util"],
+ min_sdk_version: "30",
+ }
+
+ java_library {
+ name: "another_util",
+ srcs: ["a.java"],
+ min_sdk_version: "31",
+ }
+ `)
+}
diff --git a/java/systemserver_classpath_fragment.go b/java/systemserver_classpath_fragment.go
index 10dbd01e2..be28fe9c2 100644
--- a/java/systemserver_classpath_fragment.go
+++ b/java/systemserver_classpath_fragment.go
@@ -72,10 +72,15 @@ func (s *SystemServerClasspathModule) ShouldSupportSdkVersion(ctx android.BaseMo
}
type systemServerClasspathFragmentProperties struct {
- // The contents of this systemserverclasspath_fragment, could be either java_library, or java_sdk_library.
+ // List of system_server classpath jars, could be either java_library, or java_sdk_library.
//
// The order of this list matters as it is the order that is used in the SYSTEMSERVERCLASSPATH.
Contents []string
+
+ // List of jars that system_server loads dynamically using separate classloaders.
+ //
+ // The order does not matter.
+ Standalone_contents []string
}
func systemServerClasspathFactory() android.Module {
@@ -88,8 +93,12 @@ func systemServerClasspathFactory() android.Module {
}
func (s *SystemServerClasspathModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- if len(s.properties.Contents) == 0 {
- ctx.PropertyErrorf("contents", "empty contents are not allowed")
+ if len(s.properties.Contents) == 0 && len(s.properties.Standalone_contents) == 0 {
+ ctx.PropertyErrorf("contents", "Either contents or standalone_contents needs to be non-empty")
+ }
+
+ if s.ShouldIgnore() {
+ return
}
configuredJars := s.configuredJars(ctx)
@@ -128,8 +137,17 @@ func IsSystemServerClasspathFragmentContentDepTag(tag blueprint.DependencyTag) b
func (s *SystemServerClasspathModule) ComponentDepsMutator(ctx android.BottomUpMutatorContext) {
module := ctx.Module()
+ var deps []string
+ deps = append(deps, s.properties.Contents...)
+ deps = append(deps, s.properties.Standalone_contents...)
- for _, name := range s.properties.Contents {
+ for _, name := range deps {
ctx.AddDependency(module, systemServerClasspathFragmentContentDepTag, name)
}
}
+
+func (s *SystemServerClasspathModule) ShouldIgnore() bool {
+ // Ignore this `systemserverclasspath_fragment` if it only contains `standalone_contents` because
+ // it is for T and above.
+ return len(s.properties.Contents) == 0
+}
diff --git a/java/systemserver_classpath_fragment_test.go b/java/systemserver_classpath_fragment_test.go
index 9ad50dd4a..ba328e7b1 100644
--- a/java/systemserver_classpath_fragment_test.go
+++ b/java/systemserver_classpath_fragment_test.go
@@ -99,7 +99,7 @@ func TestPlatformSystemServerClasspathModule_AndroidMkEntries(t *testing.T) {
func TestSystemServerClasspathFragmentWithoutContents(t *testing.T) {
prepareForTestWithSystemServerClasspath.
ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(
- `\Qempty contents are not allowed\E`)).
+ `\QEither contents or standalone_contents needs to be non-empty\E`)).
RunTestWithBp(t, `
systemserverclasspath_fragment {
name: "systemserverclasspath-fragment",
diff --git a/rust/rust.go b/rust/rust.go
index f068b3d7b..cdeecc191 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -328,10 +328,6 @@ func (mod *Module) SdkVersion() string {
return ""
}
-func (mod *Module) MinSdkVersion() string {
- return ""
-}
-
func (mod *Module) AlwaysSdk() bool {
return false
}
@@ -1276,15 +1272,13 @@ func (mod *Module) HostToolPath() android.OptionalPath {
var _ android.ApexModule = (*Module)(nil)
-func (mod *Module) minSdkVersion() string {
+func (mod *Module) MinSdkVersion() string {
return String(mod.Properties.Min_sdk_version)
}
-var _ android.ApexModule = (*Module)(nil)
-
// Implements android.ApexModule
func (mod *Module) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion android.ApiLevel) error {
- minSdkVersion := mod.minSdkVersion()
+ minSdkVersion := mod.MinSdkVersion()
if minSdkVersion == "apex_inherit" {
return nil
}
diff --git a/scripts/OWNERS b/scripts/OWNERS
index 2b9c2ded9..573134ed8 100644
--- a/scripts/OWNERS
+++ b/scripts/OWNERS
@@ -3,4 +3,4 @@ per-file build-mainline-modules.sh = ngeoffray@google.com,paulduffin@google.com,
per-file build-aml-prebuilts.sh = ngeoffray@google.com,paulduffin@google.com,mast@google.com
per-file construct_context.py = ngeoffray@google.com,calin@google.com,mathieuc@google.com,skvadrik@google.com
per-file conv_linker_config.py = kiyoungkim@google.com, jiyong@google.com, jooyung@google.com
-per-file gen_ndk*.sh = sophiez@google.com, allenhair@google.com
+per-file gen_ndk*.sh,gen_java*.sh = sophiez@google.com, allenhair@google.com \ No newline at end of file
diff --git a/scripts/gen_java_usedby_apex.sh b/scripts/gen_java_usedby_apex.sh
new file mode 100755
index 000000000..e3985414b
--- /dev/null
+++ b/scripts/gen_java_usedby_apex.sh
@@ -0,0 +1,48 @@
+#!/bin/bash -e
+
+# Copyright 2020 Google Inc. All rights reserved.
+#
+# 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.
+
+printHelp() {
+ echo "**************************** Usage Instructions ****************************"
+ echo "This script is used to generate the Mainline modules used-by Java symbols."
+ echo ""
+ echo "To run this script use: ./gen_java_usedby_apex.sh \$BINARY_DEXDEPS_PATH \$OUTPUT_FILE_PATH \$JAR_AND_APK_LIST"
+ echo "For example: If all jar and apk files are '/myJar.jar /myApk.apk' and output write to /myModule.txt then the command would be:"
+ echo "./gen_java_usedby_apex.sh \$BINARY_DEXDEPS_PATH /myModule.txt /myJar.jar /myApk.apk"
+}
+
+genUsedByList() {
+ dexdeps="$1"
+ shift
+ out="$1"
+ shift
+ rm -f "$out"
+ touch "$out"
+ echo "<externals>" >> "$out"
+ for x in "$@"; do
+ "$dexdeps" "$x" >> "$out" || echo "</external>" >> "$out"
+ done
+ echo "</externals>" >> "$out"
+}
+
+if [[ "$1" == "help" ]]
+then
+ printHelp
+elif [[ "$#" -lt 2 ]]
+then
+ echo "Wrong argument length. Expecting at least 2 argument representing dexdeps path, output path, followed by a list of jar or apk files in the Mainline module."
+else
+ genUsedByList "$@"
+fi \ No newline at end of file
diff --git a/sdk/sdk.go b/sdk/sdk.go
index b1c8aebf9..d8196fffc 100644
--- a/sdk/sdk.go
+++ b/sdk/sdk.go
@@ -257,7 +257,13 @@ func newSdkModule(moduleExports bool) *sdk {
// Create an instance of the dynamically created struct that contains all the
// properties for the member type specific list properties.
s.dynamicMemberTypeListProperties = s.dynamicSdkMemberTypes.createMemberListProperties()
- s.AddProperties(&s.properties, s.dynamicMemberTypeListProperties)
+
+ ignoredProperties := struct {
+ // `systemserverclasspath_fragments` is for T and above.
+ Systemserverclasspath_fragments []string
+ }{}
+
+ s.AddProperties(&s.properties, s.dynamicMemberTypeListProperties, &ignoredProperties)
// Make sure that the prebuilt visibility property is verified for errors.
android.AddVisibilityProperty(s, "prebuilt_visibility", &s.properties.Prebuilt_visibility)