• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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