diff --git a/android/container.go b/android/container.go index 1a8041872..10aff4d2b 100644 --- a/android/container.go +++ b/android/container.go @@ -178,13 +178,40 @@ var ctsContainerBoundaryFunc containerBoundaryFunc = func(mctx ModuleContext) bo return false } +type unstableInfo struct { + // Determines if the module contains the private APIs of the platform. + ContainsPlatformPrivateApis bool +} + +var unstableInfoProvider = blueprint.NewProvider[unstableInfo]() + +func determineUnstableModule(mctx ModuleContext) bool { + module := mctx.Module() + unstableModule := module.Name() == "framework-minus-apex" + if installable, ok := module.(InstallableModule); ok { + for _, staticDepTag := range installable.StaticDependencyTags() { + mctx.VisitDirectDepsWithTag(staticDepTag, func(dep Module) { + if unstableInfo, ok := OtherModuleProvider(mctx, dep, unstableInfoProvider); ok { + unstableModule = unstableModule || unstableInfo.ContainsPlatformPrivateApis + } + }) + } + } + return unstableModule +} + +var unstableContainerBoundaryFunc containerBoundaryFunc = func(mctx ModuleContext) bool { + return determineUnstableModule(mctx) +} + // Map of [*container] to the [containerBoundaryFunc] var containerBoundaryFunctionsTable = map[*container]containerBoundaryFunc{ - VendorContainer: vendorContainerBoundaryFunc, - SystemContainer: systemContainerBoundaryFunc, - ProductContainer: productContainerBoundaryFunc, - ApexContainer: apexContainerBoundaryFunc, - CtsContainer: ctsContainerBoundaryFunc, + VendorContainer: vendorContainerBoundaryFunc, + SystemContainer: systemContainerBoundaryFunc, + ProductContainer: productContainerBoundaryFunc, + ApexContainer: apexContainerBoundaryFunc, + CtsContainer: ctsContainerBoundaryFunc, + UnstableContainer: unstableContainerBoundaryFunc, } // ---------------------------------------------------------------------------- @@ -264,11 +291,12 @@ var ( name: "cts", restricted: []restriction{ { - dependency: SystemContainer, - errorMessage: "CTS module should not depend on the modules belonging to the " + - "system partition, including \"framework\". Depending on the system " + - "partition may lead to disclosure of implementation details and regression " + - "due to API changes across platform versions. Try depending on the stubs instead.", + dependency: UnstableContainer, + errorMessage: "CTS module should not depend on the modules that contain the " + + "platform implementation details, including \"framework\". Depending on these " + + "modules may lead to disclosure of implementation details and regression " + + "due to API changes across platform versions. Try depending on the stubs instead " + + "and ensure that the module sets an appropriate 'sdk_version'.", allowedExceptions: []exceptionHandleFuncLabel{ checkStubs, checkNotStaticOrDynamicDepTag, @@ -278,12 +306,19 @@ var ( }, } + // Container signifying that the module contains unstable platform private APIs + UnstableContainer = &container{ + name: "unstable", + restricted: nil, + } + allContainers = []*container{ VendorContainer, SystemContainer, ProductContainer, ApexContainer, CtsContainer, + UnstableContainer, } ) @@ -385,6 +420,12 @@ func getContainerModuleInfo(ctx ModuleContext, module Module) (ContainersInfo, b } func setContainerInfo(ctx ModuleContext) { + // Required to determine the unstable container. This provider is set here instead of the + // unstableContainerBoundaryFunc in order to prevent setting the provider multiple times. + SetProvider(ctx, unstableInfoProvider, unstableInfo{ + ContainsPlatformPrivateApis: determineUnstableModule(ctx), + }) + if _, ok := ctx.Module().(InstallableModule); ok { containersInfo := generateContainerInfo(ctx) ctx.Module().base().containersInfo = containersInfo diff --git a/java/container_test.go b/java/container_test.go index 344185553..25cfa4c7e 100644 --- a/java/container_test.go +++ b/java/container_test.go @@ -65,6 +65,18 @@ func TestJavaContainersModuleProperties(t *testing.T) { "general-tests", ], } + java_library { + name: "bar", + static_libs: [ + "framework-minus-apex", + ], + } + java_library { + name: "baz", + static_libs: [ + "bar", + ], + } `) testcases := []struct { @@ -73,6 +85,7 @@ func TestJavaContainersModuleProperties(t *testing.T) { isVendorContainer bool isProductContainer bool isCts bool + isUnstable bool }{ { moduleName: "foo", @@ -80,6 +93,7 @@ func TestJavaContainersModuleProperties(t *testing.T) { isVendorContainer: false, isProductContainer: false, isCts: false, + isUnstable: false, }, { moduleName: "foo_vendor", @@ -87,6 +101,7 @@ func TestJavaContainersModuleProperties(t *testing.T) { isVendorContainer: true, isProductContainer: false, isCts: false, + isUnstable: false, }, { moduleName: "foo_soc_specific", @@ -94,6 +109,7 @@ func TestJavaContainersModuleProperties(t *testing.T) { isVendorContainer: true, isProductContainer: false, isCts: false, + isUnstable: false, }, { moduleName: "foo_product_specific", @@ -101,6 +117,7 @@ func TestJavaContainersModuleProperties(t *testing.T) { isVendorContainer: false, isProductContainer: true, isCts: false, + isUnstable: false, }, { moduleName: "foo_cts_test", @@ -108,6 +125,7 @@ func TestJavaContainersModuleProperties(t *testing.T) { isVendorContainer: false, isProductContainer: false, isCts: true, + isUnstable: false, }, { moduleName: "foo_non_cts_test", @@ -115,6 +133,23 @@ func TestJavaContainersModuleProperties(t *testing.T) { isVendorContainer: false, isProductContainer: false, isCts: false, + isUnstable: false, + }, + { + moduleName: "bar", + isSystemContainer: true, + isVendorContainer: false, + isProductContainer: false, + isCts: false, + isUnstable: true, + }, + { + moduleName: "baz", + isSystemContainer: true, + isVendorContainer: false, + isProductContainer: false, + isCts: false, + isUnstable: true, }, } @@ -125,5 +160,7 @@ func TestJavaContainersModuleProperties(t *testing.T) { checkContainerMatch(t, c.moduleName, "system", c.isSystemContainer, android.InList(android.SystemContainer, belongingContainers)) checkContainerMatch(t, c.moduleName, "vendor", c.isVendorContainer, android.InList(android.VendorContainer, belongingContainers)) checkContainerMatch(t, c.moduleName, "product", c.isProductContainer, android.InList(android.ProductContainer, belongingContainers)) + checkContainerMatch(t, c.moduleName, "cts", c.isCts, android.InList(android.CtsContainer, belongingContainers)) + checkContainerMatch(t, c.moduleName, "unstable", c.isUnstable, android.InList(android.UnstableContainer, belongingContainers)) } } diff --git a/java/testing.go b/java/testing.go index e1bf5376e..0e85022ce 100644 --- a/java/testing.go +++ b/java/testing.go @@ -542,6 +542,16 @@ func gatherRequiredDepsForTest() string { }, compile_dex: true, } + java_library { + name: "framework-minus-apex", + srcs: ["a.java"], + sdk_version: "none", + system_modules: "stable-core-platform-api-stubs-system-modules", + aidl: { + export_include_dirs: ["framework/aidl"], + }, + compile_dex: true, + } android_app { name: "framework-res",