Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 94aab86d authored by bohu's avatar bohu Committed by Mark Salyzyn
Browse files

Emulator: enhance logcat -Q to handle qemu pipe device

Upon opening, qemu pipe (a.k.a. goldfish pipe) requires a purpose
string so that emulator can route the content to the right channel
on the host.

This CL will ask emulator to send the content to pipe based 'logcat'
service on the host.

Change-Id:  Icc71f81d5b95b64ea315fe10da82ff704416e449
parent 4278f711
Loading
Loading
Loading
Loading
+54 −11
Original line number Original line Diff line number Diff line
@@ -41,6 +41,7 @@
#include <vector>
#include <vector>


#include <android-base/file.h>
#include <android-base/file.h>
#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <android-base/strings.h>
#include <cutils/sched_policy.h>
#include <cutils/sched_policy.h>
@@ -1195,39 +1196,71 @@ static int __logcat(android_logcat_context_internal* context) {
            } break;
            } break;


            case 'Q':
            case 'Q':
#define KERNEL_OPTION "androidboot.logcat="
#define LOGCAT_FILTER "androidboot.logcat="
#define CONSOLE_PIPE_OPTION "androidboot.consolepipe="
#define CONSOLE_OPTION "androidboot.console="
#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
                // This is a *hidden* option used to start a version of logcat
                // in an emulated device only.  It basically looks for
                // in an emulated device only.  It basically looks for
                // androidboot.logcat= on the kernel command line.  If
                // androidboot.logcat= on the kernel command line.  If
                // something is found, it extracts a log filter and uses it to
                // something is found, it extracts a log filter and uses it to
                // run the program.  If nothing is found, the program should
                // run the program. The logcat output will go to consolepipe if
                // quit immediately.
                // androiboot.consolepipe (e.g. qemu_pipe) is given, otherwise,
                // it goes to androidboot.console (e.g. tty)
                {
                {
                    std::string cmdline;
                    // if not in emulator, exit quietly
                    if (false == android::base::GetBoolProperty(QEMU_PROPERTY, false)) {
                        context->retval = EXIT_SUCCESS;
                        goto exit;
                    }

                    std::string cmdline = android::base::GetProperty(QEMU_CMDLINE, "");
                    if (cmdline.empty()) {
                        android::base::ReadFileToString("/proc/cmdline", &cmdline);
                        android::base::ReadFileToString("/proc/cmdline", &cmdline);
                    }


                    const char* logcat = strstr(cmdline.c_str(), KERNEL_OPTION);
                    const char* logcatFilter = strstr(cmdline.c_str(), LOGCAT_FILTER);
                    // if nothing found or invalid filters, exit quietly
                    // if nothing found or invalid filters, exit quietly
                    if (!logcat) {
                    if (!logcatFilter) {
                        context->retval = EXIT_SUCCESS;
                        context->retval = EXIT_SUCCESS;
                        goto exit;
                        goto exit;
                    }
                    }


                    const char* p = logcat + strlen(KERNEL_OPTION);
                    const char* p = logcatFilter + strlen(LOGCAT_FILTER);
                    const char* q = strpbrk(p, " \t\n\r");
                    const char* q = strpbrk(p, " \t\n\r");
                    if (!q) q = p + strlen(p);
                    if (!q) q = p + strlen(p);
                    forceFilters = std::string(p, q);
                    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 =
                    const char* console =
                        strstr(cmdline.c_str(), CONSOLE_OPTION);
                        strstr(cmdline.c_str(), CONSOLE_OPTION);
                    if (!console) break;


                    if (consolePipe) {
                        p = consolePipe + strlen(CONSOLE_PIPE_OPTION);
                    } else if (console) {
                        p = console + strlen(CONSOLE_OPTION);
                        p = console + strlen(CONSOLE_OPTION);
                    } else {
                        context->retval = EXIT_FAILURE;
                        goto exit;
                    }

                    q = strpbrk(p, " \t\n\r");
                    q = strpbrk(p, " \t\n\r");
                    int len = q ? q - p : strlen(p);
                    int len = q ? q - p : strlen(p);
                    std::string devname = "/dev/" + std::string(p, len);
                    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();
                    cmdline.erase();


                    if (context->error) {
                    if (context->error) {
@@ -1239,6 +1272,16 @@ static int __logcat(android_logcat_context_internal* context) {
                    devname.erase();
                    devname.erase();
                    if (!fp) break;
                    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
                    // close output and error channels, replace with console
                    android::close_output(context);
                    android::close_output(context);
                    android::close_error(context);
                    android::close_error(context);