1 /*
2 * Copyright (C) 2022 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #define ATRACE_TAG (ATRACE_TAG_THERMAL | ATRACE_TAG_HAL)
18
19 #include "thermal_watcher.h"
20
21 #include <android-base/file.h>
22 #include <android-base/logging.h>
23 #include <android-base/stringprintf.h>
24 #include <android-base/strings.h>
25 #include <cutils/uevent.h>
26 #include <dirent.h>
27 #include <linux/netlink.h>
28 #include <linux/thermal.h>
29 #include <sys/inotify.h>
30 #include <sys/resource.h>
31 #include <sys/types.h>
32 #include <utils/Trace.h>
33
34 #include <chrono>
35 #include <fstream>
36
37 #include "../thermal-helper.h"
38
39 namespace aidl {
40 namespace android {
41 namespace hardware {
42 namespace thermal {
43 namespace implementation {
44
45 namespace {
46
nlErrorHandle(struct sockaddr_nl * nla,struct nlmsgerr * err,void * arg)47 static int nlErrorHandle(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg) {
48 int *ret = reinterpret_cast<int *>(arg);
49 *ret = err->error;
50 LOG(ERROR) << __func__ << "nl_groups: " << nla->nl_groups << ", nl_pid: " << nla->nl_pid;
51
52 return NL_STOP;
53 }
54
nlFinishHandle(struct nl_msg * msg,void * arg)55 static int nlFinishHandle(struct nl_msg *msg, void *arg) {
56 int *ret = reinterpret_cast<int *>(arg);
57 *ret = 1;
58 struct nlmsghdr *nlh = nlmsg_hdr(msg);
59
60 LOG(VERBOSE) << __func__ << ": nlmsg type: " << nlh->nlmsg_type;
61
62 return NL_OK;
63 }
64
nlAckHandle(struct nl_msg * msg,void * arg)65 static int nlAckHandle(struct nl_msg *msg, void *arg) {
66 int *ret = reinterpret_cast<int *>(arg);
67 *ret = 1;
68 struct nlmsghdr *nlh = nlmsg_hdr(msg);
69
70 LOG(VERBOSE) << __func__ << ": nlmsg type: " << nlh->nlmsg_type;
71
72 return NL_OK;
73 }
74
nlSeqCheckHandle(struct nl_msg * msg,void * arg)75 static int nlSeqCheckHandle(struct nl_msg *msg, void *arg) {
76 int *ret = reinterpret_cast<int *>(arg);
77 *ret = 1;
78 struct nlmsghdr *nlh = nlmsg_hdr(msg);
79
80 LOG(VERBOSE) << __func__ << ": nlmsg type: " << nlh->nlmsg_type;
81
82 return NL_OK;
83 }
84
85 struct HandlerArgs {
86 const char *group;
87 int id;
88 };
89
nlSendMsg(struct nl_sock * sock,struct nl_msg * msg,int (* rx_handler)(struct nl_msg *,void *),void * data)90 static int nlSendMsg(struct nl_sock *sock, struct nl_msg *msg,
91 int (*rx_handler)(struct nl_msg *, void *), void *data) {
92 int err, done = 0;
93
94 std::unique_ptr<nl_cb, decltype(&nl_cb_put)> cb(nl_cb_alloc(NL_CB_DEFAULT), nl_cb_put);
95
96 err = nl_send_auto_complete(sock, msg);
97 if (err < 0)
98 return err;
99
100 err = 0;
101 nl_cb_err(cb.get(), NL_CB_CUSTOM, nlErrorHandle, &err);
102 nl_cb_set(cb.get(), NL_CB_FINISH, NL_CB_CUSTOM, nlFinishHandle, &done);
103 nl_cb_set(cb.get(), NL_CB_ACK, NL_CB_CUSTOM, nlAckHandle, &done);
104
105 if (rx_handler != NULL)
106 nl_cb_set(cb.get(), NL_CB_VALID, NL_CB_CUSTOM, rx_handler, data);
107
108 while (err == 0 && done == 0) nl_recvmsgs(sock, cb.get());
109
110 return err;
111 }
112
nlFamilyHandle(struct nl_msg * msg,void * arg)113 static int nlFamilyHandle(struct nl_msg *msg, void *arg) {
114 struct HandlerArgs *grp = reinterpret_cast<struct HandlerArgs *>(arg);
115 struct nlattr *tb[CTRL_ATTR_MAX + 1];
116 struct genlmsghdr *gnlh = (struct genlmsghdr *)nlmsg_data(nlmsg_hdr(msg));
117 struct nlattr *mcgrp;
118 int rem_mcgrp;
119
120 nla_parse(tb, CTRL_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL);
121
122 if (!tb[CTRL_ATTR_MCAST_GROUPS]) {
123 LOG(ERROR) << __func__ << "Multicast group not found";
124 return -1;
125 }
126
127 nla_for_each_nested(mcgrp, tb[CTRL_ATTR_MCAST_GROUPS], rem_mcgrp) {
128 struct nlattr *tb_mcgrp[CTRL_ATTR_MCAST_GRP_MAX + 1];
129
130 nla_parse(tb_mcgrp, CTRL_ATTR_MCAST_GRP_MAX, reinterpret_cast<nlattr *>(nla_data(mcgrp)),
131 nla_len(mcgrp), NULL);
132
133 if (!tb_mcgrp[CTRL_ATTR_MCAST_GRP_NAME] || !tb_mcgrp[CTRL_ATTR_MCAST_GRP_ID])
134 continue;
135
136 if (strncmp(reinterpret_cast<char *>(nla_data(tb_mcgrp[CTRL_ATTR_MCAST_GRP_NAME])),
137 grp->group, nla_len(tb_mcgrp[CTRL_ATTR_MCAST_GRP_NAME])) != 0)
138 continue;
139
140 grp->id = nla_get_u32(tb_mcgrp[CTRL_ATTR_MCAST_GRP_ID]);
141
142 break;
143 }
144
145 return 0;
146 }
147
nlGetMulticastId(struct nl_sock * sock,const char * family,const char * group)148 static int nlGetMulticastId(struct nl_sock *sock, const char *family, const char *group) {
149 int err = 0, ctrlid;
150 struct HandlerArgs grp = {
151 .group = group,
152 .id = -ENOENT,
153 };
154
155 std::unique_ptr<nl_msg, decltype(&nlmsg_free)> msg(nlmsg_alloc(), nlmsg_free);
156
157 ctrlid = genl_ctrl_resolve(sock, "nlctrl");
158
159 genlmsg_put(msg.get(), 0, 0, ctrlid, 0, 0, CTRL_CMD_GETFAMILY, 0);
160
161 nla_put_string(msg.get(), CTRL_ATTR_FAMILY_NAME, family);
162
163 err = nlSendMsg(sock, msg.get(), nlFamilyHandle, &grp);
164 if (err)
165 return err;
166
167 err = grp.id;
168 LOG(INFO) << group << " multicast_id: " << grp.id;
169
170 return err;
171 }
172
socketAddMembership(struct nl_sock * sock,const char * group)173 static bool socketAddMembership(struct nl_sock *sock, const char *group) {
174 int mcid = nlGetMulticastId(sock, THERMAL_GENL_FAMILY_NAME, group);
175 if (mcid < 0) {
176 LOG(ERROR) << "Failed to get multicast id: " << group;
177 return false;
178 }
179
180 if (nl_socket_add_membership(sock, mcid)) {
181 LOG(ERROR) << "Failed to add netlink socket membership: " << group;
182 return false;
183 }
184
185 LOG(INFO) << "Added netlink socket membership: " << group;
186 return true;
187 }
188
handleEvent(struct nl_msg * n,void * arg)189 static int handleEvent(struct nl_msg *n, void *arg) {
190 struct nlmsghdr *nlh = nlmsg_hdr(n);
191 struct genlmsghdr *glh = genlmsg_hdr(nlh);
192 struct nlattr *attrs[THERMAL_GENL_ATTR_MAX + 1];
193 int *tz_id = reinterpret_cast<int *>(arg);
194
195 genlmsg_parse(nlh, 0, attrs, THERMAL_GENL_ATTR_MAX, NULL);
196
197 if (glh->cmd == THERMAL_GENL_EVENT_TZ_TRIP_UP) {
198 LOG(INFO) << "THERMAL_GENL_EVENT_TZ_TRIP_UP";
199 if (attrs[THERMAL_GENL_ATTR_TZ_ID]) {
200 LOG(INFO) << "Thermal zone id: " << nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]);
201 *tz_id = nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]);
202 }
203 if (attrs[THERMAL_GENL_ATTR_TZ_TRIP_ID])
204 LOG(INFO) << "Thermal zone trip id: "
205 << nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_ID]);
206 }
207
208 if (glh->cmd == THERMAL_GENL_EVENT_TZ_TRIP_DOWN) {
209 LOG(INFO) << "THERMAL_GENL_EVENT_TZ_TRIP_DOWN";
210 if (attrs[THERMAL_GENL_ATTR_TZ_ID]) {
211 LOG(INFO) << "Thermal zone id: " << nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]);
212 *tz_id = nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]);
213 }
214 if (attrs[THERMAL_GENL_ATTR_TZ_TRIP_ID])
215 LOG(INFO) << "Thermal zone trip id: "
216 << nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_ID]);
217 }
218
219 if (glh->cmd == THERMAL_GENL_EVENT_TZ_GOV_CHANGE) {
220 LOG(INFO) << "THERMAL_GENL_EVENT_TZ_GOV_CHANGE";
221 if (attrs[THERMAL_GENL_ATTR_TZ_ID]) {
222 LOG(INFO) << "Thermal zone id: " << nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]);
223 *tz_id = nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]);
224 }
225 if (attrs[THERMAL_GENL_ATTR_GOV_NAME])
226 LOG(INFO) << "Governor name: " << nla_get_string(attrs[THERMAL_GENL_ATTR_GOV_NAME]);
227 }
228
229 if (glh->cmd == THERMAL_GENL_EVENT_TZ_CREATE) {
230 LOG(INFO) << "THERMAL_GENL_EVENT_TZ_CREATE";
231 if (attrs[THERMAL_GENL_ATTR_TZ_ID]) {
232 LOG(INFO) << "Thermal zone id: " << nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]);
233 *tz_id = nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]);
234 }
235 if (attrs[THERMAL_GENL_ATTR_TZ_NAME])
236 LOG(INFO) << "Thermal zone name: " << nla_get_string(attrs[THERMAL_GENL_ATTR_TZ_NAME]);
237 }
238
239 if (glh->cmd == THERMAL_GENL_EVENT_TZ_DELETE) {
240 LOG(INFO) << "THERMAL_GENL_EVENT_TZ_DELETE";
241 if (attrs[THERMAL_GENL_ATTR_TZ_ID]) {
242 LOG(INFO) << "Thermal zone id: " << nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]);
243 *tz_id = nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]);
244 }
245 }
246
247 if (glh->cmd == THERMAL_GENL_EVENT_TZ_DISABLE) {
248 LOG(INFO) << "THERMAL_GENL_EVENT_TZ_DISABLE";
249 if (attrs[THERMAL_GENL_ATTR_TZ_ID]) {
250 LOG(INFO) << "Thermal zone id: " << nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]);
251 *tz_id = nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]);
252 }
253 }
254
255 if (glh->cmd == THERMAL_GENL_EVENT_TZ_ENABLE) {
256 LOG(INFO) << "THERMAL_GENL_EVENT_TZ_ENABLE";
257 if (attrs[THERMAL_GENL_ATTR_TZ_ID]) {
258 LOG(INFO) << "Thermal zone id: " << nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]);
259 *tz_id = nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]);
260 }
261 }
262
263 if (glh->cmd == THERMAL_GENL_EVENT_TZ_TRIP_CHANGE) {
264 LOG(INFO) << "THERMAL_GENL_EVENT_TZ_TRIP_CHANGE";
265 if (attrs[THERMAL_GENL_ATTR_TZ_ID]) {
266 LOG(INFO) << "Thermal zone id: " << nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]);
267 *tz_id = nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]);
268 }
269 if (attrs[THERMAL_GENL_ATTR_TZ_TRIP_ID])
270 LOG(INFO) << "Trip id:: " << nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_ID]);
271 if (attrs[THERMAL_GENL_ATTR_TZ_TRIP_TYPE])
272 LOG(INFO) << "Trip type: " << nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_TYPE]);
273 if (attrs[THERMAL_GENL_ATTR_TZ_TRIP_TEMP])
274 LOG(INFO) << "Trip temp: " << nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_TEMP]);
275 if (attrs[THERMAL_GENL_ATTR_TZ_TRIP_HYST])
276 LOG(INFO) << "Trip hyst: " << nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_HYST]);
277 }
278
279 if (glh->cmd == THERMAL_GENL_EVENT_TZ_TRIP_ADD) {
280 LOG(INFO) << "THERMAL_GENL_EVENT_TZ_TRIP_ADD";
281 if (attrs[THERMAL_GENL_ATTR_TZ_ID])
282 LOG(INFO) << "Thermal zone id: " << nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]);
283 if (attrs[THERMAL_GENL_ATTR_TZ_TRIP_ID])
284 LOG(INFO) << "Trip id:: " << nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_ID]);
285 if (attrs[THERMAL_GENL_ATTR_TZ_TRIP_TYPE])
286 LOG(INFO) << "Trip type: " << nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_TYPE]);
287 if (attrs[THERMAL_GENL_ATTR_TZ_TRIP_TEMP])
288 LOG(INFO) << "Trip temp: " << nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_TEMP]);
289 if (attrs[THERMAL_GENL_ATTR_TZ_TRIP_HYST])
290 LOG(INFO) << "Trip hyst: " << nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_HYST]);
291 }
292
293 if (glh->cmd == THERMAL_GENL_EVENT_TZ_TRIP_DELETE) {
294 LOG(INFO) << "THERMAL_GENL_EVENT_TZ_TRIP_DELETE";
295 if (attrs[THERMAL_GENL_ATTR_TZ_ID]) {
296 LOG(INFO) << "Thermal zone id: " << nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]);
297 *tz_id = nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]);
298 }
299 if (attrs[THERMAL_GENL_ATTR_TZ_TRIP_ID])
300 LOG(INFO) << "Trip id:: " << nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_ID]);
301 }
302
303 if (glh->cmd == THERMAL_GENL_EVENT_CDEV_STATE_UPDATE) {
304 LOG(INFO) << "THERMAL_GENL_EVENT_CDEV_STATE_UPDATE";
305 if (attrs[THERMAL_GENL_ATTR_CDEV_ID])
306 LOG(INFO) << "Cooling device id: " << nla_get_u32(attrs[THERMAL_GENL_ATTR_CDEV_ID]);
307 if (attrs[THERMAL_GENL_ATTR_CDEV_CUR_STATE])
308 LOG(INFO) << "Cooling device current state: "
309 << nla_get_u32(attrs[THERMAL_GENL_ATTR_CDEV_CUR_STATE]);
310 }
311
312 if (glh->cmd == THERMAL_GENL_EVENT_CDEV_ADD) {
313 LOG(INFO) << "THERMAL_GENL_EVENT_CDEV_ADD";
314 if (attrs[THERMAL_GENL_ATTR_CDEV_NAME])
315 LOG(INFO) << "Cooling device name: " << nla_get_u32(attrs[THERMAL_GENL_ATTR_CDEV_NAME]);
316 if (attrs[THERMAL_GENL_ATTR_CDEV_ID])
317 LOG(INFO) << "Cooling device id: " << nla_get_u32(attrs[THERMAL_GENL_ATTR_CDEV_ID]);
318 if (attrs[THERMAL_GENL_ATTR_CDEV_MAX_STATE])
319 LOG(INFO) << "Cooling device max state: "
320 << nla_get_u32(attrs[THERMAL_GENL_ATTR_CDEV_MAX_STATE]);
321 }
322
323 if (glh->cmd == THERMAL_GENL_EVENT_CDEV_DELETE) {
324 LOG(INFO) << "THERMAL_GENL_EVENT_CDEV_DELETE";
325 if (attrs[THERMAL_GENL_ATTR_CDEV_ID])
326 LOG(INFO) << "Cooling device id: " << nla_get_u32(attrs[THERMAL_GENL_ATTR_CDEV_ID]);
327 }
328
329 if (glh->cmd == THERMAL_GENL_SAMPLING_TEMP) {
330 LOG(INFO) << "THERMAL_GENL_SAMPLING_TEMP";
331 if (attrs[THERMAL_GENL_ATTR_TZ_ID]) {
332 LOG(INFO) << "Thermal zone id: " << nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]);
333 *tz_id = nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]);
334 }
335 if (attrs[THERMAL_GENL_ATTR_TZ_TEMP])
336 LOG(INFO) << "Thermal zone temp: " << nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TEMP]);
337 }
338
339 return 0;
340 }
341
342 } // namespace
343
registerFilesToWatch(const std::set<std::string> & sensors_to_watch)344 void ThermalWatcher::registerFilesToWatch(const std::set<std::string> &sensors_to_watch) {
345 LOG(INFO) << "Uevent register file to watch...";
346 monitored_sensors_.insert(sensors_to_watch.begin(), sensors_to_watch.end());
347
348 uevent_fd_.reset((TEMP_FAILURE_RETRY(uevent_open_socket(64 * 1024, true))));
349 if (uevent_fd_.get() < 0) {
350 LOG(ERROR) << "failed to open uevent socket";
351 return;
352 }
353
354 fcntl(uevent_fd_, F_SETFL, O_NONBLOCK);
355
356 looper_->addFd(uevent_fd_.get(), 0, ::android::Looper::EVENT_INPUT, nullptr, nullptr);
357 sleep_ms_ = std::chrono::milliseconds(0);
358 last_update_time_ = boot_clock::now();
359 }
360
registerFilesToWatchNl(const std::set<std::string> & sensors_to_watch)361 void ThermalWatcher::registerFilesToWatchNl(const std::set<std::string> &sensors_to_watch) {
362 LOG(INFO) << "Thermal genl register file to watch...";
363 monitored_sensors_.insert(sensors_to_watch.begin(), sensors_to_watch.end());
364
365 sk_thermal = nl_socket_alloc();
366 if (!sk_thermal) {
367 LOG(ERROR) << "nl_socket_alloc failed";
368 return;
369 }
370
371 if (genl_connect(sk_thermal)) {
372 LOG(ERROR) << "genl_connect failed: sk_thermal";
373 return;
374 }
375
376 thermal_genl_fd_.reset(nl_socket_get_fd(sk_thermal));
377 if (thermal_genl_fd_.get() < 0) {
378 LOG(ERROR) << "Failed to create thermal netlink socket";
379 return;
380 }
381
382 if (!socketAddMembership(sk_thermal, THERMAL_GENL_EVENT_GROUP_NAME)) {
383 return;
384 }
385
386 /*
387 * Currently, only the update_temperature() will send thermal genl samlping events
388 * from kernel. To avoid thermal-hal busy because samlping events are sent
389 * too frequently, ignore thermal genl samlping events until we figure out how to use it.
390 *
391 if (!socketAddMembership(sk_thermal, THERMAL_GENL_SAMPLING_GROUP_NAME)) {
392 return;
393 }
394 */
395
396 fcntl(thermal_genl_fd_, F_SETFL, O_NONBLOCK);
397 looper_->addFd(thermal_genl_fd_.get(), 0, ::android::Looper::EVENT_INPUT, nullptr, nullptr);
398 sleep_ms_ = std::chrono::milliseconds(0);
399 last_update_time_ = boot_clock::now();
400 }
401
startWatchingDeviceFiles()402 bool ThermalWatcher::startWatchingDeviceFiles() {
403 if (cb_) {
404 auto ret = this->run("FileWatcherThread", -10);
405 if (ret != ::android::NO_ERROR) {
406 LOG(ERROR) << "ThermalWatcherThread start fail";
407 return false;
408 } else {
409 LOG(INFO) << "ThermalWatcherThread started";
410 return true;
411 }
412 }
413 return false;
414 }
parseUevent(std::set<std::string> * sensors_set)415 void ThermalWatcher::parseUevent(std::set<std::string> *sensors_set) {
416 bool thermal_event = false;
417 constexpr int kUeventMsgLen = 2048;
418 char msg[kUeventMsgLen + 2];
419 char *cp;
420
421 while (true) {
422 int n = uevent_kernel_multicast_recv(uevent_fd_.get(), msg, kUeventMsgLen);
423 if (n <= 0) {
424 if (errno != EAGAIN && errno != EWOULDBLOCK) {
425 LOG(ERROR) << "Error reading from Uevent Fd";
426 }
427 break;
428 }
429
430 if (n >= kUeventMsgLen) {
431 LOG(ERROR) << "Uevent overflowed buffer, discarding";
432 continue;
433 }
434
435 msg[n] = '\0';
436 msg[n + 1] = '\0';
437
438 cp = msg;
439 while (*cp) {
440 std::string uevent = cp;
441 auto findSubSystemThermal = uevent.find("SUBSYSTEM=thermal");
442 if (!thermal_event) {
443 if (::android::base::StartsWith(uevent, "SUBSYSTEM=")) {
444 if (findSubSystemThermal != std::string::npos) {
445 thermal_event = true;
446 } else {
447 break;
448 }
449 }
450 } else {
451 auto start_pos = uevent.find("NAME=");
452 if (start_pos != std::string::npos) {
453 start_pos += 5;
454 std::string name = uevent.substr(start_pos);
455 if (monitored_sensors_.find(name) != monitored_sensors_.end()) {
456 sensors_set->insert(name);
457 }
458 break;
459 }
460 }
461 while (*cp++) {
462 }
463 }
464 }
465 }
466
467 // TODO(b/175367921): Consider for potentially adding more type of event in the function
468 // instead of just add the sensors to the list.
parseGenlink(std::set<std::string> * sensors_set)469 void ThermalWatcher::parseGenlink(std::set<std::string> *sensors_set) {
470 int err = 0, done = 0, tz_id = -1;
471
472 std::unique_ptr<nl_cb, decltype(&nl_cb_put)> cb(nl_cb_alloc(NL_CB_DEFAULT), nl_cb_put);
473
474 nl_cb_err(cb.get(), NL_CB_CUSTOM, nlErrorHandle, &err);
475 nl_cb_set(cb.get(), NL_CB_FINISH, NL_CB_CUSTOM, nlFinishHandle, &done);
476 nl_cb_set(cb.get(), NL_CB_ACK, NL_CB_CUSTOM, nlAckHandle, &done);
477 nl_cb_set(cb.get(), NL_CB_SEQ_CHECK, NL_CB_CUSTOM, nlSeqCheckHandle, &done);
478 nl_cb_set(cb.get(), NL_CB_VALID, NL_CB_CUSTOM, handleEvent, &tz_id);
479
480 while (!done && !err) {
481 nl_recvmsgs(sk_thermal, cb.get());
482
483 if (tz_id < 0) {
484 break;
485 }
486
487 std::string name;
488 if (getThermalZoneTypeById(tz_id, &name) &&
489 monitored_sensors_.find(name) != monitored_sensors_.end()) {
490 sensors_set->insert(name);
491 }
492 }
493 }
494
wake()495 void ThermalWatcher::wake() {
496 looper_->wake();
497 }
498
threadLoop()499 bool ThermalWatcher::threadLoop() {
500 LOG(VERBOSE) << "ThermalWatcher polling...";
501
502 int fd;
503 std::set<std::string> sensors;
504
505 auto time_elapsed_ms = std::chrono::duration_cast<std::chrono::milliseconds>(boot_clock::now() -
506 last_update_time_);
507
508 if (time_elapsed_ms < sleep_ms_ &&
509 looper_->pollOnce(sleep_ms_.count(), &fd, nullptr, nullptr) >= 0) {
510 ATRACE_NAME("ThermalWatcher::threadLoop - receive event");
511 if (fd != uevent_fd_.get() && fd != thermal_genl_fd_.get()) {
512 return true;
513 } else if (fd == thermal_genl_fd_.get()) {
514 parseGenlink(&sensors);
515 } else if (fd == uevent_fd_.get()) {
516 parseUevent(&sensors);
517 }
518 // Ignore cb_ if uevent is not from monitored sensors
519 if (sensors.size() == 0) {
520 return true;
521 }
522 }
523
524 sleep_ms_ = cb_(sensors);
525 last_update_time_ = boot_clock::now();
526 return true;
527 }
528
529 } // namespace implementation
530 } // namespace thermal
531 } // namespace hardware
532 } // namespace android
533 } // namespace aidl
534