Use custom module for versioned font files

The prebuilt_versioned_font module includes font files based on build
flags. With this custom module, we can refer the build flags directly
instead of propagating buildflags from mk file to bp file with randomly
generated namespaces.

This module has two mandatory properties, versionFlag and
defaultVersion.
The versionFlag is a build flag used for versioning.
The defaultVersion is a default version string used for environment that
does not have build flags, e.g. SDK builds.

For example,

prebuilt_versioned_font {
  name: "NotoSans.ttf",
  versionFlag: "RELEASE_PACKAGE_NOTO_SANS",
  defaultVersion: "1.000",
}

then, if RELEASE_PACKAGE_NOTO_SANS is 2.000, the font file located in

{root}/font/2.000/NotoSans.ttf

is loaded. The directory name and file name can be configured with
optional fontFile property and fontFile property.

Bug: N/A
Test: m and manually confirmed the versioned font files are included.
Merged-In: I2d09de745cb28f50196ffe8857ca9578f2eb6ee1
Change-Id: I2d09de745cb28f50196ffe8857ca9578f2eb6ee1
diff --git a/Android.bp b/Android.bp
index b7f2478..37ab91e 100644
--- a/Android.bp
+++ b/Android.bp
@@ -244,3 +244,20 @@
         ":NotoSerifYezidi-VF",
     ],
 }
+
+bootstrap_go_package {
+    name: "soong-noto-fonts",
+    pkgPath: "android/soong/external/noto-fonts",
+    deps: [
+        "blueprint",
+        "blueprint-pathtools",
+        "soong",
+        "soong-android",
+        "soong-cc",
+        "soong-genrule",
+    ],
+    srcs: [
+        "noto-fonts.go",
+    ],
+    pluginFor: ["soong_build"],
+}
diff --git a/emoji-compat/Android.bp b/emoji-compat/Android.bp
index 4ea10ca..2d4ba47 100644
--- a/emoji-compat/Android.bp
+++ b/emoji-compat/Android.bp
@@ -46,48 +46,24 @@
     ],
 }
 
