• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Frequently used words (click to add to your profile)

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

system/hardware/interfaces-mnstshlylh


Commit MetaInfo

Revisão78688b149314ec16cb2d90507a5908e5f2ba0fda (tree)
Hora2020-04-21 00:04:02
AutorChih-Wei Huang <cwhuang@linu...>
CommiterChih-Wei Huang

Mensagem de Log

Add powerbtnd thread

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

Mudança Sumário

Diff

--- a/suspend/1.0/default/SystemSuspend.cpp
+++ b/suspend/1.0/default/SystemSuspend.cpp
@@ -19,11 +19,15 @@
1919 #include <android-base/file.h>
2020 #include <android-base/logging.h>
2121 #include <android-base/properties.h>
22+#include <android-base/stringprintf.h>
2223 #include <android-base/strings.h>
2324 #include <google/protobuf/text_format.h>
2425 #include <hidl/Status.h>
2526 #include <hwbinder/IPCThreadState.h>
2627
28+#include <linux/uinput.h>
29+#include <dirent.h>
30+#include <poll.h>
2731 #include <sys/stat.h>
2832 #include <sys/types.h>
2933
@@ -32,9 +36,11 @@
3236 #include <string>
3337 #include <thread>
3438
39+using ::android::base::GetBoolProperty;
3540 using ::android::base::GetProperty;
3641 using ::android::base::ReadFdToString;
3742 using ::android::base::WriteStringToFd;
43+using ::android::base::StringPrintf;
3844 using ::android::hardware::Void;
3945 using ::std::string;
4046
@@ -49,6 +55,146 @@ static const char kSleepState[] = "mem";
4955 static constexpr char kSysPowerWakeLock[] = "/sys/power/wake_lock";
5056 static constexpr char kSysPowerWakeUnlock[] = "/sys/power/wake_unlock";
5157
58+class PowerbtndThread {
59+ public:
60+ PowerbtndThread();
61+ void sendKeyPower(bool longpress);
62+ void sendKeyWakeup();
63+
64+ private:
65+ void emitKey(int key_code, int val);
66+ void run();
67+ unique_fd mUinputFd;
68+};
69+
70+PowerbtndThread::PowerbtndThread()
71+ : mUinputFd(open("/dev/uinput", O_WRONLY | O_NDELAY))
72+{
73+ if (mUinputFd < 0) {
74+ LOG(ERROR) << "could not open uinput device: " << strerror(errno);
75+ return;
76+ }
77+
78+ struct uinput_user_dev ud;
79+ memset(&ud, 0, sizeof(ud));
80+ strcpy(ud.name, "Android Power Button");
81+ write(mUinputFd, &ud, sizeof(ud));
82+ ioctl(mUinputFd, UI_SET_EVBIT, EV_KEY);
83+ ioctl(mUinputFd, UI_SET_KEYBIT, KEY_POWER);
84+ ioctl(mUinputFd, UI_SET_KEYBIT, KEY_WAKEUP);
85+ ioctl(mUinputFd, UI_DEV_CREATE, 0);
86+
87+ std::thread([this] { run(); }).detach();
88+ LOG(INFO) << "automatic system suspend enabled";
89+}
90+
91+void PowerbtndThread::sendKeyPower(bool longpress)
92+{
93+ emitKey(KEY_POWER, 1);
94+ if (longpress) sleep(2);
95+ emitKey(KEY_POWER, 0);
96+}
97+
98+void PowerbtndThread::sendKeyWakeup()
99+{
100+ emitKey(KEY_WAKEUP, 1);
101+ emitKey(KEY_WAKEUP, 0);
102+}
103+
104+void PowerbtndThread::emitKey(int key_code, int val)
105+{
106+ struct input_event iev;
107+ iev.type = EV_KEY;
108+ iev.code = key_code;
109+ iev.value = val;
110+ iev.time.tv_sec = 0;
111+ iev.time.tv_usec = 0;
112+ write(mUinputFd, &iev, sizeof(iev));
113+ iev.type = EV_SYN;
114+ iev.code = SYN_REPORT;
115+ iev.value = 0;
116+ write(mUinputFd, &iev, sizeof(iev));
117+ LOG(INFO) << StringPrintf("send key %d (%d) on fd %d", key_code, val, mUinputFd.get());
118+}
119+
120+void PowerbtndThread::run()
121+{
122+ int cnt = 0, timeout = -1, pollres;
123+ bool longpress = true;
124+ bool doubleclick = GetBoolProperty("poweroff.doubleclick", false);
125+ struct pollfd pfds[3];
126+ const char *dirname = "/dev/input";
127+
128+ if (DIR *dir = opendir(dirname)) {
129+ struct dirent *de;
130+ while ((cnt < 3) && (de = readdir(dir))) {
131+ int fd;
132+ char name[PATH_MAX];
133+ if (de->d_name[0] != 'e') /* eventX */
134+ continue;
135+ snprintf(name, PATH_MAX, "%s/%s", dirname, de->d_name);
136+ fd = open(name, O_RDWR | O_NONBLOCK);
137+ if (fd < 0) {
138+ LOG(ERROR) << StringPrintf("could not open %s, %s", name, strerror(errno));
139+ continue;
140+ }
141+ name[sizeof(name) - 1] = '\0';
142+ if (ioctl(fd, EVIOCGNAME(sizeof(name) - 1), &name) < 1) {
143+ LOG(ERROR) << StringPrintf("could not get device name for %s, %s", name, strerror(errno));
144+ name[0] = '\0';
145+ }
146+ // TODO: parse /etc/excluded-input-devices.xml
147+ if (strcmp(name, "Power Button")) {
148+ close(fd);
149+ continue;
150+ }
151+
152+ LOG(INFO) << StringPrintf("open %s(%s) ok fd=%d", de->d_name, name, fd);
153+ pfds[cnt].events = POLLIN;
154+ pfds[cnt++].fd = fd;
155+ }
156+ closedir(dir);
157+ }
158+
159+ while (cnt > 0) {
160+ if ((pollres = poll(pfds, cnt, timeout)) < 0) {
161+ LOG(ERROR) << "poll error: " << strerror(errno);
162+ break;
163+ }
164+ LOG(VERBOSE) << "pollres=" << pollres << " timeout=" << timeout;
165+ if (pollres == 0) {
166+ LOG(INFO) << "timeout, send one power key";
167+ sendKeyPower(0);
168+ timeout = -1;
169+ longpress = true;
170+ continue;
171+ }
172+ for (int i = 0; i < cnt; ++i) {
173+ if (pfds[i].revents & POLLIN) {
174+ struct input_event iev;
175+ size_t res = read(pfds[i].fd, &iev, sizeof(iev));
176+ if (res < sizeof(iev)) {
177+ LOG(WARNING) << StringPrintf("insufficient input data(%zd)? fd=%d", res, pfds[i].fd);
178+ continue;
179+ }
180+ LOG(DEBUG) << StringPrintf("type=%d code=%d value=%d from fd=%d", iev.type, iev.code, iev.value, pfds[i].fd);
181+ if (iev.type == EV_KEY && iev.code == KEY_POWER && !iev.value) {
182+ if (!doubleclick || timeout > 0) {
183+ sendKeyPower(longpress);
184+ timeout = -1;
185+ } else {
186+ timeout = 1000; // one second
187+ }
188+ } else if (iev.type == EV_SYN && iev.code == SYN_REPORT && iev.value) {
189+ LOG(INFO) << "got a resuming event";
190+ longpress = false;
191+ timeout = 1000; // one second
192+ }
193+ }
194+ }
195+ }
196+}
197+
52198 // This function assumes that data in fd is small enough that it can be read in one go.
53199 // We use this function instead of the ones available in libbase because it doesn't block
54200 // indefinitely when reading from socket streams which are used for testing.
@@ -101,6 +247,7 @@ SystemSuspend::SystemSuspend(unique_fd wakeupCountFd, unique_fd stateFd, size_t
101247 : mSuspendCounter(0),
102248 mWakeupCountFd(std::move(wakeupCountFd)),
103249 mStateFd(std::move(stateFd)),
250+ mPwrbtnd(new PowerbtndThread()),
104251 mMaxStatsEntries(maxStatsEntries),
105252 mBaseSleepTime(baseSleepTime),
106253 mSleepTime(baseSleepTime),
@@ -259,6 +406,8 @@ void SystemSuspend::initAutosuspend() {
259406
260407 if (!success) {
261408 PLOG(VERBOSE) << "error writing to /sys/power/state";
409+ } else {
410+ mPwrbtnd->sendKeyWakeup();
262411 }
263412
264413 mControlService->notifyWakeup(success);
--- a/suspend/1.0/default/SystemSuspend.h
+++ b/suspend/1.0/default/SystemSuspend.h
@@ -46,6 +46,7 @@ using WakeLockIdType = std::string;
4646
4747 using namespace std::chrono_literals;
4848
49+class PowerbtndThread;
4950 class SystemSuspend;
5051
5152 std::string readFd(int fd);
@@ -90,6 +91,7 @@ class SystemSuspend : public ISystemSuspend {
9091 unique_fd mWakeupCountFd;
9192 unique_fd mStateFd;
9293 std::string mSleepState;
94+ PowerbtndThread *mPwrbtnd;
9395
9496 // mStats can be inconsistent with with mSuspendCounter since we use two separate locks to
9597 // protect these. However, since mStats is only for debugging we prioritize performance.
--- a/suspend/1.0/default/android.system.suspend@1.0-service.rc
+++ b/suspend/1.0/default/android.system.suspend@1.0-service.rc
@@ -1,5 +1,5 @@
11 service system_suspend /system/bin/hw/android.system.suspend@1.0-service
22 class hal
33 user system
4- group system wakelock
4+ group system wakelock uhid input
55 capabilities BLOCK_SUSPEND