Support writing inputs/outputs of actions of modules into a file from the moduleInfo.actionDefs.

An example module variant in the module-actions.json:
{
	"Name": "metalava-gradle-plugin-deps",
	"Variations": null,
	"DependencyVariations": null,
	"Deps": [
		{
			"Name": "prebuilts_gradle-plugin_license",
			"Variations": null,
			"DependencyVariations": null,
			"Tag": ""
		}
	],
	"Type": "",
	"Blueprint": "prebuilts/gradle-plugin/Android.bp",
	"Module": {
		"Actions": [
			{
				"Inputs": [
					"prebuilts/gradle-plugin/com/android/tools/lint/lint-api/30.1.0-alpha13/lint-api-30.1.0-alpha13.jar",
					"prebuilts/gradle-plugin/com/android/tools/lint/lint-checks/30.1.0-alpha13/lint-checks-30.1.0-alpha13.jar",
					"prebuilts/gradle-plugin/com/android/tools/lint/lint/30.1.0-alpha13/lint-30.1.0-alpha13.jar",
					"prebuilts/gradle-plugin/com/android/tools/lint/lint-gradle/30.1.0-alpha13/lint-gradle-30.1.0-alpha13.jar",
					"prebuilts/gradle-plugin/com/android/tools/lint/lint-model/30.1.0-alpha13/lint-model-30.1.0-alpha13.jar",
					"prebuilts/gradle-plugin/com/android/tools/common/30.1.0-alpha13/common-30.1.0-alpha13.jar",
					"prebuilts/gradle-plugin/com/android/tools/sdk-common/30.1.0-alpha13/sdk-common-30.1.0-alpha13.jar",
					"prebuilts/gradle-plugin/com/android/tools/sdklib/30.1.0-alpha13/sdklib-30.1.0-alpha13.jar",
					"prebuilts/gradle-plugin/com/android/tools/external/org-jetbrains/uast/30.1.0-alpha13/uast-30.1.0-alpha13.jar",
					"prebuilts/gradle-plugin/com/android/tools/external/com-intellij/intellij-core/30.1.0-alpha13/intellij-core-30.1.0-alpha13.jar",
					"prebuilts/gradle-plugin/com/android/tools/external/com-intellij/kotlin-compiler/30.1.0-alpha13/kotlin-compiler-30.1.0-alpha13.jar",
					"prebuilts/gradle-plugin/com/android/tools/repository/30.1.0-alpha13/repository-30.1.0-alpha13.jar",
					"prebuilts/gradle-plugin/com/android/tools/build/manifest-merger/30.1.0-alpha13/manifest-merger-30.1.0-alpha13.jar"
				],
				"Outputs": [
					"out/soong/.intermediates/prebuilts/gradle-plugin/metalava-gradle-plugin-deps/linux_glibc_common/combined/metalava-gradle-plugin-deps.jar"
				]
			},
			{
				"Inputs": null,
				"Outputs": [
					"out/soong/.intermediates/prebuilts/gradle-plugin/metalava-gradle-plugin-deps/linux_glibc_common/meta_lic"
				]
			}
		]
	}
}

Test: local
Change-Id: Icbb7236507251e257f6773b110ae8a0788eef41e
diff --git a/context.go b/context.go
index e0442ce..d93b957 100644
--- a/context.go
+++ b/context.go
@@ -2297,26 +2297,6 @@
 	AddJSONData(d *map[string]interface{})
 }
 
