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
diff --git a/init/service.cpp b/init/service.cpp
index bdecc32..e7bbf7b 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -172,6 +172,7 @@
 
 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 @@
     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 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::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);