Frozen requirements can explain themselves.
Bug: 261198242
Test: aidl_test
Change-Id: I420a00f9bb92687e86c2aa73a2b8b19d2f0386b9
diff --git a/build/aidl_gen_rule.go b/build/aidl_gen_rule.go
index 472a93e..9e7c950 100644
--- a/build/aidl_gen_rule.go
+++ b/build/aidl_gen_rule.go
@@ -63,23 +63,24 @@
)
type aidlGenProperties struct {
- Srcs []string `android:"path"`
- AidlRoot string // base directory for the input aidl file
- Imports []string
- Headers []string
- Stability *string
- Min_sdk_version *string
- Platform_apis bool
- Lang string // target language [java|cpp|ndk|rust]
- BaseName string
- GenLog bool
- Version string
- GenRpc bool
- GenTrace bool
- Unstable *bool
- NotFrozen bool
- Visibility []string
- Flags []string
+ Srcs []string `android:"path"`
+ AidlRoot string // base directory for the input aidl file
+ Imports []string
+ Headers []string
+ Stability *string
+ Min_sdk_version *string
+ Platform_apis bool
+ Lang string // target language [java|cpp|ndk|rust]
+ BaseName string
+ GenLog bool
+ Version string
+ GenRpc bool
+ GenTrace bool
+ Unstable *bool
+ NotFrozen bool
+ RequireFrozenReason string
+ Visibility []string
+ Flags []string
}
type aidlGenRule struct {
diff --git a/build/aidl_interface.go b/build/aidl_interface.go
index e7076b0..de09e0a 100644
--- a/build/aidl_interface.go
+++ b/build/aidl_interface.go
@@ -105,8 +105,9 @@
// AidlVersionInfo keeps the *-source module for each (aidl_interface & lang) and the list of
// not-frozen versions (which shouldn't be used by other modules)
type AidlVersionInfo struct {
- notFrozen []string
- sourceMap map[string]string
+ notFrozen []string
+ requireFrozenReasons []string
+ sourceMap map[string]string
}
var AidlVersionInfoProvider = blueprint.NewMutatorProvider(AidlVersionInfo{}, "checkAidlGeneratedModules")
@@ -118,6 +119,7 @@
// {foo-V1-ndk-source, foo-V2-ndk-source}.
func (info *AidlVersionInfo) merge(other AidlVersionInfo) []string {
info.notFrozen = append(info.notFrozen, other.notFrozen...)
+ info.requireFrozenReasons = append(info.requireFrozenReasons, other.requireFrozenReasons...)
if other.sourceMap == nil {
return nil
@@ -137,14 +139,15 @@
return nil
}
-func reportUsingNotFrozenError(ctx android.BaseModuleContext, notFrozen []string) {
+func reportUsingNotFrozenError(ctx android.BaseModuleContext, notFrozen []string, requireFrozenReason []string) {
// TODO(b/154066686): Replace it with a common method instead of listing up module types.
// Test libraries are exempted.
if android.InList(ctx.ModuleType(), []string{"cc_test_library", "android_test", "cc_benchmark", "cc_test"}) {
return
}
- for _, name := range notFrozen {
- ctx.ModuleErrorf("%v is an unfrozen development version, and it can't be used because it is either explicitly disabled (with `frozen: false`) or this is a release branch and all interfaces without `owners: ...` specified must be frozen.", name)
+ for i, name := range notFrozen {
+ reason := requireFrozenReason[i]
+ ctx.ModuleErrorf("%v is an unfrozen development version, and it can't be used because %q", name, reason)
}
}
@@ -171,11 +174,14 @@
}
if gen, ok := mctx.Module().(*aidlGenRule); ok {
var notFrozen []string
+ var requireFrozenReasons []string
if gen.properties.NotFrozen {
notFrozen = []string{strings.TrimSuffix(mctx.ModuleName(), "-source")}
+ requireFrozenReasons = []string{gen.properties.RequireFrozenReason}
}
mctx.SetProvider(AidlVersionInfoProvider, AidlVersionInfo{
- notFrozen: notFrozen,
+ notFrozen: notFrozen,
+ requireFrozenReasons: requireFrozenReasons,
sourceMap: map[string]string{
gen.properties.BaseName + "-" + gen.properties.Lang: gen.Name(),
},
@@ -193,7 +199,7 @@
}
})
if !isAidlGeneratedModule(mctx.Module()) && len(info.notFrozen) > 0 {
- reportUsingNotFrozenError(mctx, info.notFrozen)
+ reportUsingNotFrozenError(mctx, info.notFrozen, info.requireFrozenReasons)
}
if mctx.Failed() {
return
@@ -846,6 +852,34 @@
})
}
+func (i *aidlInterface) checkRequireFrozenAndReason(mctx android.EarlyModuleContext) (bool, string) {
+ if proptools.Bool(i.properties.Unstable) {
+ return false, "it's an unstable interface"
+ }
+
+ if proptools.Bool(i.properties.Frozen) {
+ return true, "it's explicitly marked as `frozen: true`"
+ }
+
+ if i.Owner() == "" {
+ if !mctx.Config().DefaultAppTargetSdk(mctx).IsPreview() {
+ return true, "this is a release branch - freeze it or set 'owners:'"
+ } else if mctx.Config().IsEnvTrue("AIDL_FROZEN_REL") {
+ return true, "this is a release branch (simulated by setting AIDL_FROZEN_REL) - freeze it or set 'owners:'"
+ }
+ } else {
+ // has an OWNER
+ // REL branches don't enforce downstream interfaces or owned interfaces
+ // to be frozen. Instead, these interfaces are verified by other tests
+ // like vts_treble_vintf_vendor_test
+ if android.InList(i.Owner(), strings.Fields(mctx.Config().Getenv("AIDL_FROZEN_OWNERS"))) {
+ return true, "the owner field is in environment variable AIDL_FROZEN_OWNERS"
+ }
+ }
+
+ return false, "by default, we don't require the interface to be frozen"
+}
+
func aidlInterfaceHook(mctx android.DefaultableHookContext, i *aidlInterface) {
if hasVersionSuffix(i.ModuleBase.Name()) {
mctx.PropertyErrorf("name", "aidl_interface should not have '-V<number> suffix")
@@ -889,22 +923,11 @@
mctx.PropertyErrorf("owner", "aidl_interface in a soong_namespace must have the 'owner' property set.")
}
- sdkIsFinal := !mctx.Config().DefaultAppTargetSdk(mctx).IsPreview()
- requireFrozenNoOwner := i.Owner() == "" && (sdkIsFinal || mctx.Config().IsEnvTrue("AIDL_FROZEN_REL"))
- requireFrozenWithOwner := i.Owner() != "" && android.InList(i.Owner(), strings.Fields(mctx.Config().Getenv("AIDL_FROZEN_OWNERS")))
- requireFrozenByOwner := requireFrozenNoOwner || requireFrozenWithOwner
-
- // Two different types of 'unstable' here
- // - 'unstable: true' meaning the module is never stable
- // - current unfrozen ToT version
- //
- // OEM branches may remove 'i.Owner()' here to apply the check to all interfaces, in
- // addition to core platform interfaces. Otherwise, we rely on vts_treble_vintf_vendor_test.
- requireFrozenVersion := proptools.BoolDefault(i.properties.Frozen, false) || (!unstable && requireFrozenByOwner)
+ requireFrozenVersion, requireFrozenReason := i.checkRequireFrozenAndReason(mctx)
// surface error early, main check is via checkUnstableModuleMutator
if requireFrozenVersion && !i.hasVersion() {
- mctx.PropertyErrorf("versions", "must be set (need to be frozen) when \"unstable\" is false, PLATFORM_VERSION_CODENAME is REL, and \"owner\" property is missing.")
+ mctx.PropertyErrorf("versions", "must be set (need to be frozen) because: %q", requireFrozenReason)
}
vndkEnabled := proptools.Bool(i.properties.VndkProperties.Vndk.Enabled) ||
@@ -938,16 +961,16 @@
if !shouldGenerate {
continue
}
- libs = append(libs, addLibrary(mctx, i, nextVersion, lang, requireFrozenVersion))
+ libs = append(libs, addLibrary(mctx, i, nextVersion, lang, requireFrozenVersion, requireFrozenReason))
for _, version := range versions {
- libs = append(libs, addLibrary(mctx, i, version, lang, false))
+ libs = append(libs, addLibrary(mctx, i, version, lang, false, "this is a known frozen version"))
}
}
// In the future, we may want to force the -cpp backend to be on host,
// and limit its visibility, even if it's not created normally
if i.shouldGenerateCppBackend() && len(i.properties.Imports) == 0 {
- libs = append(libs, addLibrary(mctx, i, nextVersion, langCppAnalyzer, false))
+ libs = append(libs, addLibrary(mctx, i, nextVersion, langCppAnalyzer, false, "analysis always uses latest version even if frozen"))
}
if unstable {
diff --git a/build/aidl_interface_backends.go b/build/aidl_interface_backends.go
index 9c9e47e..71f8964 100644
--- a/build/aidl_interface_backends.go
+++ b/build/aidl_interface_backends.go
@@ -27,21 +27,21 @@
"github.com/google/blueprint/proptools"
)
-func addLibrary(mctx android.DefaultableHookContext, i *aidlInterface, version string, lang string, notFrozen bool) string {
+func addLibrary(mctx android.DefaultableHookContext, i *aidlInterface, version string, lang string, notFrozen bool, requireFrozenReason string) string {
if lang == langJava {
- return addJavaLibrary(mctx, i, version, notFrozen)
+ return addJavaLibrary(mctx, i, version, notFrozen, requireFrozenReason)
} else if lang == langRust {
- return addRustLibrary(mctx, i, version, notFrozen)
+ return addRustLibrary(mctx, i, version, notFrozen, requireFrozenReason)
} else if lang == langCppAnalyzer {
- return addCppAnalyzerLibrary(mctx, i, version, notFrozen)
+ return addCppAnalyzerLibrary(mctx, i, version, notFrozen, requireFrozenReason)
} else if lang == langCpp || lang == langNdk || lang == langNdkPlatform {
- return addCppLibrary(mctx, i, version, lang, notFrozen)
+ return addCppLibrary(mctx, i, version, lang, notFrozen, requireFrozenReason)
} else {
panic(fmt.Errorf("unsupported language backend %q\n", lang))
}
}
-func addCppLibrary(mctx android.DefaultableHookContext, i *aidlInterface, version string, lang string, notFrozen bool) string {
+func addCppLibrary(mctx android.DefaultableHookContext, i *aidlInterface, version string, lang string, notFrozen bool, requireFrozenReason string) string {
cppSourceGen := i.versionedName(version) + "-" + lang + "-source"
cppModuleGen := i.versionedName(version) + "-" + lang
@@ -79,20 +79,21 @@
mctx.CreateModule(aidlGenFactory, &nameProperties{
Name: proptools.StringPtr(cppSourceGen),
}, &aidlGenProperties{
- Srcs: srcs,
- AidlRoot: aidlRoot,
- Imports: i.getImportsForVersion(version),
- Headers: i.properties.Headers,
- Stability: i.properties.Stability,
- Min_sdk_version: i.minSdkVersion(lang),
- Lang: lang,
- BaseName: i.ModuleBase.Name(),
- GenLog: genLog,
- Version: i.versionForInitVersionCompat(version),
- GenTrace: genTrace,
- Unstable: i.properties.Unstable,
- NotFrozen: notFrozen,
- Flags: i.flagsForAidlGenRule(version),
+ Srcs: srcs,
+ AidlRoot: aidlRoot,
+ Imports: i.getImportsForVersion(version),
+ Headers: i.properties.Headers,
+ Stability: i.properties.Stability,
+ Min_sdk_version: i.minSdkVersion(lang),
+ Lang: lang,
+ BaseName: i.ModuleBase.Name(),
+ GenLog: genLog,
+ Version: i.versionForInitVersionCompat(version),
+ GenTrace: genTrace,
+ Unstable: i.properties.Unstable,
+ NotFrozen: notFrozen,
+ RequireFrozenReason: requireFrozenReason,
+ Flags: i.flagsForAidlGenRule(version),
})
importExportDependencies := []string{}
@@ -220,7 +221,7 @@
return cppModuleGen
}
-func addCppAnalyzerLibrary(mctx android.DefaultableHookContext, i *aidlInterface, version string, notFrozen bool) string {
+func addCppAnalyzerLibrary(mctx android.DefaultableHookContext, i *aidlInterface, version string, notFrozen bool, requireFrozenReason string) string {
cppAnalyzerSourceGen := i.versionedName("") + "-cpp-analyzer-source"
cppAnalyzerModuleGen := i.versionedName("") + "-cpp-analyzer"
@@ -232,17 +233,18 @@
mctx.CreateModule(aidlGenFactory, &nameProperties{
Name: proptools.StringPtr(cppAnalyzerSourceGen),
}, &aidlGenProperties{
- Srcs: srcs,
- AidlRoot: aidlRoot,
- Imports: i.getImportsForVersion(version),
- Stability: i.properties.Stability,
- Min_sdk_version: i.minSdkVersion(langCpp),
- Lang: langCppAnalyzer,
- BaseName: i.ModuleBase.Name(),
- Version: i.versionForInitVersionCompat(version),
- Unstable: i.properties.Unstable,
- NotFrozen: notFrozen,
- Flags: i.flagsForAidlGenRule(version),
+ Srcs: srcs,
+ AidlRoot: aidlRoot,
+ Imports: i.getImportsForVersion(version),
+ Stability: i.properties.Stability,
+ Min_sdk_version: i.minSdkVersion(langCpp),
+ Lang: langCppAnalyzer,
+ BaseName: i.ModuleBase.Name(),
+ Version: i.versionForInitVersionCompat(version),
+ Unstable: i.properties.Unstable,
+ NotFrozen: notFrozen,
+ RequireFrozenReason: requireFrozenReason,
+ Flags: i.flagsForAidlGenRule(version),
})
importExportDependencies := []string{}
@@ -306,7 +308,7 @@
return cppAnalyzerModuleGen
}
-func addJavaLibrary(mctx android.DefaultableHookContext, i *aidlInterface, version string, notFrozen bool) string {
+func addJavaLibrary(mctx android.DefaultableHookContext, i *aidlInterface, version string, notFrozen bool, requireFrozenReason string) string {
javaSourceGen := i.versionedName(version) + "-java-source"
javaModuleGen := i.versionedName(version) + "-java"
srcs, aidlRoot := i.srcsForVersion(mctx, version)
@@ -330,21 +332,22 @@
mctx.CreateModule(aidlGenFactory, &nameProperties{
Name: proptools.StringPtr(javaSourceGen),
}, &aidlGenProperties{
- Srcs: srcs,
- AidlRoot: aidlRoot,
- Imports: i.getImportsForVersion(version),
- Headers: i.properties.Headers,
- Stability: i.properties.Stability,
- Min_sdk_version: minSdkVersion,
- Platform_apis: proptools.Bool(i.properties.Backend.Java.Platform_apis),
- Lang: langJava,
- BaseName: i.ModuleBase.Name(),
- Version: version,
- GenRpc: proptools.Bool(i.properties.Backend.Java.Gen_rpc),
- GenTrace: i.genTrace(langJava),
- Unstable: i.properties.Unstable,
- NotFrozen: notFrozen,
- Flags: i.flagsForAidlGenRule(version),
+ Srcs: srcs,
+ AidlRoot: aidlRoot,
+ Imports: i.getImportsForVersion(version),
+ Headers: i.properties.Headers,
+ Stability: i.properties.Stability,
+ Min_sdk_version: minSdkVersion,
+ Platform_apis: proptools.Bool(i.properties.Backend.Java.Platform_apis),
+ Lang: langJava,
+ BaseName: i.ModuleBase.Name(),
+ Version: version,
+ GenRpc: proptools.Bool(i.properties.Backend.Java.Gen_rpc),
+ GenTrace: i.genTrace(langJava),
+ Unstable: i.properties.Unstable,
+ NotFrozen: notFrozen,
+ RequireFrozenReason: requireFrozenReason,
+ Flags: i.flagsForAidlGenRule(version),
})
mctx.CreateModule(aidlImplementationGeneratorFactory, &nameProperties{
@@ -382,7 +385,7 @@
return javaModuleGen
}
-func addRustLibrary(mctx android.DefaultableHookContext, i *aidlInterface, version string, notFrozen bool) string {
+func addRustLibrary(mctx android.DefaultableHookContext, i *aidlInterface, version string, notFrozen bool, requireFrozenReason string) string {
rustSourceGen := i.versionedName(version) + "-rust-source"
rustModuleGen := i.versionedName(version) + "-rust"
srcs, aidlRoot := i.srcsForVersion(mctx, version)
@@ -396,18 +399,19 @@
mctx.CreateModule(aidlGenFactory, &nameProperties{
Name: proptools.StringPtr(rustSourceGen),
}, &aidlGenProperties{
- Srcs: srcs,
- AidlRoot: aidlRoot,
- Imports: i.getImportsForVersion(version),
- Headers: i.properties.Headers,
- Stability: i.properties.Stability,
- Min_sdk_version: i.minSdkVersion(langRust),
- Lang: langRust,
- BaseName: i.ModuleBase.Name(),
- Version: i.versionForInitVersionCompat(version),
- Unstable: i.properties.Unstable,
- NotFrozen: notFrozen,
- Flags: i.flagsForAidlGenRule(version),
+ Srcs: srcs,
+ AidlRoot: aidlRoot,
+ Imports: i.getImportsForVersion(version),
+ Headers: i.properties.Headers,
+ Stability: i.properties.Stability,
+ Min_sdk_version: i.minSdkVersion(langRust),
+ Lang: langRust,
+ BaseName: i.ModuleBase.Name(),
+ Version: i.versionForInitVersionCompat(version),
+ Unstable: i.properties.Unstable,
+ NotFrozen: notFrozen,
+ RequireFrozenReason: requireFrozenReason,
+ Flags: i.flagsForAidlGenRule(version),
})
versionedRustName := fixRustName(i.versionedName(version))
diff --git a/build/aidl_test.go b/build/aidl_test.go
index b6f88ad..198cfb5 100644
--- a/build/aidl_test.go
+++ b/build/aidl_test.go
@@ -262,7 +262,7 @@
},
},
}`
- expectedError := `module "foo_interface": versions: must be set \(need to be frozen\) when "unstable" is false, PLATFORM_VERSION_CODENAME is REL, and "owner" property is missing.`
+ expectedError := `module "foo_interface": versions: must be set \(need to be frozen\) because`
testAidlError(t, expectedError, vintfWithoutVersionBp, setReleaseEnv())
testAidlError(t, expectedError, vintfWithoutVersionBp, setTestFreezeEnv())
@@ -291,9 +291,10 @@
"aidl_api/foo/1/.hash": nil,
})
- expectedError := `foo-V2-java is an unfrozen development version`
- testAidlError(t, expectedError, unstableVersionUsageInJavaBp, setReleaseEnv(), files)
- testAidlError(t, expectedError, unstableVersionUsageInJavaBp, setTestFreezeEnv(), files)
+ expectedError1 := `foo-V2-java is an unfrozen development version, and it can't be used because "this is a release branch - freeze it or set 'owners:'"`
+ testAidlError(t, expectedError1, unstableVersionUsageInJavaBp, setReleaseEnv(), files)
+ expectedError2 := `foo-V2-java is an unfrozen development version, and it can't be used because "this is a release branch \(simulated by setting AIDL_FROZEN_REL\) - freeze it or set 'owners:'"`
+ testAidlError(t, expectedError2, unstableVersionUsageInJavaBp, setTestFreezeEnv(), files)
testAidl(t, unstableVersionUsageInJavaBp, files)
// A stable version can be used in release version
@@ -486,7 +487,7 @@
"aidl_api/xxx/1/.hash": nil,
})
- expectedError := `versions: must be set \(need to be frozen\) when`
+ expectedError := `versions: must be set \(need to be frozen\) because`
testAidlError(t, expectedError, frozenTest, files, setReleaseEnv())
testAidlError(t, expectedError, frozenTest, files, setTestFreezeEnv())
@@ -685,7 +686,7 @@
libs: ["foo-V1-java"],
}`
- expectedError := `"foo_interface": versions: must be set \(need to be frozen\) when "unstable" is false, PLATFORM_VERSION_CODENAME is REL, and "owner" property is missing.`
+ expectedError := `"foo_interface": versions: must be set \(need to be frozen\) because`
testAidlError(t, expectedError, nonVersionedModuleUsageInJavaBp, setReleaseEnv())
testAidlError(t, expectedError, nonVersionedModuleUsageInJavaBp, setTestFreezeEnv())
testAidl(t, nonVersionedModuleUsageInJavaBp)
@@ -724,7 +725,7 @@
libs: ["foo-V1-java"],
}`
- expectedError := `"foo_interface": versions: must be set \(need to be frozen\) when "unstable" is false, PLATFORM_VERSION_CODENAME is REL, and "owner" property is missing.`
+ expectedError := `"foo_interface": versions: must be set \(need to be frozen\) because`
testAidl(t, nonVersionedModuleUsageInJavaBp, setReleaseEnv())
testAidlError(t, expectedError, nonVersionedModuleUsageInJavaBp, setTestFreezeEnv())
testAidl(t, nonVersionedModuleUsageInJavaBp)