-// A JSONDataAction contains the inputs and outputs of actions of a module. Which helps pass such
-// data to be included in the JSON module graph.
-type JSONDataAction struct {
-	Inputs  []string
-	Outputs []string
-}
-
-// FormatJSONDataActions puts the content of a list of JSONDataActions into a standard format to be
-// appended into the JSON module graph.
-func FormatJSONDataActions(jsonDataActions []JSONDataAction) []map[string]interface{} {
-	var actions []map[string]interface{}
-	for _, jsonDataAction := range jsonDataActions {
-		actions = append(actions, map[string]interface{}{
-			"Inputs":  jsonDataAction.Inputs,
-			"Outputs": jsonDataAction.Outputs,
-		})
-	}
-	return actions
-}
-
 func jsonModuleFromModuleInfo(m *moduleInfo) *JsonModule {
 	result := &JsonModule{
 		jsonModuleName: *jsonModuleNameFromModuleInfo(m),
@@ -2325,11 +2305,9 @@
 		Blueprint:      m.relBlueprintsFile,
 		Module:         make(map[string]interface{}),
 	}
-
 	if j, ok := m.logicModule.(JSONDataSupplier); ok {
 		j.AddJSONData(&result.Module)
 	}
-
 	for _, p := range m.providers {
 		if j, ok := p.(JSONDataSupplier); ok {
 			j.AddJSONData(&result.Module)
@@ -2338,20 +2316,68 @@
 	return result
 }
 
-func (c *Context) PrintJSONGraph(w io.Writer) {
-	modules := make([]*JsonModule, 0)
+func jsonModuleWithActionsFromModuleInfo(m *moduleInfo) *JsonModule {
+	result := &JsonModule{
+		jsonModuleName: jsonModuleName{
+			Name: m.Name(),
+		},
+		Deps:      make([]jsonDep, 0),
+		Type:      m.typeName,
+		Blueprint: m.relBlueprintsFile,
+		Module:    make(map[string]interface{}),
+	}
+	var actions []map[string]interface{}
+	for _, bDef := range m.actionDefs.buildDefs {
+		actions = append(actions, map[string]interface{}{
+			"Inputs": append(
+				getNinjaStringsWithNilPkgNames(bDef.Inputs),
+				getNinjaStringsWithNilPkgNames(bDef.Implicits)...),
+			"Outputs": append(
+				getNinjaStringsWithNilPkgNames(bDef.Outputs),
+				getNinjaStringsWithNilPkgNames(bDef.ImplicitOutputs)...),
+		})
+	}
+	result.Module["Actions"] = actions
+	return result
+}
+
+// Gets a list of strings from the given list of ninjaStrings by invoking ninjaString.Value with
+// nil pkgNames on each of the input ninjaStrings.
+func getNinjaStringsWithNilPkgNames(nStrs []ninjaString) []string {
+	var strs []string
+	for _, nstr := range nStrs {
+		strs = append(strs, nstr.Value(nil))
+	}
+	return strs
+}
+
+// PrintJSONGraph prints info of modules in a JSON file.
+func (c *Context) PrintJSONGraphAndActions(wGraph io.Writer, wActions io.Writer) {
+	modulesToGraph := make([]*JsonModule, 0)
+	modulesToActions := make([]*JsonModule, 0)
 	for _, m := range c.modulesSorted {
 		jm := jsonModuleFromModuleInfo(m)
+		jmWithActions := jsonModuleWithActionsFromModuleInfo(m)
 		for _, d := range m.directDeps {
 			jm.Deps = append(jm.Deps, jsonDep{
 				jsonModuleName: *jsonModuleNameFromModuleInfo(d.module),
 				Tag:            fmt.Sprintf("%T %+v", d.tag, d.tag),
 			})
+			jmWithActions.Deps = append(jmWithActions.Deps, jsonDep{
+				jsonModuleName: jsonModuleName{
+					Name: d.module.Name(),
+				},
+			})
+
 		}
-
-		modules = append(modules, jm)
+		modulesToGraph = append(modulesToGraph, jm)
+		modulesToActions = append(modulesToActions, jmWithActions)
 	}
+	writeJson(wGraph, modulesToGraph)
+	writeJson(wActions, modulesToActions)
+}
 
+func writeJson(w io.Writer, modules []*JsonModule) {
 	e := json.NewEncoder(w)
 	e.SetIndent("", "\t")
 	e.Encode(modules)