summaryrefslogtreecommitdiffstats
path: root/init
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2009-01-09 17:51:25 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2009-01-09 17:51:25 -0800
commit5ae090ed949cea9d1e7ab1552b455a229f8f9757 (patch)
tree555f686d531f29f4907d80655e7b0a7e69f2a180 /init
parent35237d135807af84bf9b0e5b8d7f8633e58db6f5 (diff)
downloadsystem_core-5ae090ed949cea9d1e7ab1552b455a229f8f9757.zip
system_core-5ae090ed949cea9d1e7ab1552b455a229f8f9757.tar.gz
system_core-5ae090ed949cea9d1e7ab1552b455a229f8f9757.tar.bz2
auto import from //branches/cupcake/...@125939
Diffstat (limited to 'init')
-rw-r--r--init/devices.c1
-rw-r--r--init/init.c157
-rw-r--r--init/init.h7
-rw-r--r--init/keywords.h1
-rw-r--r--init/parser.c45
5 files changed, 183 insertions, 28 deletions
diff --git a/init/devices.c b/init/devices.c
index f86eab9..44e263d 100644
--- a/init/devices.c
+++ b/init/devices.c
@@ -122,6 +122,7 @@ static struct perms_ devperms[] = {
{ "/dev/msm_pcm_out", 0660, AID_SYSTEM, AID_AUDIO, 1 },
{ "/dev/msm_pcm_in", 0660, AID_SYSTEM, AID_AUDIO, 1 },
{ "/dev/msm_pcm_ctl", 0660, AID_SYSTEM, AID_AUDIO, 1 },
+ { "/dev/msm_snd", 0660, AID_SYSTEM, AID_AUDIO, 1 },
{ "/dev/msm_mp3", 0660, AID_SYSTEM, AID_AUDIO, 1 },
{ "/dev/smd0", 0640, AID_RADIO, AID_RADIO, 0 },
{ "/dev/qmi", 0640, AID_RADIO, AID_RADIO, 0 },
diff --git a/init/init.c b/init/init.c
index 3616840..b8b4f40 100644
--- a/init/init.c
+++ b/init/init.c
@@ -37,6 +37,7 @@
#include <cutils/sockets.h>
#include <termios.h>
#include <linux/kd.h>
+#include <linux/keychord.h>
#include <sys/system_properties.h>
@@ -60,6 +61,9 @@ static char bootloader[32];
static char hardware[32];
static unsigned revision = 0;
static char qemu[32];
+static struct input_keychord *keychords = 0;
+static int keychords_count = 0;
+static int keychords_length = 0;
static void drain_action_queue(void);
@@ -233,7 +237,7 @@ void service_start(struct service *svc)
setpgid(0, getpid());
- /* as requested, set our gid, supplemental gids, and uid */
+ /* as requested, set our gid, supplemental gids, and uid */
if (svc->gid) {
setgid(svc->gid);
}
@@ -658,17 +662,101 @@ void open_devnull_stdio(void)
exit(1);
}
+void add_service_keycodes(struct service *svc)
+{
+ struct input_keychord *keychord;
+ int i, size;
+
+ if (svc->keycodes) {
+ /* add a new keychord to the list */
+ size = sizeof(*keychord) + svc->nkeycodes * sizeof(keychord->keycodes[0]);
+ keychords = realloc(keychords, keychords_length + size);
+ if (!keychords) {
+ ERROR("could not allocate keychords\n");
+ keychords_length = 0;
+ keychords_count = 0;
+ return;
+ }
+
+ keychord = (struct input_keychord *)((char *)keychords + keychords_length);
+ keychord->version = KEYCHORD_VERSION;
+ keychord->id = keychords_count + 1;
+ keychord->count = svc->nkeycodes;
+ svc->keychord_id = keychord->id;
+
+ for (i = 0; i < svc->nkeycodes; i++) {
+ keychord->keycodes[i] = svc->keycodes[i];
+ }
+ keychords_count++;
+ keychords_length += size;
+ }
+}
+
+int open_keychord()
+{
+ int fd, ret;
+
+ service_for_each(add_service_keycodes);
+
+ /* nothing to do if no services require keychords */
+ if (!keychords)
+ return -1;
+
+ fd = open("/dev/keychord", O_RDWR);
+ if (fd < 0) {
+ ERROR("could not open /dev/keychord\n");
+ return fd;
+ }
+ fcntl(fd, F_SETFD, FD_CLOEXEC);
+
+ ret = write(fd, keychords, keychords_length);
+ if (ret != keychords_length) {
+ ERROR("could not configure /dev/keychord %d (%d)\n", ret, errno);
+ close(fd);
+ fd = -1;
+ }
+
+ free(keychords);
+ keychords = 0;
+
+ return fd;
+}
+
+void handle_keychord(int fd)
+{
+ struct service *svc;
+ int ret;
+ __u16 id;
+
+ ret = read(fd, &id, sizeof(id));
+ if (ret != sizeof(id)) {
+ ERROR("could not read keychord id\n");
+ return;
+ }
+
+ svc = service_find_by_keychord(id);
+ if (svc) {
+ INFO("starting service %s from keychord\n", svc->name);
+ service_start(svc);
+ } else {
+ ERROR("service for keychord %d not found\n", id);
+ }
+}
+
int main(int argc, char **argv)
{
int device_fd = -1;
int property_set_fd = -1;
int signal_recv_fd = -1;
+ int keychord_fd = -1;
+ int fd_count;
int s[2];
int fd;
struct sigaction act;
char tmp[PROP_VALUE_MAX];
struct pollfd ufds[4];
char *tmpdev;
+ char* debuggable;
act.sa_handler = sigchld_handler;
act.sa_flags = SA_NOCLDSTOP;
@@ -721,6 +809,12 @@ int main(int argc, char **argv)
device_fd = device_init();
property_init();
+
+ // only listen for keychords if ro.debuggable is true
+ debuggable = property_get("ro.debuggable");
+ if (debuggable && !strcmp(debuggable, "1")) {
+ keychord_fd = open_keychord();
+ }
if (console[0]) {
snprintf(tmp, sizeof(tmp), "/dev/%s", console);
@@ -733,27 +827,27 @@ int main(int argc, char **argv)
close(fd);
if( load_565rle_image(INIT_IMAGE_FILE) ) {
- fd = open("/dev/tty0", O_WRONLY);
- if (fd >= 0) {
- const char *msg;
+ fd = open("/dev/tty0", O_WRONLY);
+ 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);
- }
+ "\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);
+ }
}
if (qemu[0])
@@ -823,6 +917,16 @@ int main(int argc, char **argv)
ufds[1].events = POLLIN;
ufds[2].fd = signal_recv_fd;
ufds[2].events = POLLIN;
+ fd_count = 3;
+
+ if (keychord_fd > 0) {
+ ufds[3].fd = keychord_fd;
+ ufds[3].events = POLLIN;
+ fd_count++;
+ } else {
+ ufds[3].events = 0;
+ ufds[3].revents = 0;
+ }
#if BOOTCHART
bootchart_count = bootchart_init();
@@ -836,11 +940,10 @@ int main(int argc, char **argv)
#endif
for(;;) {
- int nr, timeout = -1;
+ int nr, i, timeout = -1;
- ufds[0].revents = 0;
- ufds[1].revents = 0;
- ufds[2].revents = 0;
+ for (i = 0; i < fd_count; i++)
+ ufds[i].revents = 0;
drain_action_queue();
restart_processes();
@@ -861,7 +964,7 @@ int main(int argc, char **argv)
}
}
#endif
- nr = poll(ufds, 3, timeout);
+ nr = poll(ufds, fd_count, timeout);
if (nr <= 0)
continue;
@@ -878,6 +981,8 @@ int main(int argc, char **argv)
if (ufds[1].revents == POLLIN)
handle_property_set_fd(property_set_fd);
+ if (ufds[3].revents == POLLIN)
+ handle_keychord(keychord_fd);
}
return 0;
diff --git a/init/init.h b/init/init.h
index 4ff0c69..b686869 100644
--- a/init/init.h
+++ b/init/init.h
@@ -139,12 +139,19 @@ struct service {
int nargs;
char *args[1];
struct action onrestart; /* Actions to execute on restart. */
+
+ /* keycodes for triggering this service via /dev/keychord */
+ int *keycodes;
+ int nkeycodes;
+ int keychord_id;
};
int parse_config_file(const char *fn);
struct service *service_find_by_name(const char *name);
struct service *service_find_by_pid(pid_t pid);
+struct service *service_find_by_keychord(int keychord_id);
+void service_for_each(void (*func)(struct service *svc));
void service_for_each_class(const char *classname,
void (*func)(struct service *svc));
void service_for_each_flags(unsigned matchflags,
diff --git a/init/keywords.h b/init/keywords.h
index 058996e..6f47379 100644
--- a/init/keywords.h
+++ b/init/keywords.h
@@ -45,6 +45,7 @@ enum {
KEYWORD(ifup, COMMAND, 1, do_ifup)
KEYWORD(insmod, COMMAND, 1, do_insmod)
KEYWORD(import, COMMAND, 1, do_import)
+ KEYWORD(keycodes, OPTION, 0, 0)
KEYWORD(mkdir, COMMAND, 1, do_mkdir)
KEYWORD(mount, COMMAND, 3, do_mount)
KEYWORD(on, SECTION, 0, 0)
diff --git a/init/parser.c b/init/parser.c
index a51691b..6a22d24 100644
--- a/init/parser.c
+++ b/init/parser.c
@@ -158,6 +158,9 @@ int lookup_keyword(const char *s)
if (!strcmp(s, "nsmod")) return K_insmod;
if (!strcmp(s, "mport")) return K_import;
break;
+ case 'k':
+ if (!strcmp(s, "eycodes")) return K_keycodes;
+ break;
case 'l':
if (!strcmp(s, "oglevel")) return K_loglevel;
break;
@@ -183,7 +186,7 @@ int lookup_keyword(const char *s)
if (!strcmp(s, "tart")) return K_start;
if (!strcmp(s, "top")) return K_stop;
if (!strcmp(s, "ymlink")) return K_symlink;
- if (!strcmp(s, "ysclktz")) return K_sysclktz;
+ if (!strcmp(s, "ysclktz")) return K_sysclktz;
break;
case 't':
if (!strcmp(s, "rigger")) return K_trigger;
@@ -440,6 +443,29 @@ struct service *service_find_by_pid(pid_t pid)
return 0;
}
+struct service *service_find_by_keychord(int keychord_id)
+{
+ struct listnode *node;
+ struct service *svc;
+ list_for_each(node, &service_list) {
+ svc = node_to_item(node, struct service, slist);
+ if (svc->keychord_id == keychord_id) {
+ return svc;
+ }
+ }
+ return 0;
+}
+
+void service_for_each(void (*func)(struct service *svc))
+{
+ struct listnode *node;
+ struct service *svc;
+ list_for_each(node, &service_list) {
+ svc = node_to_item(node, struct service, slist);
+ func(svc);
+ }
+}
+
void service_for_each_class(const char *classname,
void (*func)(struct service *svc))
{
@@ -586,7 +612,7 @@ static void parse_line_service(struct parse_state *state, int nargs, char **args
{
struct service *svc = state->context;
struct command *cmd;
- int kw, kw_nargs;
+ int i, kw, kw_nargs;
if (nargs == 0) {
return;
@@ -624,6 +650,21 @@ static void parse_line_service(struct parse_state *state, int nargs, char **args
svc->nr_supp_gids = n - 2;
}
break;
+ case K_keycodes:
+ if (nargs < 2) {
+ parse_error(state, "keycodes option requires atleast one keycode\n");
+ } else {
+ svc->keycodes = malloc((nargs - 1) * sizeof(svc->keycodes[0]));
+ if (!svc->keycodes) {
+ parse_error(state, "could not allocate keycodes\n");
+ } else {
+ svc->nkeycodes = nargs - 1;
+ for (i = 1; i < nargs; i++) {
+ svc->keycodes[i - 1] = atoi(args[i]);
+ }
+ }
+ }
+ break;
case K_oneshot:
svc->flags |= SVC_ONESHOT;
break;