1*333d2b36SAndroid Build Coastguard Worker// Copyright 2024 Google Inc. All rights reserved. 2*333d2b36SAndroid Build Coastguard Worker// 3*333d2b36SAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License"); 4*333d2b36SAndroid Build Coastguard Worker// you may not use this file except in compliance with the License. 5*333d2b36SAndroid Build Coastguard Worker// You may obtain a copy of the License at 6*333d2b36SAndroid Build Coastguard Worker// 7*333d2b36SAndroid Build Coastguard Worker// http://www.apache.org/licenses/LICENSE-2.0 8*333d2b36SAndroid Build Coastguard Worker// 9*333d2b36SAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software 10*333d2b36SAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS, 11*333d2b36SAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*333d2b36SAndroid Build Coastguard Worker// See the License for the specific language governing permissions and 13*333d2b36SAndroid Build Coastguard Worker// limitations under the License. 14*333d2b36SAndroid Build Coastguard Worker 15*333d2b36SAndroid Build Coastguard Workerpackage android 16*333d2b36SAndroid Build Coastguard Worker 17*333d2b36SAndroid Build Coastguard Workerimport ( 18*333d2b36SAndroid Build Coastguard Worker "fmt" 19*333d2b36SAndroid Build Coastguard Worker "reflect" 20*333d2b36SAndroid Build Coastguard Worker "slices" 21*333d2b36SAndroid Build Coastguard Worker "strings" 22*333d2b36SAndroid Build Coastguard Worker 23*333d2b36SAndroid Build Coastguard Worker "github.com/google/blueprint" 24*333d2b36SAndroid Build Coastguard Worker) 25*333d2b36SAndroid Build Coastguard Worker 26*333d2b36SAndroid Build Coastguard Worker// ---------------------------------------------------------------------------- 27*333d2b36SAndroid Build Coastguard Worker// Start of the definitions of exception functions and the lookup table. 28*333d2b36SAndroid Build Coastguard Worker// 29*333d2b36SAndroid Build Coastguard Worker// Functions cannot be used as a value passed in providers, because functions are not 30*333d2b36SAndroid Build Coastguard Worker// hashable. As a workaround, the [exceptionHandleFuncLabel] enum values are passed using providers, 31*333d2b36SAndroid Build Coastguard Worker// and the corresponding functions are called from [exceptionHandleFunctionsTable] map. 32*333d2b36SAndroid Build Coastguard Worker// ---------------------------------------------------------------------------- 33*333d2b36SAndroid Build Coastguard Worker 34*333d2b36SAndroid Build Coastguard Workertype exceptionHandleFunc func(ModuleContext, Module, Module) bool 35*333d2b36SAndroid Build Coastguard Worker 36*333d2b36SAndroid Build Coastguard Workertype StubsAvailableModule interface { 37*333d2b36SAndroid Build Coastguard Worker IsStubsModule() bool 38*333d2b36SAndroid Build Coastguard Worker} 39*333d2b36SAndroid Build Coastguard Worker 40*333d2b36SAndroid Build Coastguard Worker// Returns true if the dependency module is a stubs module 41*333d2b36SAndroid Build Coastguard Workervar depIsStubsModule exceptionHandleFunc = func(_ ModuleContext, _, dep Module) bool { 42*333d2b36SAndroid Build Coastguard Worker if stubsModule, ok := dep.(StubsAvailableModule); ok { 43*333d2b36SAndroid Build Coastguard Worker return stubsModule.IsStubsModule() 44*333d2b36SAndroid Build Coastguard Worker } 45*333d2b36SAndroid Build Coastguard Worker return false 46*333d2b36SAndroid Build Coastguard Worker} 47*333d2b36SAndroid Build Coastguard Worker 48*333d2b36SAndroid Build Coastguard Worker// Returns true if the dependency module belongs to any of the apexes. 49*333d2b36SAndroid Build Coastguard Workervar depIsApexModule exceptionHandleFunc = func(mctx ModuleContext, _, dep Module) bool { 50*333d2b36SAndroid Build Coastguard Worker depContainersInfo, _ := getContainerModuleInfo(mctx, dep) 51*333d2b36SAndroid Build Coastguard Worker return InList(ApexContainer, depContainersInfo.belongingContainers) 52*333d2b36SAndroid Build Coastguard Worker} 53*333d2b36SAndroid Build Coastguard Worker 54*333d2b36SAndroid Build Coastguard Worker// Returns true if the module and the dependent module belongs to common apexes. 55*333d2b36SAndroid Build Coastguard Workervar belongsToCommonApexes exceptionHandleFunc = func(mctx ModuleContext, m, dep Module) bool { 56*333d2b36SAndroid Build Coastguard Worker mContainersInfo, _ := getContainerModuleInfo(mctx, m) 57*333d2b36SAndroid Build Coastguard Worker depContainersInfo, _ := getContainerModuleInfo(mctx, dep) 58*333d2b36SAndroid Build Coastguard Worker 59*333d2b36SAndroid Build Coastguard Worker return HasIntersection(mContainersInfo.ApexNames(), depContainersInfo.ApexNames()) 60*333d2b36SAndroid Build Coastguard Worker} 61*333d2b36SAndroid Build Coastguard Worker 62*333d2b36SAndroid Build Coastguard Worker// Returns true when all apexes that the module belongs to are non updatable. 63*333d2b36SAndroid Build Coastguard Worker// For an apex module to be allowed to depend on a non-apex partition module, 64*333d2b36SAndroid Build Coastguard Worker// all apexes that the module belong to must be non updatable. 65*333d2b36SAndroid Build Coastguard Workervar belongsToNonUpdatableApex exceptionHandleFunc = func(mctx ModuleContext, m, _ Module) bool { 66*333d2b36SAndroid Build Coastguard Worker mContainersInfo, _ := getContainerModuleInfo(mctx, m) 67*333d2b36SAndroid Build Coastguard Worker 68*333d2b36SAndroid Build Coastguard Worker return !mContainersInfo.UpdatableApex() 69*333d2b36SAndroid Build Coastguard Worker} 70*333d2b36SAndroid Build Coastguard Worker 71*333d2b36SAndroid Build Coastguard Worker// Returns true if the dependency is added via dependency tags that are not used to tag dynamic 72*333d2b36SAndroid Build Coastguard Worker// dependency tags. 73*333d2b36SAndroid Build Coastguard Workervar depIsNotDynamicDepTag exceptionHandleFunc = func(ctx ModuleContext, m, dep Module) bool { 74*333d2b36SAndroid Build Coastguard Worker mInstallable, _ := m.(InstallableModule) 75*333d2b36SAndroid Build Coastguard Worker depTag := ctx.OtherModuleDependencyTag(dep) 76*333d2b36SAndroid Build Coastguard Worker return !InList(depTag, mInstallable.DynamicDependencyTags()) 77*333d2b36SAndroid Build Coastguard Worker} 78*333d2b36SAndroid Build Coastguard Worker 79*333d2b36SAndroid Build Coastguard Worker// Returns true if the dependency is added via dependency tags that are not used to tag static 80*333d2b36SAndroid Build Coastguard Worker// or dynamic dependency tags. These dependencies do not affect the module in compile time or in 81*333d2b36SAndroid Build Coastguard Worker// runtime, thus are not significant enough to raise an error. 82*333d2b36SAndroid Build Coastguard Workervar depIsNotStaticOrDynamicDepTag exceptionHandleFunc = func(ctx ModuleContext, m, dep Module) bool { 83*333d2b36SAndroid Build Coastguard Worker mInstallable, _ := m.(InstallableModule) 84*333d2b36SAndroid Build Coastguard Worker depTag := ctx.OtherModuleDependencyTag(dep) 85*333d2b36SAndroid Build Coastguard Worker return !InList(depTag, append(mInstallable.StaticDependencyTags(), mInstallable.DynamicDependencyTags()...)) 86*333d2b36SAndroid Build Coastguard Worker} 87*333d2b36SAndroid Build Coastguard Worker 88*333d2b36SAndroid Build Coastguard Workervar globallyAllowlistedDependencies = []string{ 89*333d2b36SAndroid Build Coastguard Worker // Modules that provide annotations used within the platform and apexes. 90*333d2b36SAndroid Build Coastguard Worker "aconfig-annotations-lib", 91*333d2b36SAndroid Build Coastguard Worker "framework-annotations-lib", 92*333d2b36SAndroid Build Coastguard Worker "unsupportedappusage", 93*333d2b36SAndroid Build Coastguard Worker 94*333d2b36SAndroid Build Coastguard Worker // TODO(b/363016634): Remove from the allowlist when the module is converted 95*333d2b36SAndroid Build Coastguard Worker // to java_sdk_library and the java_aconfig_library modules depend on the stub. 96*333d2b36SAndroid Build Coastguard Worker "aconfig_storage_stub", 97*333d2b36SAndroid Build Coastguard Worker 98*333d2b36SAndroid Build Coastguard Worker // framework-res provides core resources essential for building apps and system UI. 99*333d2b36SAndroid Build Coastguard Worker // This module is implicitly added as a dependency for java modules even when the 100*333d2b36SAndroid Build Coastguard Worker // dependency specifies sdk_version. 101*333d2b36SAndroid Build Coastguard Worker "framework-res", 102*333d2b36SAndroid Build Coastguard Worker 103*333d2b36SAndroid Build Coastguard Worker // jacocoagent is implicitly added as a dependency in coverage builds, and is not installed 104*333d2b36SAndroid Build Coastguard Worker // on the device. 105*333d2b36SAndroid Build Coastguard Worker "jacocoagent", 106*333d2b36SAndroid Build Coastguard Worker} 107*333d2b36SAndroid Build Coastguard Worker 108*333d2b36SAndroid Build Coastguard Worker// Returns true when the dependency is globally allowlisted for inter-container dependency 109*333d2b36SAndroid Build Coastguard Workervar depIsGloballyAllowlisted exceptionHandleFunc = func(_ ModuleContext, _, dep Module) bool { 110*333d2b36SAndroid Build Coastguard Worker return InList(dep.Name(), globallyAllowlistedDependencies) 111*333d2b36SAndroid Build Coastguard Worker} 112*333d2b36SAndroid Build Coastguard Worker 113*333d2b36SAndroid Build Coastguard Worker// Labels of exception functions, which are used to determine special dependencies that allow 114*333d2b36SAndroid Build Coastguard Worker// otherwise restricted inter-container dependencies 115*333d2b36SAndroid Build Coastguard Workertype exceptionHandleFuncLabel int 116*333d2b36SAndroid Build Coastguard Worker 117*333d2b36SAndroid Build Coastguard Workerconst ( 118*333d2b36SAndroid Build Coastguard Worker checkStubs exceptionHandleFuncLabel = iota 119*333d2b36SAndroid Build Coastguard Worker checkApexModule 120*333d2b36SAndroid Build Coastguard Worker checkInCommonApexes 121*333d2b36SAndroid Build Coastguard Worker checkApexIsNonUpdatable 122*333d2b36SAndroid Build Coastguard Worker checkNotDynamicDepTag 123*333d2b36SAndroid Build Coastguard Worker checkNotStaticOrDynamicDepTag 124*333d2b36SAndroid Build Coastguard Worker checkGlobalAllowlistedDep 125*333d2b36SAndroid Build Coastguard Worker) 126*333d2b36SAndroid Build Coastguard Worker 127*333d2b36SAndroid Build Coastguard Worker// Map of [exceptionHandleFuncLabel] to the [exceptionHandleFunc] 128*333d2b36SAndroid Build Coastguard Workervar exceptionHandleFunctionsTable = map[exceptionHandleFuncLabel]exceptionHandleFunc{ 129*333d2b36SAndroid Build Coastguard Worker checkStubs: depIsStubsModule, 130*333d2b36SAndroid Build Coastguard Worker checkApexModule: depIsApexModule, 131*333d2b36SAndroid Build Coastguard Worker checkInCommonApexes: belongsToCommonApexes, 132*333d2b36SAndroid Build Coastguard Worker checkApexIsNonUpdatable: belongsToNonUpdatableApex, 133*333d2b36SAndroid Build Coastguard Worker checkNotDynamicDepTag: depIsNotDynamicDepTag, 134*333d2b36SAndroid Build Coastguard Worker checkNotStaticOrDynamicDepTag: depIsNotStaticOrDynamicDepTag, 135*333d2b36SAndroid Build Coastguard Worker checkGlobalAllowlistedDep: depIsGloballyAllowlisted, 136*333d2b36SAndroid Build Coastguard Worker} 137*333d2b36SAndroid Build Coastguard Worker 138*333d2b36SAndroid Build Coastguard Worker// ---------------------------------------------------------------------------- 139*333d2b36SAndroid Build Coastguard Worker// Start of the definitions of container determination functions. 140*333d2b36SAndroid Build Coastguard Worker// 141*333d2b36SAndroid Build Coastguard Worker// Similar to the above section, below defines the functions used to determine 142*333d2b36SAndroid Build Coastguard Worker// the container of each modules. 143*333d2b36SAndroid Build Coastguard Worker// ---------------------------------------------------------------------------- 144*333d2b36SAndroid Build Coastguard Worker 145*333d2b36SAndroid Build Coastguard Workertype containerBoundaryFunc func(mctx ModuleContext) bool 146*333d2b36SAndroid Build Coastguard Worker 147*333d2b36SAndroid Build Coastguard Workervar vendorContainerBoundaryFunc containerBoundaryFunc = func(mctx ModuleContext) bool { 148*333d2b36SAndroid Build Coastguard Worker m, ok := mctx.Module().(ImageInterface) 149*333d2b36SAndroid Build Coastguard Worker return mctx.Module().InstallInVendor() || (ok && m.VendorVariantNeeded(mctx)) 150*333d2b36SAndroid Build Coastguard Worker} 151*333d2b36SAndroid Build Coastguard Worker 152*333d2b36SAndroid Build Coastguard Workervar systemContainerBoundaryFunc containerBoundaryFunc = func(mctx ModuleContext) bool { 153*333d2b36SAndroid Build Coastguard Worker module := mctx.Module() 154*333d2b36SAndroid Build Coastguard Worker 155*333d2b36SAndroid Build Coastguard Worker return !module.InstallInTestcases() && 156*333d2b36SAndroid Build Coastguard Worker !module.InstallInData() && 157*333d2b36SAndroid Build Coastguard Worker !module.InstallInRamdisk() && 158*333d2b36SAndroid Build Coastguard Worker !module.InstallInVendorRamdisk() && 159*333d2b36SAndroid Build Coastguard Worker !module.InstallInDebugRamdisk() && 160*333d2b36SAndroid Build Coastguard Worker !module.InstallInRecovery() && 161*333d2b36SAndroid Build Coastguard Worker !module.InstallInVendor() && 162*333d2b36SAndroid Build Coastguard Worker !module.InstallInOdm() && 163*333d2b36SAndroid Build Coastguard Worker !module.InstallInProduct() && 164*333d2b36SAndroid Build Coastguard Worker determineModuleKind(module.base(), mctx.blueprintBaseModuleContext()) == platformModule 165*333d2b36SAndroid Build Coastguard Worker} 166*333d2b36SAndroid Build Coastguard Worker 167*333d2b36SAndroid Build Coastguard Workervar productContainerBoundaryFunc containerBoundaryFunc = func(mctx ModuleContext) bool { 168*333d2b36SAndroid Build Coastguard Worker m, ok := mctx.Module().(ImageInterface) 169*333d2b36SAndroid Build Coastguard Worker return mctx.Module().InstallInProduct() || (ok && m.ProductVariantNeeded(mctx)) 170*333d2b36SAndroid Build Coastguard Worker} 171*333d2b36SAndroid Build Coastguard Worker 172*333d2b36SAndroid Build Coastguard Workervar apexContainerBoundaryFunc containerBoundaryFunc = func(mctx ModuleContext) bool { 173*333d2b36SAndroid Build Coastguard Worker _, ok := ModuleProvider(mctx, AllApexInfoProvider) 174*333d2b36SAndroid Build Coastguard Worker return ok 175*333d2b36SAndroid Build Coastguard Worker} 176*333d2b36SAndroid Build Coastguard Worker 177*333d2b36SAndroid Build Coastguard Workervar ctsContainerBoundaryFunc containerBoundaryFunc = func(mctx ModuleContext) bool { 178*333d2b36SAndroid Build Coastguard Worker props := mctx.Module().GetProperties() 179*333d2b36SAndroid Build Coastguard Worker for _, prop := range props { 180*333d2b36SAndroid Build Coastguard Worker val := reflect.ValueOf(prop).Elem() 181*333d2b36SAndroid Build Coastguard Worker if val.Kind() == reflect.Struct { 182*333d2b36SAndroid Build Coastguard Worker testSuites := val.FieldByName("Test_suites") 183*333d2b36SAndroid Build Coastguard Worker if testSuites.IsValid() && testSuites.Kind() == reflect.Slice && slices.Contains(testSuites.Interface().([]string), "cts") { 184*333d2b36SAndroid Build Coastguard Worker return true 185*333d2b36SAndroid Build Coastguard Worker } 186*333d2b36SAndroid Build Coastguard Worker } 187*333d2b36SAndroid Build Coastguard Worker } 188*333d2b36SAndroid Build Coastguard Worker return false 189*333d2b36SAndroid Build Coastguard Worker} 190*333d2b36SAndroid Build Coastguard Worker 191*333d2b36SAndroid Build Coastguard Workertype unstableInfo struct { 192*333d2b36SAndroid Build Coastguard Worker // Determines if the module contains the private APIs of the platform. 193*333d2b36SAndroid Build Coastguard Worker ContainsPlatformPrivateApis bool 194*333d2b36SAndroid Build Coastguard Worker} 195*333d2b36SAndroid Build Coastguard Worker 196*333d2b36SAndroid Build Coastguard Workervar unstableInfoProvider = blueprint.NewProvider[unstableInfo]() 197*333d2b36SAndroid Build Coastguard Worker 198*333d2b36SAndroid Build Coastguard Workerfunc determineUnstableModule(mctx ModuleContext) bool { 199*333d2b36SAndroid Build Coastguard Worker module := mctx.Module() 200*333d2b36SAndroid Build Coastguard Worker unstableModule := module.Name() == "framework-minus-apex" 201*333d2b36SAndroid Build Coastguard Worker if installable, ok := module.(InstallableModule); ok { 202*333d2b36SAndroid Build Coastguard Worker for _, staticDepTag := range installable.StaticDependencyTags() { 203*333d2b36SAndroid Build Coastguard Worker mctx.VisitDirectDepsWithTag(staticDepTag, func(dep Module) { 204*333d2b36SAndroid Build Coastguard Worker if unstableInfo, ok := OtherModuleProvider(mctx, dep, unstableInfoProvider); ok { 205*333d2b36SAndroid Build Coastguard Worker unstableModule = unstableModule || unstableInfo.ContainsPlatformPrivateApis 206*333d2b36SAndroid Build Coastguard Worker } 207*333d2b36SAndroid Build Coastguard Worker }) 208*333d2b36SAndroid Build Coastguard Worker } 209*333d2b36SAndroid Build Coastguard Worker } 210*333d2b36SAndroid Build Coastguard Worker return unstableModule 211*333d2b36SAndroid Build Coastguard Worker} 212*333d2b36SAndroid Build Coastguard Worker 213*333d2b36SAndroid Build Coastguard Workervar unstableContainerBoundaryFunc containerBoundaryFunc = func(mctx ModuleContext) bool { 214*333d2b36SAndroid Build Coastguard Worker return determineUnstableModule(mctx) 215*333d2b36SAndroid Build Coastguard Worker} 216*333d2b36SAndroid Build Coastguard Worker 217*333d2b36SAndroid Build Coastguard Worker// Map of [*container] to the [containerBoundaryFunc] 218*333d2b36SAndroid Build Coastguard Workervar containerBoundaryFunctionsTable = map[*container]containerBoundaryFunc{ 219*333d2b36SAndroid Build Coastguard Worker VendorContainer: vendorContainerBoundaryFunc, 220*333d2b36SAndroid Build Coastguard Worker SystemContainer: systemContainerBoundaryFunc, 221*333d2b36SAndroid Build Coastguard Worker ProductContainer: productContainerBoundaryFunc, 222*333d2b36SAndroid Build Coastguard Worker ApexContainer: apexContainerBoundaryFunc, 223*333d2b36SAndroid Build Coastguard Worker CtsContainer: ctsContainerBoundaryFunc, 224*333d2b36SAndroid Build Coastguard Worker UnstableContainer: unstableContainerBoundaryFunc, 225*333d2b36SAndroid Build Coastguard Worker} 226*333d2b36SAndroid Build Coastguard Worker 227*333d2b36SAndroid Build Coastguard Worker// ---------------------------------------------------------------------------- 228*333d2b36SAndroid Build Coastguard Worker// End of the definitions of container determination functions. 229*333d2b36SAndroid Build Coastguard Worker// ---------------------------------------------------------------------------- 230*333d2b36SAndroid Build Coastguard Worker 231*333d2b36SAndroid Build Coastguard Workertype InstallableModule interface { 232*333d2b36SAndroid Build Coastguard Worker StaticDependencyTags() []blueprint.DependencyTag 233*333d2b36SAndroid Build Coastguard Worker DynamicDependencyTags() []blueprint.DependencyTag 234*333d2b36SAndroid Build Coastguard Worker} 235*333d2b36SAndroid Build Coastguard Worker 236*333d2b36SAndroid Build Coastguard Workertype restriction struct { 237*333d2b36SAndroid Build Coastguard Worker // container of the dependency 238*333d2b36SAndroid Build Coastguard Worker dependency *container 239*333d2b36SAndroid Build Coastguard Worker 240*333d2b36SAndroid Build Coastguard Worker // Error message to be emitted to the user when the dependency meets this restriction 241*333d2b36SAndroid Build Coastguard Worker errorMessage string 242*333d2b36SAndroid Build Coastguard Worker 243*333d2b36SAndroid Build Coastguard Worker // List of labels of allowed exception functions that allows bypassing this restriction. 244*333d2b36SAndroid Build Coastguard Worker // If any of the functions mapped to each labels returns true, this dependency would be 245*333d2b36SAndroid Build Coastguard Worker // considered allowed and an error will not be thrown. 246*333d2b36SAndroid Build Coastguard Worker allowedExceptions []exceptionHandleFuncLabel 247*333d2b36SAndroid Build Coastguard Worker} 248*333d2b36SAndroid Build Coastguard Workertype container struct { 249*333d2b36SAndroid Build Coastguard Worker // The name of the container i.e. partition, api domain 250*333d2b36SAndroid Build Coastguard Worker name string 251*333d2b36SAndroid Build Coastguard Worker 252*333d2b36SAndroid Build Coastguard Worker // Map of dependency restricted containers. 253*333d2b36SAndroid Build Coastguard Worker restricted []restriction 254*333d2b36SAndroid Build Coastguard Worker} 255*333d2b36SAndroid Build Coastguard Worker 256*333d2b36SAndroid Build Coastguard Workervar ( 257*333d2b36SAndroid Build Coastguard Worker VendorContainer = &container{ 258*333d2b36SAndroid Build Coastguard Worker name: VendorVariation, 259*333d2b36SAndroid Build Coastguard Worker restricted: nil, 260*333d2b36SAndroid Build Coastguard Worker } 261*333d2b36SAndroid Build Coastguard Worker 262*333d2b36SAndroid Build Coastguard Worker SystemContainer = &container{ 263*333d2b36SAndroid Build Coastguard Worker name: "system", 264*333d2b36SAndroid Build Coastguard Worker restricted: []restriction{ 265*333d2b36SAndroid Build Coastguard Worker { 266*333d2b36SAndroid Build Coastguard Worker dependency: VendorContainer, 267*333d2b36SAndroid Build Coastguard Worker errorMessage: "Module belonging to the system partition other than HALs is " + 268*333d2b36SAndroid Build Coastguard Worker "not allowed to depend on the vendor partition module, in order to support " + 269*333d2b36SAndroid Build Coastguard Worker "independent development/update cycles and to support the Generic System " + 270*333d2b36SAndroid Build Coastguard Worker "Image. Try depending on HALs, VNDK or AIDL instead.", 271*333d2b36SAndroid Build Coastguard Worker allowedExceptions: []exceptionHandleFuncLabel{ 272*333d2b36SAndroid Build Coastguard Worker checkStubs, 273*333d2b36SAndroid Build Coastguard Worker checkNotDynamicDepTag, 274*333d2b36SAndroid Build Coastguard Worker checkGlobalAllowlistedDep, 275*333d2b36SAndroid Build Coastguard Worker }, 276*333d2b36SAndroid Build Coastguard Worker }, 277*333d2b36SAndroid Build Coastguard Worker }, 278*333d2b36SAndroid Build Coastguard Worker } 279*333d2b36SAndroid Build Coastguard Worker 280*333d2b36SAndroid Build Coastguard Worker ProductContainer = &container{ 281*333d2b36SAndroid Build Coastguard Worker name: ProductVariation, 282*333d2b36SAndroid Build Coastguard Worker restricted: []restriction{ 283*333d2b36SAndroid Build Coastguard Worker { 284*333d2b36SAndroid Build Coastguard Worker dependency: VendorContainer, 285*333d2b36SAndroid Build Coastguard Worker errorMessage: "Module belonging to the product partition is not allowed to " + 286*333d2b36SAndroid Build Coastguard Worker "depend on the vendor partition module, as this may lead to security " + 287*333d2b36SAndroid Build Coastguard Worker "vulnerabilities. Try depending on the HALs or utilize AIDL instead.", 288*333d2b36SAndroid Build Coastguard Worker allowedExceptions: []exceptionHandleFuncLabel{ 289*333d2b36SAndroid Build Coastguard Worker checkStubs, 290*333d2b36SAndroid Build Coastguard Worker checkNotDynamicDepTag, 291*333d2b36SAndroid Build Coastguard Worker checkGlobalAllowlistedDep, 292*333d2b36SAndroid Build Coastguard Worker }, 293*333d2b36SAndroid Build Coastguard Worker }, 294*333d2b36SAndroid Build Coastguard Worker }, 295*333d2b36SAndroid Build Coastguard Worker } 296*333d2b36SAndroid Build Coastguard Worker 297*333d2b36SAndroid Build Coastguard Worker ApexContainer = initializeApexContainer() 298*333d2b36SAndroid Build Coastguard Worker 299*333d2b36SAndroid Build Coastguard Worker CtsContainer = &container{ 300*333d2b36SAndroid Build Coastguard Worker name: "cts", 301*333d2b36SAndroid Build Coastguard Worker restricted: []restriction{ 302*333d2b36SAndroid Build Coastguard Worker { 303*333d2b36SAndroid Build Coastguard Worker dependency: UnstableContainer, 304*333d2b36SAndroid Build Coastguard Worker errorMessage: "CTS module should not depend on the modules that contain the " + 305*333d2b36SAndroid Build Coastguard Worker "platform implementation details, including \"framework\". Depending on these " + 306*333d2b36SAndroid Build Coastguard Worker "modules may lead to disclosure of implementation details and regression " + 307*333d2b36SAndroid Build Coastguard Worker "due to API changes across platform versions. Try depending on the stubs instead " + 308*333d2b36SAndroid Build Coastguard Worker "and ensure that the module sets an appropriate 'sdk_version'.", 309*333d2b36SAndroid Build Coastguard Worker allowedExceptions: []exceptionHandleFuncLabel{ 310*333d2b36SAndroid Build Coastguard Worker checkStubs, 311*333d2b36SAndroid Build Coastguard Worker checkNotStaticOrDynamicDepTag, 312*333d2b36SAndroid Build Coastguard Worker checkGlobalAllowlistedDep, 313*333d2b36SAndroid Build Coastguard Worker }, 314*333d2b36SAndroid Build Coastguard Worker }, 315*333d2b36SAndroid Build Coastguard Worker }, 316*333d2b36SAndroid Build Coastguard Worker } 317*333d2b36SAndroid Build Coastguard Worker 318*333d2b36SAndroid Build Coastguard Worker // Container signifying that the module contains unstable platform private APIs 319*333d2b36SAndroid Build Coastguard Worker UnstableContainer = &container{ 320*333d2b36SAndroid Build Coastguard Worker name: "unstable", 321*333d2b36SAndroid Build Coastguard Worker restricted: nil, 322*333d2b36SAndroid Build Coastguard Worker } 323*333d2b36SAndroid Build Coastguard Worker 324*333d2b36SAndroid Build Coastguard Worker allContainers = []*container{ 325*333d2b36SAndroid Build Coastguard Worker VendorContainer, 326*333d2b36SAndroid Build Coastguard Worker SystemContainer, 327*333d2b36SAndroid Build Coastguard Worker ProductContainer, 328*333d2b36SAndroid Build Coastguard Worker ApexContainer, 329*333d2b36SAndroid Build Coastguard Worker CtsContainer, 330*333d2b36SAndroid Build Coastguard Worker UnstableContainer, 331*333d2b36SAndroid Build Coastguard Worker } 332*333d2b36SAndroid Build Coastguard Worker) 333*333d2b36SAndroid Build Coastguard Worker 334*333d2b36SAndroid Build Coastguard Workerfunc initializeApexContainer() *container { 335*333d2b36SAndroid Build Coastguard Worker apexContainer := &container{ 336*333d2b36SAndroid Build Coastguard Worker name: "apex", 337*333d2b36SAndroid Build Coastguard Worker restricted: []restriction{ 338*333d2b36SAndroid Build Coastguard Worker { 339*333d2b36SAndroid Build Coastguard Worker dependency: SystemContainer, 340*333d2b36SAndroid Build Coastguard Worker errorMessage: "Module belonging to Apex(es) is not allowed to depend on the " + 341*333d2b36SAndroid Build Coastguard Worker "modules belonging to the system partition. Either statically depend on the " + 342*333d2b36SAndroid Build Coastguard Worker "module or convert the depending module to java_sdk_library and depend on " + 343*333d2b36SAndroid Build Coastguard Worker "the stubs.", 344*333d2b36SAndroid Build Coastguard Worker allowedExceptions: []exceptionHandleFuncLabel{ 345*333d2b36SAndroid Build Coastguard Worker checkStubs, 346*333d2b36SAndroid Build Coastguard Worker checkApexModule, 347*333d2b36SAndroid Build Coastguard Worker checkInCommonApexes, 348*333d2b36SAndroid Build Coastguard Worker checkApexIsNonUpdatable, 349*333d2b36SAndroid Build Coastguard Worker checkNotStaticOrDynamicDepTag, 350*333d2b36SAndroid Build Coastguard Worker checkGlobalAllowlistedDep, 351*333d2b36SAndroid Build Coastguard Worker }, 352*333d2b36SAndroid Build Coastguard Worker }, 353*333d2b36SAndroid Build Coastguard Worker }, 354*333d2b36SAndroid Build Coastguard Worker } 355*333d2b36SAndroid Build Coastguard Worker 356*333d2b36SAndroid Build Coastguard Worker apexContainer.restricted = append(apexContainer.restricted, restriction{ 357*333d2b36SAndroid Build Coastguard Worker dependency: apexContainer, 358*333d2b36SAndroid Build Coastguard Worker errorMessage: "Module belonging to Apex(es) is not allowed to depend on the " + 359*333d2b36SAndroid Build Coastguard Worker "modules belonging to other Apex(es). Either include the depending " + 360*333d2b36SAndroid Build Coastguard Worker "module in the Apex or convert the depending module to java_sdk_library " + 361*333d2b36SAndroid Build Coastguard Worker "and depend on its stubs.", 362*333d2b36SAndroid Build Coastguard Worker allowedExceptions: []exceptionHandleFuncLabel{ 363*333d2b36SAndroid Build Coastguard Worker checkStubs, 364*333d2b36SAndroid Build Coastguard Worker checkInCommonApexes, 365*333d2b36SAndroid Build Coastguard Worker checkNotStaticOrDynamicDepTag, 366*333d2b36SAndroid Build Coastguard Worker checkGlobalAllowlistedDep, 367*333d2b36SAndroid Build Coastguard Worker }, 368*333d2b36SAndroid Build Coastguard Worker }) 369*333d2b36SAndroid Build Coastguard Worker 370*333d2b36SAndroid Build Coastguard Worker return apexContainer 371*333d2b36SAndroid Build Coastguard Worker} 372*333d2b36SAndroid Build Coastguard Worker 373*333d2b36SAndroid Build Coastguard Workertype ContainersInfo struct { 374*333d2b36SAndroid Build Coastguard Worker belongingContainers []*container 375*333d2b36SAndroid Build Coastguard Worker 376*333d2b36SAndroid Build Coastguard Worker belongingApexes []ApexInfo 377*333d2b36SAndroid Build Coastguard Worker} 378*333d2b36SAndroid Build Coastguard Worker 379*333d2b36SAndroid Build Coastguard Workerfunc (c *ContainersInfo) BelongingContainers() []*container { 380*333d2b36SAndroid Build Coastguard Worker return c.belongingContainers 381*333d2b36SAndroid Build Coastguard Worker} 382*333d2b36SAndroid Build Coastguard Worker 383*333d2b36SAndroid Build Coastguard Workerfunc (c *ContainersInfo) ApexNames() (ret []string) { 384*333d2b36SAndroid Build Coastguard Worker for _, apex := range c.belongingApexes { 385*333d2b36SAndroid Build Coastguard Worker ret = append(ret, apex.InApexVariants...) 386*333d2b36SAndroid Build Coastguard Worker } 387*333d2b36SAndroid Build Coastguard Worker slices.Sort(ret) 388*333d2b36SAndroid Build Coastguard Worker return ret 389*333d2b36SAndroid Build Coastguard Worker} 390*333d2b36SAndroid Build Coastguard Worker 391*333d2b36SAndroid Build Coastguard Worker// Returns true if any of the apex the module belongs to is updatable. 392*333d2b36SAndroid Build Coastguard Workerfunc (c *ContainersInfo) UpdatableApex() bool { 393*333d2b36SAndroid Build Coastguard Worker for _, apex := range c.belongingApexes { 394*333d2b36SAndroid Build Coastguard Worker if apex.Updatable { 395*333d2b36SAndroid Build Coastguard Worker return true 396*333d2b36SAndroid Build Coastguard Worker } 397*333d2b36SAndroid Build Coastguard Worker } 398*333d2b36SAndroid Build Coastguard Worker return false 399*333d2b36SAndroid Build Coastguard Worker} 400*333d2b36SAndroid Build Coastguard Worker 401*333d2b36SAndroid Build Coastguard Workervar ContainersInfoProvider = blueprint.NewProvider[ContainersInfo]() 402*333d2b36SAndroid Build Coastguard Worker 403*333d2b36SAndroid Build Coastguard Workerfunc satisfyAllowedExceptions(ctx ModuleContext, allowedExceptionLabels []exceptionHandleFuncLabel, m, dep Module) bool { 404*333d2b36SAndroid Build Coastguard Worker for _, label := range allowedExceptionLabels { 405*333d2b36SAndroid Build Coastguard Worker if exceptionHandleFunctionsTable[label](ctx, m, dep) { 406*333d2b36SAndroid Build Coastguard Worker return true 407*333d2b36SAndroid Build Coastguard Worker } 408*333d2b36SAndroid Build Coastguard Worker } 409*333d2b36SAndroid Build Coastguard Worker return false 410*333d2b36SAndroid Build Coastguard Worker} 411*333d2b36SAndroid Build Coastguard Worker 412*333d2b36SAndroid Build Coastguard Workerfunc (c *ContainersInfo) GetViolations(mctx ModuleContext, m, dep Module, depInfo ContainersInfo) []string { 413*333d2b36SAndroid Build Coastguard Worker var violations []string 414*333d2b36SAndroid Build Coastguard Worker 415*333d2b36SAndroid Build Coastguard Worker // Any containers that the module belongs to but the dependency does not belong to must be examined. 416*333d2b36SAndroid Build Coastguard Worker _, containersUniqueToModule, _ := ListSetDifference(c.belongingContainers, depInfo.belongingContainers) 417*333d2b36SAndroid Build Coastguard Worker 418*333d2b36SAndroid Build Coastguard Worker // Apex container should be examined even if both the module and the dependency belong to 419*333d2b36SAndroid Build Coastguard Worker // the apex container to check that the two modules belong to the same apex. 420*333d2b36SAndroid Build Coastguard Worker if InList(ApexContainer, c.belongingContainers) && !InList(ApexContainer, containersUniqueToModule) { 421*333d2b36SAndroid Build Coastguard Worker containersUniqueToModule = append(containersUniqueToModule, ApexContainer) 422*333d2b36SAndroid Build Coastguard Worker } 423*333d2b36SAndroid Build Coastguard Worker 424*333d2b36SAndroid Build Coastguard Worker for _, containerUniqueToModule := range containersUniqueToModule { 425*333d2b36SAndroid Build Coastguard Worker for _, restriction := range containerUniqueToModule.restricted { 426*333d2b36SAndroid Build Coastguard Worker if InList(restriction.dependency, depInfo.belongingContainers) { 427*333d2b36SAndroid Build Coastguard Worker if !satisfyAllowedExceptions(mctx, restriction.allowedExceptions, m, dep) { 428*333d2b36SAndroid Build Coastguard Worker violations = append(violations, restriction.errorMessage) 429*333d2b36SAndroid Build Coastguard Worker } 430*333d2b36SAndroid Build Coastguard Worker } 431*333d2b36SAndroid Build Coastguard Worker } 432*333d2b36SAndroid Build Coastguard Worker } 433*333d2b36SAndroid Build Coastguard Worker 434*333d2b36SAndroid Build Coastguard Worker return violations 435*333d2b36SAndroid Build Coastguard Worker} 436*333d2b36SAndroid Build Coastguard Worker 437*333d2b36SAndroid Build Coastguard Workerfunc generateContainerInfo(ctx ModuleContext) ContainersInfo { 438*333d2b36SAndroid Build Coastguard Worker var containers []*container 439*333d2b36SAndroid Build Coastguard Worker 440*333d2b36SAndroid Build Coastguard Worker for _, cnt := range allContainers { 441*333d2b36SAndroid Build Coastguard Worker if containerBoundaryFunctionsTable[cnt](ctx) { 442*333d2b36SAndroid Build Coastguard Worker containers = append(containers, cnt) 443*333d2b36SAndroid Build Coastguard Worker } 444*333d2b36SAndroid Build Coastguard Worker } 445*333d2b36SAndroid Build Coastguard Worker 446*333d2b36SAndroid Build Coastguard Worker var belongingApexes []ApexInfo 447*333d2b36SAndroid Build Coastguard Worker if apexInfo, ok := ModuleProvider(ctx, AllApexInfoProvider); ok { 448*333d2b36SAndroid Build Coastguard Worker belongingApexes = apexInfo.ApexInfos 449*333d2b36SAndroid Build Coastguard Worker } 450*333d2b36SAndroid Build Coastguard Worker 451*333d2b36SAndroid Build Coastguard Worker return ContainersInfo{ 452*333d2b36SAndroid Build Coastguard Worker belongingContainers: containers, 453*333d2b36SAndroid Build Coastguard Worker belongingApexes: belongingApexes, 454*333d2b36SAndroid Build Coastguard Worker } 455*333d2b36SAndroid Build Coastguard Worker} 456*333d2b36SAndroid Build Coastguard Worker 457*333d2b36SAndroid Build Coastguard Workerfunc getContainerModuleInfo(ctx ModuleContext, module Module) (ContainersInfo, bool) { 458*333d2b36SAndroid Build Coastguard Worker if ctx.Module() == module { 459*333d2b36SAndroid Build Coastguard Worker return ctx.getContainersInfo(), true 460*333d2b36SAndroid Build Coastguard Worker } 461*333d2b36SAndroid Build Coastguard Worker 462*333d2b36SAndroid Build Coastguard Worker return OtherModuleProvider(ctx, module, ContainersInfoProvider) 463*333d2b36SAndroid Build Coastguard Worker} 464*333d2b36SAndroid Build Coastguard Worker 465*333d2b36SAndroid Build Coastguard Workerfunc setContainerInfo(ctx ModuleContext) { 466*333d2b36SAndroid Build Coastguard Worker // Required to determine the unstable container. This provider is set here instead of the 467*333d2b36SAndroid Build Coastguard Worker // unstableContainerBoundaryFunc in order to prevent setting the provider multiple times. 468*333d2b36SAndroid Build Coastguard Worker SetProvider(ctx, unstableInfoProvider, unstableInfo{ 469*333d2b36SAndroid Build Coastguard Worker ContainsPlatformPrivateApis: determineUnstableModule(ctx), 470*333d2b36SAndroid Build Coastguard Worker }) 471*333d2b36SAndroid Build Coastguard Worker 472*333d2b36SAndroid Build Coastguard Worker if _, ok := ctx.Module().(InstallableModule); ok { 473*333d2b36SAndroid Build Coastguard Worker containersInfo := generateContainerInfo(ctx) 474*333d2b36SAndroid Build Coastguard Worker ctx.setContainersInfo(containersInfo) 475*333d2b36SAndroid Build Coastguard Worker SetProvider(ctx, ContainersInfoProvider, containersInfo) 476*333d2b36SAndroid Build Coastguard Worker } 477*333d2b36SAndroid Build Coastguard Worker} 478*333d2b36SAndroid Build Coastguard Worker 479*333d2b36SAndroid Build Coastguard Workerfunc checkContainerViolations(ctx ModuleContext) { 480*333d2b36SAndroid Build Coastguard Worker if _, ok := ctx.Module().(InstallableModule); ok { 481*333d2b36SAndroid Build Coastguard Worker containersInfo, _ := getContainerModuleInfo(ctx, ctx.Module()) 482*333d2b36SAndroid Build Coastguard Worker ctx.VisitDirectDeps(func(dep Module) { 483*333d2b36SAndroid Build Coastguard Worker if !dep.Enabled(ctx) { 484*333d2b36SAndroid Build Coastguard Worker return 485*333d2b36SAndroid Build Coastguard Worker } 486*333d2b36SAndroid Build Coastguard Worker 487*333d2b36SAndroid Build Coastguard Worker // Pre-existing violating dependencies are tracked in containerDependencyViolationAllowlist. 488*333d2b36SAndroid Build Coastguard Worker // If this dependency is allowlisted, do not check for violation. 489*333d2b36SAndroid Build Coastguard Worker // If not, check if this dependency matches any restricted dependency and 490*333d2b36SAndroid Build Coastguard Worker // satisfies any exception functions, which allows bypassing the 491*333d2b36SAndroid Build Coastguard Worker // restriction. If all of the exceptions are not satisfied, throw an error. 492*333d2b36SAndroid Build Coastguard Worker if depContainersInfo, ok := getContainerModuleInfo(ctx, dep); ok { 493*333d2b36SAndroid Build Coastguard Worker if allowedViolations, ok := ContainerDependencyViolationAllowlist[ctx.ModuleName()]; ok && InList(dep.Name(), allowedViolations) { 494*333d2b36SAndroid Build Coastguard Worker return 495*333d2b36SAndroid Build Coastguard Worker } else { 496*333d2b36SAndroid Build Coastguard Worker violations := containersInfo.GetViolations(ctx, ctx.Module(), dep, depContainersInfo) 497*333d2b36SAndroid Build Coastguard Worker if len(violations) > 0 { 498*333d2b36SAndroid Build Coastguard Worker errorMessage := fmt.Sprintf("%s cannot depend on %s. ", ctx.ModuleName(), dep.Name()) 499*333d2b36SAndroid Build Coastguard Worker errorMessage += strings.Join(violations, " ") 500*333d2b36SAndroid Build Coastguard Worker ctx.ModuleErrorf(errorMessage) 501*333d2b36SAndroid Build Coastguard Worker } 502*333d2b36SAndroid Build Coastguard Worker } 503*333d2b36SAndroid Build Coastguard Worker } 504*333d2b36SAndroid Build Coastguard Worker }) 505*333d2b36SAndroid Build Coastguard Worker } 506*333d2b36SAndroid Build Coastguard Worker} 507