HostStubGen: Write verbose/debug log to a file
See below for the log filename.
Also disable an unimplemented flag.
Bug: 311174191
Test: ./scripts/run-all-tests.sh
Test: m framework-minus-apex.ravenwood
and examine console output and
out/soong/.intermediates/frameworks/base/framework-minus-apex.ravenwood-base/android_common/gen/hoststubgen_framework-minus-apex.log
Change-Id: I9997370c93e2fe90276d5f3e657d45d440ca0a59
diff --git a/Ravenwood.bp b/Ravenwood.bp
index ca73378..68095d4 100644
--- a/Ravenwood.bp
+++ b/Ravenwood.bp
@@ -32,6 +32,8 @@
cmd: "$(location hoststubgen) " +
"@$(location ravenwood/ravenwood-standard-options.txt) " +
+ "--debug-log $(location hoststubgen_framework-minus-apex.log) " +
+
"--out-impl-jar $(location ravenwood.jar) " +
"--gen-keep-all-file $(location hoststubgen_keep_all.txt) " +
@@ -52,6 +54,8 @@
// Following files are created just as FYI.
"hoststubgen_keep_all.txt",
"hoststubgen_dump.txt",
+
+ "hoststubgen_framework-minus-apex.log",
],
visibility: ["//visibility:private"],
}
diff --git a/ravenwood/ravenwood-standard-options.txt b/ravenwood/ravenwood-standard-options.txt
index 8ad21fa..f64f26d 100644
--- a/ravenwood/ravenwood-standard-options.txt
+++ b/ravenwood/ravenwood-standard-options.txt
@@ -1,6 +1,6 @@
# File containing standard options to HostStubGen for Ravenwood
---debug
+# --debug # To enable debug log on consone
# Keep all classes / methods / fields, but make the methods throw.
--default-throw
diff --git a/tools/hoststubgen/hoststubgen/invoketest/hoststubgen-invoke-test.sh b/tools/hoststubgen/hoststubgen/invoketest/hoststubgen-invoke-test.sh
index 91e6814..d97dd7c 100755
--- a/tools/hoststubgen/hoststubgen/invoketest/hoststubgen-invoke-test.sh
+++ b/tools/hoststubgen/hoststubgen/invoketest/hoststubgen-invoke-test.sh
@@ -235,10 +235,6 @@
"Duplicate or conflicting argument found: --in-jar" \
""
-EXTRA_ARGS="--quiet" run_hoststubgen_for_failure "Conflicting arg" \
- "Duplicate or conflicting argument found: --quiet" \
- ""
-
echo "All tests passed"
exit 0
\ No newline at end of file
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGen.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGen.kt
index dbcf3a5..4e0cd09 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGen.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGen.kt
@@ -239,7 +239,7 @@
errors: HostStubGenErrors,
) {
log.i("Converting %s into [stub: %s, impl: %s] ...", inJar, outStubJar, outImplJar)
- log.i("Checker is %s", if (enableChecker) "enabled" else "disabled")
+ log.i("ASM CheckClassAdapter is %s", if (enableChecker) "enabled" else "disabled")
val start = System.currentTimeMillis()
@@ -264,7 +264,7 @@
}
}
val end = System.currentTimeMillis()
- log.v("Done transforming the jar in %.1f second(s).", (end - start) / 1000.0)
+ log.i("Done transforming the jar in %.1f second(s).", (end - start) / 1000.0)
}
private fun <T> maybeWithZipOutputStream(filename: String?, block: (ZipOutputStream?) -> T): T {
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenLogger.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenLogger.kt
index 5e71a36..18065ba 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenLogger.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenLogger.kt
@@ -15,10 +15,12 @@
*/
package com.android.hoststubgen
-import java.io.OutputStream
-import java.io.PrintStream
+import java.io.BufferedOutputStream
+import java.io.FileOutputStream
+import java.io.PrintWriter
+import java.io.Writer
-val log: HostStubGenLogger = HostStubGenLogger()
+val log: HostStubGenLogger = HostStubGenLogger().setConsoleLogLevel(LogLevel.Info)
/** Logging level */
enum class LogLevel {
@@ -30,15 +32,13 @@
Debug,
}
-/** Simple logging class. */
-class HostStubGenLogger(
- private var out: PrintStream = System.out!!,
- var level: LogLevel = LogLevel.Info,
-) {
- companion object {
- private val sNullPrintStream: PrintStream = PrintStream(OutputStream.nullOutputStream())
- }
-
+/**
+ * Simple logging class.
+ *
+ * By default, it has no printers set. Use [setConsoleLogLevel] or [addFilePrinter] to actually
+ * write log.
+ */
+class HostStubGenLogger {
private var indentLevel: Int = 0
get() = field
set(value) {
@@ -47,6 +47,56 @@
}
private var indent: String = ""
+ private val printers: MutableList<LogPrinter> = mutableListOf()
+
+ private var consolePrinter: LogPrinter? = null
+
+ private var maxLogLevel = LogLevel.None
+
+ private fun updateMaxLogLevel() {
+ maxLogLevel = LogLevel.None
+
+ printers.forEach {
+ if (maxLogLevel < it.logLevel) {
+ maxLogLevel = it.logLevel
+ }
+ }
+ }
+
+ private fun addPrinter(printer: LogPrinter) {
+ printers.add(printer)
+ updateMaxLogLevel()
+ }
+
+ private fun removePrinter(printer: LogPrinter) {
+ printers.remove(printer)
+ updateMaxLogLevel()
+ }
+
+ fun setConsoleLogLevel(level: LogLevel): HostStubGenLogger {
+ // If there's already a console log printer set, remove it, and then add a new one
+ consolePrinter?.let {
+ removePrinter(it)
+ }
+ val cp = StreamPrinter(level, PrintWriter(System.out))
+ addPrinter(cp)
+ consolePrinter = cp
+
+ return this
+ }
+
+ fun addFilePrinter(level: LogLevel, logFilename: String): HostStubGenLogger {
+ addPrinter(StreamPrinter(level, PrintWriter(BufferedOutputStream(
+ FileOutputStream(logFilename)))))
+
+ return this
+ }
+
+ /** Flush all the printers */
+ fun flush() {
+ printers.forEach { it.flush() }
+ }
+
fun indent() {
indentLevel++
}
@@ -68,92 +118,71 @@
}
fun isEnabled(level: LogLevel): Boolean {
- return level.ordinal <= this.level.ordinal
+ return level.ordinal <= maxLogLevel.ordinal
}
- private fun println(message: String) {
- out.print(indent)
- out.println(message)
+ private fun println(level: LogLevel, message: String) {
+ printers.forEach {
+ if (it.logLevel.ordinal >= level.ordinal) {
+ it.println(level, indent, message)
+ }
+ }
+ }
+
+ private fun println(level: LogLevel, format: String, vararg args: Any?) {
+ if (isEnabled(level)) {
+ println(level, String.format(format, *args))
+ }
}
/** Log an error. */
fun e(message: String) {
- if (level.ordinal < LogLevel.Error.ordinal) {
- return
- }
- println(message)
+ println(LogLevel.Error, message)
}
/** Log an error. */
fun e(format: String, vararg args: Any?) {
- if (level.ordinal < LogLevel.Error.ordinal) {
- return
- }
- e(String.format(format, *args))
+ println(LogLevel.Error, format, *args)
}
/** Log a warning. */
fun w(message: String) {
- if (level.ordinal < LogLevel.Warn.ordinal) {
- return
- }
- println(message)
+ println(LogLevel.Warn, message)
}
/** Log a warning. */
fun w(format: String, vararg args: Any?) {
- if (level.ordinal < LogLevel.Warn.ordinal) {
- return
- }
- w(String.format(format, *args))
+ println(LogLevel.Warn, format, *args)
}
/** Log an info message. */
fun i(message: String) {
- if (level.ordinal < LogLevel.Info.ordinal) {
- return
- }
- println(message)
+ println(LogLevel.Info, message)
}
- /** Log a debug message. */
+ /** Log an info message. */
fun i(format: String, vararg args: Any?) {
- if (level.ordinal < LogLevel.Warn.ordinal) {
- return
- }
- i(String.format(format, *args))
+ println(LogLevel.Info, format, *args)
}
/** Log a verbose message. */
fun v(message: String) {
- if (level.ordinal < LogLevel.Verbose.ordinal) {
- return
- }
- println(message)
+ println(LogLevel.Verbose, message)
}
/** Log a verbose message. */
fun v(format: String, vararg args: Any?) {
- if (level.ordinal < LogLevel.Verbose.ordinal) {
- return
- }
- v(String.format(format, *args))
+ println(LogLevel.Verbose, format, *args)
}
/** Log a debug message. */
fun d(message: String) {
- if (level.ordinal < LogLevel.Debug.ordinal) {
- return
- }
- println(message)
+ println(LogLevel.Debug, message)
}
/** Log a debug message. */
fun d(format: String, vararg args: Any?) {
- if (level.ordinal < LogLevel.Warn.ordinal) {
- return
- }
- d(String.format(format, *args))
+ println(LogLevel.Debug, format, *args)
}
inline fun forVerbose(block: () -> Unit) {
@@ -168,31 +197,65 @@
}
}
- /** Return a stream for error. */
- fun getErrorPrintStream(): PrintStream {
- if (level.ordinal < LogLevel.Error.ordinal) {
- return sNullPrintStream
- }
-
- // TODO Apply indent
- return PrintStream(out)
+ /** Return a Writer for a given log level. */
+ fun getWriter(level: LogLevel): Writer {
+ return MultiplexingWriter(level)
}
- /** Return a stream for verbose messages. */
- fun getVerbosePrintStream(): PrintStream {
- if (level.ordinal < LogLevel.Verbose.ordinal) {
- return sNullPrintStream
+ private inner class MultiplexingWriter(val level: LogLevel) : Writer() {
+ private inline fun forPrinters(callback: (LogPrinter) -> Unit) {
+ printers.forEach {
+ if (it.logLevel.ordinal >= level.ordinal) {
+ callback(it)
+ }
+ }
}
- // TODO Apply indent
- return PrintStream(out)
+
+ override fun close() {
+ flush()
+ }
+
+ override fun flush() {
+ forPrinters {
+ it.flush()
+ }
+ }
+
+ override fun write(cbuf: CharArray, off: Int, len: Int) {
+ // TODO Apply indent
+ forPrinters {
+ it.write(cbuf, off, len)
+ }
+ }
+ }
+}
+
+private interface LogPrinter {
+ val logLevel: LogLevel
+
+ fun println(logLevel: LogLevel, indent: String, message: String)
+
+ // TODO: This should be removed once MultiplexingWriter starts applying indent, at which point
+ // println() should be used instead.
+ fun write(cbuf: CharArray, off: Int, len: Int)
+
+ fun flush()
+}
+
+private class StreamPrinter(
+ override val logLevel: LogLevel,
+ val out: PrintWriter,
+) : LogPrinter {
+ override fun println(logLevel: LogLevel, indent: String, message: String) {
+ out.print(indent)
+ out.println(message)
}
- /** Return a stream for debug messages. */
- fun getInfoPrintStream(): PrintStream {
- if (level.ordinal < LogLevel.Info.ordinal) {
- return sNullPrintStream
- }
- // TODO Apply indent
- return PrintStream(out)
+ override fun write(cbuf: CharArray, off: Int, len: Int) {
+ out.write(cbuf, off, len)
}
-}
\ No newline at end of file
+
+ override fun flush() {
+ out.flush()
+ }
+}
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenOptions.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenOptions.kt
index 0ae52af..d2ead18 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenOptions.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/HostStubGenOptions.kt
@@ -101,9 +101,7 @@
var defaultPolicy: SetOnce<FilterPolicy> = SetOnce(FilterPolicy.Remove),
- var logLevel: SetOnce<LogLevel> = SetOnce(LogLevel.Info),
-
- var cleanUpOnError: SetOnce<Boolean> = SetOnce(true),
+ var cleanUpOnError: SetOnce<Boolean> = SetOnce(false),
var enableClassChecker: SetOnce<Boolean> = SetOnce(false),
var enablePreTrace: SetOnce<Boolean> = SetOnce(false),
@@ -143,6 +141,11 @@
return name
}
+ fun setLogFile(level: LogLevel, filename: String) {
+ log.addFilePrinter(level, filename)
+ log.i("$level log file: $filename")
+ }
+
while (true) {
val arg = ai.nextArgOptional()
if (arg == null) {
@@ -161,9 +164,9 @@
// TODO: Write help
"-h", "--help" -> TODO("Help is not implemented yet")
- "-v", "--verbose" -> ret.logLevel.set(LogLevel.Verbose)
- "-d", "--debug" -> ret.logLevel.set(LogLevel.Debug)
- "-q", "--quiet" -> ret.logLevel.set(LogLevel.None)
+ "-v", "--verbose" -> log.setConsoleLogLevel(LogLevel.Verbose)
+ "-d", "--debug" -> log.setConsoleLogLevel(LogLevel.Debug)
+ "-q", "--quiet" -> log.setConsoleLogLevel(LogLevel.None)
"--in-jar" -> ret.inJar.setNextStringArg().ensureFileExists()
"--out-stub-jar" -> ret.outStubJar.setNextStringArg()
@@ -211,7 +214,7 @@
ret.keepStaticInitializerAnnotations.addUniqueAnnotationArg()
"--package-redirect" ->
- ret.packageRedirects += parsePackageRedirect(ai.nextArgRequired(arg))
+ ret.packageRedirects += parsePackageRedirect(nextArg())
"--annotation-allowed-classes-file" ->
ret.annotationAllowedClassesFile.setNextStringArg()
@@ -246,13 +249,15 @@
"--gen-input-dump-file" -> ret.inputJarDumpFile.setNextStringArg()
+ "--verbose-log" -> setLogFile(LogLevel.Verbose, nextArg())
+ "--debug-log" -> setLogFile(LogLevel.Debug, nextArg())
+
else -> throw ArgumentsException("Unknown option: $arg")
}
} catch (e: SetOnce.SetMoreThanOnceException) {
throw ArgumentsException("Duplicate or conflicting argument found: $arg")
}
}
- log.w(ret.toString())
if (!ret.inJar.isSet) {
throw ArgumentsException("Required option missing: --in-jar")
@@ -377,7 +382,6 @@
intersectStubJars=$intersectStubJars,
policyOverrideFile=$policyOverrideFile,
defaultPolicy=$defaultPolicy,
- logLevel=$logLevel,
cleanUpOnError=$cleanUpOnError,
enableClassChecker=$enableClassChecker,
enablePreTrace=$enablePreTrace,
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/Main.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/Main.kt
index 38ba0cc..4882c00 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/Main.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/Main.kt
@@ -17,6 +17,8 @@
package com.android.hoststubgen
+import java.io.PrintWriter
+
const val COMMAND_NAME = "HostStubGen"
/**
@@ -25,13 +27,12 @@
fun main(args: Array<String>) {
var success = false
var clanupOnError = false
+
try {
// Parse the command line arguments.
val options = HostStubGenOptions.parseArgs(args)
clanupOnError = options.cleanUpOnError.get
- log.level = options.logLevel.get
-
log.v("HostStubGen started")
log.v("Options: $options")
@@ -39,17 +40,18 @@
HostStubGen(options).run()
success = true
- } catch (e: Exception) {
+ } catch (e: Throwable) {
log.e("$COMMAND_NAME: Error: ${e.message}")
if (e !is UserErrorException) {
- e.printStackTrace(log.getErrorPrintStream())
+ e.printStackTrace(PrintWriter(log.getWriter(LogLevel.Error)))
}
if (clanupOnError) {
- TODO("clanupOnError is not implemented yet")
+ TODO("Remove output jars here")
}
+ } finally {
+ log.i("$COMMAND_NAME finished")
+ log.flush()
}
- log.v("HostStubGen finished")
-
System.exit(if (success) 0 else 1 )
}
diff --git a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/BaseAdapter.kt b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/BaseAdapter.kt
index f25e862..96e4a3f 100644
--- a/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/BaseAdapter.kt
+++ b/tools/hoststubgen/hoststubgen/src/com/android/hoststubgen/visitors/BaseAdapter.kt
@@ -16,6 +16,7 @@
package com.android.hoststubgen.visitors
import com.android.hoststubgen.HostStubGenErrors
+import com.android.hoststubgen.LogLevel
import com.android.hoststubgen.asm.ClassNodes
import com.android.hoststubgen.asm.getPackageNameFromClassName
import com.android.hoststubgen.asm.resolveClassName
@@ -229,7 +230,7 @@
): ClassVisitor {
var next = nextVisitor
- val verbosePrinter = PrintWriter(log.getVerbosePrintStream())
+ val verbosePrinter = PrintWriter(log.getWriter(LogLevel.Verbose))
// Inject TraceClassVisitor for debugging.
if (options.enablePostTrace) {