Java APIs used by Mainline modules.

Add scripts to generate java APIs used by Mainline modules. This is
aosp/1879177 with fixed build error that caused by dexdeps analyzing
resource only APKs which doesn't contains any .dex files. Now skip the
error generates in that case in gen_java_usedby_apex.sh

Test: TARGET_BUILD_APPS=com.android.adbd m dist apps_only
Change-Id: Id539cbe1b7306ace69c047f95ffc02265a467511
Merged-In: Id539cbe1b7306ace69c047f95ffc02265a467511
diff --git a/apex/androidmk.go b/apex/androidmk.go
index ebf0833..ba28e35 100644
--- a/apex/androidmk.go
+++ b/apex/androidmk.go
@@ -446,23 +446,18 @@
 					fmt.Fprintf(w, dist)
 				}
 
-				if a.apisUsedByModuleFile.String() != "" {
-					goal := "apps_only"
-					distFile := a.apisUsedByModuleFile.String()
-					fmt.Fprintf(w, "ifneq (,$(filter $(my_register_name),$(TARGET_BUILD_APPS)))\n"+
-						" $(call dist-for-goals,%s,%s:ndk_apis_usedby_apex/$(notdir %s))\n"+
-						"endif\n",
-						goal, distFile, distFile)
-				}
-
-				if a.apisBackedByModuleFile.String() != "" {
-					goal := "apps_only"
-					distFile := a.apisBackedByModuleFile.String()
-					fmt.Fprintf(w, "ifneq (,$(filter $(my_register_name),$(TARGET_BUILD_APPS)))\n"+
-						" $(call dist-for-goals,%s,%s:ndk_apis_backedby_apex/$(notdir %s))\n"+
-						"endif\n",
-						goal, distFile, distFile)
-				}
+				distCoverageFiles(w, "ndk_apis_usedby_apex", a.nativeApisUsedByModuleFile.String())
+				distCoverageFiles(w, "ndk_apis_usedby_apex", a.nativeApisBackedByModuleFile.String())
+				distCoverageFiles(w, "java_apis_used_by_apex", a.javaApisUsedByModuleFile.String())
 			}
 		}}
 }
+
+func distCoverageFiles(w io.Writer, dir string, distfile string) {
+	if distfile != "" {
+		goal := "apps_only"
+		fmt.Fprintf(w, "ifneq (,$(filter $(my_register_name),$(TARGET_BUILD_APPS)))\n"+
+			" $(call dist-for-goals,%s,%s:%s/$(notdir %s))\n"+
+			"endif\n", goal, distfile, dir, distfile)
+	}
+}
diff --git a/apex/apex.go b/apex/apex.go
index a2b16f1..77b2d13 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -413,8 +413,9 @@
 	isCompressed bool
 
 	// Path of API coverage generate file
-	apisUsedByModuleFile   android.ModuleOutPath
-	apisBackedByModuleFile android.ModuleOutPath
+	nativeApisUsedByModuleFile   android.ModuleOutPath
+	nativeApisBackedByModuleFile android.ModuleOutPath
+	javaApisUsedByModuleFile     android.ModuleOutPath
 }
 
 // apexFileClass represents a type of file that can be included in APEX.
diff --git a/apex/builder.go b/apex/builder.go
index d2e6ad8..e3e06bb 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -67,6 +67,7 @@
 	pctx.HostBinToolVariable("make_f2fs", "make_f2fs")
 	pctx.HostBinToolVariable("sload_f2fs", "sload_f2fs")
 	pctx.HostBinToolVariable("apex_compression_tool", "apex_compression_tool")
+	pctx.HostBinToolVariable("dexdeps", "dexdeps")
 	pctx.SourcePathVariable("genNdkUsedbyApexPath", "build/soong/scripts/gen_ndk_usedby_apex.sh")
 }
 
@@ -696,12 +697,12 @@
 				"readelf":   "${config.ClangBin}/llvm-readelf",
 			},
 		})
-		a.apisUsedByModuleFile = apisUsedbyOutputFile
+		a.nativeApisUsedByModuleFile = apisUsedbyOutputFile
 
-		var libNames []string
+		var nativeLibNames []string
 		for _, f := range a.filesInfo {
 			if f.class == nativeSharedLib {
-				libNames = append(libNames, f.stem())
+				nativeLibNames = append(nativeLibNames, f.stem())
 			}
 		}
 		apisBackedbyOutputFile := android.PathForModuleOut(ctx, a.Name()+"_backing.txt")
