diff options
author | Viorel Suman <viorel.suman@intel.com> | 2016-03-09 17:50:10 +0200 |
---|---|---|
committer | Viorel Suman <viorel.suman@intel.com> | 2016-03-17 21:00:15 +0200 |
commit | caafe5c6204bc2066e6201a67ecd7cd1b3f8d015 (patch) | |
tree | ee1f184b3655bfbfdf739bf1ce1f5e4412fca4ca /init | |
parent | 371e7ea170d749489a0eb7085347f58b7be63734 (diff) | |
download | core-caafe5c6204bc2066e6201a67ecd7cd1b3f8d015.tar.gz core-caafe5c6204bc2066e6201a67ecd7cd1b3f8d015.tar.bz2 core-caafe5c6204bc2066e6201a67ecd7cd1b3f8d015.zip |
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
Diffstat (limited to 'init')
-rw-r--r-- | init/init.cpp | 48 | ||||
-rw-r--r-- | init/init.h | 5 | ||||
-rw-r--r-- | init/readme.txt | 5 | ||||
-rw-r--r-- | init/service.cpp | 13 | ||||
-rw-r--r-- | init/service.h | 1 |
5 files changed, 33 insertions, 39 deletions
diff --git a/init/init.cpp b/init/init.cpp index bac27df88..704597d2d 100644 --- a/init/init.cpp +++ b/init/init.cpp @@ -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; - } - - 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)); - close(fd); + 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, ":"); } + 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; } diff --git a/init/init.h b/init/init.h index b6a095b94..c844489ac 100644 --- a/init/init.h +++ b/init/init.h @@ -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; diff --git a/init/readme.txt b/init/readme.txt index ef85ccf1f..7d453c674 100644 --- a/init/readme.txt +++ b/init/readme.txt @@ -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. diff --git a/init/service.cpp b/init/service.cpp index bdecc324f..e7bbf7b20 100644 --- a/init/service.cpp +++ b/init/service.cpp @@ -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); diff --git a/init/service.h b/init/service.h index 35abde9b7..b003ca0cc 100644 --- a/init/service.h +++ b/init/service.h @@ -129,6 +129,7 @@ private: std::string name_; std::string classname_; + std::string console_; unsigned flags_; pid_t pid_; |