[Ravenwood] Dump supported APIs to CSV
Bug: 292141694
Test: ./ravenwood/scripts/ravenwood-stats-collector.sh
and examine the generated files
Change-Id: I3ea52f20ca54644f3ab724f23ae3e8f0e08e269f
diff --git a/Ravenwood.bp b/Ravenwood.bp
index 7c7c0e2..74382a6 100644
--- a/Ravenwood.bp
+++ b/Ravenwood.bp
@@ -34,6 +34,7 @@
"--debug-log $(location hoststubgen_framework-minus-apex.log) " +
"--stats-file $(location hoststubgen_framework-minus-apex_stats.csv) " +
+ "--supported-api-list-file $(location hoststubgen_framework-minus-apex_apis.csv) " +
"--out-impl-jar $(location ravenwood.jar) " +
@@ -58,6 +59,7 @@
"hoststubgen_framework-minus-apex.log",
"hoststubgen_framework-minus-apex_stats.csv",
+ "hoststubgen_framework-minus-apex_apis.csv",
],
visibility: ["//visibility:private"],
}
@@ -90,6 +92,18 @@
],
}
+genrule {
+ name: "framework-minus-apex.ravenwood.apis",
+ defaults: ["ravenwood-internal-only-visibility-genrule"],
+ cmd: "cp $(in) $(out)",
+ srcs: [
+ ":framework-minus-apex.ravenwood-base{hoststubgen_framework-minus-apex_apis.csv}",
+ ],
+ out: [
+ "hoststubgen_framework-minus-apex_apis.csv",
+ ],
+}
+
java_library {
name: "services.core-for-hoststubgen",
installable: false, // host only jar.
@@ -108,6 +122,7 @@
"--debug-log $(location hoststubgen_services.core.log) " +
"--stats-file $(location hoststubgen_services.core_stats.csv) " +
+ "--supported-api-list-file $(location hoststubgen_services.core_apis.csv) " +
"--out-impl-jar $(location ravenwood.jar) " +
@@ -132,6 +147,7 @@
"hoststubgen_services.core.log",
"hoststubgen_services.core_stats.csv",
+ "hoststubgen_services.core_apis.csv",
],
visibility: ["//visibility:private"],
}
@@ -161,6 +177,18 @@
],
}
+genrule {
+ name: "services.core.ravenwood.apis",
+ defaults: ["ravenwood-internal-only-visibility-genrule"],
+ cmd: "cp $(in) $(out)",
+ srcs: [
+ ":services.core.ravenwood-base{hoststubgen_services.core_apis.csv}",
+ ],
+ out: [
+ "hoststubgen_services.core_apis.csv",
+ ],
+}
+
java_library {
name: "services.core.ravenwood-jarjar",
installable: false,
diff --git a/ravenwood/Android.bp b/ravenwood/Android.bp
index 8905ad3..3337419 100644
--- a/ravenwood/Android.bp
+++ b/ravenwood/Android.bp
@@ -163,6 +163,8 @@
test_suites: ["general-tests"],
data: [
":framework-minus-apex.ravenwood.stats",
+ ":framework-minus-apex.ravenwood.apis",
":services.core.ravenwood.stats",
+ ":services.core.ravenwood.apis",
],
}
diff --git a/ravenwood/scripts/ravenwood-stats-collector.sh b/ravenwood/scripts/ravenwood-stats-collector.sh
index 4dcaa2b..b5843d0 100755
--- a/ravenwood/scripts/ravenwood-stats-collector.sh
+++ b/ravenwood/scripts/ravenwood-stats-collector.sh
@@ -17,8 +17,9 @@
set -e
-# Output file
-out=/tmp/ravenwood-stats-all.csv
+# Output files
+stats=/tmp/ravenwood-stats-all.csv
+apis=/tmp/ravenwood-apis-all.csv
# Where the input files are.
path=$ANDROID_BUILD_TOP/out/host/linux-x86/testcases/ravenwood-stats-checker/x86_64/
@@ -41,12 +42,28 @@
sed -e '1d' -e "s/^/$jar,/" $file
}
-collect() {
- echo 'Jar,PackageName,ClassName,SupportedMethods,TotalMethods'
- dump "framework-minus-apex" hoststubgen_framework-minus-apex_stats.csv
- dump "service.core" hoststubgen_services.core_stats.csv
+collect_stats() {
+ local out="$1"
+ {
+ echo 'Jar,PackageName,ClassName,SupportedMethods,TotalMethods'
+ dump "framework-minus-apex" hoststubgen_framework-minus-apex_stats.csv
+ dump "service.core" hoststubgen_services.core_stats.csv
+ } > "$out"
+
+ echo "Stats CVS created at $out"
}
-collect >$out
+collect_apis() {
+ local out="$1"
+ {
+ echo 'Jar,PackageName,ClassName,MethodName,Descriptor'
+ dump "framework-minus-apex" hoststubgen_framework-minus-apex_apis.csv
+ dump "service.core" hoststubgen_services.core_apis.csv
+ } > "$out"
-echo "Full dump CVS created at $out"
+ echo "API CVS created at $out"
+}
+
+
+collect_stats $stats
+collect_apis $apis
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGen.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGen.kt
index 803dc28..2f432cc 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGen.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGen.kt
@@ -85,9 +85,13 @@
// Dump statistics, if specified.
options.statsFile.ifSet {
- PrintWriter(it).use { pw -> stats.dump(pw) }
+ PrintWriter(it).use { pw -> stats.dumpOverview(pw) }
log.i("Dump file created at $it")
}
+ options.apiListFile.ifSet {
+ PrintWriter(it).use { pw -> stats.dumpApis(pw) }
+ log.i("API list file created at $it")
+ }
}
/**
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenOptions.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenOptions.kt
index 9ff798a..e192516 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenOptions.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenOptions.kt
@@ -110,6 +110,8 @@
var enableNonStubMethodCallDetection: SetOnce<Boolean> = SetOnce(false),
var statsFile: SetOnce<String?> = SetOnce(null),
+
+ var apiListFile: SetOnce<String?> = SetOnce(null),
) {
companion object {
@@ -255,6 +257,7 @@
"--debug-log" -> setLogFile(LogLevel.Debug, nextArg())
"--stats-file" -> ret.statsFile.setNextStringArg()
+ "--supported-api-list-file" -> ret.apiListFile.setNextStringArg()
else -> throw ArgumentsException("Unknown option: $arg")
}
@@ -392,6 +395,7 @@
enablePostTrace=$enablePostTrace,
enableNonStubMethodCallDetection=$enableNonStubMethodCallDetection,
statsFile=$statsFile,
+ apiListFile=$apiListFile,
}
""".trimIndent()
}
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenStats.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenStats.kt
index 50518e1..da61469 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenStats.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenStats.kt
@@ -29,8 +29,25 @@
private val stats = mutableMapOf<String, Stats>()
- fun onVisitPolicyForMethod(fullClassName: String, methodName: String, descriptor: String,
- policy: FilterPolicyWithReason, access: Int) {
+ data class Api(
+ val fullClassName: String,
+ val methodName: String,
+ val methodDesc: String,
+ )
+
+ private val apis = mutableListOf<Api>()
+
+ fun onVisitPolicyForMethod(
+ fullClassName: String,
+ methodName: String,
+ descriptor: String,
+ policy: FilterPolicyWithReason,
+ access: Int
+ ) {
+ if (policy.policy.isSupported) {
+ apis.add(Api(fullClassName, methodName, descriptor))
+ }
+
// Ignore methods that aren't public
if ((access and Opcodes.ACC_PUBLIC) == 0) return
// Ignore methods that are abstract
@@ -39,7 +56,7 @@
if (policy.isIgnoredForStats) return
val packageName = resolvePackageName(fullClassName)
- val className = resolveClassName(fullClassName)
+ val className = resolveOuterClassName(fullClassName)
// Ignore methods for certain generated code
if (className.endsWith("Proto")
@@ -60,11 +77,11 @@
classStats.total += 1
}
- fun dump(pw: PrintWriter) {
+ fun dumpOverview(pw: PrintWriter) {
pw.printf("PackageName,ClassName,SupportedMethods,TotalMethods\n")
- stats.forEach { (packageName, packageStats) ->
+ stats.toSortedMap().forEach { (packageName, packageStats) ->
if (packageStats.supported > 0) {
- packageStats.children.forEach { (className, classStats) ->
+ packageStats.children.toSortedMap().forEach { (className, classStats) ->
pw.printf("%s,%s,%d,%d\n", packageName, className,
classStats.supported, classStats.total)
}
@@ -72,12 +89,26 @@
}
}
+ fun dumpApis(pw: PrintWriter) {
+ pw.printf("PackageName,ClassName,MethodName,MethodDesc\n")
+ apis.sortedWith(compareBy({ it.fullClassName }, { it.methodName }, { it.methodDesc }))
+ .forEach { api ->
+ pw.printf(
+ "%s,%s,%s,%s\n",
+ csvEscape(resolvePackageName(api.fullClassName)),
+ csvEscape(resolveClassName(api.fullClassName)),
+ csvEscape(api.methodName),
+ csvEscape(api.methodDesc),
+ )
+ }
+ }
+
private fun resolvePackageName(fullClassName: String): String {
val start = fullClassName.lastIndexOf('/')
return fullClassName.substring(0, start).toHumanReadableClassName()
}
- private fun resolveClassName(fullClassName: String): String {
+ private fun resolveOuterClassName(fullClassName: String): String {
val start = fullClassName.lastIndexOf('/')
val end = fullClassName.indexOf('$')
if (end == -1) {
@@ -86,4 +117,13 @@
return fullClassName.substring(start + 1, end)
}
}
+
+ private fun resolveClassName(fullClassName: String): String {
+ val pos = fullClassName.lastIndexOf('/')
+ if (pos == -1) {
+ return fullClassName
+ } else {
+ return fullClassName.substring(pos + 1)
+ }
+ }
}
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/Utils.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/Utils.kt
index aa63d8d9..10179ee 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/Utils.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/Utils.kt
@@ -89,3 +89,10 @@
}
}
}
+
+/**
+ * Escape a string for a CSV field.
+ */
+fun csvEscape(value: String): String {
+ return "\"" + value.replace("\"", "\"\"") + "\""
+}