afdo: Remove -fprofile-sample-accurate flag am: 9825a6c7f8
Original change: https://googleplex-android-review.googlesource.com/c/platform/build/soong/+/23587699
Change-Id: Icb2fabcf494be1efad247b366f101fa6fb4b779e
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/aidl_library/Android.bp b/aidl_library/Android.bp
new file mode 100644
index 0000000..ec21504
--- /dev/null
+++ b/aidl_library/Android.bp
@@ -0,0 +1,32 @@
+// Copyright 2023 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+bootstrap_go_package {
+ name: "soong-aidl-library",
+ pkgPath: "android/soong/aidl_library",
+ deps: [
+ "soong-android",
+ ],
+ srcs: [
+ "aidl_library.go",
+ ],
+ testSrcs: [
+ "aidl_library_test.go",
+ ],
+ pluginFor: ["soong_build"],
+}
diff --git a/aidl_library/aidl_library.go b/aidl_library/aidl_library.go
new file mode 100644
index 0000000..8a84e6b
--- /dev/null
+++ b/aidl_library/aidl_library.go
@@ -0,0 +1,174 @@
+// Copyright 2023 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 aidl_library
+
+import (
+ "android/soong/android"
+ "android/soong/bazel"
+
+ "github.com/google/blueprint"
+ "github.com/google/blueprint/proptools"
+)
+
+var PrepareForTestWithAidlLibrary = android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
+ registerAidlLibraryBuildComponents(ctx)
+})
+
+func init() {
+ registerAidlLibraryBuildComponents(android.InitRegistrationContext)
+}
+
+func registerAidlLibraryBuildComponents(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("aidl_library", AidlLibraryFactory)
+}
+
+type aidlLibraryProperties struct {
+ // srcs lists files that are included in this module for aidl compilation
+ Srcs []string `android:"path"`
+
+ // hdrs lists the headers that are imported by srcs but are not compiled by aidl to language binding code
+ // hdrs is provided to support Bazel migration. It is a no-op until
+ // we enable input sandbox in aidl compilation action
+ Hdrs []string `android:"path"`
+
+ // The prefix to strip from the paths of the .aidl files
+ // The remaining path is the package path of the aidl interface
+ Strip_import_prefix *string
+
+ // List of aidl files or aidl_library depended on by the module
+ Deps []string `android:"arch_variant"`
+}
+
+type AidlLibrary struct {
+ android.ModuleBase
+ android.BazelModuleBase
+ properties aidlLibraryProperties
+}
+
+type bazelAidlLibraryAttributes struct {
+ Srcs bazel.LabelListAttribute
+ Hdrs bazel.LabelListAttribute
+ Strip_import_prefix *string
+ Deps bazel.LabelListAttribute
+}
+
+func (lib *AidlLibrary) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
+ srcs := bazel.MakeLabelListAttribute(
+ android.BazelLabelForModuleSrc(
+ ctx,
+ lib.properties.Srcs,
+ ),
+ )
+
+ hdrs := bazel.MakeLabelListAttribute(
+ android.BazelLabelForModuleSrc(
+ ctx,
+ lib.properties.Hdrs,
+ ),
+ )
+
+ tags := []string{"apex_available=//apex_available:anyapex"}
+ deps := bazel.MakeLabelListAttribute(android.BazelLabelForModuleDeps(ctx, lib.properties.Deps))
+
+ attrs := &bazelAidlLibraryAttributes{
+ Srcs: srcs,
+ Hdrs: hdrs,
+ Strip_import_prefix: lib.properties.Strip_import_prefix,
+ Deps: deps,
+ }
+
+ props := bazel.BazelTargetModuleProperties{
+ Rule_class: "aidl_library",
+ Bzl_load_location: "//build/bazel/rules/aidl:aidl_library.bzl",
+ }
+
+ ctx.CreateBazelTargetModule(
+ props,
+ android.CommonAttributes{
+ Name: lib.Name(),
+ Tags: bazel.MakeStringListAttribute(tags),
+ },
+ attrs,
+ )
+}
+
+type AidlLibraryInfo struct {
+ // The direct aidl files of the module
+ Srcs android.Paths
+ // The include dirs to the direct aidl files and those provided from aidl_library deps
+ IncludeDirs android.DepSet
+}
+
+// AidlLibraryProvider provides the srcs and the transitive include dirs
+var AidlLibraryProvider = blueprint.NewProvider(AidlLibraryInfo{})
+
+func (lib *AidlLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ includeDirsDepSetBuilder := android.NewDepSetBuilder(android.PREORDER)
+
+ if len(lib.properties.Srcs) == 0 && len(lib.properties.Hdrs) == 0 {
+ ctx.ModuleErrorf("at least srcs or hdrs prop must be non-empty")
+ }
+
+ srcs := android.PathsForModuleSrc(ctx, lib.properties.Srcs)
+ if lib.properties.Strip_import_prefix != nil {
+ srcs = android.PathsWithModuleSrcSubDir(
+ ctx,
+ srcs,
+ android.String(lib.properties.Strip_import_prefix))
+ }
+
+ includeDir := android.PathForModuleSrc(
+ ctx,
+ proptools.StringDefault(lib.properties.Strip_import_prefix, ""),
+ )
+
+ includeDirsDepSetBuilder.Direct(includeDir)
+
+ for _, dep := range ctx.GetDirectDepsWithTag(aidlLibraryTag) {
+ if ctx.OtherModuleHasProvider(dep, AidlLibraryProvider) {
+ info := ctx.OtherModuleProvider(dep, AidlLibraryProvider).(AidlLibraryInfo)
+ includeDirsDepSetBuilder.Transitive(&info.IncludeDirs)
+ }
+ }
+
+ // TODO(b/279960133) Propagate direct and transitive headers/srcs when aidl action sandboxes inputs
+ ctx.SetProvider(AidlLibraryProvider, AidlLibraryInfo{
+ Srcs: srcs,
+ IncludeDirs: *includeDirsDepSetBuilder.Build(),
+ })
+}
+
+// aidl_library contains a list of .aidl files and the strip_import_prefix to
+// to strip from the paths of the .aidl files. The sub-path left-over after stripping
+// corresponds to the aidl package path the aidl interfaces are scoped in
+func AidlLibraryFactory() android.Module {
+ module := &AidlLibrary{}
+ module.AddProperties(&module.properties)
+ android.InitAndroidModule(module)
+ android.InitBazelModule(module)
+ return module
+}
+
+type aidlDependencyTag struct {
+ blueprint.BaseDependencyTag
+}
+
+var aidlLibraryTag = aidlDependencyTag{}
+
+func (lib *AidlLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {
+ for _, dep := range lib.properties.Deps {
+ ctx.AddDependency(lib, aidlLibraryTag, dep)
+ }
+}
diff --git a/aidl_library/aidl_library_test.go b/aidl_library/aidl_library_test.go
new file mode 100644
index 0000000..d9b410a
--- /dev/null
+++ b/aidl_library/aidl_library_test.go
@@ -0,0 +1,122 @@
+// Copyright 2023 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 aidl_library
+
+import (
+ "android/soong/android"
+ "testing"
+)
+
+func TestAidlLibrary(t *testing.T) {
+ t.Parallel()
+ ctx := android.GroupFixturePreparers(
+ PrepareForTestWithAidlLibrary,
+ android.MockFS{
+ "package_bar/Android.bp": []byte(`
+ aidl_library {
+ name: "bar",
+ srcs: ["x/y/Bar.aidl"],
+ strip_import_prefix: "x",
+ }
+ `),
+ }.AddToFixture(),
+ android.MockFS{
+ "package_foo/Android.bp": []byte(`
+ aidl_library {
+ name: "foo",
+ srcs: ["a/b/Foo.aidl"],
+ hdrs: ["Header.aidl"],
+ strip_import_prefix: "a",
+ deps: ["bar"],
+ }
+ `),
+ }.AddToFixture(),
+ ).RunTest(t).TestContext
+
+ foo := ctx.ModuleForTests("foo", "").Module().(*AidlLibrary)
+ actualInfo := ctx.ModuleProvider(foo, AidlLibraryProvider).(AidlLibraryInfo)
+
+ android.AssertArrayString(
+ t,
+ "aidl include dirs",
+ []string{"package_foo/a", "package_bar/x"},
+ actualInfo.IncludeDirs.ToList().Strings(),
+ )
+
+ android.AssertPathsRelativeToTopEquals(
+ t,
+ "aidl srcs paths",
+ []string{"package_foo/a/b/Foo.aidl"},
+ actualInfo.Srcs,
+ )
+}
+
+func TestAidlLibraryWithoutStripImportPrefix(t *testing.T) {
+ t.Parallel()
+ ctx := android.GroupFixturePreparers(
+ PrepareForTestWithAidlLibrary,
+ android.MockFS{
+ "package_bar/Android.bp": []byte(`
+ aidl_library {
+ name: "bar",
+ srcs: ["x/y/Bar.aidl"],
+ }
+ `),
+ }.AddToFixture(),
+ android.MockFS{
+ "package_foo/Android.bp": []byte(`
+ aidl_library {
+ name: "foo",
+ srcs: ["a/b/Foo.aidl"],
+ hdrs: ["Header.aidl"],
+ deps: ["bar"],
+ }
+ `),
+ }.AddToFixture(),
+ ).RunTest(t).TestContext
+
+ foo := ctx.ModuleForTests("foo", "").Module().(*AidlLibrary)
+ actualInfo := ctx.ModuleProvider(foo, AidlLibraryProvider).(AidlLibraryInfo)
+
+ android.AssertArrayString(
+ t,
+ "aidl include dirs",
+ []string{"package_foo", "package_bar"},
+ actualInfo.IncludeDirs.ToList().Strings(),
+ )
+
+ android.AssertPathsRelativeToTopEquals(
+ t,
+ "aidl srcs paths",
+ []string{"package_foo/a/b/Foo.aidl"},
+ actualInfo.Srcs,
+ )
+}
+
+func TestAidlLibraryWithNoSrcsHdrsDeps(t *testing.T) {
+ t.Parallel()
+ android.GroupFixturePreparers(
+ PrepareForTestWithAidlLibrary,
+ android.MockFS{
+ "package_bar/Android.bp": []byte(`
+ aidl_library {
+ name: "bar",
+ }
+ `),
+ }.AddToFixture(),
+ ).
+ ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern("at least srcs or hdrs prop must be non-empty")).
+ RunTest(t)
+}
diff --git a/android/apex.go b/android/apex.go
index c9b4a0b..35e1d02 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -451,6 +451,14 @@
AvailableToGkiApex = "com.android.gki.*"
)
+var (
+ AvailableToRecognziedWildcards = []string{
+ AvailableToPlatform,
+ AvailableToAnyApex,
+ AvailableToGkiApex,
+ }
+)
+
// CheckAvailableForApex provides the default algorithm for checking the apex availability. When the
// availability is empty, it defaults to ["//apex_available:platform"] which means "available to the
// platform but not available to any APEX". When the list is not empty, `what` is matched against
@@ -909,3 +917,9 @@
return true
})
}
+
+// Implemented by apexBundle.
+type ApexTestInterface interface {
+ // Return true if the apex bundle is an apex_test
+ IsTestApex() bool
+}
diff --git a/android/mutator.go b/android/mutator.go
index 4ec9604..013fa77 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -758,6 +758,35 @@
return attr
}
+func ApexAvailableTagsWithoutTestApexes(ctx BaseModuleContext, mod Module) bazel.StringListAttribute {
+ attr := bazel.StringListAttribute{}
+ if am, ok := mod.(ApexModule); ok {
+ apexAvailableWithoutTestApexes := removeTestApexes(ctx, am.apexModuleBase().ApexAvailable())
+ // If a user does not specify apex_available in Android.bp, then soong provides a default.
+ // To avoid verbosity of BUILD files, remove this default from user-facing BUILD files.
+ if len(am.apexModuleBase().ApexProperties.Apex_available) == 0 {
+ apexAvailableWithoutTestApexes = []string{}
+ }
+ attr.Value = ConvertApexAvailableToTags(apexAvailableWithoutTestApexes)
+ }
+ return attr
+}
+
+func removeTestApexes(ctx BaseModuleContext, apex_available []string) []string {
+ testApexes := []string{}
+ for _, aa := range apex_available {
+ // ignore the wildcards
+ if InList(aa, AvailableToRecognziedWildcards) {
+ continue
+ }
+ mod, _ := ctx.ModuleFromName(aa)
+ if apex, ok := mod.(ApexTestInterface); ok && apex.IsTestApex() {
+ testApexes = append(testApexes, aa)
+ }
+ }
+ return RemoveListFromList(CopyOf(apex_available), testApexes)
+}
+
func ConvertApexAvailableToTags(apexAvailable []string) []string {
if len(apexAvailable) == 0 {
// We need nil specifically to make bp2build not add the tags property at all,
@@ -771,6 +800,13 @@
return result
}
+// ConvertApexAvailableToTagsWithoutTestApexes converts a list of apex names to a list of bazel tags
+// This function drops any test apexes from the input.
+func ConvertApexAvailableToTagsWithoutTestApexes(ctx BaseModuleContext, apexAvailable []string) []string {
+ noTestApexes := removeTestApexes(ctx, apexAvailable)
+ return ConvertApexAvailableToTags(noTestApexes)
+}
+
func (t *topDownMutatorContext) createBazelTargetModule(
bazelProps bazel.BazelTargetModuleProperties,
commonAttrs CommonAttributes,
diff --git a/android/proto.go b/android/proto.go
index 09e50c8..cebbd59 100644
--- a/android/proto.go
+++ b/android/proto.go
@@ -234,7 +234,7 @@
}
}
- tags := ApexAvailableTags(ctx.Module())
+ tags := ApexAvailableTagsWithoutTestApexes(ctx.(TopDownMutatorContext), ctx.Module())
ctx.CreateBazelTargetModule(
bazel.BazelTargetModuleProperties{Rule_class: "proto_library"},
diff --git a/android/test_asserts.go b/android/test_asserts.go
index 4143f15..5cc7e4a 100644
--- a/android/test_asserts.go
+++ b/android/test_asserts.go
@@ -17,6 +17,7 @@
import (
"fmt"
"reflect"
+ "regexp"
"strings"
"testing"
)
@@ -137,6 +138,20 @@
}
}
+// AssertStringMatches checks if the string matches the given regular expression. If it does not match,
+// then an error is reported with the supplied message including a reason for why it failed.
+func AssertStringMatches(t *testing.T, message, s, expectedRex string) {
+ t.Helper()
+ ok, err := regexp.MatchString(expectedRex, s)
+ if err != nil {
+ t.Fatalf("regexp failure trying to match %s against `%s` expression: %s", s, expectedRex, err)
+ return
+ }
+ if !ok {
+ t.Errorf("%s does not match regular expression %s", s, expectedRex)
+ }
+}
+
// AssertStringListContains checks if the list of strings contains the expected string. If it does
// not then it reports an error prefixed with the supplied message and including a reason for why it
// failed.
diff --git a/android/updatable_modules.go b/android/updatable_modules.go
index 6d0eeb7..db45637 100644
--- a/android/updatable_modules.go
+++ b/android/updatable_modules.go
@@ -33,4 +33,4 @@
// * AOSP - xx9990000
// * x-mainline-prod - xx9990000
// * master - 990090000
-const DefaultUpdatableModuleVersion = "340090000"
+const DefaultUpdatableModuleVersion = "349990000"
diff --git a/apex/apex.go b/apex/apex.go
index c1c9e5c..fa9233e 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -1823,6 +1823,7 @@
Certificate() java.Certificate
BaseModuleName() string
LintDepSets() java.LintDepSets
+ PrivAppAllowlist() android.OptionalPath
}
var _ androidApp = (*java.AndroidApp)(nil)
@@ -1843,7 +1844,7 @@
return buildId
}
-func apexFileForAndroidApp(ctx android.BaseModuleContext, aapp androidApp) apexFile {
+func apexFilesForAndroidApp(ctx android.BaseModuleContext, aapp androidApp) []apexFile {
appDir := "app"
if aapp.Privileged() {
appDir = "priv-app"
@@ -1865,7 +1866,18 @@
}); ok {
af.overriddenPackageName = app.OverriddenManifestPackageName()
}
- return af
+
+ apexFiles := []apexFile{}
+
+ if allowlist := aapp.PrivAppAllowlist(); allowlist.Valid() {
+ dirInApex := filepath.Join("etc", "permissions")
+ privAppAllowlist := newApexFile(ctx, allowlist.Path(), aapp.BaseModuleName()+"_privapp", dirInApex, etc, aapp)
+ apexFiles = append(apexFiles, privAppAllowlist)
+ }
+
+ apexFiles = append(apexFiles, af)
+
+ return apexFiles
}
func apexFileForRuntimeResourceOverlay(ctx android.BaseModuleContext, rro java.RuntimeResourceOverlayModule) apexFile {
@@ -2310,12 +2322,12 @@
case androidAppTag:
switch ap := child.(type) {
case *java.AndroidApp:
- vctx.filesInfo = append(vctx.filesInfo, apexFileForAndroidApp(ctx, ap))
+ vctx.filesInfo = append(vctx.filesInfo, apexFilesForAndroidApp(ctx, ap)...)
return true // track transitive dependencies
case *java.AndroidAppImport:
- vctx.filesInfo = append(vctx.filesInfo, apexFileForAndroidApp(ctx, ap))
+ vctx.filesInfo = append(vctx.filesInfo, apexFilesForAndroidApp(ctx, ap)...)
case *java.AndroidTestHelperApp:
- vctx.filesInfo = append(vctx.filesInfo, apexFileForAndroidApp(ctx, ap))
+ vctx.filesInfo = append(vctx.filesInfo, apexFilesForAndroidApp(ctx, ap)...)
case *java.AndroidAppSet:
appDir := "app"
if ap.Privileged() {
@@ -3790,3 +3802,7 @@
func invalidCompileMultilib(ctx android.TopDownMutatorContext, value string) {
ctx.PropertyErrorf("compile_multilib", "Invalid value: %s", value)
}
+
+func (a *apexBundle) IsTestApex() bool {
+ return a.testApex
+}
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 139b77e..66ba0a8 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -6165,6 +6165,7 @@
sdk_version: "current",
system_modules: "none",
privileged: true,
+ privapp_allowlist: "privapp_allowlist_com.android.AppFooPriv.xml",
stl: "none",
apex_available: [ "myapex" ],
}
@@ -6194,6 +6195,7 @@
ensureContains(t, copyCmds, "image.apex/app/AppFoo@TEST.BUILD_ID/AppFoo.apk")
ensureContains(t, copyCmds, "image.apex/priv-app/AppFooPriv@TEST.BUILD_ID/AppFooPriv.apk")
+ ensureContains(t, copyCmds, "image.apex/etc/permissions/privapp_allowlist_com.android.AppFooPriv.xml")
appZipRule := ctx.ModuleForTests("AppFoo", "android_common_apex10000").Description("zip jni libs")
// JNI libraries are uncompressed
@@ -6208,6 +6210,18 @@
// ... and not directly inside the APEX
ensureNotContains(t, copyCmds, "image.apex/lib64/"+jni+".so")
}
+
+ apexBundle := module.Module().(*apexBundle)
+ data := android.AndroidMkDataForTest(t, ctx, apexBundle)
+ var builder strings.Builder
+ data.Custom(&builder, apexBundle.Name(), "TARGET_", "", data)
+ androidMk := builder.String()
+ ensureContains(t, androidMk, "LOCAL_MODULE := AppFooPriv.myapex")
+ ensureContains(t, androidMk, "LOCAL_MODULE := AppFoo.myapex")
+ ensureMatches(t, androidMk, "LOCAL_SOONG_INSTALLED_MODULE := \\S+AppFooPriv.apk")
+ ensureMatches(t, androidMk, "LOCAL_SOONG_INSTALLED_MODULE := \\S+AppFoo.apk")
+ ensureMatches(t, androidMk, "LOCAL_SOONG_INSTALL_PAIRS := \\S+AppFooPriv.apk")
+ ensureContains(t, androidMk, "LOCAL_SOONG_INSTALL_PAIRS := privapp_allowlist_com.android.AppFooPriv.xml:$(PRODUCT_OUT)/apex/myapex/etc/permissions/privapp_allowlist_com.android.AppFooPriv.xml")
}
func TestApexWithAppImportBuildId(t *testing.T) {
diff --git a/bp2build/Android.bp b/bp2build/Android.bp
index b6635c4..9ec3a40 100644
--- a/bp2build/Android.bp
+++ b/bp2build/Android.bp
@@ -19,6 +19,7 @@
"testing.go",
],
deps: [
+ "soong-aidl-library",
"soong-android",
"soong-android-allowlists",
"soong-android-soongconfig",
@@ -37,6 +38,7 @@
],
testSrcs: [
"aar_conversion_test.go",
+ "aidl_library_conversion_test.go",
"android_app_certificate_conversion_test.go",
"android_app_conversion_test.go",
"apex_conversion_test.go",
diff --git a/bp2build/aidl_library_conversion_test.go b/bp2build/aidl_library_conversion_test.go
new file mode 100644
index 0000000..0522da4
--- /dev/null
+++ b/bp2build/aidl_library_conversion_test.go
@@ -0,0 +1,119 @@
+// Copyright 2023 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 bp2build
+
+import (
+ "testing"
+
+ "android/soong/aidl_library"
+ "android/soong/android"
+)
+
+func runAidlLibraryTestCase(t *testing.T, tc Bp2buildTestCase) {
+ t.Helper()
+ (&tc).ModuleTypeUnderTest = "aidl_library"
+ (&tc).ModuleTypeUnderTestFactory = aidl_library.AidlLibraryFactory
+ RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {}, tc)
+}
+
+func TestAidlLibrary(t *testing.T) {
+ testcases := []struct {
+ name string
+ bp string
+ expectedBazelAttrs AttrNameToString
+ }{
+ {
+ name: "aidl_library with strip_import_prefix",
+ bp: `
+ aidl_library {
+ name: "foo",
+ srcs: ["aidl/foo.aidl"],
+ hdrs: ["aidl/header.aidl"],
+ strip_import_prefix: "aidl",
+ }`,
+ expectedBazelAttrs: AttrNameToString{
+ "srcs": `["aidl/foo.aidl"]`,
+ "hdrs": `["aidl/header.aidl"]`,
+ "strip_import_prefix": `"aidl"`,
+ "tags": `["apex_available=//apex_available:anyapex"]`,
+ },
+ },
+ {
+ name: "aidl_library without strip_import_prefix",
+ bp: `
+ aidl_library {
+ name: "foo",
+ srcs: ["aidl/foo.aidl"],
+ hdrs: ["aidl/header.aidl"],
+ }`,
+ expectedBazelAttrs: AttrNameToString{
+ "srcs": `["aidl/foo.aidl"]`,
+ "hdrs": `["aidl/header.aidl"]`,
+ "tags": `["apex_available=//apex_available:anyapex"]`,
+ },
+ },
+ }
+
+ for _, test := range testcases {
+ t.Run(test.name, func(t *testing.T) {
+ expectedBazelTargets := []string{
+ MakeBazelTargetNoRestrictions("aidl_library", "foo", test.expectedBazelAttrs),
+ }
+ runAidlLibraryTestCase(t, Bp2buildTestCase{
+ Description: test.name,
+ Blueprint: test.bp,
+ ExpectedBazelTargets: expectedBazelTargets,
+ })
+ })
+ }
+}
+
+func TestAidlLibraryWithDeps(t *testing.T) {
+ bp := `
+ aidl_library {
+ name: "bar",
+ srcs: ["Bar.aidl"],
+ hdrs: ["aidl/BarHeader.aidl"],
+ }
+ aidl_library {
+ name: "foo",
+ srcs: ["aidl/Foo.aidl"],
+ hdrs: ["aidl/FooHeader.aidl"],
+ strip_import_prefix: "aidl",
+ deps: ["bar"],
+ }`
+
+ t.Run("aidl_library with deps", func(t *testing.T) {
+ expectedBazelTargets := []string{
+ MakeBazelTargetNoRestrictions("aidl_library", "bar", AttrNameToString{
+ "srcs": `["Bar.aidl"]`,
+ "hdrs": `["aidl/BarHeader.aidl"]`,
+ "tags": `["apex_available=//apex_available:anyapex"]`,
+ }),
+ MakeBazelTargetNoRestrictions("aidl_library", "foo", AttrNameToString{
+ "srcs": `["aidl/Foo.aidl"]`,
+ "hdrs": `["aidl/FooHeader.aidl"]`,
+ "strip_import_prefix": `"aidl"`,
+ "deps": `[":bar"]`,
+ "tags": `["apex_available=//apex_available:anyapex"]`,
+ }),
+ }
+ runAidlLibraryTestCase(t, Bp2buildTestCase{
+ Description: "aidl_library with deps",
+ Blueprint: bp,
+ ExpectedBazelTargets: expectedBazelTargets,
+ })
+ })
+}
diff --git a/bp2build/cc_library_conversion_test.go b/bp2build/cc_library_conversion_test.go
index 7165ac4..bd8450f 100644
--- a/bp2build/cc_library_conversion_test.go
+++ b/bp2build/cc_library_conversion_test.go
@@ -18,6 +18,7 @@
"fmt"
"testing"
+ "android/soong/aidl_library"
"android/soong/android"
"android/soong/cc"
)
@@ -63,6 +64,7 @@
ctx.RegisterModuleType("cc_library_static", cc.LibraryStaticFactory)
ctx.RegisterModuleType("cc_prebuilt_library_static", cc.PrebuiltStaticLibraryFactory)
ctx.RegisterModuleType("cc_library_headers", cc.LibraryHeaderFactory)
+ ctx.RegisterModuleType("aidl_library", aidl_library.AidlLibraryFactory)
}
func TestCcLibrarySimple(t *testing.T) {
@@ -3310,6 +3312,46 @@
})
}
+func TestCcLibraryWithAidlLibrary(t *testing.T) {
+ runCcLibraryTestCase(t, Bp2buildTestCase{
+ Description: "cc_library with aidl_library",
+ ModuleTypeUnderTest: "cc_library",
+ ModuleTypeUnderTestFactory: cc.LibraryFactory,
+ Blueprint: `
+aidl_library {
+ name: "A_aidl",
+ srcs: ["aidl/A.aidl"],
+ hdrs: ["aidl/Header.aidl"],
+ strip_import_prefix: "aidl",
+}
+cc_library {
+ name: "foo",
+ aidl: {
+ libs: ["A_aidl"],
+ }
+}`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTargetNoRestrictions("aidl_library", "A_aidl", AttrNameToString{
+ "srcs": `["aidl/A.aidl"]`,
+ "hdrs": `["aidl/Header.aidl"]`,
+ "strip_import_prefix": `"aidl"`,
+ "tags": `["apex_available=//apex_available:anyapex"]`,
+ }),
+ MakeBazelTarget("cc_aidl_library", "foo_cc_aidl_library", AttrNameToString{
+ "deps": `[":A_aidl"]`,
+ }),
+ MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
+ "implementation_whole_archive_deps": `[":foo_cc_aidl_library"]`,
+ "local_includes": `["."]`,
+ }),
+ MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
+ "implementation_whole_archive_deps": `[":foo_cc_aidl_library"]`,
+ "local_includes": `["."]`,
+ }),
+ },
+ })
+}
+
func TestCcLibraryWithAidlSrcs(t *testing.T) {
runCcLibraryTestCase(t, Bp2buildTestCase{
Description: "cc_library with aidl srcs",
@@ -3392,37 +3434,77 @@
}
func TestCcLibraryWithExportAidlHeaders(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_library with export aidl headers",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Blueprint: `
-cc_library {
- name: "foo",
- srcs: [
- "Foo.aidl",
- ],
- aidl: {
- export_aidl_headers: true,
- }
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("aidl_library", "foo_aidl_library", AttrNameToString{
- "srcs": `["Foo.aidl"]`,
- }),
- MakeBazelTarget("cc_aidl_library", "foo_cc_aidl_library", AttrNameToString{
- "deps": `[":foo_aidl_library"]`,
- }),
- MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
- "whole_archive_deps": `[":foo_cc_aidl_library"]`,
- "local_includes": `["."]`,
- }),
- MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "whole_archive_deps": `[":foo_cc_aidl_library"]`,
- "local_includes": `["."]`,
- }),
+ t.Parallel()
+
+ expectedBazelTargets := []string{
+ MakeBazelTarget("cc_aidl_library", "foo_cc_aidl_library", AttrNameToString{
+ "deps": `[":foo_aidl_library"]`,
+ }),
+ MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
+ "whole_archive_deps": `[":foo_cc_aidl_library"]`,
+ "local_includes": `["."]`,
+ }),
+ MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
+ "whole_archive_deps": `[":foo_cc_aidl_library"]`,
+ "local_includes": `["."]`,
+ }),
+ }
+ testCases := []struct {
+ description string
+ bp string
+ expectedBazelTargets []string
+ }{
+ {
+ description: "cc_library with aidl srcs and aidl.export_aidl_headers set",
+ bp: `
+ cc_library {
+ name: "foo",
+ srcs: [
+ "Foo.aidl",
+ ],
+ aidl: {
+ export_aidl_headers: true,
+ }
+ }`,
+ expectedBazelTargets: append(
+ expectedBazelTargets,
+ MakeBazelTarget("aidl_library", "foo_aidl_library", AttrNameToString{
+ "srcs": `["Foo.aidl"]`,
+ })),
},
- })
+ {
+ description: "cc_library with aidl.libs and aidl.export_aidl_headers set",
+ bp: `
+ aidl_library {
+ name: "foo_aidl_library",
+ srcs: ["Foo.aidl"],
+ }
+ cc_library {
+ name: "foo",
+ aidl: {
+ libs: ["foo_aidl_library"],
+ export_aidl_headers: true,
+ }
+ }`,
+ expectedBazelTargets: append(
+ expectedBazelTargets,
+ MakeBazelTargetNoRestrictions("aidl_library", "foo_aidl_library", AttrNameToString{
+ "srcs": `["Foo.aidl"]`,
+ "tags": `["apex_available=//apex_available:anyapex"]`,
+ }),
+ ),
+ },
+ }
+
+ for _, testCase := range testCases {
+ runCcLibraryTestCase(t, Bp2buildTestCase{
+ Description: "cc_library with export aidl headers",
+ ModuleTypeUnderTest: "cc_library",
+ ModuleTypeUnderTestFactory: cc.LibraryFactory,
+ Blueprint: testCase.bp,
+ ExpectedBazelTargets: testCase.expectedBazelTargets,
+ })
+ }
}
func TestCcLibraryWithTargetApex(t *testing.T) {
diff --git a/cc/Android.bp b/cc/Android.bp
index be2cc5a..f49dc1a 100644
--- a/cc/Android.bp
+++ b/cc/Android.bp
@@ -9,6 +9,7 @@
"blueprint",
"blueprint-pathtools",
"soong",
+ "soong-aidl-library",
"soong-android",
"soong-bazel",
"soong-cc-config",
@@ -22,7 +23,6 @@
srcs: [
"afdo.go",
"fdo_profile.go",
-
"androidmk.go",
"api_level.go",
"bp2build.go",
diff --git a/cc/binary.go b/cc/binary.go
index 097f822..98b9923 100644
--- a/cc/binary.go
+++ b/cc/binary.go
@@ -661,7 +661,7 @@
// shared with cc_test
binaryAttrs := binaryBp2buildAttrs(ctx, m)
- tags := android.ApexAvailableTags(m)
+ tags := android.ApexAvailableTagsWithoutTestApexes(ctx, m)
ctx.CreateBazelTargetModule(bazel.BazelTargetModuleProperties{
Rule_class: "cc_binary",
Bzl_load_location: "//build/bazel/rules/cc:cc_binary.bzl",
diff --git a/cc/bp2build.go b/cc/bp2build.go
index adf5a08..e825277 100644
--- a/cc/bp2build.go
+++ b/cc/bp2build.go
@@ -268,7 +268,7 @@
attrs.Srcs_c = partitionedSrcs[cSrcPartition]
attrs.Srcs_as = partitionedSrcs[asSrcPartition]
- attrs.Apex_available = android.ConvertApexAvailableToTags(apexAvailable)
+ attrs.Apex_available = android.ConvertApexAvailableToTagsWithoutTestApexes(ctx.(android.TopDownMutatorContext), apexAvailable)
if !partitionedSrcs[protoSrcPartition].IsEmpty() {
// TODO(b/208815215): determine whether this is used and add support if necessary
@@ -717,6 +717,8 @@
compilerAttrs := compilerAttributes{}
linkerAttrs := linkerAttributes{}
+ var aidlLibs bazel.LabelList
+
// Iterate through these axes in a deterministic order. This is required
// because processing certain dependencies may result in concatenating
// elements along other axes. (For example, processing NoConfig may result
@@ -732,6 +734,7 @@
compilerAttrs.lexopts.SetSelectValue(axis, cfg, baseCompilerProps.Lex.Flags)
}
(&compilerAttrs).bp2buildForAxisAndConfig(ctx, axis, cfg, baseCompilerProps)
+ aidlLibs.Append(android.BazelLabelForModuleDeps(ctx, baseCompilerProps.Aidl.Libs))
}
var exportHdrs []string
@@ -804,7 +807,14 @@
(&linkerAttrs).wholeArchiveDeps.Add(protoDep.wholeStaticLib)
(&linkerAttrs).implementationWholeArchiveDeps.Add(protoDep.implementationWholeStaticLib)
- aidlDep := bp2buildCcAidlLibrary(ctx, module, compilerAttrs.aidlSrcs, linkerAttrs)
+ aidlDep := bp2buildCcAidlLibrary(
+ ctx, module,
+ compilerAttrs.aidlSrcs,
+ bazel.LabelListAttribute{
+ Value: aidlLibs,
+ },
+ linkerAttrs,
+ )
if aidlDep != nil {
if lib, ok := module.linker.(*libraryDecorator); ok {
if proptools.Bool(lib.Properties.Aidl.Export_aidl_headers) {
@@ -900,11 +910,15 @@
func bp2buildCcAidlLibrary(
ctx android.Bp2buildMutatorContext,
m *Module,
- aidlLabelList bazel.LabelListAttribute,
+ aidlSrcs bazel.LabelListAttribute,
+ aidlLibs bazel.LabelListAttribute,
linkerAttrs linkerAttributes,
) *bazel.LabelAttribute {
- if !aidlLabelList.IsEmpty() {
- aidlLibs, aidlSrcs := aidlLabelList.Partition(func(src bazel.Label) bool {
+ var aidlLibsFromSrcs, aidlFiles bazel.LabelListAttribute
+ apexAvailableTags := android.ApexAvailableTagsWithoutTestApexes(ctx.(android.TopDownMutatorContext), ctx.Module())
+
+ if !aidlSrcs.IsEmpty() {
+ aidlLibsFromSrcs, aidlFiles = aidlSrcs.Partition(func(src bazel.Label) bool {
if fg, ok := android.ToFileGroupAsLibrary(ctx, src.OriginalModuleName); ok &&
fg.ShouldConvertToAidlLibrary(ctx) {
return true
@@ -912,57 +926,61 @@
return false
})
- apexAvailableTags := android.ApexAvailableTags(ctx.Module())
- sdkAttrs := bp2BuildParseSdkAttributes(m)
-
- if !aidlSrcs.IsEmpty() {
+ if !aidlFiles.IsEmpty() {
aidlLibName := m.Name() + "_aidl_library"
ctx.CreateBazelTargetModule(
bazel.BazelTargetModuleProperties{
Rule_class: "aidl_library",
Bzl_load_location: "//build/bazel/rules/aidl:aidl_library.bzl",
},
- android.CommonAttributes{Name: aidlLibName},
- &aidlLibraryAttributes{
- Srcs: aidlSrcs,
+ android.CommonAttributes{
+ Name: aidlLibName,
Tags: apexAvailableTags,
},
- )
- aidlLibs.Add(&bazel.LabelAttribute{Value: &bazel.Label{Label: ":" + aidlLibName}})
- }
-
- if !aidlLibs.IsEmpty() {
- ccAidlLibrarylabel := m.Name() + "_cc_aidl_library"
- // Since parent cc_library already has these dependencies, we can add them as implementation
- // deps so that they don't re-export
- implementationDeps := linkerAttrs.deps.Clone()
- implementationDeps.Append(linkerAttrs.implementationDeps)
- implementationDynamicDeps := linkerAttrs.dynamicDeps.Clone()
- implementationDynamicDeps.Append(linkerAttrs.implementationDynamicDeps)
-
- ctx.CreateBazelTargetModule(
- bazel.BazelTargetModuleProperties{
- Rule_class: "cc_aidl_library",
- Bzl_load_location: "//build/bazel/rules/cc:cc_aidl_library.bzl",
- },
- android.CommonAttributes{Name: ccAidlLibrarylabel},
- &ccAidlLibraryAttributes{
- Deps: aidlLibs,
- Implementation_deps: *implementationDeps,
- Implementation_dynamic_deps: *implementationDynamicDeps,
- Tags: apexAvailableTags,
- sdkAttributes: sdkAttrs,
+ &aidlLibraryAttributes{
+ Srcs: aidlFiles,
},
)
- label := &bazel.LabelAttribute{
- Value: &bazel.Label{
- Label: ":" + ccAidlLibrarylabel,
- },
- }
- return label
+ aidlLibsFromSrcs.Add(&bazel.LabelAttribute{Value: &bazel.Label{Label: ":" + aidlLibName}})
}
}
+ allAidlLibs := aidlLibs.Clone()
+ allAidlLibs.Append(aidlLibsFromSrcs)
+
+ if !allAidlLibs.IsEmpty() {
+ ccAidlLibrarylabel := m.Name() + "_cc_aidl_library"
+ // Since parent cc_library already has these dependencies, we can add them as implementation
+ // deps so that they don't re-export
+ implementationDeps := linkerAttrs.deps.Clone()
+ implementationDeps.Append(linkerAttrs.implementationDeps)
+ implementationDynamicDeps := linkerAttrs.dynamicDeps.Clone()
+ implementationDynamicDeps.Append(linkerAttrs.implementationDynamicDeps)
+
+ sdkAttrs := bp2BuildParseSdkAttributes(m)
+
+ ctx.CreateBazelTargetModule(
+ bazel.BazelTargetModuleProperties{
+ Rule_class: "cc_aidl_library",
+ Bzl_load_location: "//build/bazel/rules/cc:cc_aidl_library.bzl",
+ },
+ android.CommonAttributes{Name: ccAidlLibrarylabel},
+ &ccAidlLibraryAttributes{
+ Deps: *allAidlLibs,
+ Implementation_deps: *implementationDeps,
+ Implementation_dynamic_deps: *implementationDynamicDeps,
+ Tags: apexAvailableTags,
+ sdkAttributes: sdkAttrs,
+ },
+ )
+ label := &bazel.LabelAttribute{
+ Value: &bazel.Label{
+ Label: ":" + ccAidlLibrarylabel,
+ },
+ }
+ return label
+ }
+
return nil
}
diff --git a/cc/cc.go b/cc/cc.go
index 0addb60..307441d 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -27,6 +27,7 @@
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
+ "android/soong/aidl_library"
"android/soong/android"
"android/soong/bazel/cquery"
"android/soong/cc/config"
@@ -110,6 +111,9 @@
// Used by DepsMutator to pass system_shared_libs information to check_elf_file.py.
SystemSharedLibs []string
+ // Used by DepMutator to pass aidl_library modules to aidl compiler
+ AidlLibs []string
+
// If true, statically link the unwinder into native libraries/binaries.
StaticUnwinderIfLegacy bool
@@ -182,6 +186,9 @@
// For Darwin builds, the path to the second architecture's output that should
// be combined with this architectures's output into a FAT MachO file.
DarwinSecondArchOutput android.OptionalPath
+
+ // Paths to direct srcs and transitive include dirs from direct aidl_library deps
+ AidlLibraryInfos []aidl_library.AidlLibraryInfo
}
// LocalOrGlobalFlags contains flags that need to have values set globally by the build system or locally by the module
@@ -765,6 +772,7 @@
stubImplDepTag = dependencyTag{name: "stub_impl"}
JniFuzzLibTag = dependencyTag{name: "jni_fuzz_lib_tag"}
FdoProfileTag = dependencyTag{name: "fdo_profile"}
+ aidlLibraryTag = dependencyTag{name: "aidl_library"}
)
func IsSharedDepTag(depTag blueprint.DependencyTag) bool {
@@ -2685,6 +2693,14 @@
}
}
+ if len(deps.AidlLibs) > 0 {
+ actx.AddDependency(
+ c,
+ aidlLibraryTag,
+ deps.AidlLibs...,
+ )
+ }
+
updateImportedLibraryDependency(ctx)
}
@@ -2989,6 +3005,17 @@
return
}
+ if depTag == aidlLibraryTag {
+ if ctx.OtherModuleHasProvider(dep, aidl_library.AidlLibraryProvider) {
+ depPaths.AidlLibraryInfos = append(
+ depPaths.AidlLibraryInfos,
+ ctx.OtherModuleProvider(
+ dep,
+ aidl_library.AidlLibraryProvider).(aidl_library.AidlLibraryInfo),
+ )
+ }
+ }
+
ccDep, ok := dep.(LinkableInterface)
if !ok {
diff --git a/cc/cc_test.go b/cc/cc_test.go
index 3ae4b15..2fd0121 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -24,6 +24,7 @@
"strings"
"testing"
+ "android/soong/aidl_library"
"android/soong/android"
"android/soong/bazel/cquery"
)
@@ -4419,9 +4420,65 @@
}
}
+func TestAidlLibraryWithHeader(t *testing.T) {
+ t.Parallel()
+ ctx := android.GroupFixturePreparers(
+ prepareForCcTest,
+ aidl_library.PrepareForTestWithAidlLibrary,
+ android.MockFS{
+ "package_bar/Android.bp": []byte(`
+ aidl_library {
+ name: "bar",
+ srcs: ["x/y/Bar.aidl"],
+ strip_import_prefix: "x",
+ }
+ `)}.AddToFixture(),
+ android.MockFS{
+ "package_foo/Android.bp": []byte(`
+ aidl_library {
+ name: "foo",
+ srcs: ["a/b/Foo.aidl"],
+ strip_import_prefix: "a",
+ deps: ["bar"],
+ }
+ cc_library {
+ name: "libfoo",
+ aidl: {
+ libs: ["foo"],
+ }
+ }
+ `),
+ }.AddToFixture(),
+ ).RunTest(t).TestContext
+
+ libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_static")
+ manifest := android.RuleBuilderSboxProtoForTests(t, libfoo.Output("aidl.sbox.textproto"))
+ aidlCommand := manifest.Commands[0].GetCommand()
+
+ expectedAidlFlags := "-Ipackage_foo/a -Ipackage_bar/x"
+ if !strings.Contains(aidlCommand, expectedAidlFlags) {
+ t.Errorf("aidl command %q does not contain %q", aidlCommand, expectedAidlFlags)
+ }
+
+ outputs := strings.Join(libfoo.AllOutputs(), " ")
+
+ android.AssertStringDoesContain(t, "aidl-generated header", outputs, "gen/aidl/b/BpFoo.h")
+ android.AssertStringDoesContain(t, "aidl-generated header", outputs, "gen/aidl/b/BnFoo.h")
+ android.AssertStringDoesContain(t, "aidl-generated header", outputs, "gen/aidl/b/Foo.h")
+ android.AssertStringDoesContain(t, "aidl-generated cpp", outputs, "b/Foo.cpp")
+ // Confirm that the aidl header doesn't get compiled to cpp and h files
+ android.AssertStringDoesNotContain(t, "aidl-generated header", outputs, "gen/aidl/y/BpBar.h")
+ android.AssertStringDoesNotContain(t, "aidl-generated header", outputs, "gen/aidl/y/BnBar.h")
+ android.AssertStringDoesNotContain(t, "aidl-generated header", outputs, "gen/aidl/y/Bar.h")
+ android.AssertStringDoesNotContain(t, "aidl-generated cpp", outputs, "y/Bar.cpp")
+}
+
func TestAidlFlagsPassedToTheAidlCompiler(t *testing.T) {
t.Parallel()
- ctx := testCc(t, `
+ ctx := android.GroupFixturePreparers(
+ prepareForCcTest,
+ aidl_library.PrepareForTestWithAidlLibrary,
+ ).RunTestWithBp(t, `
cc_library {
name: "libfoo",
srcs: ["a/Foo.aidl"],
@@ -4706,7 +4763,15 @@
})
t.Run("ensure only aidl headers are exported", func(t *testing.T) {
- ctx := testCc(t, genRuleModules+`
+ ctx := android.GroupFixturePreparers(
+ prepareForCcTest,
+ aidl_library.PrepareForTestWithAidlLibrary,
+ ).RunTestWithBp(t, `
+ aidl_library {
+ name: "libfoo_aidl",
+ srcs: ["x/y/Bar.aidl"],
+ strip_import_prefix: "x",
+ }
cc_library_shared {
name: "libfoo",
srcs: [
@@ -4715,10 +4780,11 @@
"a.proto",
],
aidl: {
+ libs: ["libfoo_aidl"],
export_aidl_headers: true,
}
}
- `)
+ `).TestContext
foo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module()
checkIncludeDirs(t, ctx, foo,
expectedIncludeDirs(`
@@ -4729,11 +4795,17 @@
.intermediates/libfoo/android_arm64_armv8-a_shared/gen/aidl/b.h
.intermediates/libfoo/android_arm64_armv8-a_shared/gen/aidl/Bnb.h
.intermediates/libfoo/android_arm64_armv8-a_shared/gen/aidl/Bpb.h
+ .intermediates/libfoo/android_arm64_armv8-a_shared/gen/aidl/y/Bar.h
+ .intermediates/libfoo/android_arm64_armv8-a_shared/gen/aidl/y/BnBar.h
+ .intermediates/libfoo/android_arm64_armv8-a_shared/gen/aidl/y/BpBar.h
`),
expectedOrderOnlyDeps(`
.intermediates/libfoo/android_arm64_armv8-a_shared/gen/aidl/b.h
.intermediates/libfoo/android_arm64_armv8-a_shared/gen/aidl/Bnb.h
.intermediates/libfoo/android_arm64_armv8-a_shared/gen/aidl/Bpb.h
+ .intermediates/libfoo/android_arm64_armv8-a_shared/gen/aidl/y/Bar.h
+ .intermediates/libfoo/android_arm64_armv8-a_shared/gen/aidl/y/BnBar.h
+ .intermediates/libfoo/android_arm64_armv8-a_shared/gen/aidl/y/BpBar.h
`),
)
})
diff --git a/cc/compiler.go b/cc/compiler.go
index 88985b6..5da745e 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -120,6 +120,9 @@
Lex *LexProperties
Aidl struct {
+ // List of aidl_library modules
+ Libs []string
+
// list of directories that will be added to the aidl include paths.
Include_dirs []string
@@ -272,6 +275,7 @@
deps.GeneratedSources = append(deps.GeneratedSources, compiler.Properties.Generated_sources...)
deps.GeneratedSources = removeListFromList(deps.GeneratedSources, compiler.Properties.Exclude_generated_sources)
deps.GeneratedHeaders = append(deps.GeneratedHeaders, compiler.Properties.Generated_headers...)
+ deps.AidlLibs = append(deps.AidlLibs, compiler.Properties.Aidl.Libs...)
android.ProtoDeps(ctx, &compiler.Proto)
if compiler.hasSrcExt(".proto") {
@@ -561,7 +565,7 @@
"-I"+android.PathForModuleGen(ctx, "yacc", ctx.ModuleDir()).String())
}
- if compiler.hasSrcExt(".aidl") {
+ if compiler.hasAidl(deps) {
flags.aidlFlags = append(flags.aidlFlags, compiler.Properties.Aidl.Flags...)
if len(compiler.Properties.Aidl.Local_include_dirs) > 0 {
localAidlIncludeDirs := android.PathsForModuleSrc(ctx, compiler.Properties.Aidl.Local_include_dirs)
@@ -572,6 +576,14 @@
flags.aidlFlags = append(flags.aidlFlags, includeDirsToFlags(rootAidlIncludeDirs))
}
+ var rootAidlIncludeDirs android.Paths
+ for _, aidlLibraryInfo := range deps.AidlLibraryInfos {
+ rootAidlIncludeDirs = append(rootAidlIncludeDirs, aidlLibraryInfo.IncludeDirs.ToList()...)
+ }
+ if len(rootAidlIncludeDirs) > 0 {
+ flags.aidlFlags = append(flags.aidlFlags, includeDirsToFlags(rootAidlIncludeDirs))
+ }
+
if proptools.BoolDefault(compiler.Properties.Aidl.Generate_traces, true) {
flags.aidlFlags = append(flags.aidlFlags, "-t")
}
@@ -660,6 +672,10 @@
return nil
}
+func (compiler *baseCompiler) hasAidl(deps PathDeps) bool {
+ return len(deps.AidlLibraryInfos) > 0 || compiler.hasSrcExt(".aidl")
+}
+
func (compiler *baseCompiler) compile(ctx ModuleContext, flags Flags, deps PathDeps) Objects {
pathDeps := deps.GeneratedDeps
pathDeps = append(pathDeps, ndkPathDeps(ctx)...)
@@ -668,7 +684,7 @@
srcs := append(android.Paths(nil), compiler.srcsBeforeGen...)
- srcs, genDeps, info := genSources(ctx, srcs, buildFlags)
+ srcs, genDeps, info := genSources(ctx, deps.AidlLibraryInfos, srcs, buildFlags)
pathDeps = append(pathDeps, genDeps...)
compiler.pathDeps = pathDeps
diff --git a/cc/gen.go b/cc/gen.go
index dfbb177..dbb9560 100644
--- a/cc/gen.go
+++ b/cc/gen.go
@@ -18,7 +18,9 @@
"path/filepath"
"strings"
+ "android/soong/aidl_library"
"android/soong/bazel"
+
"github.com/google/blueprint"
"android/soong/android"
@@ -124,11 +126,6 @@
headerBn := outDir.Join(ctx, aidlPackage, "Bn"+shortName+".h")
headerBp := outDir.Join(ctx, aidlPackage, "Bp"+shortName+".h")
- baseDir := strings.TrimSuffix(aidlFile.String(), aidlFile.Rel())
- if baseDir != "" {
- aidlFlags += " -I" + baseDir
- }
-
cmd := rule.Command()
cmd.BuiltTool("aidl-cpp").
FlagWithDepFile("-d", depFile).
@@ -282,7 +279,10 @@
syspropOrderOnlyDeps android.Paths
}
-func genSources(ctx android.ModuleContext, srcFiles android.Paths,
+func genSources(
+ ctx android.ModuleContext,
+ aidlLibraryInfos []aidl_library.AidlLibraryInfo,
+ srcFiles android.Paths,
buildFlags builderFlags) (android.Paths, android.Paths, generatedSourceInfo) {
var info generatedSourceInfo
@@ -330,7 +330,8 @@
aidlRule = android.NewRuleBuilder(pctx, ctx).Sbox(android.PathForModuleGen(ctx, "aidl"),
android.PathForModuleGen(ctx, "aidl.sbox.textproto"))
}
- cppFile, aidlHeaders := genAidl(ctx, aidlRule, srcFile, buildFlags.aidlFlags)
+ baseDir := strings.TrimSuffix(srcFile.String(), srcFile.Rel())
+ cppFile, aidlHeaders := genAidl(ctx, aidlRule, srcFile, buildFlags.aidlFlags+" -I"+baseDir)
srcFiles[i] = cppFile
info.aidlHeaders = append(info.aidlHeaders, aidlHeaders...)
@@ -352,6 +353,24 @@
}
}
+ for _, aidlLibraryInfo := range aidlLibraryInfos {
+ for _, aidlSrc := range aidlLibraryInfo.Srcs {
+ if aidlRule == nil {
+ // TODO(b/279960133): Sandbox inputs to ensure aidl headers are explicitly specified
+ aidlRule = android.NewRuleBuilder(pctx, ctx).Sbox(android.PathForModuleGen(ctx, "aidl"),
+ android.PathForModuleGen(ctx, "aidl.sbox.textproto"))
+ }
+ cppFile, aidlHeaders := genAidl(ctx, aidlRule, aidlSrc, buildFlags.aidlFlags)
+
+ srcFiles = append(srcFiles, cppFile)
+ info.aidlHeaders = append(info.aidlHeaders, aidlHeaders...)
+ // Use the generated headers as order only deps to ensure that they are up to date when
+ // needed.
+ // TODO: Reduce the size of the ninja file by using one order only dep for the whole rule
+ info.aidlOrderOnlyDeps = append(info.aidlOrderOnlyDeps, aidlHeaders...)
+ }
+ }
+
if aidlRule != nil {
aidlRule.Build("aidl", "gen aidl")
}
diff --git a/cc/library.go b/cc/library.go
index 7051f72..542e675 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -428,11 +428,11 @@
var tagsForStaticVariant bazel.StringListAttribute
if compilerAttrs.stubsSymbolFile == nil && len(compilerAttrs.stubsVersions.Value) == 0 {
- tagsForStaticVariant = android.ApexAvailableTags(m)
+ tagsForStaticVariant = android.ApexAvailableTagsWithoutTestApexes(ctx, m)
}
tagsForStaticVariant.Append(bazel.StringListAttribute{Value: staticAttrs.Apex_available})
- tagsForSharedVariant := android.ApexAvailableTags(m)
+ tagsForSharedVariant := android.ApexAvailableTagsWithoutTestApexes(ctx, m)
tagsForSharedVariant.Append(bazel.StringListAttribute{Value: sharedAttrs.Apex_available})
ctx.CreateBazelTargetModuleWithRestrictions(staticProps,
@@ -2109,7 +2109,7 @@
// Optionally export aidl headers.
if Bool(library.Properties.Aidl.Export_aidl_headers) {
- if library.baseCompiler.hasSrcExt(".aidl") {
+ if library.baseCompiler.hasAidl(deps) {
dir := android.PathForModuleGen(ctx, "aidl")
library.reexportDirs(dir)
@@ -2994,7 +2994,7 @@
Bzl_load_location: fmt.Sprintf("//build/bazel/rules/cc:%s.bzl", modType),
}
- tags := android.ApexAvailableTags(module)
+ tags := android.ApexAvailableTagsWithoutTestApexes(ctx, module)
ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: module.Name(), Tags: tags}, attrs)
}
diff --git a/cc/library_headers.go b/cc/library_headers.go
index 1dee726..ce9c4aa 100644
--- a/cc/library_headers.go
+++ b/cc/library_headers.go
@@ -151,7 +151,7 @@
Bzl_load_location: "//build/bazel/rules/cc:cc_library_headers.bzl",
}
- tags := android.ApexAvailableTags(module)
+ tags := android.ApexAvailableTagsWithoutTestApexes(ctx, module)
ctx.CreateBazelTargetModule(props, android.CommonAttributes{
Name: module.Name(),
diff --git a/cc/object.go b/cc/object.go
index d65cdea..5d61872 100644
--- a/cc/object.go
+++ b/cc/object.go
@@ -226,7 +226,7 @@
Bzl_load_location: "//build/bazel/rules/cc:cc_object.bzl",
}
- tags := android.ApexAvailableTags(m)
+ tags := android.ApexAvailableTagsWithoutTestApexes(ctx, m)
ctx.CreateBazelTargetModule(props, android.CommonAttributes{
Name: m.Name(),
diff --git a/cc/prebuilt.go b/cc/prebuilt.go
index 0b5841e..44cd0d7 100644
--- a/cc/prebuilt.go
+++ b/cc/prebuilt.go
@@ -389,7 +389,7 @@
name += "_bp2build_cc_library_static"
}
- tags := android.ApexAvailableTags(module)
+ tags := android.ApexAvailableTagsWithoutTestApexes(ctx, module)
ctx.CreateBazelTargetModuleWithRestrictions(props, android.CommonAttributes{Name: name, Tags: tags}, attrs, prebuiltAttrs.Enabled)
_true := true
@@ -420,7 +420,7 @@
}
name := android.RemoveOptionalPrebuiltPrefix(module.Name())
- tags := android.ApexAvailableTags(module)
+ tags := android.ApexAvailableTagsWithoutTestApexes(ctx, module)
ctx.CreateBazelTargetModuleWithRestrictions(props, android.CommonAttributes{Name: name, Tags: tags}, attrs, prebuiltAttrs.Enabled)
}
@@ -650,7 +650,7 @@
}
name := android.RemoveOptionalPrebuiltPrefix(module.Name())
- tags := android.ApexAvailableTags(module)
+ tags := android.ApexAvailableTagsWithoutTestApexes(ctx, module)
ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: name, Tags: tags}, attrs)
}
@@ -813,7 +813,7 @@
}
name := android.RemoveOptionalPrebuiltPrefix(module.Name())
- tags := android.ApexAvailableTags(module)
+ tags := android.ApexAvailableTagsWithoutTestApexes(ctx, module)
ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: name, Tags: tags}, attrs)
}
diff --git a/cc/proto.go b/cc/proto.go
index 97470e5..5d9aef6 100644
--- a/cc/proto.go
+++ b/cc/proto.go
@@ -207,7 +207,7 @@
protoAttrs.Min_sdk_version = m.Properties.Min_sdk_version
name := m.Name() + suffix
- tags := android.ApexAvailableTags(m)
+ tags := android.ApexAvailableTagsWithoutTestApexes(ctx.(android.TopDownMutatorContext), m)
ctx.CreateBazelTargetModule(
bazel.BazelTargetModuleProperties{
Rule_class: rule_class,
diff --git a/cc/sysprop.go b/cc/sysprop.go
index 0df290a..7ddd476 100644
--- a/cc/sysprop.go
+++ b/cc/sysprop.go
@@ -38,7 +38,7 @@
}
func Bp2buildSysprop(ctx android.Bp2buildMutatorContext, labels SyspropLibraryLabels, srcs bazel.LabelListAttribute, minSdkVersion *string) {
- apexAvailableTags := android.ApexAvailableTags(ctx.Module())
+ apexAvailableTags := android.ApexAvailableTagsWithoutTestApexes(ctx.(android.TopDownMutatorContext), ctx.Module())
ctx.CreateBazelTargetModule(
bazel.BazelTargetModuleProperties{
Rule_class: "sysprop_library",
diff --git a/genrule/genrule.go b/genrule/genrule.go
index f5da50e..00adb70 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -940,7 +940,7 @@
}
}
- tags := android.ApexAvailableTags(m)
+ tags := android.ApexAvailableTagsWithoutTestApexes(ctx, m)
if ctx.ModuleType() == "gensrcs" {
// The Output_extension prop is not in an immediately accessible field
diff --git a/java/app.go b/java/app.go
index 706f99a..8d96557 100755
--- a/java/app.go
+++ b/java/app.go
@@ -33,8 +33,17 @@
func init() {
RegisterAppBuildComponents(android.InitRegistrationContext)
+ pctx.HostBinToolVariable("ModifyAllowlistCmd", "modify_permissions_allowlist")
}
+var (
+ modifyAllowlist = pctx.AndroidStaticRule("modifyAllowlist",
+ blueprint.RuleParams{
+ Command: "${ModifyAllowlistCmd} $in $packageName $out",
+ CommandDeps: []string{"${ModifyAllowlistCmd}"},
+ }, "packageName")
+)
+
func RegisterAppBuildComponents(ctx android.RegistrationContext) {
ctx.RegisterModuleType("android_app", AndroidAppFactory)
ctx.RegisterModuleType("android_test", AndroidTestFactory)
@@ -115,6 +124,9 @@
// Prefer using other specific properties if build behaviour must be changed; avoid using this
// flag for anything but neverallow rules (unless the behaviour change is invisible to owners).
Updatable *bool
+
+ // Specifies the file that contains the allowlist for this app.
+ Privapp_allowlist *string `android:"path"`
}
// android_app properties that can be overridden by override_android_app
@@ -179,6 +191,8 @@
android.ApexBundleDepsInfo
javaApiUsedByOutputFile android.ModuleOutPath
+
+ privAppAllowlist android.OptionalPath
}
func (a *AndroidApp) IsInstallable() bool {
@@ -205,6 +219,10 @@
return a.jniCoverageOutputs
}
+func (a *AndroidApp) PrivAppAllowlist() android.OptionalPath {
+ return a.privAppAllowlist
+}
+
var _ AndroidLibraryDependency = (*AndroidApp)(nil)
type Certificate struct {
@@ -269,6 +287,16 @@
ctx.AddDependency(ctx.Module(), certificateTag, cert)
}
+ if a.appProperties.Privapp_allowlist != nil && !Bool(a.appProperties.Privileged) {
+ // There are a few uids that are explicitly considered privileged regardless of their
+ // app's location. Bluetooth is one such app. It should arguably be moved to priv-app,
+ // but for now, allow it not to be in priv-app.
+ privilegedBecauseOfUid := ctx.ModuleName() == "Bluetooth"
+ if !privilegedBecauseOfUid {
+ ctx.PropertyErrorf("privapp_allowlist", "privileged must be set in order to use privapp_allowlist (with a few exceptions)")
+ }
+ }
+
for _, cert := range a.appProperties.Additional_certificates {
cert = android.SrcIsModule(cert)
if cert != "" {
@@ -591,7 +619,6 @@
}
}
-
return mainCertificate, certificates
}
@@ -599,6 +626,35 @@
return a.installApkName
}
+func (a *AndroidApp) createPrivappAllowlist(ctx android.ModuleContext) android.Path {
+ if a.appProperties.Privapp_allowlist == nil {
+ return nil
+ }
+
+ isOverrideApp := a.GetOverriddenBy() != ""
+ if !isOverrideApp {
+ // if this is not an override, we don't need to rewrite the existing privapp allowlist
+ return android.PathForModuleSrc(ctx, *a.appProperties.Privapp_allowlist)
+ }
+
+ if a.overridableAppProperties.Package_name == nil {
+ ctx.PropertyErrorf("privapp_allowlist", "package_name must be set to use privapp_allowlist")
+ }
+
+ packageName := *a.overridableAppProperties.Package_name
+ fileName := "privapp_allowlist_" + packageName + ".xml"
+ outPath := android.PathForModuleOut(ctx, fileName).OutputPath
+ ctx.Build(pctx, android.BuildParams{
+ Rule: modifyAllowlist,
+ Input: android.PathForModuleSrc(ctx, *a.appProperties.Privapp_allowlist),
+ Output: outPath,
+ Args: map[string]string{
+ "packageName": packageName,
+ },
+ })
+ return &outPath
+}
+
func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) {
var apkDeps android.Paths
@@ -734,11 +790,21 @@
BuildBundleModule(ctx, bundleFile, a.exportPackage, jniJarFile, dexJarFile)
a.bundleFile = bundleFile
+ allowlist := a.createPrivappAllowlist(ctx)
+ if allowlist != nil {
+ a.privAppAllowlist = android.OptionalPathForPath(allowlist)
+ }
+
apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
// Install the app package.
- if (Bool(a.Module.properties.Installable) || ctx.Host()) && apexInfo.IsForPlatform() &&
- !a.appProperties.PreventInstall {
+ shouldInstallAppPackage := (Bool(a.Module.properties.Installable) || ctx.Host()) && apexInfo.IsForPlatform() && !a.appProperties.PreventInstall
+ if shouldInstallAppPackage {
+ if a.privAppAllowlist.Valid() {
+ allowlistInstallPath := android.PathForModuleInstall(ctx, "etc", "permissions")
+ allowlistInstallFilename := a.installApkName + ".xml"
+ ctx.InstallFile(allowlistInstallPath, allowlistInstallFilename, a.privAppAllowlist.Path())
+ }
var extraInstalledPaths android.Paths
for _, extra := range a.extraOutputFiles {
@@ -925,6 +991,10 @@
// For OutputFileProducer interface
func (a *AndroidApp) OutputFiles(tag string) (android.Paths, error) {
switch tag {
+ // In some instances, it can be useful to reference the aapt-generated flags from another
+ // target, e.g., system server implements services declared in the framework-res manifest.
+ case ".aapt.proguardOptionsFile":
+ return []android.Path{a.proguardOptionsFile}, nil
case ".aapt.srcjar":
return []android.Path{a.aaptSrcJar}, nil
case ".export-package.apk":
diff --git a/java/app_import.go b/java/app_import.go
index 85b35eb..3097d7f 100644
--- a/java/app_import.go
+++ b/java/app_import.go
@@ -376,6 +376,10 @@
return a.provenanceMetaDataFile
}
+func (a *AndroidAppImport) PrivAppAllowlist() android.OptionalPath {
+ return android.OptionalPath{}
+}
+
var dpiVariantGroupType reflect.Type
var archVariantGroupType reflect.Type
var supportedDpis = []string{"ldpi", "mdpi", "hdpi", "xhdpi", "xxhdpi", "xxxhdpi"}
diff --git a/java/app_test.go b/java/app_test.go
index b154bc9..746ab75 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -3547,3 +3547,124 @@
android.AssertStringDoesContain(t, testCase.desc, manifestFixerArgs, "--targetSdkVersion "+testCase.targetSdkVersionExpected)
}
}
+
+func TestPrivappAllowlist(t *testing.T) {
+ testJavaError(t, "privileged must be set in order to use privapp_allowlist", `
+ android_app {
+ name: "foo",
+ srcs: ["a.java"],
+ privapp_allowlist: "perms.xml",
+ }
+ `)
+
+ result := PrepareForTestWithJavaDefaultModules.RunTestWithBp(
+ t,
+ `
+ android_app {
+ name: "foo",
+ srcs: ["a.java"],
+ privapp_allowlist: "privapp_allowlist_com.android.foo.xml",
+ privileged: true,
+ sdk_version: "current",
+ }
+ override_android_app {
+ name: "bar",
+ base: "foo",
+ package_name: "com.google.android.foo",
+ }
+ `,
+ )
+ app := result.ModuleForTests("foo", "android_common")
+ overrideApp := result.ModuleForTests("foo", "android_common_bar")
+
+ // verify that privapp allowlist is created for override apps
+ overrideApp.Output("out/soong/.intermediates/foo/android_common_bar/privapp_allowlist_com.google.android.foo.xml")
+ expectedAllowlistInput := "privapp_allowlist_com.android.foo.xml"
+ overrideActualAllowlistInput := overrideApp.Rule("modifyAllowlist").Input.String()
+ if expectedAllowlistInput != overrideActualAllowlistInput {
+ t.Errorf("expected override allowlist to be %q; got %q", expectedAllowlistInput, overrideActualAllowlistInput)
+ }
+
+ // verify that permissions are copied to device
+ app.Output("out/soong/target/product/test_device/system/etc/permissions/foo.xml")
+ overrideApp.Output("out/soong/target/product/test_device/system/etc/permissions/bar.xml")
+}
+
+func TestPrivappAllowlistAndroidMk(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ PrepareForTestWithJavaDefaultModules,
+ android.PrepareForTestWithAndroidMk,
+ ).RunTestWithBp(
+ t,
+ `
+ android_app {
+ name: "foo",
+ srcs: ["a.java"],
+ privapp_allowlist: "privapp_allowlist_com.android.foo.xml",
+ privileged: true,
+ sdk_version: "current",
+ }
+ override_android_app {
+ name: "bar",
+ base: "foo",
+ package_name: "com.google.android.foo",
+ }
+ `,
+ )
+ baseApp := result.ModuleForTests("foo", "android_common")
+ overrideApp := result.ModuleForTests("foo", "android_common_bar")
+
+ baseAndroidApp := baseApp.Module().(*AndroidApp)
+ baseEntries := android.AndroidMkEntriesForTest(t, result.TestContext, baseAndroidApp)[0]
+ android.AssertStringMatches(
+ t,
+ "androidmk has incorrect LOCAL_SOONG_INSTALLED_MODULE; expected to find foo.apk",
+ baseEntries.EntryMap["LOCAL_SOONG_INSTALLED_MODULE"][0],
+ "\\S+foo.apk",
+ )
+ android.AssertStringMatches(
+ t,
+ "androidmk has incorrect LOCAL_SOONG_INSTALL_PAIRS; expected to it to include foo.apk",
+ baseEntries.EntryMap["LOCAL_SOONG_INSTALL_PAIRS"][0],
+ "\\S+foo.apk",
+ )
+ android.AssertStringMatches(
+ t,
+ "androidmk has incorrect LOCAL_SOONG_INSTALL_PAIRS; expected to it to include app",
+ baseEntries.EntryMap["LOCAL_SOONG_INSTALL_PAIRS"][0],
+ "\\S+foo.apk:\\S+/target/product/test_device/system/priv-app/foo/foo.apk",
+ )
+ android.AssertStringMatches(
+ t,
+ "androidmk has incorrect LOCAL_SOONG_INSTALL_PAIRS; expected to it to include privapp_allowlist",
+ baseEntries.EntryMap["LOCAL_SOONG_INSTALL_PAIRS"][0],
+ "privapp_allowlist_com.android.foo.xml:\\S+/target/product/test_device/system/etc/permissions/foo.xml",
+ )
+
+ overrideAndroidApp := overrideApp.Module().(*AndroidApp)
+ overrideEntries := android.AndroidMkEntriesForTest(t, result.TestContext, overrideAndroidApp)[0]
+ android.AssertStringMatches(
+ t,
+ "androidmk has incorrect LOCAL_SOONG_INSTALLED_MODULE; expected to find bar.apk",
+ overrideEntries.EntryMap["LOCAL_SOONG_INSTALLED_MODULE"][0],
+ "\\S+bar.apk",
+ )
+ android.AssertStringMatches(
+ t,
+ "androidmk has incorrect LOCAL_SOONG_INSTALL_PAIRS; expected to it to include bar.apk",
+ overrideEntries.EntryMap["LOCAL_SOONG_INSTALL_PAIRS"][0],
+ "\\S+bar.apk",
+ )
+ android.AssertStringMatches(
+ t,
+ "androidmk has incorrect LOCAL_SOONG_INSTALL_PAIRS; expected to it to include app",
+ overrideEntries.EntryMap["LOCAL_SOONG_INSTALL_PAIRS"][0],
+ "\\S+bar.apk:\\S+/target/product/test_device/system/priv-app/bar/bar.apk",
+ )
+ android.AssertStringMatches(
+ t,
+ "androidmk has incorrect LOCAL_SOONG_INSTALL_PAIRS; expected to it to include privapp_allowlist",
+ overrideEntries.EntryMap["LOCAL_SOONG_INSTALL_PAIRS"][0],
+ "\\S+soong/.intermediates/foo/android_common_bar/privapp_allowlist_com.google.android.foo.xml:\\S+/target/product/test_device/system/etc/permissions/bar.xml",
+ )
+}
diff --git a/java/java.go b/java/java.go
index 683e546..ccb1507 100644
--- a/java/java.go
+++ b/java/java.go
@@ -2836,7 +2836,7 @@
return android.IsConvertedToAidlLibrary(ctx, src.OriginalModuleName)
})
- apexAvailableTags := android.ApexAvailableTags(ctx.Module())
+ apexAvailableTags := android.ApexAvailableTagsWithoutTestApexes(ctx, ctx.Module())
if !aidlSrcs.IsEmpty() {
aidlLibName := m.Name() + "_aidl_library"
diff --git a/java/prebuilt_apis.go b/java/prebuilt_apis.go
index 206d995..0740467 100644
--- a/java/prebuilt_apis.go
+++ b/java/prebuilt_apis.go
@@ -135,6 +135,19 @@
mctx.CreateModule(genrule.GenRuleFactory, &genruleProps)
}
+func createLatestApiModuleExtensionVersionFile(mctx android.LoadHookContext, name string, version string) {
+ genruleProps := struct {
+ Name *string
+ Srcs []string
+ Out []string
+ Cmd *string
+ }{}
+ genruleProps.Name = proptools.StringPtr(name)
+ genruleProps.Out = []string{name}
+ genruleProps.Cmd = proptools.StringPtr("echo " + version + " > $(out)")
+ mctx.CreateModule(genrule.GenRuleFactory, &genruleProps)
+}
+
func createEmptyFile(mctx android.LoadHookContext, name string) {
props := struct {
Name *string
@@ -233,9 +246,10 @@
type latestApiInfo struct {
module, scope, path string
version int
+ isExtensionApiFile bool
}
- getLatest := func(files []string) map[string]latestApiInfo {
+ getLatest := func(files []string, isExtensionApiFile bool) map[string]latestApiInfo {
m := make(map[string]latestApiInfo)
for _, f := range files {
module, version, scope := parseFinalizedPrebuiltPath(mctx, f)
@@ -245,16 +259,16 @@
key := module + "." + scope
info, exists := m[key]
if !exists || version > info.version {
- m[key] = latestApiInfo{module, scope, f, version}
+ m[key] = latestApiInfo{module, scope, f, version, isExtensionApiFile}
}
}
return m
}
- latest := getLatest(apiLevelFiles)
+ latest := getLatest(apiLevelFiles, false)
if p.properties.Extensions_dir != nil {
extensionApiFiles := globExtensionDirs(mctx, p, "api/*.txt")
- for k, v := range getLatest(extensionApiFiles) {
+ for k, v := range getLatest(extensionApiFiles, true) {
if _, exists := latest[k]; !exists {
mctx.ModuleErrorf("Module %v finalized for extension %d but never during an API level; likely error", v.module, v.version)
}
@@ -267,6 +281,12 @@
for _, k := range android.SortedKeys(latest) {
info := latest[k]
name := PrebuiltApiModuleName(info.module, info.scope, "latest")
+ latestExtensionVersionModuleName := PrebuiltApiModuleName(info.module, info.scope, "latest.extension_version")
+ if info.isExtensionApiFile {
+ createLatestApiModuleExtensionVersionFile(mctx, latestExtensionVersionModuleName, strconv.Itoa(info.version))
+ } else {
+ createLatestApiModuleExtensionVersionFile(mctx, latestExtensionVersionModuleName, "-1")
+ }
createApiModule(mctx, name, info.path)
}
diff --git a/scripts/Android.bp b/scripts/Android.bp
index 9367ff0..97f6ab4 100644
--- a/scripts/Android.bp
+++ b/scripts/Android.bp
@@ -237,3 +237,20 @@
name: "jars-to-module-info-java",
src: "jars-to-module-info-java.sh",
}
+
+python_binary_host {
+ name: "modify_permissions_allowlist",
+ main: "modify_permissions_allowlist.py",
+ srcs: [
+ "modify_permissions_allowlist.py",
+ ],
+}
+
+python_test_host {
+ name: "modify_permissions_allowlist_test",
+ main: "modify_permissions_allowlist_test.py",
+ srcs: [
+ "modify_permissions_allowlist_test.py",
+ "modify_permissions_allowlist.py",
+ ],
+}
diff --git a/scripts/modify_permissions_allowlist.py b/scripts/modify_permissions_allowlist.py
new file mode 100755
index 0000000..38ec7ec
--- /dev/null
+++ b/scripts/modify_permissions_allowlist.py
@@ -0,0 +1,70 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2022 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.
+#
+"""A tool for modifying privileged permission allowlists."""
+
+from __future__ import print_function
+
+import argparse
+import sys
+from xml.dom import minidom
+
+
+class InvalidRootNodeException(Exception):
+ pass
+
+
+class InvalidNumberOfPrivappPermissionChildren(Exception):
+ pass
+
+
+def modify_allowlist(allowlist_dom, package_name):
+ if allowlist_dom.documentElement.tagName != 'permissions':
+ raise InvalidRootNodeException
+ nodes = allowlist_dom.getElementsByTagName('privapp-permissions')
+ if nodes.length != 1:
+ raise InvalidNumberOfPrivappPermissionChildren
+ privapp_permissions = nodes[0]
+ privapp_permissions.setAttribute('package', package_name)
+
+
+def parse_args():
+ """Parse commandline arguments."""
+
+ parser = argparse.ArgumentParser()
+ parser.add_argument('input', help='input allowlist template file')
+ parser.add_argument(
+ 'package_name', help='package name to use in the allowlist'
+ )
+ parser.add_argument('output', help='output allowlist file')
+
+ return parser.parse_args()
+
+
+def main():
+ try:
+ args = parse_args()
+ doc = minidom.parse(args.input)
+ modify_allowlist(doc, args.package_name)
+ with open(args.output, 'w') as output_file:
+ doc.writexml(output_file, encoding='utf-8')
+ except Exception as err:
+ print('error: ' + str(err), file=sys.stderr)
+ sys.exit(-1)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/scripts/modify_permissions_allowlist_test.py b/scripts/modify_permissions_allowlist_test.py
new file mode 100755
index 0000000..ee8b12c
--- /dev/null
+++ b/scripts/modify_permissions_allowlist_test.py
@@ -0,0 +1,76 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2022 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.
+#
+"""Unit tests for modify_permissions_allowlist.py."""
+
+from __future__ import print_function
+
+import unittest
+
+from xml.dom import minidom
+
+from modify_permissions_allowlist import InvalidRootNodeException, InvalidNumberOfPrivappPermissionChildren, modify_allowlist
+
+
+class ModifyPermissionsAllowlistTest(unittest.TestCase):
+
+ def test_invalid_root(self):
+ xml_data = '<foo></foo>'
+ xml_dom = minidom.parseString(xml_data)
+ self.assertRaises(InvalidRootNodeException, modify_allowlist, xml_dom, 'x')
+
+ def test_no_packages(self):
+ xml_data = '<permissions></permissions>'
+ xml_dom = minidom.parseString(xml_data)
+ self.assertRaises(
+ InvalidNumberOfPrivappPermissionChildren, modify_allowlist, xml_dom, 'x'
+ )
+
+ def test_multiple_packages(self):
+ xml_data = (
+ '<permissions>'
+ ' <privapp-permissions package="foo.bar"></privapp-permissions>'
+ ' <privapp-permissions package="bar.baz"></privapp-permissions>'
+ '</permissions>'
+ )
+ xml_dom = minidom.parseString(xml_data)
+ self.assertRaises(
+ InvalidNumberOfPrivappPermissionChildren, modify_allowlist, xml_dom, 'x'
+ )
+
+ def test_modify_package_name(self):
+ xml_data = (
+ '<permissions>'
+ ' <privapp-permissions package="foo.bar">'
+ ' <permission name="myperm1"/>'
+ ' </privapp-permissions>'
+ '</permissions>'
+ )
+ xml_dom = minidom.parseString(xml_data)
+ modify_allowlist(xml_dom, 'bar.baz')
+ expected_data = (
+ '<?xml version="1.0" ?>'
+ '<permissions>'
+ ' <privapp-permissions package="bar.baz">'
+ ' <permission name="myperm1"/>'
+ ' </privapp-permissions>'
+ '</permissions>'
+ )
+ self.assertEqual(expected_data, xml_dom.toxml())
+
+
+if __name__ == '__main__':
+ unittest.main(verbosity=2)