Android-x86
Fork
Donation

  • R/O
  • HTTP
  • SSH
  • HTTPS

hardware-libhardware_legacy: Commit

hardware/libhardware_legacy


Commit MetaInfo

Revisión1d378ad170a6a267246b29c0dc10d5fd75c77912 (tree)
Tiempo2013-07-25 17:43:53
AutorChih-Wei Huang <cw_huang@htc....>
CommiterChih-Wei Huang

Log Message

add powerbtnd to simulate long press of power button.

On x86 PC, power button usually generates key press and release events
simultaneously. However, the android framework expects a long press
of power button to invoke the power off dialog. The daemon simulates a
long press of power button,

On poweroff.doubleclick=0, one click to power button invokes poweroff
dialog directly.

On poweroff.doubleclick=1, one click to power button suspends the system,
while double click in one second invokes poweroff dialog.

A target needs to add excluded-input-devices.xml to exclude
'Power Button' from processing by EventHub.

Cambiar Resumen

Diferencia incremental

--- a/Android.mk
+++ b/Android.mk
@@ -44,6 +44,17 @@ LOCAL_SHARED_LIBRARIES := libcutils
4444
4545 include $(BUILD_SHARED_LIBRARY)
4646
47+# powerbtn executable
48+include $(CLEAR_VARS)
49+
50+LOCAL_SRC_FILES := power/powerbtnd.c
51+
52+LOCAL_MODULE := powerbtnd
53+LOCAL_MODULE_TAGS := optional
54+LOCAL_SHARED_LIBRARIES := liblog libcutils
55+
56+include $(BUILD_EXECUTABLE)
57+
4758 # legacy_audio builds it's own set of libraries that aren't linked into
4859 # hardware_legacy
4960 include $(LEGACY_AUDIO_MAKEFILES)
--- /dev/null
+++ b/power/powerbtnd.c
@@ -0,0 +1,147 @@
1+/**
2+ * A daemon to simulate power button of Android
3+ *
4+ * Copyright (C) 2011-2012 The Android-x86 Open Source Project
5+ *
6+ * by Chih-Wei Huang <cwhuang@linux.org.tw>
7+ *
8+ * Licensed under GPLv2 or later
9+ *
10+ **/
11+
12+#define LOG_TAG "powerbtn"
13+
14+#include <sys/stat.h>
15+#include <poll.h>
16+#include <fcntl.h>
17+#include <errno.h>
18+#include <dirent.h>
19+#include <cutils/log.h>
20+#include <linux/input.h>
21+#include <linux/uinput.h>
22+#include <cutils/properties.h>
23+
24+const int MAX_POWERBTNS = 3;
25+
26+int openfds(struct pollfd pfds[])
27+{
28+ int cnt = 0;
29+ const char *dirname = "/dev/input";
30+ DIR *dir;
31+ if ((dir = opendir(dirname))) {
32+ int fd;
33+ struct dirent *de;
34+ while ((de = readdir(dir))) {
35+ if (de->d_name[0] != 'e') // eventX
36+ continue;
37+ char name[PATH_MAX];
38+ snprintf(name, PATH_MAX, "%s/%s", dirname, de->d_name);
39+ fd = open(name, O_RDWR | O_NONBLOCK);
40+ if (fd < 0) {
41+ ALOGE("could not open %s, %s", name, strerror(errno));
42+ continue;
43+ }
44+ name[sizeof(name) - 1] = '\0';
45+ if (ioctl(fd, EVIOCGNAME(sizeof(name) - 1), &name) < 1) {
46+ ALOGE("could not get device name for %s, %s\n", name, strerror(errno));
47+ name[0] = '\0';
48+ }
49+
50+ // TODO: parse /etc/excluded-input-devices.xml
51+ if (!strcmp(name, "Power Button")) {
52+ ALOGI("open %s(%s) ok", de->d_name, name);
53+ pfds[cnt].events = POLLIN;
54+ pfds[cnt++].fd = fd;
55+ if (cnt < MAX_POWERBTNS)
56+ continue;
57+ else
58+ break;
59+ }
60+ close(fd);
61+ }
62+ closedir(dir);
63+ }
64+
65+ return cnt;
66+}
67+
68+void send_power(int ufd, int down)
69+{
70+ struct input_event iev;
71+ iev.type = EV_KEY;
72+ iev.code = KEY_POWER;
73+ iev.value = down;
74+ write(ufd, &iev, sizeof(iev));
75+ iev.type = EV_SYN;
76+ iev.code = SYN_REPORT;
77+ iev.value = 0;
78+ write(ufd, &iev, sizeof(iev));
79+}
80+
81+void simulate_powerkey(int ufd, int longpress)
82+{
83+ send_power(ufd, 1);
84+ if (longpress)
85+ sleep(2);
86+ send_power(ufd, 0);
87+}
88+
89+int main()
90+{
91+ struct pollfd pfds[MAX_POWERBTNS];
92+ int cnt = openfds(pfds);
93+ int timeout = -1;
94+ char prop[PROPERTY_VALUE_MAX];
95+
96+ int ufd = open("/dev/uinput", O_WRONLY | O_NDELAY);
97+ if (ufd >= 0) {
98+ struct uinput_user_dev ud;
99+ memset(&ud, 0, sizeof(ud));
100+ strcpy(ud.name, "Android Power Button");
101+ write(ufd, &ud, sizeof(ud));
102+ ioctl(ufd, UI_SET_EVBIT, EV_KEY);
103+ ioctl(ufd, UI_SET_KEYBIT, KEY_POWER);
104+ ioctl(ufd, UI_DEV_CREATE, 0);
105+ } else {
106+ ALOGE("could not open uinput device: %s", strerror(errno));
107+ return -1;
108+ }
109+
110+ property_get("poweroff.doubleclick", prop, NULL);
111+
112+ for (;;) {
113+ int i;
114+ int pollres = poll(pfds, cnt, timeout) ;
115+ ALOGV("pollres=%d %d\n", pollres, timeout);
116+ if (pollres < 0) {
117+ ALOGE("poll error: %s", strerror(errno));
118+ break;
119+ }
120+ if (pollres == 0) { // timeout, send one power key
121+ simulate_powerkey(ufd, 0);
122+ timeout = -1;
123+ continue;
124+ }
125+ for (i = 0; i < cnt; ++i) {
126+ if (pfds[i].revents & POLLIN) {
127+ struct input_event iev;
128+ size_t res = read(pfds[i].fd, &iev, sizeof(iev));
129+ if (res < sizeof(iev)) {
130+ ALOGW("insufficient input data(%d)? fd=%d", res, pfds[i].fd);
131+ continue;
132+ }
133+ ALOGV("type=%d scancode=%d value=%d from fd=%d", iev.type, iev.code, iev.value, pfds[i].fd);
134+ if (iev.type == EV_KEY && iev.code == KEY_POWER && !iev.value) {
135+ if (prop[0] != '1' || timeout > 0) {
136+ simulate_powerkey(ufd, 1);
137+ timeout = -1;
138+ } else {
139+ timeout = 1000; // one second
140+ }
141+ }
142+ }
143+ }
144+ }
145+
146+ return 0;
147+}
Show on old repository browser