Merge "Emulator: enhance logcat -Q to handle qemu pipe device"
am: a14b5bbd2c
Change-Id: Ib19541aa9b1a18764bfe631a5b0c5bfd7b13a285
diff --git a/logcat/logcat.cpp b/logcat/logcat.cpp
index 4da5030..8134936 100644
--- a/logcat/logcat.cpp
+++ b/logcat/logcat.cpp
@@ -41,6 +41,7 @@
#include <vector>
#include <android-base/file.h>
+#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <cutils/sched_policy.h>
@@ -1195,39 +1196,71 @@
} break;
case 'Q':
-#define KERNEL_OPTION "androidboot.logcat="
+#define LOGCAT_FILTER "androidboot.logcat="
+#define CONSOLE_PIPE_OPTION "androidboot.consolepipe="
#define CONSOLE_OPTION "androidboot.console="
+#define QEMU_PROPERTY "ro.kernel.qemu"
+#define QEMU_CMDLINE "qemu.cmdline"
// This is a *hidden* option used to start a version of logcat
// in an emulated device only. It basically looks for
// androidboot.logcat= on the kernel command line. If
// something is found, it extracts a log filter and uses it to
- // run the program. If nothing is found, the program should
- // quit immediately.
+ // run the program. The logcat output will go to consolepipe if
+ // androiboot.consolepipe (e.g. qemu_pipe) is given, otherwise,
+ // it goes to androidboot.console (e.g. tty)
{
- std::string cmdline;
- android::base::ReadFileToString("/proc/cmdline", &cmdline);
-
- const char* logcat = strstr(cmdline.c_str(), KERNEL_OPTION);
- // if nothing found or invalid filters, exit quietly
- if (!logcat) {
+ // if not in emulator, exit quietly
+ if (false == android::base::GetBoolProperty(QEMU_PROPERTY, false)) {
context->retval = EXIT_SUCCESS;
goto exit;
}
- const char* p = logcat + strlen(KERNEL_OPTION);
+ std::string cmdline = android::base::GetProperty(QEMU_CMDLINE, "");
+ if (cmdline.empty()) {
+ android::base::ReadFileToString("/proc/cmdline", &cmdline);
+ }
+
+ const char* logcatFilter = strstr(cmdline.c_str(), LOGCAT_FILTER);
+ // if nothing found or invalid filters, exit quietly
+ if (!logcatFilter) {
+ context->retval = EXIT_SUCCESS;
+ goto exit;
+ }
+
+ const char* p = logcatFilter + strlen(LOGCAT_FILTER);
const char* q = strpbrk(p, " \t\n\r");
if (!q) q = p + strlen(p);
forceFilters = std::string(p, q);
- // redirect our output to the emulator console
+ // redirect our output to the emulator console pipe or console
+ const char* consolePipe =
+ strstr(cmdline.c_str(), CONSOLE_PIPE_OPTION);
const char* console =
strstr(cmdline.c_str(), CONSOLE_OPTION);
- if (!console) break;
- p = console + strlen(CONSOLE_OPTION);
+ if (consolePipe) {
+ p = consolePipe + strlen(CONSOLE_PIPE_OPTION);
+ } else if (console) {
+ p = console + strlen(CONSOLE_OPTION);
+ } else {
+ context->retval = EXIT_FAILURE;
+ goto exit;
+ }
+
q = strpbrk(p, " \t\n\r");
int len = q ? q - p : strlen(p);
std::string devname = "/dev/" + std::string(p, len);
+ std::string pipePurpose("pipe:logcat");
+ if (consolePipe) {
+ // example: "qemu_pipe,pipe:logcat"
+ // upon opening of /dev/qemu_pipe, the "pipe:logcat"
+ // string with trailing '\0' should be written to the fd
+ size_t pos = devname.find(",");
+ if (pos != std::string::npos) {
+ pipePurpose = devname.substr(pos + 1);
+ devname = devname.substr(0, pos);
+ }
+ }
cmdline.erase();
if (context->error) {
@@ -1239,6 +1272,16 @@
devname.erase();
if (!fp) break;
+ if (consolePipe) {
+ // need the trailing '\0'
+ if(!android::base::WriteFully(fileno(fp), pipePurpose.c_str(),
+ pipePurpose.size() + 1)) {
+ fclose(fp);
+ context->retval = EXIT_FAILURE;
+ goto exit;
+ }
+ }
+
// close output and error channels, replace with console
android::close_output(context);
android::close_error(context);