Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c14be38f authored by Jihoon Kang's avatar Jihoon Kang Committed by Gerrit Code Review
Browse files

Merge changes Ia693c4a5,I8e5620d2 into main

* changes:
  Revert^2 "Implement detecting container violations."
  Define additional container violations
parents f5a03c79 2a88491a
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -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 {
+65 −0
Original line number Diff line number Diff line
@@ -15,8 +15,10 @@
package android

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

	"github.com/google/blueprint"
)
@@ -395,6 +397,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

@@ -436,3 +472,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)
					}
				}
			}
		})
	}
}
+4 −0
Original line number Diff line number Diff line
@@ -870,6 +870,10 @@ var ContainerDependencyViolationAllowlist = map[string][]string{
		"net-utils-device-common-struct-base", // apex [com.android.tethering] -> system
	},

	"NfcNciApex": {
		"android.permission.flags-aconfig-java", // apex [com.android.nfcservices] -> apex [com.android.permission, test_com.android.permission]
	},

	"okhttp-norepackage": {
		"okhttp-android-util-log", // apex [com.android.adservices, com.android.devicelock, com.android.extservices] -> system
	},
+3 −0
Original line number Diff line number Diff line
@@ -1769,6 +1769,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")

+12 −0
Original line number Diff line number Diff line
@@ -74,6 +74,8 @@ func TestValidationAcrossContainersExportedPass(t *testing.T) {
					apex_available: [
						"myapex",
					],
					sdk_version: "none",
					system_modules: "none",
				}`,
		},
		{
@@ -122,6 +124,8 @@ func TestValidationAcrossContainersExportedPass(t *testing.T) {
					apex_available: [
						"myapex",
					],
					sdk_version: "none",
					system_modules: "none",
				}`,
		},
		{
@@ -345,6 +349,8 @@ func TestValidationAcrossContainersNotExportedFail(t *testing.T) {
					apex_available: [
						"myapex",
					],
					sdk_version: "none",
					system_modules: "none",
				}`,
			expectedError: `.*my_java_library_foo/myapex depends on my_java_aconfig_library_foo/otherapex/production across containers`,
		},
@@ -392,6 +398,8 @@ func TestValidationAcrossContainersNotExportedFail(t *testing.T) {
					apex_available: [
						"myapex",
					],
					sdk_version: "none",
					system_modules: "none",
				}`,
			expectedError: `.*my_android_app_foo/myapex depends on my_java_aconfig_library_foo/otherapex/production across containers`,
		},
@@ -693,6 +701,8 @@ func TestValidationAcrossContainersNotExportedFail(t *testing.T) {
					apex_available: [
						"myapex",
					],
					sdk_version: "none",
					system_modules: "none",
				}`,
			expectedError: `.*my_android_app_foo/myapex depends on my_java_aconfig_library_foo/otherapex/production across containers`,
		},
@@ -769,6 +779,8 @@ func TestValidationNotPropagateAcrossShared(t *testing.T) {
					apex_available: [
						"myapex",
					],
					sdk_version: "none",
					system_modules: "none",
				}`,
		},
	}
Loading