-soong_config_module_type {
-    name: "prebuilt_emoji_font",
-    module_type: "prebuilt_font",
-    config_namespace: "emoji_font",
-    value_variables: ["emoji_font_version"],
-    properties: ["src"],
-}
-
-prebuilt_emoji_font {
+prebuilt_versioned_font {
     name: "NotoColorEmoji.ttf",
     dist: {
         targets: ["droidcore"],
     },
-    // Need a default value because SDK build doesn't include fonts.mk.
-    src: "font/2.042/Noto-COLRv1-noflags.ttf",
-    soong_config_variables: {
-        emoji_font_version: {
-            src: "font/%s/Noto-COLRv1-noflags.ttf",
-        },
-    },
+    fontFile: "Noto-COLRv1-noflags.ttf",
+    versionFlag: "RELEASE_PACKAGE_EMOJI_FONT_VERSION",
+    defaultVersion: "2.047",
 }
 
-soong_config_module_type {
-    name: "prebuilt_flag_emoji_font",
-    module_type: "prebuilt_font",
-    config_namespace: "flag_emoji_font",
-    value_variables: ["flag_emoji_font_version"],
-    properties: ["src"],
-}
-
-prebuilt_flag_emoji_font {
+prebuilt_versioned_font {
     name: "NotoColorEmojiFlags.ttf",
     dist: {
         targets: ["droidcore"],
     },
-    // Need a default value because SDK build doesn't include fonts.mk.
-    src: "font/2.042/NotoColorEmoji-flagsonly.ttf",
-    soong_config_variables: {
-        flag_emoji_font_version: {
-            src: "font/%s/NotoColorEmoji-flagsonly.ttf",
-        },
-    },
+    fontFile: "NotoColorEmoji-flagsonly.ttf",
+    versionFlag: "RELEASE_PACKAGE_EMOJI_FONT_VERSION",
+    defaultVersion: "2.047",
 }
 
 prebuilt_font {
diff --git a/fonts.mk b/fonts.mk
index 52c55c8..0b6f06d 100644
--- a/fonts.mk
+++ b/fonts.mk
@@ -16,10 +16,6 @@
 # PRODUCT_COPY_FILES to install the font files, so that the NOTICE file can
 # get installed too.
 
-# Set emoji version in Android.bp
-$(call soong_config_set,emoji_font,emoji_font_version,$(RELEASE_PACKAGE_EMOJI_FONT_VERSION))
-$(call soong_config_set,flag_emoji_font,flag_emoji_font_version,$(RELEASE_PACKAGE_FLAG_EMOJI_FONT_VERSION))
-
 PRODUCT_PACKAGES := \
     $(PRODUCT_PACKAGES) \
     NotoColorEmoji.ttf \
@@ -213,7 +209,3 @@
     NotoSerifThai-Regular.ttf \
     NotoSerifTibetan-VF.ttf \
     NotoSerifYezidi-VF.ttf
-
-
-# Set Hebrew font version
-$(call soong_config_set,hebrew_font,hebrew_font_version,$(RELEASE_PACKAGE_HEBREW_FONT_VERSION))
diff --git a/noto-fonts.go b/noto-fonts.go
new file mode 100644
index 0000000..0c86fae
--- /dev/null
+++ b/noto-fonts.go
@@ -0,0 +1,157 @@
+package noto_fonts
+import (
+  "android/soong/android"
+  "fmt"
+  prebuilt_etc "android/soong/etc"
+  "os"
+)
+
+type fontProperties struct {
+  // An optional font file of the versioned font files.
+  // If not provided, the module name is used instead.
+  FontFile string
+
+  // An optional directory that contains versioned files.
+  // If not provided, "font" is used instead.
+  VersionDir string
+
+  // A mandatory version flag used for controlling versioning.
+  VersionFlag string
+
+  // A mandatory version string used for environment that does not have build flags, e.g. SDK build.
+  DefaultVersion string
+}
+
+type configProperties struct {
+  // An optional font file of the versioned font files.
+  // If not provided, "font_config.json" is used instead.
+  ConfigFile string
+
+  // An optional directory that contains versioned font files.
+  // If not provided, "font" is used instead.
+  VersionDir string
+
+  // A mandatory version flag used for controlling versioning.
+  VersionFlag string
+
+  // A mandatory version string used for environment that does not have build flags, e.g. SDK build.
+  DefaultVersion string
+}
+
+func init() {
+  android.RegisterModuleType("prebuilt_versioned_font", prebuiltVersionedFontFactory)
+  android.RegisterModuleType("versioned_font_config", versionedFontConfigFactory)
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// prebuilt_versioned_font definition
+///////////////////////////////////////////////////////////////////////////////
+func prebuiltVersionedFontFactory() (android.Module) {
+  // Inherit prebuilt_font module
+  module := prebuilt_etc.PrebuiltFontFactory()
+  module.AddProperties(&fontProperties{})
+  android.AddLoadHook(module, prebuiltVersionFont)
+  return module
+}
+
+func prebuiltVersionFont(ctx android.LoadHookContext) {
+  // Find fontProperties propery from the property list.
+  var fontProp *fontProperties
+  for _, p := range ctx.Module().GetProperties() {
+      _fontProp, ok := p.(*fontProperties)
+      if ok {
+        fontProp = _fontProp
+      }
+  }
+
+  // Check if the default version is specified.
+  defaultVersion := fontProp.DefaultVersion
+  if len(defaultVersion) == 0 {
+    fmt.Printf("defaultVersion is required for SDK build")
+    os.Exit(1)
+  }
+
+  // Read the version number from build flag.
+  // The build flag may not be present, in such case, use default value instead.
+  version, ok := ctx.Config().GetBuildFlag(fontProp.VersionFlag)
+  if !ok {
+    fmt.Printf("No value set to Build Flag %s. Use default version instead.", fontProp.VersionFlag)
+    version = defaultVersion
+  }
+
+  // If no VersionDir is specified, use "font" as a default.
+  if len(fontProp.VersionDir) == 0 {
+    fontProp.VersionDir = "font"
+  }
+
+  // If no FontFile is specified, use module name as a default.
+  if len(fontProp.FontFile) == 0 {
+    fontProp.FontFile = ctx.Module().Name()
+  }
+
+  // Override the src property with newly generated one.
+  type props struct {
+    Src string
+  }
+  p := &props{}
+  p.Src = fontProp.VersionDir + "/" + version + "/" + fontProp.FontFile
+  ctx.AppendProperties(p)
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// versioned_font_config definition
+///////////////////////////////////////////////////////////////////////////////
+func versionedFontConfigFactory() (android.Module) {
+  // Inherit filegroup module
+  module := android.FileGroupFactory()
+  module.AddProperties(&configProperties{})
+  android.AddLoadHook(module, versionedFontConfig)
+  return module
+}
+
+func versionedFontConfig(ctx android.LoadHookContext) {
+  // Find fontProperties propery from the property list.
+  var configProp *configProperties
+  for _, p := range ctx.Module().GetProperties() {
+      _configProp, ok := p.(*configProperties)
+      if ok {
+        configProp = _configProp
+      }
+  }
+
+  // Check if the default version is specified.
+  defaultVersion := configProp.DefaultVersion
+  if len(defaultVersion) == 0 {
+    fmt.Printf("defaultVersion is required for SDK build")
+    os.Exit(1)
+  }
+
+  // Read the version number from build flag.
+  // The build flag may not be present, in such case, use default value instead.
+  version, ok := ctx.Config().GetBuildFlag(configProp.VersionFlag)
+  if !ok {
+    fmt.Printf("No value set to Build Flag %s. Use default version instead.", configProp.VersionFlag)
+    version = defaultVersion
+  }
+
+  // If no VersionDir is specified, use "font" as a default.
+  if len(configProp.VersionDir) == 0 {
+    configProp.VersionDir = "font"
+  }
+
+  // If no ConfigFile is specified, use font_config.json instead
+  if len(configProp.ConfigFile) == 0 {
+    configProp.ConfigFile = "font_config.json"
+  }
+
+  // Override the src property with newly generated one.
+  type props struct {
+    Srcs []string
+  }
+  p := &props{}
+  p.Srcs = make([]string, 1)
+  p.Srcs[0] = configProp.VersionDir + "/" + version + "/" + configProp.ConfigFile
+  ctx.AppendProperties(p)
+}
+
diff --git a/notosanshebrew/Android.bp b/notosanshebrew/Android.bp
index 5faa58d..b059fff 100644
--- a/notosanshebrew/Android.bp
+++ b/notosanshebrew/Android.bp
@@ -45,32 +45,18 @@
     ],
 }
 
-soong_config_module_type {
-    name: "prebuilt_hebrew_font",
-    module_type: "prebuilt_font",
-    config_namespace: "hebrew_font",
-    value_variables: ["hebrew_font_version"],
-    properties: ["src"],
-}
-
-prebuilt_hebrew_font {
+prebuilt_versioned_font {
     name: "NotoSansHebrew-Regular.ttf",
-    src: "1.04/NotoSansHebrew-Regular.ttf",
-    soong_config_variables: {
-        hebrew_font_version: {
-            src: "%s/NotoSansHebrew-Regular.ttf",
-        },
-    },
+    versionDir: ".",
+    versionFlag: "RELEASE_PACKAGE_HEBREW_FONT_VERSION",
+    defaultVersion: "1.04",
 }
 
-prebuilt_hebrew_font {
+prebuilt_versioned_font {
     name: "NotoSansHebrew-Bold.ttf",
-    src: "1.04/NotoSansHebrew-Bold.ttf",
-    soong_config_variables: {
-        hebrew_font_version: {
-            src: "./%s/NotoSansHebrew-Bold.ttf",
-        },
-    },
+    versionDir: ".",
+    versionFlag: "RELEASE_PACKAGE_HEBREW_FONT_VERSION",
+    defaultVersion: "1.04",
 }
 
 filegroup {