From 70daa67062c016eea1a30be2e1de0dcba1d23a13 Mon Sep 17 00:00:00 2001 From: Viorel Suman Date: Mon, 21 Mar 2016 10:08:07 +0200 Subject: [PATCH] Multiple consoles This CL allows enabling of multiple consoles. 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: I3b24e7f6848bbe5c6475f11334c04ec536e6af88 Tracked-On: https://jira01.devtools.intel.com/browse/BP-289 Signed-off-by: Viorel Suman --- init/init.cpp | 33 ++------------------------------- init/init.h | 3 +-- init/readme.txt | 7 +++++++ init/service.cpp | 25 ++++++++++++++++--------- init/service.h | 1 + 5 files changed, 27 insertions(+), 42 deletions(-) diff --git a/init/init.cpp b/init/init.cpp index bac27df88..9b7d10881 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::string default_console = "/dev/console"; static time_t process_needs_restart; const char *ENV[32]; @@ -300,36 +299,8 @@ static int console_init_action(const std::vector& args) { std::string console = property_get("ro.boot.console"); if (!console.empty()) { - console_name = "/dev/" + console; + default_console = "/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); - } - return 0; } diff --git a/init/init.h b/init/init.h index b6a095b94..0019337ca 100644 --- a/init/init.h +++ b/init/init.h @@ -26,8 +26,7 @@ class Service; extern const char *ENV[32]; extern bool waiting_for_exec; -extern int have_console; -extern std::string console_name; +extern std::string default_console; extern struct selabel_handle *sehandle; extern struct selabel_handle *sehandle_prop; diff --git a/init/readme.txt b/init/readme.txt index ef85ccf1f..aa372eb92 100644 --- a/init/readme.txt +++ b/init/readme.txt @@ -115,6 +115,13 @@ Options Options are modifiers to services. They affect how and when init runs the service. +console [] + This service needs a console. The optional second parameter chooses a + specific console instead of the default. The default "/dev/console" can + be changed by setting the "androidboot.console" kernel parameter. In + all cases 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..e509f46e2 100644 --- a/init/service.cpp +++ b/init/service.cpp @@ -172,6 +172,7 @@ bool Service::HandleClass(const std::vector& args, std::string* err bool Service::HandleConsole(const std::vector& args, std::string* err) { flags_ |= SVC_CONSOLE; + console_ = args.size() > 1 ? "/dev/" + args[1] : ""; return true; } @@ -282,7 +283,7 @@ Service::OptionHandlerMap::Map& Service::OptionHandlerMap::map() const { constexpr std::size_t kMax = std::numeric_limits::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,10 +330,18 @@ bool Service::Start(const std::vector& dynamic_args) { } bool needs_console = (flags_ & SVC_CONSOLE); - if (needs_console && !have_console) { - ERROR("service '%s' requires console\n", name_.c_str()); - flags_ |= SVC_DISABLED; - return false; + if (needs_console) { + if (console_.empty()) { + console_ = default_console; + } + + bool have_console = (open(console_.c_str(), O_RDWR | O_CLOEXEC) != -1); + if (!have_console) { + ERROR("service '%s' couldn't open console '%s': %s\n", + name_.c_str(), console_.c_str(), strerror(errno)); + flags_ |= SVC_DISABLED; + return false; + } } struct stat sb; @@ -606,10 +615,8 @@ 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 = open(console_.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_;