LogViewerActivity: destroy process when coroutine scope is cancelled

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
This commit is contained in:
Jason A. Donenfeld 2020-09-16 15:20:32 +02:00
parent bd1679b7e0
commit 44c2afbfba

View File

@ -193,49 +193,54 @@ class LogViewerActivity : AppCompatActivity() {
private suspend fun streamingLog() = withContext(Dispatchers.IO) { private suspend fun streamingLog() = withContext(Dispatchers.IO) {
val builder = ProcessBuilder().command("logcat", "-b", "all", "-v", "threadtime", "*:V") val builder = ProcessBuilder().command("logcat", "-b", "all", "-v", "threadtime", "*:V")
builder.environment()["LC_ALL"] = "C" builder.environment()["LC_ALL"] = "C"
val process = try { var process: Process? = null
builder.start() try {
} catch (e: IOException) { process = try {
e.printStackTrace() builder.start()
return@withContext } catch (e: IOException) {
} e.printStackTrace()
val stdout = BufferedReader(InputStreamReader(process!!.inputStream, StandardCharsets.UTF_8)) return@withContext
var haveScrolled = false }
val start = System.nanoTime() val stdout = BufferedReader(InputStreamReader(process!!.inputStream, StandardCharsets.UTF_8))
var startPeriod = start var haveScrolled = false
while (true) { val start = System.nanoTime()
val line = stdout.readLine() ?: break var startPeriod = start
rawLogLines.append(line) while (true) {
rawLogLines.append('\n') val line = stdout.readLine() ?: break
val logLine = parseLine(line) rawLogLines.append(line)
withContext(Dispatchers.Main.immediate) { rawLogLines.append('\n')
if (logLine != null) { val logLine = parseLine(line)
recyclerView?.let { withContext(Dispatchers.Main.immediate) {
val shouldScroll = haveScrolled && !it.canScrollVertically(1) if (logLine != null) {
logLines.add(logLine) recyclerView?.let {
if (haveScrolled) logAdapter.notifyDataSetChanged() val shouldScroll = haveScrolled && !it.canScrollVertically(1)
if (shouldScroll) logLines.add(logLine)
it.scrollToPosition(logLines.size - 1) if (haveScrolled) logAdapter.notifyDataSetChanged()
} if (shouldScroll)
} else { it.scrollToPosition(logLines.size - 1)
/* I'd prefer for the next line to be: }
} else {
/* I'd prefer for the next line to be:
* logLines.lastOrNull()?.msg += "\n$line" * logLines.lastOrNull()?.msg += "\n$line"
* However, as of writing, that causes the kotlin compiler to freak out and crash, spewing bytecode. * However, as of writing, that causes the kotlin compiler to freak out and crash, spewing bytecode.
*/ */
logLines.lastOrNull()?.apply { msg += "\n$line" } logLines.lastOrNull()?.apply { msg += "\n$line" }
if (haveScrolled) logAdapter.notifyDataSetChanged() if (haveScrolled) logAdapter.notifyDataSetChanged()
} }
if (!haveScrolled) { if (!haveScrolled) {
val end = System.nanoTime() val end = System.nanoTime()
val scroll = (end - start) > 1000000000L * 2.5 || !stdout.ready() val scroll = (end - start) > 1000000000L * 2.5 || !stdout.ready()
if (logLines.isNotEmpty() && (scroll || (end - startPeriod) > 1000000000L / 4)) { if (logLines.isNotEmpty() && (scroll || (end - startPeriod) > 1000000000L / 4)) {
logAdapter.notifyDataSetChanged() logAdapter.notifyDataSetChanged()
recyclerView?.scrollToPosition(logLines.size - 1) recyclerView?.scrollToPosition(logLines.size - 1)
startPeriod = end startPeriod = end
}
if (scroll) haveScrolled = true
} }
if (scroll) haveScrolled = true
} }
} }
} finally {
process?.destroy()
} }
} }