• R/O
  • HTTP
  • SSH
  • HTTPS

コミット

タグ
未設定

よく使われているワード(クリックで追加)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

system/core


コミットメタ情報

リビジョンfa6adf9ae8fec2a9862187c7a5a39c197737b0af (tree)
日時2019-03-28 19:34:54
作者Chih-Wei Huang <cwhuang@linu...>
コミッターChih-Wei Huang

ログメッセージ

libsuspend: add powerbtnd thread

Also send wakeup key on resume to ensure the system wakes up normally.

変更サマリ

差分

--- a/libsuspend/autosuspend_wakeup_count.cpp
+++ b/libsuspend/autosuspend_wakeup_count.cpp
@@ -32,20 +32,28 @@
3232 #include <android-base/logging.h>
3333 #include <android-base/strings.h>
3434 #include <android-base/properties.h>
35+#include <android-base/stringprintf.h>
36+
37+#include <linux/uinput.h>
38+#include <dirent.h>
39+#include <poll.h>
3540
3641 #include "autosuspend_ops.h"
3742
3843 #define BASE_SLEEP_TIME 100000
3944 #define MAX_SLEEP_TIME 60000000
45+#define MAX_POWERBTNS 3
4046
4147 static constexpr char default_sleep_state[] = "mem";
4248 static constexpr char fallback_sleep_state[] = "freeze";
4349
4450 static int state_fd = -1;
51+static int uinput_fd = -1;
4552 static int wakeup_count_fd;
4653
4754 using android::base::GetProperty;
4855 using android::base::ReadFdToString;
56+using android::base::StringPrintf;
4957 using android::base::Trim;
5058 using android::base::WriteStringToFd;
5159
@@ -66,6 +74,151 @@ static void update_sleep_time(bool success) {
6674 sleep_time = MIN(sleep_time * 2, MAX_SLEEP_TIME);
6775 }
6876
77+static void emit_key(int ufd, int key_code, int val)
78+{
79+ struct input_event iev;
80+ iev.type = EV_KEY;
81+ iev.code = key_code;
82+ iev.value = val;
83+ iev.time.tv_sec = 0;
84+ iev.time.tv_usec = 0;
85+ write(ufd, &iev, sizeof(iev));
86+ iev.type = EV_SYN;
87+ iev.code = SYN_REPORT;
88+ iev.value = 0;
89+ write(ufd, &iev, sizeof(iev));
90+ LOG(INFO) << StringPrintf("send key %d (%d) on fd %d", key_code, val, ufd);
91+}
92+
93+static void send_key_wakeup(int ufd)
94+{
95+ emit_key(ufd, KEY_WAKEUP, 1);
96+ emit_key(ufd, KEY_WAKEUP, 0);
97+}
98+
99+static void send_key_power(int ufd, bool longpress)
100+{
101+ emit_key(ufd, KEY_POWER, 1);
102+ if (longpress) sleep(2);
103+ emit_key(ufd, KEY_POWER, 0);
104+}
105+
106+static int openfds(struct pollfd pfds[])
107+{
108+ int cnt = 0;
109+ const char *dirname = "/dev/input";
110+ struct dirent *de;
111+ DIR *dir;
112+
113+ if ((dir = opendir(dirname))) {
114+ while ((cnt < MAX_POWERBTNS) && (de = readdir(dir))) {
115+ int fd;
116+ char name[PATH_MAX];
117+ if (de->d_name[0] != 'e') /* eventX */
118+ continue;
119+ snprintf(name, PATH_MAX, "%s/%s", dirname, de->d_name);
120+ fd = open(name, O_RDWR | O_NONBLOCK);
121+ if (fd < 0) {
122+ LOG(ERROR) << StringPrintf("could not open %s, %s", name, strerror(errno));
123+ continue;
124+ }
125+ name[sizeof(name) - 1] = '\0';
126+ if (ioctl(fd, EVIOCGNAME(sizeof(name) - 1), &name) < 1) {
127+ LOG(ERROR) << StringPrintf("could not get device name for %s, %s", name, strerror(errno));
128+ name[0] = '\0';
129+ }
130+ // TODO: parse /etc/excluded-input-devices.xml
131+ if (strcmp(name, "Power Button")) {
132+ close(fd);
133+ continue;
134+ }
135+
136+ LOG(INFO) << StringPrintf("open %s(%s) ok fd=%d", de->d_name, name, fd);
137+ pfds[cnt].events = POLLIN;
138+ pfds[cnt++].fd = fd;
139+ }
140+ closedir(dir);
141+ }
142+
143+ return cnt;
144+}
145+
146+static void *powerbtnd_thread_func(void *arg __attribute__((unused)))
147+{
148+ int cnt, timeout, pollres;
149+ bool longpress = true;
150+ bool doubleclick = android::base::GetBoolProperty("poweroff.doubleclick", false);
151+ struct pollfd pfds[MAX_POWERBTNS];
152+
153+ timeout = -1;
154+ cnt = openfds(pfds);
155+
156+ while (cnt > 0) {
157+ if ((pollres = poll(pfds, cnt, timeout)) < 0) {
158+ LOG(ERROR) << "poll error: " << strerror(errno);
159+ break;
160+ }
161+ LOG(VERBOSE) << "pollres=" << pollres << " timeout=" << timeout;
162+ if (pollres == 0) {
163+ LOG(INFO) << "timeout, send one power key";
164+ send_key_power(uinput_fd, 0);
165+ timeout = -1;
166+ longpress = true;
167+ continue;
168+ }
169+ for (int i = 0; i < cnt; ++i) {
170+ if (pfds[i].revents & POLLIN) {
171+ struct input_event iev;
172+ size_t res = read(pfds[i].fd, &iev, sizeof(iev));
173+ if (res < sizeof(iev)) {
174+ LOG(WARNING) << StringPrintf("insufficient input data(%zd)? fd=%d", res, pfds[i].fd);
175+ continue;
176+ }
177+ LOG(DEBUG) << StringPrintf("type=%d code=%d value=%d from fd=%d", iev.type, iev.code, iev.value, pfds[i].fd);
178+ if (iev.type == EV_KEY && iev.code == KEY_POWER && !iev.value) {
179+ if (!doubleclick || timeout > 0) {
180+ send_key_power(uinput_fd, longpress);
181+ timeout = -1;
182+ } else {
183+ timeout = 1000; // one second
184+ }
185+ } else if (iev.type == EV_SYN && iev.code == SYN_REPORT && iev.value) {
186+ LOG(INFO) << "got a resuming event";
187+ longpress = false;
188+ timeout = 1000; // one second
189+ }
190+ }
191+ }
192+ }
193+
194+ return NULL;
195+}
196+
197+static void init_android_power_button()
198+{
199+ static pthread_t powerbtnd_thread;
200+ struct uinput_user_dev ud;
201+
202+ if (uinput_fd >= 0) return;
203+
204+ uinput_fd = open("/dev/uinput", O_WRONLY | O_NDELAY);
205+ if (uinput_fd < 0) {
206+ LOG(ERROR) << "could not open uinput device: " << strerror(errno);
207+ return;
208+ }
209+
210+ memset(&ud, 0, sizeof(ud));
211+ strcpy(ud.name, "Android Power Button");
212+ write(uinput_fd, &ud, sizeof(ud));
213+ ioctl(uinput_fd, UI_SET_EVBIT, EV_KEY);
214+ ioctl(uinput_fd, UI_SET_KEYBIT, KEY_POWER);
215+ ioctl(uinput_fd, UI_SET_KEYBIT, KEY_WAKEUP);
216+ ioctl(uinput_fd, UI_DEV_CREATE, 0);
217+
218+ pthread_create(&powerbtnd_thread, NULL, powerbtnd_thread_func, NULL);
219+ pthread_setname_np(powerbtnd_thread, "powerbtnd");
220+}
221+
69222 static bool sleep_state_available(const char *state)
70223 {
71224 std::string buf;
@@ -128,6 +281,9 @@ static void* suspend_thread_func(void* arg __attribute__((unused))) {
128281 if (WriteStringToFd(wakeup_count, wakeup_count_fd)) {
129282 LOG(VERBOSE) << "write " << sleep_state << " to " << sys_power_state;
130283 success = WriteStringToFd(sleep_state, state_fd);
284+ if (success) {
285+ send_key_wakeup(uinput_fd);
286+ }
131287
132288 void (*func)(bool success) = wakeup_func;
133289 if (func != NULL) {
@@ -266,5 +422,6 @@ struct autosuspend_ops autosuspend_wakeup_count_ops = {
266422 };
267423
268424 struct autosuspend_ops* autosuspend_wakeup_count_init(void) {
425+ init_android_power_button();
269426 return &autosuspend_wakeup_count_ops;
270427 }