Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Android/build/build/soong/android/   (Android Betriebssystem Version 17©)  Datei vom 26.5.2026 mit Größe 17 kB image not shown  

Quelle  container.go   Sprache: unbekannt

 
Spracherkennung für: .go vermutete Sprache: Unknown {[0] [0] [0]} [Methode: Schwerpunktbildung, einfache Gewichte, sechs Dimensionen]

// Copyright 2024 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package android

import (
 "fmt"
 "reflect"
 "slices"
 "strings"

 "github.com/google/blueprint"
)

//go:generate go run ../../blueprint/gobtools/codegen

// ----------------------------------------------------------------------------
// Start of the definitions of exception functions and the lookup table.
//
// Functions cannot be used as a value passed in providers, because functions are not
// hashable. As a workaround, the [exceptionHandleFuncLabel] enum values are passed using providers,
// and the corresponding functions are called from [exceptionHandleFunctionsTable] map.
// ----------------------------------------------------------------------------

type exceptionHandleFunc func(ModuleContext, Module, ModuleProxy) bool

type StubsAvailableModule interface {
 IsStubsModule() bool
}

// Returns true if the dependency module is a stubs module
var depIsStubsModule exceptionHandleFunc = func(mctx ModuleContext, _ Module, dep ModuleProxy) bool {
 return OtherModulePointerProviderOrDefault(mctx, dep, CommonModuleInfoProvider).IsStubsModule
}

// Returns true if the dependency module belongs to any of the apexes.
var depIsApexModule exceptionHandleFunc = func(mctx ModuleContext, _ Module, dep ModuleProxy) bool {
 depContainersInfo, _ := getContainerModuleInfo(mctx, dep)
 return InList(ApexContainer, depContainersInfo.belongingContainers)
}

// Returns true if the module and the dependent module belongs to common apexes.
var belongsToCommonApexes exceptionHandleFunc = func(mctx ModuleContext, m Module, dep ModuleProxy) bool {
 mContainersInfo, _ := getContainerModuleInfo(mctx, m)
 depContainersInfo, _ := getContainerModuleInfo(mctx, dep)

 return HasIntersection(mContainersInfo.ApexNames(), depContainersInfo.ApexNames())
}

// Returns true when all apexes that the module belongs to are non updatable.
// For an apex module to be allowed to depend on a non-apex partition module,
// all apexes that the module belong to must be non updatable.
var belongsToNonUpdatableApex exceptionHandleFunc = func(mctx ModuleContext, m Module, _ ModuleProxy) bool {
 mContainersInfo, _ := getContainerModuleInfo(mctx, m)

 return !mContainersInfo.UpdatableApex()
}

// Returns true if the dependency is added via dependency tags that are not used to tag dynamic
// dependency tags.
var depIsNotDynamicDepTag exceptionHandleFunc = func(ctx ModuleContext, m Module, dep ModuleProxy) bool {
 mInstallable, _ := m.(InstallableModule)
 depTag := ctx.OtherModuleDependencyTag(dep)
 return !InList(depTag, mInstallable.DynamicDependencyTags())
}

// Returns true if the dependency is added via dependency tags that are not used to tag static
// or dynamic dependency tags. These dependencies do not affect the module in compile time or in
// runtime, thus are not significant enough to raise an error.
var depIsNotStaticOrDynamicDepTag exceptionHandleFunc = func(ctx ModuleContext, m Module, dep ModuleProxy) bool {
 mInstallable, _ := m.(InstallableModule)
 depTag := ctx.OtherModuleDependencyTag(dep)
 return !InList(depTag, append(mInstallable.StaticDependencyTags(), mInstallable.DynamicDependencyTags()...))
}

var globallyAllowlistedDependencies = []string{
 // Modules that provide annotations used within the platform and apexes.
 "aconfig-annotations-lib",
 "framework-annotations-lib",
 "unsupportedappusage",

 // TODO(b/363016634): Remove from the allowlist when the module is converted
 // to java_sdk_library and the java_aconfig_library modules depend on the stub.
 "aconfig_storage_stub",

 // framework-res provides core resources essential for building apps and system UI.
 // This module is implicitly added as a dependency for java modules even when the
 // dependency specifies sdk_version.
 "framework-res",

 // jacocoagent is implicitly added as a dependency in coverage builds, and is not installed
 // on the device.
 "jacocoagent",
}

