[NETD-BPF#34] Add a tag for bpf to specify the install folder

Currently, the bpf module netd.o (source system/netd/bpf_progs/netd.c)
will be built to /system/etc/bpf/netd.o. In Android T, it will be moved
to mainline module com.android.tethering.

The expected behavior is:
- In T device, it uses the netd.o in mainline module.
- In pre-T devices, it uses the original netd, built from platform.

However, netd.o will be double loaded if the tethering module is
installed in Pre-T devices. Because:
1. bpf in apex is packed into /apex/MAINLINE_MODULE/etc/bpf/
2. bpf in platform is packed into /system/etc/bpf/
3. bpfloader in pre-T loads ANY bpf modules under
/apex/com.android.tethering/etc/bpf/ and /system/etc/bpf/.

We can't change the behavior of bpfloader in pre-T devices. We can't
delete the /system/etc/bpf/netd.o from pre-T devices. Both of them are
not mainline modules. So the mainlined netd.o needs to be packed into a
folder other than /apex/com.android.tethering/etc/bpf/ or
/system/etc/bpf/.

This commit adds a tag 'sub_dir' for bpf module. The installation path
of bpf modules will be:
- /system/etc/bpf/SUB_DIR/     (for platform code)
- /apex/MAINLINE_MODULE/etc/bpf/SUB_DIR/     (for mainline module)

Bug: 202086915
Test: add test in apex_test.go and build
Merged-In: Icc6619768ab006de9f86620a7df1bb2853eaba13
Change-Id: Icc6619768ab006de9f86620a7df1bb2853eaba13
diff --git a/apex/apex.go b/apex/apex.go
index f92e75d..65b9c54 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -1572,8 +1572,8 @@
 	return af
 }
 
-func apexFileForBpfProgram(ctx android.BaseModuleContext, builtFile android.Path, bpfProgram bpf.BpfModule) apexFile {
-	dirInApex := filepath.Join("etc", "bpf")
+func apexFileForBpfProgram(ctx android.BaseModuleContext, builtFile android.Path, apex_sub_dir string, bpfProgram bpf.BpfModule) apexFile {
+	dirInApex := filepath.Join("etc", "bpf", apex_sub_dir)
 	return newApexFile(ctx, builtFile, builtFile.Base(), dirInApex, etc, bpfProgram)
 }
 
@@ -1772,8 +1772,9 @@
 			case bpfTag:
 				if bpfProgram, ok := child.(bpf.BpfModule); ok {
 					filesToCopy, _ := bpfProgram.OutputFiles("")
+					apex_sub_dir := bpfProgram.SubDir()
 					for _, bpfFile := range filesToCopy {
-						filesInfo = append(filesInfo, apexFileForBpfProgram(ctx, bpfFile, bpfProgram))
+						filesInfo = append(filesInfo, apexFileForBpfProgram(ctx, bpfFile, apex_sub_dir, bpfProgram))
 					}
 				} else {
 					ctx.PropertyErrorf("bpfs", "%q is not a bpf module", depName)
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 663a9a0..f3c3b44 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -622,7 +622,7 @@
 			java_libs: ["myjar"],
 			apps: ["AppFoo"],
 			rros: ["rro"],
-			bpfs: ["bpf"],
+			bpfs: ["bpf", "netd_test"],
 			updatable: false,
 		}
 
@@ -675,6 +675,12 @@
 			srcs: ["bpf.c", "bpf2.c"],
 		}
 
+		bpf {
+			name: "netd_test",
+			srcs: ["netd_test.c"],
+			sub_dir: "netd",
+		}
+
 	`)
 	ensureExactContents(t, ctx, "myapex", "android_common_myapex_image", []string{
 		"etc/myetc",
@@ -684,6 +690,7 @@
 		"overlay/blue/rro.apk",
 		"etc/bpf/bpf.o",
 		"etc/bpf/bpf2.o",
+		"etc/bpf/netd/netd_test.o",
 	})
 }
 
diff --git a/bpf/bpf.go b/bpf/bpf.go
index 9f0c86c..187b4db 100644
--- a/bpf/bpf.go
+++ b/bpf/bpf.go
@@ -54,12 +54,16 @@
 	android.Module
 
 	OutputFiles(tag string) (android.Paths, error)
+
+	// Returns the sub install directory if the bpf module is included by apex.
+	SubDir() string
 }
 
 type BpfProperties struct {
 	Srcs         []string `android:"path"`
 	Cflags       []string
 	Include_dirs []string
+	Sub_dir      string
 }
 
 type bpf struct {
@@ -121,6 +125,10 @@
 			fmt.Fprintln(w)
 			fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir)
 			fmt.Fprintln(w)
+			localModulePath := "LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/bpf"
+			if len(bpf.properties.Sub_dir) > 0 {
+				localModulePath += "/" + bpf.properties.Sub_dir
+			}
 			for _, obj := range bpf.objs {
 				objName := name + "_" + obj.Base()
 				names = append(names, objName)
@@ -130,7 +138,7 @@
 				fmt.Fprintln(w, "LOCAL_PREBUILT_MODULE_FILE :=", obj.String())
 				fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", obj.Base())
 				fmt.Fprintln(w, "LOCAL_MODULE_CLASS := ETC")
-				fmt.Fprintln(w, "LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/bpf")
+				fmt.Fprintln(w, localModulePath)
 				fmt.Fprintln(w, "include $(BUILD_PREBUILT)")
 				fmt.Fprintln(w)
 			}
@@ -154,6 +162,10 @@
 	}
 }
 
+func (bpf *bpf) SubDir() string {
+	return bpf.properties.Sub_dir
+}
+
 var _ android.OutputFileProducer = (*bpf)(nil)
 
 func BpfFactory() android.Module {