diff options
author | 2024-08-30 20:18:53 +0000 | |
---|---|---|
committer | 2024-08-30 20:18:53 +0000 | |
commit | 7344482ff3e38659519ca63ebc9b3f78ce6d4d8e (patch) | |
tree | b78ed3eef62c71b43172a5f58307e4f32fc449eb /android | |
parent | c540beef74e30cf30a4a1cc3f250b2ddbe45ad42 (diff) | |
parent | 85bc19380567dfee327f04162587633673e3dcf7 (diff) |
Merge "Revert^4 "Implement detecting container violations."" into main
Diffstat (limited to 'android')
-rw-r--r-- | android/apex.go | 12 | ||||
-rw-r--r-- | android/container.go | 65 | ||||
-rw-r--r-- | android/module.go | 3 |
3 files changed, 80 insertions, 0 deletions
diff --git a/android/apex.go b/android/apex.go index 79ee0a8f8..b19c47795 100644 --- a/android/apex.go +++ b/android/apex.go @@ -16,6 +16,7 @@ package android import ( "fmt" + "reflect" "slices" "sort" "strconv" @@ -145,6 +146,17 @@ func (i ApexInfo) InApexModule(apexModuleName string) bool { return false } +// To satisfy the comparable interface +func (i ApexInfo) Equal(other any) bool { + otherApexInfo, ok := other.(ApexInfo) + return ok && i.ApexVariationName == otherApexInfo.ApexVariationName && + i.MinSdkVersion == otherApexInfo.MinSdkVersion && + i.Updatable == otherApexInfo.Updatable && + i.UsePlatformApis == otherApexInfo.UsePlatformApis && + reflect.DeepEqual(i.InApexVariants, otherApexInfo.InApexVariants) && + reflect.DeepEqual(i.InApexModules, otherApexInfo.InApexModules) +} + // ApexTestForInfo stores the contents of APEXes for which this module is a test - although this // module is not part of the APEX - and thus has access to APEX internals. type ApexTestForInfo struct { diff --git a/android/container.go b/android/container.go index 722b241c1..c048d6c73 100644 --- a/android/container.go +++ b/android/container.go @@ -15,8 +15,10 @@ package android import ( + "fmt" "reflect" "slices" + "strings" "github.com/google/blueprint" ) @@ -398,6 +400,40 @@ func (c *ContainersInfo) UpdatableApex() bool { var ContainersInfoProvider = blueprint.NewProvider[ContainersInfo]() +func satisfyAllowedExceptions(ctx ModuleContext, allowedExceptionLabels []exceptionHandleFuncLabel, m, dep Module) bool { + for _, label := range allowedExceptionLabels { + if exceptionHandleFunctionsTable[label](ctx, m, dep) { + return true + } + } + return false +} + +func (c *ContainersInfo) GetViolations(mctx ModuleContext, m, dep Module, 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 @@ -439,3 +475,32 @@ func setContainerInfo(ctx ModuleContext) { SetProvider(ctx, ContainersInfoProvider, containersInfo) } } + +func checkContainerViolations(ctx ModuleContext) { + if _, ok := ctx.Module().(InstallableModule); ok { + containersInfo, _ := getContainerModuleInfo(ctx, ctx.Module()) + ctx.VisitDirectDepsIgnoreBlueprint(func(dep Module) { + if !dep.Enabled(ctx) { + 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) + } + } + } + }) + } +} diff --git a/android/module.go b/android/module.go index 9f73729fb..7ce4e0535 100644 --- a/android/module.go +++ b/android/module.go @@ -1755,6 +1755,9 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext) } setContainerInfo(ctx) + if ctx.Config().Getenv("DISABLE_CONTAINER_CHECK") != "true" { + checkContainerViolations(ctx) + } ctx.licenseMetadataFile = PathForModuleOut(ctx, "meta_lic") |