// Returns true when the dependency is globally allowlisted for inter-container dependency
var depIsGloballyAllowlisted exceptionHandleFunc = func(_ ModuleContext, _ Module, dep ModuleProxy) bool {
 return InList(dep.Name(), globallyAllowlistedDependencies)
}

// Labels of exception functions, which are used to determine special dependencies that allow
// otherwise restricted inter-container dependencies
type exceptionHandleFuncLabel int

const (
 checkStubs exceptionHandleFuncLabel = iota
 checkApexModule
 checkInCommonApexes
 checkApexIsNonUpdatable
 checkNotDynamicDepTag
 checkNotStaticOrDynamicDepTag
 checkGlobalAllowlistedDep
)

// Map of [exceptionHandleFuncLabel] to the [exceptionHandleFunc]
var exceptionHandleFunctionsTable = map[exceptionHandleFuncLabel]exceptionHandleFunc{
 checkStubs:                    depIsStubsModule,
 checkApexModule:               depIsApexModule,
 checkInCommonApexes:           belongsToCommonApexes,
 checkApexIsNonUpdatable:       belongsToNonUpdatableApex,
 checkNotDynamicDepTag:         depIsNotDynamicDepTag,
 checkNotStaticOrDynamicDepTag: depIsNotStaticOrDynamicDepTag,
 checkGlobalAllowlistedDep:     depIsGloballyAllowlisted,
}

// ----------------------------------------------------------------------------
// Start of the definitions of container determination functions.
//
// Similar to the above section, below defines the functions used to determine
// the container of each modules.
// ----------------------------------------------------------------------------

type containerBoundaryFunc func(mctx ModuleContext) bool

var vendorContainerBoundaryFunc containerBoundaryFunc = func(mctx ModuleContext) bool {
 m, ok := mctx.Module().(ImageInterface)
 return mctx.Module().InstallInVendor() || (ok && m.VendorVariantNeeded(mctx))
}

var systemContainerBoundaryFunc containerBoundaryFunc = func(mctx ModuleContext) bool {
 module := mctx.Module()

 return !module.InstallInTestcases() &&
  !module.InstallInData() &&
  !module.InstallInRamdisk() &&
  !module.InstallInVendorRamdisk() &&
  !module.InstallInDebugRamdisk() &&
  !module.InstallInRecovery() &&
  !module.InstallInVendor() &&
  !module.InstallInOdm() &&
  !module.InstallInProduct() &&
  determineModuleKind(module.base(), mctx.blueprintBaseModuleContext()) == platformModule
}

var productContainerBoundaryFunc containerBoundaryFunc = func(mctx ModuleContext) bool {
 m, ok := mctx.Module().(ImageInterface)
 return mctx.Module().InstallInProduct() || (ok && m.ProductVariantNeeded(mctx))
}

var apexContainerBoundaryFunc containerBoundaryFunc = func(mctx ModuleContext) bool {
 // TODO(b/394955484): a module can't determine the apexes it belongs to any more
 return false
}

var ctsContainerBoundaryFunc containerBoundaryFunc = func(mctx ModuleContext) bool {
 props := mctx.Module().GetProperties()
 for _, prop := range props {
  val := reflect.ValueOf(prop).Elem()
  if val.Kind() == reflect.Struct {
   testSuites := val.FieldByName("Test_suites")
   if testSuites.IsValid() && testSuites.Kind() == reflect.Slice && slices.ContainsFunc(testSuites.Interface().([]string), func(s string) bool {
    return s == "cts" || strings.HasPrefix(s, "mts")
   }) {
    return true
   }
  }
 }
 return false
}

