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