Fix few issues with filegroups

Bug: http://b/64121881
Bug: http://b/78188880

- Allow filegroup's properties to be extended by a LoadHook
- Support a filegroup (':module') in a prebuilt's 'Srcs' property to
export files from a different path as the prebuilt's sources.

This change also includes a refactoring that moves genrule/filegroup.go
to android/filegroup.go so that FileGroupFactory is visible in
prebuilt_test.go.

Test: Test
https://android-review.googlesource.com/c/platform/development/+/469159
in clang-tools branch on Linux, Darwin.  Test regular build in
aosp/master.

Change-Id: I3ff6215ab2e62955f039fd1086c31f1bd50ebcf6
diff --git a/android/filegroup.go b/android/filegroup.go
new file mode 100644
index 0000000..b284ce0
--- /dev/null
+++ b/android/filegroup.go
@@ -0,0 +1,94 @@
+// Copyright 2016 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 android
+
+import (
+	"io"
+	"strings"
+	"text/template"
+)
+
+func init() {
+	RegisterModuleType("filegroup", FileGroupFactory)
+}
+
+type fileGroupProperties struct {
+	// srcs lists files that will be included in this filegroup
+	Srcs []string
+
+	Exclude_srcs []string
+
+	// The base path to the files.  May be used by other modules to determine which portion
+	// of the path to use.  For example, when a filegroup is used as data in a cc_test rule,
+	// the base path is stripped off the path and the remaining path is used as the
+	// installation directory.
+	Path *string
+
+	// Create a make variable with the specified name that contains the list of files in the
+	// filegroup, relative to the root of the source tree.
+	Export_to_make_var *string
+}
+
+type fileGroup struct {
+	ModuleBase
+	properties fileGroupProperties
+	srcs       Paths
+}
+
+var _ SourceFileProducer = (*fileGroup)(nil)
+
+// filegroup modules contain a list of files, and can be used to export files across package
+// boundaries.  filegroups (and genrules) can be referenced from srcs properties of other modules
+// using the syntax ":module".
+func FileGroupFactory() Module {
+	module := &fileGroup{}
+	module.AddProperties(&module.properties)
+	InitAndroidModule(module)
+	return module
+}
+
+func (fg *fileGroup) DepsMutator(ctx BottomUpMutatorContext) {
+	ExtractSourcesDeps(ctx, fg.properties.Srcs)
+	ExtractSourcesDeps(ctx, fg.properties.Exclude_srcs)
+}
+
+func (fg *fileGroup) GenerateAndroidBuildActions(ctx ModuleContext) {
+	fg.srcs = ctx.ExpandSourcesSubDir(fg.properties.Srcs, fg.properties.Exclude_srcs, String(fg.properties.Path))
+}
+
+func (fg *fileGroup) Srcs() Paths {
+	return append(Paths{}, fg.srcs...)
+}
+
+var androidMkTemplate = template.Must(template.New("filegroup").Parse(`
+ifdef {{.makeVar}}
+  $(error variable {{.makeVar}} set by soong module is already set in make)
+endif
+{{.makeVar}} := {{.value}}
+.KATI_READONLY := {{.makeVar}}
+`))
+
+func (fg *fileGroup) AndroidMk() AndroidMkData {
+	return AndroidMkData{
+		Custom: func(w io.Writer, name, prefix, moduleDir string, data AndroidMkData) {
+			if makeVar := String(fg.properties.Export_to_make_var); makeVar != "" {
+				androidMkTemplate.Execute(w, map[string]string{
+					"makeVar": makeVar,
+					"value":   strings.Join(fg.srcs.Strings(), " "),
+				})
+			}
+		},
+	}
+}