summaryrefslogtreecommitdiff
path: root/android
diff options
context:
space:
mode:
author Jihoon Kang <jihoonkang@google.com> 2024-08-30 20:18:53 +0000
committer Gerrit Code Review <noreply-gerritcodereview@google.com> 2024-08-30 20:18:53 +0000
commit7344482ff3e38659519ca63ebc9b3f78ce6d4d8e (patch)
treeb78ed3eef62c71b43172a5f58307e4f32fc449eb /android
parentc540beef74e30cf30a4a1cc3f250b2ddbe45ad42 (diff)
parent85bc19380567dfee327f04162587633673e3dcf7 (diff)
Merge "Revert^4 "Implement detecting container violations."" into main
Diffstat (limited to 'android')
-rw-r--r--android/apex.go12
-rw-r--r--android/container.go65
-rw-r--r--android/module.go3
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")