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

Commit caafe5c6 authored by Viorel Suman's avatar Viorel Suman
Browse files

Enable multiple consoles

This CL allows enabling of multiple consoles. The expected format
of "androidboot.console" kernel parameter is a list of available
consoles, as follows:

  androidboot.console=tty0:ttyS0

A service can be mapped to a specific console by providing the
optional argument, IE "tty0", to "console" service attribute as follows:

service fbconsole /system/bin/sh
    class core
    console tty0
    disabled
    user shell
    group shell log readproc
    seclabel u:r:shell:s0

Bug: None
Change-Id: I3f8556425c8651bd121995869700f18b23365d55
Tracked-On: https://jira01.devtools.intel.com/browse/BP-289
parent 371e7ea1
Loading
Loading
Loading
Loading
+16 −32
Original line number Diff line number Diff line
@@ -74,8 +74,7 @@ static int property_triggers_enabled = 0;

static char qemu[32];

int have_console;
std::string console_name = "/dev/console";
std::vector<std::string> console_names;
static time_t process_needs_restart;

const char *ENV[32];
@@ -298,38 +297,23 @@ static int keychord_init_action(const std::vector<std::string>& args)

static int console_init_action(const std::vector<std::string>& args)
{
    std::string console = property_get("ro.boot.console");
    if (!console.empty()) {
        console_name = "/dev/" + console;
    std::vector<std::string> consoles;
    std::string c_prop = property_get("ro.boot.console");
    if (c_prop.empty()) {
        // Property is missing, so check the system console by default.
        consoles.emplace_back(DEFAULT_CONSOLE);
    } else {
        consoles = android::base::Split(c_prop, ":");
    }

    int fd = open(console_name.c_str(), O_RDWR | O_CLOEXEC);
    if (fd >= 0)
        have_console = 1;
    close(fd);

    fd = open("/dev/tty0", O_WRONLY | O_CLOEXEC);
    if (fd >= 0) {
        const char *msg;
            msg = "\n"
        "\n"
        "\n"
        "\n"
        "\n"
        "\n"
        "\n"  // console is 40 cols x 30 lines
        "\n"
        "\n"
        "\n"
        "\n"
        "\n"
        "\n"
        "\n"
        "             A N D R O I D ";
        write(fd, msg, strlen(msg));
    for (const auto& c : consoles) {
        std::string console = "/dev/" + c;
        int fd = open(console.c_str(), O_RDWR | O_CLOEXEC);
        if (fd != -1) {
            console_names.emplace_back(c);
            close(fd);
        }

    }
    return 0;
}

+3 −2
Original line number Diff line number Diff line
@@ -18,16 +18,17 @@
#define _INIT_INIT_H

#include <string>
#include <vector>

class Action;
class Service;

#define COMMAND_RETRY_TIMEOUT 5
#define DEFAULT_CONSOLE "console"

extern const char *ENV[32];
extern bool waiting_for_exec;
extern int have_console;
extern std::string console_name;
extern std::vector<std::string> console_names;
extern struct selabel_handle *sehandle;
extern struct selabel_handle *sehandle_prop;

+5 −0
Original line number Diff line number Diff line
@@ -115,6 +115,11 @@ Options
Options are modifiers to services.  They affect how and when init
runs the service.

console [<console>]
  This service needs a console. The optional second parameter chooses a
  specific console instead of the default "/dev/console". The leading "/dev/"
  should be omitted, so "/dev/tty0" would be specified as just "console tty0".

critical
  This is a device-critical service. If it exits more than four times in
  four minutes, the device will reboot into recovery mode.
+8 −5
Original line number Diff line number Diff line
@@ -172,6 +172,7 @@ bool Service::HandleClass(const std::vector<std::string>& args, std::string* err

bool Service::HandleConsole(const std::vector<std::string>& args, std::string* err) {
    flags_ |= SVC_CONSOLE;
    console_ = args.size() > 1 ? args[1] : DEFAULT_CONSOLE;
    return true;
}

@@ -282,7 +283,7 @@ Service::OptionHandlerMap::Map& Service::OptionHandlerMap::map() const {
    constexpr std::size_t kMax = std::numeric_limits<std::size_t>::max();
    static const Map option_handlers = {
        {"class",       {1,     1,    &Service::HandleClass}},
        {"console",     {0,     0,    &Service::HandleConsole}},
        {"console",     {0,     1,    &Service::HandleConsole}},
        {"critical",    {0,     0,    &Service::HandleCritical}},
        {"disabled",    {0,     0,    &Service::HandleDisabled}},
        {"group",       {1,     NR_SVC_SUPP_GIDS + 1, &Service::HandleGroup}},
@@ -329,7 +330,7 @@ bool Service::Start(const std::vector<std::string>& dynamic_args) {
    }

    bool needs_console = (flags_ & SVC_CONSOLE);
    if (needs_console && !have_console) {
    if (needs_console && console_names.empty()) {
        ERROR("service '%s' requires console\n", name_.c_str());
        flags_ |= SVC_DISABLED;
        return false;
@@ -606,10 +607,12 @@ void Service::ZapStdio() const {
}

void Service::OpenConsole() const {
    int fd;
    if ((fd = open(console_name.c_str(), O_RDWR)) < 0) {
        fd = open("/dev/null", O_RDWR);
    int fd = -1;
    if (std::find(console_names.begin(), console_names.end(), console_) != console_names.end()) {
        std::string c_path = "/dev/" + console_;
        fd = open(c_path.c_str(), O_RDWR);
    }
    if (fd == -1) fd = open("/dev/null", O_RDWR);
    ioctl(fd, TIOCSCTTY, 0);
    dup2(fd, 0);
    dup2(fd, 1);
+1 −0
Original line number Diff line number Diff line
@@ -129,6 +129,7 @@ private:

    std::string name_;
    std::string classname_;
    std::string console_;

    unsigned flags_;
    pid_t pid_;