in android/tooling/rib-intellij-plugin/src/main/kotlin/com/uber/intellij/plugin/android/rib/io/LogcatRequestProcessor.kt [54:102]
override fun <T> execute(request: Request<T>): ListenableFuture<T> {
return service.submit(
Callable<T> {
val sequence: Int = counter.getAndIncrement() % MAX_SEQUENCE
// Send command to Android device via intent broadcast
var shellCommand: String = String.format(SHELL_COMMAND_TEMPLATE, sequence, request.command)
request.params.forEach {
shellCommand += String.format(PARAM_TEMPLATE, it.first, it.second)
}
val broadcastReceiver = StringMatchReceiver(ADB_BROADCAST_SUCCESS_MESSAGE)
request.device.executeShellCommand(shellCommand, broadcastReceiver)
if (!broadcastReceiver.matched) {
error("Failed to broadcast intent")
}
// Parse logcat for response in separate thread
val receiver = LogCatOutputReceiver(request.device, request.clazz, LogCatMessageParser())
val logCatCommand = String.format(LOGCAT_COMMAND_TEMPLATE, sequence)
request.device.executeShellCommand(logCatCommand, receiver)
// .. and wait for result value to be set
var timeWaitingMs: Long = 0
var retryCount = 0
while (result == null) {
Thread.sleep(SLEEP_INCREMENT)
timeWaitingMs += SLEEP_INCREMENT
if (timeWaitingMs > request.timeoutMs) {
if (retryCount++ > request.numRetries) {
error("Timed out waiting for response to be output in logcat")
} else {
request.device.executeShellCommand(logCatCommand, receiver)
timeWaitingMs = 0
}
}
if (error != null) {
error("Response could not be parsed: $error")
}
}
val response: Response<*> = result as Response<*>
if (response.errorDescription?.isNotEmpty() == true) {
error("Command failed: ${response.errorDescription}")
}
result as T
},
)
}