keychords.c revision a866695ebe3a396a0ec411c0f99e0921c74c0fd2
1a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross/*
2a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross * Copyright (C) 2010 The Android Open Source Project
3a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross *
4a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross * Licensed under the Apache License, Version 2.0 (the "License");
5a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross * you may not use this file except in compliance with the License.
6a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross * You may obtain a copy of the License at
7a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross *
8a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross *      http://www.apache.org/licenses/LICENSE-2.0
9a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross *
10a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross * Unless required by applicable law or agreed to in writing, software
11a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross * distributed under the License is distributed on an "AS IS" BASIS,
12a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross * See the License for the specific language governing permissions and
14a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross * limitations under the License.
15a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross */
16a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross
17a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross#include <errno.h>
18a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross#include <fcntl.h>
19a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross#include <stdlib.h>
20a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross#include <sys/stat.h>
21a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross#include <sys/types.h>
22a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross#include <linux/keychord.h>
23a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross
24a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross#include "init.h"
25a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross#include "property_service.h"
26a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross
27a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Crossstatic struct input_keychord *keychords = 0;
28a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Crossstatic int keychords_count = 0;
29a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Crossstatic int keychords_length = 0;
30a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Crossstatic int keychord_fd = -1;
31a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross
32a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Crossvoid add_service_keycodes(struct service *svc)
33a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross{
34a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross    struct input_keychord *keychord;
35a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross    int i, size;
36a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross
37a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross    if (svc->keycodes) {
38a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross        /* add a new keychord to the list */
39a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross        size = sizeof(*keychord) + svc->nkeycodes * sizeof(keychord->keycodes[0]);
40a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross        keychords = realloc(keychords, keychords_length + size);
41a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross        if (!keychords) {
42a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross            ERROR("could not allocate keychords\n");
43a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross            keychords_length = 0;
44a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross            keychords_count = 0;
45a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross            return;
46a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross        }
47a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross
48a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross        keychord = (struct input_keychord *)((char *)keychords + keychords_length);
49a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross        keychord->version = KEYCHORD_VERSION;
50a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross        keychord->id = keychords_count + 1;
51a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross        keychord->count = svc->nkeycodes;
52a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross        svc->keychord_id = keychord->id;
53a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross
54a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross        for (i = 0; i < svc->nkeycodes; i++) {
55a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross            keychord->keycodes[i] = svc->keycodes[i];
56a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross        }
57a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross        keychords_count++;
58a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross        keychords_length += size;
59a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross    }
60a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross}
61a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross
62a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Crossvoid keychord_init()
63a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross{
64a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross    int fd, ret;
65a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross
66a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross    service_for_each(add_service_keycodes);
67a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross
68a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross    /* nothing to do if no services require keychords */
69a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross    if (!keychords)
70a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross        return;
71a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross
72a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross    fd = open("/dev/keychord", O_RDWR);
73a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross    if (fd < 0) {
74a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross        ERROR("could not open /dev/keychord\n");
75a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross        return;
76a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross    }
77a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross    fcntl(fd, F_SETFD, FD_CLOEXEC);
78a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross
79a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross    ret = write(fd, keychords, keychords_length);
80a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross    if (ret != keychords_length) {
81a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross        ERROR("could not configure /dev/keychord %d (%d)\n", ret, errno);
82a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross        close(fd);
83a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross        fd = -1;
84a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross    }
85a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross
86a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross    free(keychords);
87a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross    keychords = 0;
88a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross
89a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross    keychord_fd = fd;
90a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross}
91a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross
92a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Crossvoid handle_keychord()
93a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross{
94a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross    struct service *svc;
95a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross    const char* debuggable;
96a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross    const char* adb_enabled;
97a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross    int ret;
98a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross    __u16 id;
99a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross
100a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross    // only handle keychords if ro.debuggable is set or adb is enabled.
101a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross    // the logic here is that bugreports should be enabled in userdebug or eng builds
102a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross    // and on user builds for users that are developers.
103a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross    debuggable = property_get("ro.debuggable");
104a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross    adb_enabled = property_get("init.svc.adbd");
105a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross    if ((debuggable && !strcmp(debuggable, "1")) ||
106a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross        (adb_enabled && !strcmp(adb_enabled, "running"))) {
107a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross        ret = read(keychord_fd, &id, sizeof(id));
108a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross        if (ret != sizeof(id)) {
109a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross            ERROR("could not read keychord id\n");
110a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross            return;
111a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross        }
112a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross
113a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross        svc = service_find_by_keychord(id);
114a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross        if (svc) {
115a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross            INFO("starting service %s from keychord\n", svc->name);
116a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross            service_start(svc, NULL);
117a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross        } else {
118a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross            ERROR("service for keychord %d not found\n", id);
119a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross        }
120a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross    }
121a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross}
122a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross
123a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Crossint get_keychord_fd()
124a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross{
125a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross    return keychord_fd;
126a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross}
127