@@ -711,9 +712,25 @@
 			Tool(android.PathForSource(ctx, "build/soong/scripts/gen_ndk_backedby_apex.sh")).
 			Output(apisBackedbyOutputFile).
 			Input(ndkLibraryList).
-			Flags(libNames)
+			Flags(nativeLibNames)
 		rule.Build("ndk_backedby_list", "Generate API libraries backed by Apex")
-		a.apisBackedByModuleFile = apisBackedbyOutputFile
+		a.nativeApisBackedByModuleFile = apisBackedbyOutputFile
+
+		var javaLibOrApkPath []android.Path
+		for _, f := range a.filesInfo {
+			if f.class == javaSharedLib || f.class == app {
+				javaLibOrApkPath = append(javaLibOrApkPath, f.builtFile)
+			}
+		}
+		javaApiUsedbyOutputFile := android.PathForModuleOut(ctx, a.Name()+"_using.xml")
+		javaUsedByRule := android.NewRuleBuilder(pctx, ctx)
+		javaUsedByRule.Command().
+			Tool(android.PathForSource(ctx, "build/soong/scripts/gen_java_usedby_apex.sh")).
+			BuiltTool("dexdeps").
+			Output(javaApiUsedbyOutputFile).
+			Inputs(javaLibOrApkPath)
+		javaUsedByRule.Build("java_usedby_list", "Generate Java APIs used by Apex")
+		a.javaApisUsedByModuleFile = javaApiUsedbyOutputFile
 
 		bundleConfig := a.buildBundleConfig(ctx)
 
diff --git a/apex/testing.go b/apex/testing.go
index 69bd73e..337c862 100644
--- a/apex/testing.go
+++ b/apex/testing.go
@@ -24,6 +24,7 @@
 	android.MockFS{
 		// Needed by apex.
 		"system/core/rootdir/etc/public.libraries.android.txt": nil,
+		"build/soong/scripts/gen_java_usedby_apex.sh":          nil,
 		"build/soong/scripts/gen_ndk_backedby_apex.sh":         nil,
 		// Needed by prebuilt_apex.
 		"build/soong/scripts/unpack-prebuilt-apex.sh": nil,
diff --git a/scripts/OWNERS b/scripts/OWNERS
index 2b9c2de..573134e 100644
--- a/scripts/OWNERS
+++ b/scripts/OWNERS
@@ -3,4 +3,4 @@
 per-file build-aml-prebuilts.sh = ngeoffray@google.com,paulduffin@google.com,mast@google.com
 per-file construct_context.py = ngeoffray@google.com,calin@google.com,mathieuc@google.com,skvadrik@google.com
 per-file conv_linker_config.py = kiyoungkim@google.com, jiyong@google.com, jooyung@google.com
-per-file gen_ndk*.sh = sophiez@google.com, allenhair@google.com
+per-file gen_ndk*.sh,gen_java*.sh = sophiez@google.com, allenhair@google.com
\ No newline at end of file
diff --git a/scripts/gen_java_usedby_apex.sh b/scripts/gen_java_usedby_apex.sh
new file mode 100755
index 0000000..251d7aa
--- /dev/null
+++ b/scripts/gen_java_usedby_apex.sh
@@ -0,0 +1,46 @@
+#!/bin/bash -e
+
+# Copyright 2020 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.
+
+printHelp() {
+    echo "**************************** Usage Instructions ****************************"
+    echo "This script is used to generate the Mainline modules used-by Java symbols."
+    echo ""
+    echo "To run this script use: ./gen_java_usedby_apex.sh \$BINARY_DEXDEPS_PATH \$OUTPUT_FILE_PATH \$JAR_AND_APK_LIST"
+    echo "For example: If all jar and apk files are '/myJar.jar /myApk.apk' and output write to /myModule.txt then the command would be:"
+    echo "./gen_java_usedby_apex.sh \$BINARY_DEXDEPS_PATH /myModule.txt /myJar.jar /myApk.apk"
+}
+
+genUsedByList() {
+  dexdeps="$1"
+  shift
+  out="$1"
+  shift
+  rm -f "$out"
+  touch "$out"
+  for x in "$@"; do
+    "$dexdeps" "$x" >> "$out" || true
+  done
+}
+
+if [[ "$1" == "help" ]]
+then
+  printHelp
+elif [[ "$#" -lt 2 ]]
+then
+  echo "Wrong argument length. Expecting at least 2 argument representing dexdeps path, output path, followed by a list of jar or apk files in the Mainline module."
+else
+  genUsedByList "$@"
+fi
\ No newline at end of file