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