Rename device_config --> aconfig and definitions --> declarations

Bug: 285303012
Test: for x in next trunk trunk_food trunk_staging ; do lunch aosp_panther-$x-eng ; m nothing ; done
Change-Id: I3375f46b3ecbbc516d1bee6ab3f80725fcccde8f
diff --git a/aconfig/Android.bp b/aconfig/Android.bp
new file mode 100644
index 0000000..d19b543
--- /dev/null
+++ b/aconfig/Android.bp
@@ -0,0 +1,32 @@
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+bootstrap_go_package {
+    name: "soong-aconfig",
+    pkgPath: "android/soong/aconfig",
+    deps: [
+        "blueprint",
+        "blueprint-pathtools",
+        "sbox_proto",
+        "soong",
+        "soong-android",
+        "soong-bazel",
+        "soong-android",
+        "soong-java",
+    ],
+    srcs: [
+        "aconfig_declarations.go",
+        "aconfig_values.go",
+        "aconfig_value_set.go",
+        "init.go",
+        "java_aconfig_library.go",
+        "testing.go",
+    ],
+    testSrcs: [
+        "aconfig_declarations_test.go",
+        "aconfig_values_test.go",
+        "aconfig_value_set_test.go",
+    ],
+    pluginFor: ["soong_build"],
+}
diff --git a/aconfig/aconfig_declarations.go b/aconfig/aconfig_declarations.go
new file mode 100644
index 0000000..007d529
--- /dev/null
+++ b/aconfig/aconfig_declarations.go
@@ -0,0 +1,143 @@
+// Copyright 2023 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 aconfig
+
+import (
+	"android/soong/android"
+	"fmt"
+	"github.com/google/blueprint"
+	"strings"
+)
+
+type DeclarationsModule struct {
+	android.ModuleBase
+	android.DefaultableModuleBase
+
+	// Properties for "aconfig_declarations"
+	properties struct {
+		// aconfig files, relative to this Android.bp file
+		Srcs []string `android:"path"`
+
+		// Release config flag package
+		Package string
+
+		// Values from TARGET_RELEASE / RELEASE_ACONFIG_VALUE_SETS
+		Values []string `blueprint:"mutated"`
+	}
+
+	intermediatePath android.WritablePath
+}
+
+func DeclarationsFactory() android.Module {
+	module := &DeclarationsModule{}
+
+	android.InitAndroidModule(module)
+	android.InitDefaultableModule(module)
+	module.AddProperties(&module.properties)
+	// TODO: bp2build
+	//android.InitBazelModule(module)
+
+	return module
+}
+
+type implicitValuesTagType struct {
+	blueprint.BaseDependencyTag
+}
+
+var implicitValuesTag = implicitValuesTagType{}
+
+func (module *DeclarationsModule) DepsMutator(ctx android.BottomUpMutatorContext) {
+	// Validate Properties
+	if len(module.properties.Srcs) == 0 {
+		ctx.PropertyErrorf("srcs", "missing source files")
+		return
+	}
+	if len(module.properties.Package) == 0 {
+		ctx.PropertyErrorf("package", "missing package property")
+	}
+
+	// Add a dependency on the aconfig_value_sets defined in
+	// RELEASE_ACONFIG_VALUE_SETS, and add any aconfig_values that
+	// match our package.
+	valuesFromConfig := ctx.Config().ReleaseAconfigValueSets()
+	ctx.AddDependency(ctx.Module(), implicitValuesTag, valuesFromConfig...)
+}
+
+func (module *DeclarationsModule) OutputFiles(tag string) (android.Paths, error) {
+	switch tag {
+	case "":
+		// The default output of this module is the intermediates format, which is
+		// not installable and in a private format that no other rules can handle
+		// correctly.
+		return []android.Path{module.intermediatePath}, nil
+	default:
+		return nil, fmt.Errorf("unsupported aconfig_declarations module reference tag %q", tag)
+	}
+}
+
+func joinAndPrefix(prefix string, values []string) string {
+	var sb strings.Builder
+	for _, v := range values {
+		sb.WriteString(prefix)
+		sb.WriteString(v)
+	}
+	return sb.String()
+}
+
+// Provider published by aconfig_value_set
+type declarationsProviderData struct {
+	Package          string
+	IntermediatePath android.WritablePath
+}
+
+var declarationsProviderKey = blueprint.NewProvider(declarationsProviderData{})
+
+func (module *DeclarationsModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+	// Get the values that came from the global RELEASE_ACONFIG_VALUE_SETS flag
+	ctx.VisitDirectDeps(func(dep android.Module) {
+		if !ctx.OtherModuleHasProvider(dep, valueSetProviderKey) {
+			// Other modules get injected as dependencies too, for example the license modules
+			return
+		}
+		depData := ctx.OtherModuleProvider(dep, valueSetProviderKey).(valueSetProviderData)
+		valuesFiles, ok := depData.AvailablePackages[module.properties.Package]
+		if ok {
+			for _, path := range valuesFiles {
+				module.properties.Values = append(module.properties.Values, path.String())
+			}
+		}
+	})
+
+	// Intermediate format
+	inputFiles := android.PathsForModuleSrc(ctx, module.properties.Srcs)
+	intermediatePath := android.PathForModuleOut(ctx, "intermediate.pb")
+	ctx.Build(pctx, android.BuildParams{
+		Rule:        aconfigRule,
+		Inputs:      inputFiles,
+		Output:      intermediatePath,
+		Description: "aconfig_declarations",
+		Args: map[string]string{
+			"release_version": ctx.Config().ReleaseVersion(),
+			"package":         module.properties.Package,
+			"values":          joinAndPrefix(" --values ", module.properties.Values),
+		},
+	})
+
+	ctx.SetProvider(declarationsProviderKey, declarationsProviderData{
+		Package:          module.properties.Package,
+		IntermediatePath: intermediatePath,
+	})
+
+}
diff --git a/aconfig/aconfig_declarations_test.go b/aconfig/aconfig_declarations_test.go
new file mode 100644
index 0000000..e14ca38
--- /dev/null
+++ b/aconfig/aconfig_declarations_test.go
@@ -0,0 +1,42 @@
+// Copyright 2018 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 aconfig
+
+import (
+	"strings"
+	"testing"
+
+	"android/soong/android"
+)
+
+func TestAconfigDeclarations(t *testing.T) {
+	bp := `
+		aconfig_declarations {
+			name: "module_name",
+			package: "com.example.package",
+			srcs: ["foo.aconfig"],
+		}
+	`
+	result := runTest(t, android.FixtureExpectsNoErrors, bp)
+
+	module := result.ModuleForTests("module_name", "").Module().(*DeclarationsModule)
+
+	// Check that the provider has the right contents
+	depData := result.ModuleProvider(module, declarationsProviderKey).(declarationsProviderData)
+	android.AssertStringEquals(t, "package", depData.Package, "com.example.package")
+	if !strings.HasSuffix(depData.IntermediatePath.String(), "/intermediate.pb") {
+		t.Errorf("Missing intermediates path in provider: %s", depData.IntermediatePath.String())
+	}
+}
diff --git a/aconfig/aconfig_value_set.go b/aconfig/aconfig_value_set.go
new file mode 100644
index 0000000..252908f
--- /dev/null
+++ b/aconfig/aconfig_value_set.go
@@ -0,0 +1,92 @@
+// Copyright 2023 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 aconfig
+
+import (
+	"android/soong/android"
+	"github.com/google/blueprint"
+)
+
+// Properties for "aconfig_value_set"
+type ValueSetModule struct {
+	android.ModuleBase
+	android.DefaultableModuleBase
+
+	properties struct {
+		// aconfig_values modules
+		Values []string
+	}
+}
+
+func ValueSetFactory() android.Module {
+	module := &ValueSetModule{}
+
+	android.InitAndroidModule(module)
+	android.InitDefaultableModule(module)
+	module.AddProperties(&module.properties)
+	// TODO: bp2build
+	//android.InitBazelModule(module)
+
+	return module
+}
+
+// Dependency tag for values property
+type valueSetType struct {
+	blueprint.BaseDependencyTag
+}
+
+var valueSetTag = valueSetType{}
+
+// Provider published by aconfig_value_set
+type valueSetProviderData struct {
+	// The package of each of the
+	// (map of package --> aconfig_module)
+	AvailablePackages map[string]android.Paths
+}
+
+var valueSetProviderKey = blueprint.NewProvider(valueSetProviderData{})
+
+func (module *ValueSetModule) DepsMutator(ctx android.BottomUpMutatorContext) {
+	deps := ctx.AddDependency(ctx.Module(), valueSetTag, module.properties.Values...)
+	for _, dep := range deps {
+		_, ok := dep.(*ValuesModule)
+		if !ok {
+			ctx.PropertyErrorf("values", "values must be a aconfig_values module")
+			return
+		}
+	}
+}
+
+func (module *ValueSetModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+	// Accumulate the packages of the values modules listed, and set that as an
+	// valueSetProviderKey provider that aconfig modules can read and use
+	// to append values to their aconfig actions.
+	packages := make(map[string]android.Paths)
+	ctx.VisitDirectDeps(func(dep android.Module) {
+		if !ctx.OtherModuleHasProvider(dep, valuesProviderKey) {
+			// Other modules get injected as dependencies too, for example the license modules
+			return
+		}
+		depData := ctx.OtherModuleProvider(dep, valuesProviderKey).(valuesProviderData)
+
+		srcs := make([]android.Path, len(depData.Values))
+		copy(srcs, depData.Values)
+		packages[depData.Package] = srcs
+
+	})
+	ctx.SetProvider(valueSetProviderKey, valueSetProviderData{
+		AvailablePackages: packages,
+	})
+}
diff --git a/aconfig/aconfig_value_set_test.go b/aconfig/aconfig_value_set_test.go
new file mode 100644
index 0000000..9127872
--- /dev/null
+++ b/aconfig/aconfig_value_set_test.go
@@ -0,0 +1,43 @@
+// Copyright 2018 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 aconfig
+
+import (
+	"testing"
+
+	"android/soong/android"
+)
+
+func TestAconfigValueSet(t *testing.T) {
+	bp := `
+				aconfig_values {
+					name: "one",
+					srcs: [ "blah.aconfig_values" ],
+					package: "foo.package"
+				}
+
+				aconfig_value_set {
+					name: "module_name",
+          values: [ "one" ],
+				}
+			`
+	result := runTest(t, android.FixtureExpectsNoErrors, bp)
+
+	module := result.ModuleForTests("module_name", "").Module().(*ValueSetModule)
+
+	// Check that the provider has the right contents
+	depData := result.ModuleProvider(module, valueSetProviderKey).(valueSetProviderData)
+	android.AssertStringEquals(t, "AvailablePackages", "blah.aconfig_values", depData.AvailablePackages["foo.package"][0].String())
+}
diff --git a/aconfig/aconfig_values.go b/aconfig/aconfig_values.go
new file mode 100644
index 0000000..91f1c90
--- /dev/null
+++ b/aconfig/aconfig_values.go
@@ -0,0 +1,70 @@
+// Copyright 2023 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 aconfig
+
+import (
+	"android/soong/android"
+	"github.com/google/blueprint"
+)
+
+// Properties for "aconfig_value"
+type ValuesModule struct {
+	android.ModuleBase
+	android.DefaultableModuleBase
+
+	properties struct {
+		// aconfig files, relative to this Android.bp file
+		Srcs []string `android:"path"`
+
+		// Release config flag package
+		Package string
+	}
+}
+
+func ValuesFactory() android.Module {
+	module := &ValuesModule{}
+
+	android.InitAndroidModule(module)
+	android.InitDefaultableModule(module)
+	module.AddProperties(&module.properties)
+	// TODO: bp2build
+	//android.InitBazelModule(module)
+
+	return module
+}
+
+// Provider published by aconfig_value_set
+type valuesProviderData struct {
+	// The package that this values module values
+	Package string
+
+	// The values aconfig files, relative to the root of the tree
+	Values android.Paths
+}
+
+var valuesProviderKey = blueprint.NewProvider(valuesProviderData{})
+
+func (module *ValuesModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+	if len(module.properties.Package) == 0 {
+		ctx.PropertyErrorf("package", "missing package property")
+	}
+
+	// Provide the our source files list to the aconfig_value_set as a list of files
+	providerData := valuesProviderData{
+		Package: module.properties.Package,
+		Values:  android.PathsForModuleSrc(ctx, module.properties.Srcs),
+	}
+	ctx.SetProvider(valuesProviderKey, providerData)
+}
diff --git a/aconfig/aconfig_values_test.go b/aconfig/aconfig_values_test.go
new file mode 100644
index 0000000..ab457f0
--- /dev/null
+++ b/aconfig/aconfig_values_test.go
@@ -0,0 +1,39 @@
+// Copyright 2018 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 aconfig
+
+import (
+	"testing"
+
+	"android/soong/android"
+)
+
+func TestAconfigValues(t *testing.T) {
+	bp := `
+				aconfig_values {
+					name: "module_name",
+					srcs: [ "blah.aconfig_values" ],
+					package: "foo.package"
+				}
+			`
+	result := runTest(t, android.FixtureExpectsNoErrors, bp)
+
+	module := result.ModuleForTests("module_name", "").Module().(*ValuesModule)
+
+	// Check that the provider has the right contents
+	depData := result.ModuleProvider(module, valuesProviderKey).(valuesProviderData)
+	android.AssertStringEquals(t, "package", "foo.package", depData.Package)
+	android.AssertPathsEndWith(t, "srcs", []string{"blah.aconfig_values"}, depData.Values)
+}
diff --git a/aconfig/init.go b/aconfig/init.go
new file mode 100644
index 0000000..6b433c9
--- /dev/null
+++ b/aconfig/init.go
@@ -0,0 +1,70 @@
+// Copyright 2023 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 aconfig
+
+import (
+	"android/soong/android"
+	"github.com/google/blueprint"
+)
+
+var (
+	pctx = android.NewPackageContext("android/soong/aconfig")
+
+	// For aconfig_declarations: Generate cache file
+	aconfigRule = pctx.AndroidStaticRule("aconfig",
+		blueprint.RuleParams{
+			Command: `${aconfig} create-cache` +
+				` --package ${package}` +
+				` --declarations ${in}` +
+				` ${values}` +
+				` --cache ${out}.tmp` +
+				` && ( if cmp -s ${out}.tmp ; then rm ${out}.tmp ; else mv ${out}.tmp ${out} ; fi )`,
+			//				` --build-id ${release_version}` +
+			CommandDeps: []string{
+				"${aconfig}",
+			},
+			Restat: true,
+		}, "release_version", "package", "values")
+
+	// For java_aconfig_library: Generate java file
+	srcJarRule = pctx.AndroidStaticRule("aconfig_srcjar",
+		blueprint.RuleParams{
+			Command: `rm -rf ${out}.tmp` +
+				` && mkdir -p ${out}.tmp` +
+				` && ${aconfig} create-java-lib` +
+				`    --cache ${in}` +
+				`    --out ${out}.tmp` +
+				` && $soong_zip -write_if_changed -jar -o ${out} -C ${out}.tmp -D ${out}.tmp` +
+				` && rm -rf ${out}.tmp`,
+			CommandDeps: []string{
+				"$aconfig",
+				"$soong_zip",
+			},
+			Restat: true,
+		})
+)
+
+func init() {
+	registerBuildComponents(android.InitRegistrationContext)
+	pctx.HostBinToolVariable("aconfig", "aconfig")
+	pctx.HostBinToolVariable("soong_zip", "soong_zip")
+}
+
+func registerBuildComponents(ctx android.RegistrationContext) {
+	ctx.RegisterModuleType("aconfig_declarations", DeclarationsFactory)
+	ctx.RegisterModuleType("aconfig_values", ValuesFactory)
+	ctx.RegisterModuleType("aconfig_value_set", ValueSetFactory)
+	ctx.RegisterModuleType("java_aconfig_library", JavaDeclarationsLibraryFactory)
+}
diff --git a/aconfig/java_aconfig_library.go b/aconfig/java_aconfig_library.go
new file mode 100644
index 0000000..0eeb14f
--- /dev/null
+++ b/aconfig/java_aconfig_library.go
@@ -0,0 +1,71 @@
+// Copyright 2023 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 aconfig
+
+import (
+	"android/soong/android"
+	"android/soong/java"
+	"fmt"
+	"github.com/google/blueprint"
+)
+
+type declarationsTagType struct {
+	blueprint.BaseDependencyTag
+}
+
+var declarationsTag = declarationsTagType{}
+
+type JavaAconfigDeclarationsLibraryProperties struct {
+	// name of the aconfig_declarations module to generate a library for
+	Aconfig_declarations string
+}
+
+type JavaAconfigDeclarationsLibraryCallbacks struct {
+	properties JavaAconfigDeclarationsLibraryProperties
+}
+
+func JavaDeclarationsLibraryFactory() android.Module {
+	callbacks := &JavaAconfigDeclarationsLibraryCallbacks{}
+	return java.GeneratedJavaLibraryModuleFactory("java_aconfig_library", callbacks, &callbacks.properties)
+}
+
+func (callbacks *JavaAconfigDeclarationsLibraryCallbacks) DepsMutator(module *java.GeneratedJavaLibraryModule, ctx android.BottomUpMutatorContext) {
+	declarations := callbacks.properties.Aconfig_declarations
+	if len(declarations) == 0 {
+		// TODO: Add test for this case
+		ctx.PropertyErrorf("aconfig_declarations", "aconfig_declarations property required")
+	} else {
+		ctx.AddDependency(ctx.Module(), declarationsTag, declarations)
+	}
+}
+
+func (callbacks *JavaAconfigDeclarationsLibraryCallbacks) GenerateSourceJarBuildActions(ctx android.ModuleContext) android.Path {
+	// Get the values that came from the global RELEASE_ACONFIG_VALUE_SETS flag
+	declarationsModules := ctx.GetDirectDepsWithTag(declarationsTag)
+	if len(declarationsModules) != 1 {
+		panic(fmt.Errorf("Exactly one aconfig_declarations property required"))
+	}
+	declarations := ctx.OtherModuleProvider(declarationsModules[0], declarationsProviderKey).(declarationsProviderData)
+
+	srcJarPath := android.PathForModuleGen(ctx, ctx.ModuleName()+".srcjar")
+	ctx.Build(pctx, android.BuildParams{
+		Rule:        srcJarRule,
+		Input:       declarations.IntermediatePath,
+		Output:      srcJarPath,
+		Description: "aconfig.srcjar",
+	})
+
+	return srcJarPath
+}
diff --git a/aconfig/testing.go b/aconfig/testing.go
new file mode 100644
index 0000000..60cefeb
--- /dev/null
+++ b/aconfig/testing.go
@@ -0,0 +1,29 @@
+// Copyright (C) 2021 The Android Open Source Project
+//
+// 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 aconfig
+
+import (
+	"testing"
+
+	"android/soong/android"
+)
+
+var PrepareForTestWithAconfigBuildComponents = android.FixtureRegisterWithContext(registerBuildComponents)
+
+func runTest(t *testing.T, errorHandler android.FixtureErrorHandler, bp string) *android.TestResult {
+	return android.GroupFixturePreparers(PrepareForTestWithAconfigBuildComponents).
+		ExtendWithErrorHandler(errorHandler).
+		RunTestWithBp(t, bp)
+}