// @auto-generate: gob
type unstableInfo struct {
 // Determines if the module contains the private APIs of the platform.
 ContainsPlatformPrivateApis bool
}

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.VisitDirectDepsProxyWithTag(staticDepTag, func(dep ModuleProxy) {
    if commonInfo, ok := OtherModuleProvider(mctx, dep, CommonModuleInfoProvider); ok && commonInfo.UnstableInfo != nil {
     unstableModule = unstableModule || commonInfo.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,
 UnstableContainer: unstableContainerBoundaryFunc,
}

// ----------------------------------------------------------------------------
// End of the definitions of container determination functions.
// ----------------------------------------------------------------------------

type InstallableModule interface {
 StaticDependencyTags() []blueprint.DependencyTag
 DynamicDependencyTags() []blueprint.DependencyTag
}

// @auto-generate: gob
type restriction struct {
 // container of the dependency
 dependency *container

 // Error message to be emitted to the user when the dependency meets this restriction
 errorMessage string

 // List of labels of allowed exception functions that allows bypassing this restriction.
 // If any of the functions mapped to each labels returns true, this dependency would be
 // considered allowed and an error will not be thrown.
 allowedExceptions []exceptionHandleFuncLabel
}

// @auto-generate: gob
type container struct {
 // The name of the container i.e. partition, api domain
 name string

 // Map of dependency restricted containers.
 restricted []restriction
}

var (
 VendorContainer = &container{
  name:       VendorVariation,
  restricted: nil,
 }

 SystemContainer = &container{
  name: "system",
  restricted: []restriction{
   {
    dependency: VendorContainer,
    errorMessage: "Module belonging to the system partition other than HALs is " +
     "not allowed to depend on the vendor partition module, in order to support " +
     "independent development/update cycles and to support the Generic System " +
     "Image. Try depending on HALs, VNDK or AIDL instead.",
    allowedExceptions: []exceptionHandleFuncLabel{
     checkStubs,
     checkNotDynamicDepTag,
     checkGlobalAllowlistedDep,
    },
   },
  },
 }

 ProductContainer = &container{
  name: ProductVariation,
  restricted: []restriction{
   {
    dependency: VendorContainer,
    errorMessage: "Module belonging to the product partition is not allowed to " +
     "depend on the vendor partition module, as this may lead to security " +
     "vulnerabilities. Try depending on the HALs or utilize AIDL instead.",
    allowedExceptions: []exceptionHandleFuncLabel{
     checkStubs,
     checkNotDynamicDepTag,
     checkGlobalAllowlistedDep,
    },
   },
  },
 }

 ApexContainer = initializeApexContainer()

 CtsContainer = &container{
  name: "cts",
  restricted: []restriction{
   {
    dependency: UnstableContainer,
    errorMessage: "CTS/MTS 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,
     checkGlobalAllowlistedDep,
    },
   },
  },
 }

 // Container signifying that the module contains unstable platform private APIs
 UnstableContainer = &container{
  name:       "unstable",
  restricted: nil,
 }

 allContainers = []*container{
  VendorContainer,
  SystemContainer,
  ProductContainer,
  ApexContainer,
  CtsContainer,
  UnstableContainer,
 }
)

func initializeApexContainer() *container {
 apexContainer := &container{
  name: "apex",
  restricted: []restriction{
   {
    dependency: SystemContainer,
    errorMessage: "Module belonging to Apex(es) is not allowed to depend on the " +
     "modules belonging to the system partition. Either statically depend on the " +
     "module or convert the depending module to java_sdk_library and depend on " +
     "the stubs.",
    allowedExceptions: []exceptionHandleFuncLabel{
     checkStubs,
     checkApexModule,
     checkInCommonApexes,
     checkApexIsNonUpdatable,
     checkNotStaticOrDynamicDepTag,
     checkGlobalAllowlistedDep,
    },
   },
  },
 }

 apexContainer.restricted = append(apexContainer.restricted, restriction{
  dependency: apexContainer,
  errorMessage: "Module belonging to Apex(es) is not allowed to depend on the " +
   "modules belonging to other Apex(es). Either include the depending " +
   "module in the Apex or convert the depending module to java_sdk_library " +
   "and depend on its stubs.",
  allowedExceptions: []exceptionHandleFuncLabel{
   checkStubs,
   checkInCommonApexes,
   checkNotStaticOrDynamicDepTag,
   checkGlobalAllowlistedDep,
  },
 })

 return apexContainer
}

// @auto-generate: gob
type ContainersInfo struct {
 belongingContainers []*container

 belongingApexes []ApexInfo
}

func (c *ContainersInfo) BelongingContainers() []*container {
 return c.belongingContainers
}

func (c *ContainersInfo) ApexNames() (ret []string) {
 for _, apex := range c.belongingApexes {
  ret = append(ret, apex.BaseApexName)
 }
 slices.Sort(ret)
 return ret
}

// Returns true if any of the apex the module belongs to is updatable.
func (c *ContainersInfo) UpdatableApex() bool {
 for _, apex := range c.belongingApexes {
  if apex.Updatable {
   return true
  }
 }
 return false
}

var ContainersInfoProvider = blueprint.NewProvider[ContainersInfo]()

func satisfyAllowedExceptions(ctx ModuleContext, allowedExceptionLabels []exceptionHandleFuncLabel, m Module, dep ModuleProxy) bool {
 for _, label := range allowedExceptionLabels {
  if exceptionHandleFunctionsTable[label](ctx, m, dep) {
   return true
  }
 }
 return false
}

func (c *ContainersInfo) GetViolations(mctx ModuleContext, m Module, dep ModuleProxy, depInfo ContainersInfo) []string {
 var violations []string

 // Any containers that the module belongs to but the dependency does not belong to must be examined.
 _, containersUniqueToModule, _ := ListSetDifference(c.belongingContainers, depInfo.belongingContainers)

 // Apex container should be examined even if both the module and the dependency belong to
 // the apex container to check that the two modules belong to the same apex.
 if InList(ApexContainer, c.belongingContainers) && !InList(ApexContainer, containersUniqueToModule) {
  containersUniqueToModule = append(containersUniqueToModule, ApexContainer)
 }

 for _, containerUniqueToModule := range containersUniqueToModule {
  for _, restriction := range containerUniqueToModule.restricted {
   if InList(restriction.dependency, depInfo.belongingContainers) {
    if !satisfyAllowedExceptions(mctx, restriction.allowedExceptions, m, dep) {
     violations = append(violations, restriction.errorMessage)
    }
   }
  }
 }

 return violations
}

func generateContainerInfo(ctx ModuleContext) ContainersInfo {
 var containers []*container

 for _, cnt := range allContainers {
  if containerBoundaryFunctionsTable[cnt](ctx) {
   containers = append(containers, cnt)
  }
 }

 return ContainersInfo{
  belongingContainers: containers,
  // TODO(b/394955484): a module can't determine the apexes it belongs to any more
  belongingApexes: nil,
 }
}

func getContainerModuleInfo(ctx ModuleContext, module ModuleOrProxy) (ContainersInfo, bool) {
 var info *ContainersInfo
 if EqualModules(ctx.Module(), module) {
  info = ctx.getContainersInfo()
 } else {
  info = OtherModulePointerProviderOrDefault(ctx, module, CommonModuleInfoProvider).Containers
 }
 if info != nil {
  return *info, true
 }
 return ContainersInfo{}, false
}

func setContainerInfo(ctx ModuleContext) *unstableInfo {
 if _, ok := ctx.Module().(InstallableModule); ok {
  containersInfo := generateContainerInfo(ctx)
  ctx.setContainersInfo(&containersInfo)
 }

 // Required to determine the unstable container. This provider is set module.go instead of the
 // unstableContainerBoundaryFunc in order to prevent setting the provider multiple times.
 return &unstableInfo{
  ContainsPlatformPrivateApis: determineUnstableModule(ctx),
 }
}

func checkContainerViolations(ctx ModuleContext) {
 if _, ok := ctx.Module().(InstallableModule); ok {
  containersInfo, _ := getContainerModuleInfo(ctx, ctx.Module())
  ctx.VisitDirectDepsProxy(func(dep ModuleProxy) {
   if !OtherModuleProviderOrDefault(ctx, dep, CommonModuleInfoProvider).Enabled {
    return
   }

   // Pre-existing violating dependencies are tracked in containerDependencyViolationAllowlist.
   // If this dependency is allowlisted, do not check for violation.
   // If not, check if this dependency matches any restricted dependency and
   // satisfies any exception functions, which allows bypassing the
   // restriction. If all of the exceptions are not satisfied, throw an error.
   if depContainersInfo, ok := getContainerModuleInfo(ctx, dep); ok {
    if allowedViolations, ok := ContainerDependencyViolationAllowlist[ctx.ModuleName()]; ok && InList(dep.Name(), allowedViolations) {
     return
    } else {
     violations := containersInfo.GetViolations(ctx, ctx.Module(), dep, depContainersInfo)
     if len(violations) > 0 {
      errorMessage := fmt.Sprintf("%s cannot depend on %s. ", ctx.ModuleName(), dep.Name())
      errorMessage += strings.Join(violations, " ")
      ctx.ModuleErrorf(errorMessage)
     }
    }
   }
  })
 }
}

[Dauer der Verarbeitung: 0.22 Sekunden, vorverarbeitet 2026-06-28]