summaryrefslogtreecommitdiff
path: root/thermal
diff options
context:
space:
mode:
authordavidchao <davidchao@google.com>2020-10-26 19:41:29 +0800
committerdavidchao <davidchao@google.com>2021-01-05 21:29:19 +0800
commitd9a195e7202bf7690377a0e049337ad7db51617a (patch)
tree2608b4dd0e6432332722c469a157e645217b2a71 /thermal
parentf54f9cd93cead0c43083aeb1b8bb3bce33b535db (diff)
downloadpixel-d9a195e7202bf7690377a0e049337ad7db51617a.tar.gz
thermal: use thermal genl events from kernel to notify thermal-hal
Currently, thermal core cannot support multiple thermal zones with the same adc thermistor, so we use thermal genl events to notify thermal-hal when thermal sensor across the trip point. Bug: 170682696 Test: boot and thermal-hal can receive thernal genl events from kernel. Change-Id: Idf27cd6138e03e089832185d7de030f93c956373
Diffstat (limited to 'thermal')
-rw-r--r--thermal/Android.bp1
-rw-r--r--thermal/thermal-helper.cpp17
-rw-r--r--thermal/thermal-helper.h3
-rw-r--r--thermal/utils/thermal_watcher.cpp376
-rw-r--r--thermal/utils/thermal_watcher.h7
5 files changed, 402 insertions, 2 deletions
diff --git a/thermal/Android.bp b/thermal/Android.bp
index f67c1f36..4ba9a365 100644
--- a/thermal/Android.bp
+++ b/thermal/Android.bp
@@ -23,6 +23,7 @@ cc_binary {
"libhidlbase",
"libjsoncpp",
"libutils",
+ "libnl",
"libbinder_ndk",
"android.hardware.thermal@1.0",
"android.hardware.thermal@2.0",
diff --git a/thermal/thermal-helper.cpp b/thermal/thermal-helper.cpp
index 24b44e40..6ac03dd3 100644
--- a/thermal/thermal-helper.cpp
+++ b/thermal/thermal-helper.cpp
@@ -338,6 +338,23 @@ ThermalHelper::ThermalHelper(const NotificationCallback &cb)
}
}
+bool getThermalZoneTypeById(int tz_id, std::string *type) {
+ std::string tz_type;
+ std::string path =
+ android::base::StringPrintf("%s/%s%d/%s", kThermalSensorsRoot.data(),
+ kSensorPrefix.data(), tz_id, kThermalNameFile.data());
+ LOG(INFO) << "TZ Path: " << path;
+ if (!::android::base::ReadFileToString(path, &tz_type)) {
+ LOG(ERROR) << "Failed to read sensor: " << tz_type;
+ return false;
+ }
+
+ // Strip the newline.
+ *type = ::android::base::Trim(tz_type);
+ LOG(INFO) << "TZ type: " << *type;
+ return true;
+}
+
bool ThermalHelper::readCoolingDevice(std::string_view cooling_device,
CoolingDevice_2_0 *out) const {
// Read the file. If the file can't be read temp will be empty string.
diff --git a/thermal/thermal-helper.h b/thermal/thermal-helper.h
index 6d4af8c7..a03c21ce 100644
--- a/thermal/thermal-helper.h
+++ b/thermal/thermal-helper.h
@@ -73,6 +73,9 @@ using NotificationCallback = std::function<void(const Temperature_2_0 &t)>;
using NotificationTime = std::chrono::time_point<std::chrono::steady_clock>;
using CdevRequestStatus = std::map<std::string, int>;
+// Get thermal_zone type
+bool getThermalZoneTypeById(int tz_id, std::string *);
+
struct SensorStatus {
ThrottlingSeverity severity;
ThrottlingSeverity prev_hot_severity;
diff --git a/thermal/utils/thermal_watcher.cpp b/thermal/utils/thermal_watcher.cpp
index 86d7c46f..442fa338 100644
--- a/thermal/utils/thermal_watcher.cpp
+++ b/thermal/utils/thermal_watcher.cpp
@@ -15,6 +15,11 @@
*/
#include <cutils/uevent.h>
#include <dirent.h>
+#include <linux/genetlink.h>
+#include <linux/netlink.h>
+#include <linux/thermal.h>
+#include <netlink/genl/ctrl.h>
+#include <netlink/genl/genl.h>
#include <sys/inotify.h>
#include <sys/resource.h>
#include <sys/types.h>
@@ -23,8 +28,10 @@
#include <android-base/file.h>
#include <android-base/logging.h>
+#include <android-base/stringprintf.h>
#include <android-base/strings.h>
+#include "thermal-helper.h"
#include "thermal_watcher.h"
namespace android {
@@ -35,6 +42,305 @@ namespace implementation {
using std::chrono_literals::operator""ms;
+namespace {
+
+static int nlErrorHandle(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg) {
+ int *ret = reinterpret_cast<int *>(arg);
+ *ret = err->error;
+ LOG(ERROR) << __func__ << "nl_groups: " << nla->nl_groups << ", nl_pid: " << nla->nl_pid;
+
+ return NL_STOP;
+}
+
+static int nlFinishHandle(struct nl_msg *msg, void *arg) {
+ int *ret = reinterpret_cast<int *>(arg);
+ *ret = 1;
+ struct nlmsghdr *nlh = nlmsg_hdr(msg);
+
+ LOG(VERBOSE) << __func__ << ": nlmsg type: " << nlh->nlmsg_type;
+
+ return NL_OK;
+}
+
+static int nlAckHandle(struct nl_msg *msg, void *arg) {
+ int *ret = reinterpret_cast<int *>(arg);
+ *ret = 1;
+ struct nlmsghdr *nlh = nlmsg_hdr(msg);
+
+ LOG(VERBOSE) << __func__ << ": nlmsg type: " << nlh->nlmsg_type;
+
+ return NL_OK;
+}
+
+static int nlSeqCheckHandle(struct nl_msg *msg, void *arg) {
+ int *ret = reinterpret_cast<int *>(arg);
+ *ret = 1;
+ struct nlmsghdr *nlh = nlmsg_hdr(msg);
+
+ LOG(VERBOSE) << __func__ << ": nlmsg type: " << nlh->nlmsg_type;
+
+ return NL_OK;
+}
+
+struct HandlerArgs {
+ const char *group;
+ int id;
+};
+
+static int nlSendMsg(struct nl_sock *sock, struct nl_msg *msg,
+ int (*rx_handler)(struct nl_msg *, void *), void *data) {
+ int err, done = 0;
+
+ std::unique_ptr<nl_cb, decltype(&nl_cb_put)> cb(nl_cb_alloc(NL_CB_DEFAULT), nl_cb_put);
+
+ err = nl_send_auto_complete(sock, msg);
+ if (err < 0)
+ return err;
+
+ err = 0;
+ nl_cb_err(cb.get(), NL_CB_CUSTOM, nlErrorHandle, &err);
+ nl_cb_set(cb.get(), NL_CB_FINISH, NL_CB_CUSTOM, nlFinishHandle, &done);
+ nl_cb_set(cb.get(), NL_CB_ACK, NL_CB_CUSTOM, nlAckHandle, &done);
+
+ if (rx_handler != NULL)
+ nl_cb_set(cb.get(), NL_CB_VALID, NL_CB_CUSTOM, rx_handler, data);
+
+ while (err == 0 && done == 0) nl_recvmsgs(sock, cb.get());
+
+ return err;
+}
+
+static int nlFamilyHandle(struct nl_msg *msg, void *arg) {
+ struct HandlerArgs *grp = reinterpret_cast<struct HandlerArgs *>(arg);
+ struct nlattr *tb[CTRL_ATTR_MAX + 1];
+ struct genlmsghdr *gnlh = (struct genlmsghdr *)nlmsg_data(nlmsg_hdr(msg));
+ struct nlattr *mcgrp;
+ int rem_mcgrp;
+
+ nla_parse(tb, CTRL_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL);
+
+ if (!tb[CTRL_ATTR_MCAST_GROUPS]) {
+ LOG(ERROR) << __func__ << "Multicast group not found";
+ return -1;
+ }
+
+ nla_for_each_nested(mcgrp, tb[CTRL_ATTR_MCAST_GROUPS], rem_mcgrp) {
+ struct nlattr *tb_mcgrp[CTRL_ATTR_MCAST_GRP_MAX + 1];
+
+ nla_parse(tb_mcgrp, CTRL_ATTR_MCAST_GRP_MAX, reinterpret_cast<nlattr *>(nla_data(mcgrp)),
+ nla_len(mcgrp), NULL);
+
+ if (!tb_mcgrp[CTRL_ATTR_MCAST_GRP_NAME] || !tb_mcgrp[CTRL_ATTR_MCAST_GRP_ID])
+ continue;
+
+ if (strncmp(reinterpret_cast<char *>(nla_data(tb_mcgrp[CTRL_ATTR_MCAST_GRP_NAME])),
+ grp->group, nla_len(tb_mcgrp[CTRL_ATTR_MCAST_GRP_NAME])) != 0)
+ continue;
+
+ grp->id = nla_get_u32(tb_mcgrp[CTRL_ATTR_MCAST_GRP_ID]);
+
+ break;
+ }
+
+ return 0;
+}
+
+static int nlGetMulticastId(struct nl_sock *sock, const char *family, const char *group) {
+ int err = 0, ctrlid;
+ struct HandlerArgs grp = {
+ .group = group,
+ .id = -ENOENT,
+ };
+
+ std::unique_ptr<nl_msg, decltype(&nlmsg_free)> msg(nlmsg_alloc(), nlmsg_free);
+
+ ctrlid = genl_ctrl_resolve(sock, "nlctrl");
+
+ genlmsg_put(msg.get(), 0, 0, ctrlid, 0, 0, CTRL_CMD_GETFAMILY, 0);
+
+ nla_put_string(msg.get(), CTRL_ATTR_FAMILY_NAME, family);
+
+ err = nlSendMsg(sock, msg.get(), nlFamilyHandle, &grp);
+ if (err)
+ return err;
+
+ err = grp.id;
+ LOG(INFO) << group << " multicast_id: " << grp.id;
+
+ return err;
+}
+
+static bool socketAddMembership(struct nl_sock *sock, const char *group) {
+ int mcid = nlGetMulticastId(sock, THERMAL_GENL_FAMILY_NAME, group);
+ if (mcid < 0) {
+ LOG(ERROR) << "Failed to get multicast id: " << group;
+ return false;
+ }
+
+ if (nl_socket_add_membership(sock, mcid)) {
+ LOG(ERROR) << "Failed to add netlink socket membership: " << group;
+ return false;
+ }
+
+ LOG(INFO) << "Added netlink socket membership: " << group;
+ return true;
+}
+
+static int handleEvent(struct nl_msg *n, void *arg) {
+ struct nlmsghdr *nlh = nlmsg_hdr(n);
+ struct genlmsghdr *glh = genlmsg_hdr(nlh);
+ struct nlattr *attrs[THERMAL_GENL_ATTR_MAX + 1];
+ int *tz_id = reinterpret_cast<int *>(arg);
+
+ genlmsg_parse(nlh, 0, attrs, THERMAL_GENL_ATTR_MAX, NULL);
+
+ if (glh->cmd == THERMAL_GENL_EVENT_TZ_TRIP_UP) {
+ LOG(INFO) << "THERMAL_GENL_EVENT_TZ_TRIP_UP";
+ if (attrs[THERMAL_GENL_ATTR_TZ_ID]) {
+ LOG(INFO) << "Thermal zone id: " << nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]);
+ *tz_id = nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]);
+ }
+ if (attrs[THERMAL_GENL_ATTR_TZ_TRIP_ID])
+ LOG(INFO) << "Thermal zone trip id: "
+ << nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_ID]);
+ }
+
+ if (glh->cmd == THERMAL_GENL_EVENT_TZ_TRIP_DOWN) {
+ LOG(INFO) << "THERMAL_GENL_EVENT_TZ_TRIP_DOWN";
+ if (attrs[THERMAL_GENL_ATTR_TZ_ID]) {
+ LOG(INFO) << "Thermal zone id: " << nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]);
+ *tz_id = nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]);
+ }
+ if (attrs[THERMAL_GENL_ATTR_TZ_TRIP_ID])
+ LOG(INFO) << "Thermal zone trip id: "
+ << nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_ID]);
+ }
+
+ if (glh->cmd == THERMAL_GENL_EVENT_TZ_GOV_CHANGE) {
+ LOG(INFO) << "THERMAL_GENL_EVENT_TZ_GOV_CHANGE";
+ if (attrs[THERMAL_GENL_ATTR_TZ_ID]) {
+ LOG(INFO) << "Thermal zone id: " << nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]);
+ *tz_id = nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]);
+ }
+ if (attrs[THERMAL_GENL_ATTR_GOV_NAME])
+ LOG(INFO) << "Governor name: " << nla_get_string(attrs[THERMAL_GENL_ATTR_GOV_NAME]);
+ }
+
+ if (glh->cmd == THERMAL_GENL_EVENT_TZ_CREATE) {
+ LOG(INFO) << "THERMAL_GENL_EVENT_TZ_CREATE";
+ if (attrs[THERMAL_GENL_ATTR_TZ_ID]) {
+ LOG(INFO) << "Thermal zone id: " << nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]);
+ *tz_id = nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]);
+ }
+ if (attrs[THERMAL_GENL_ATTR_TZ_NAME])
+ LOG(INFO) << "Thermal zone name: " << nla_get_string(attrs[THERMAL_GENL_ATTR_TZ_NAME]);
+ }
+
+ if (glh->cmd == THERMAL_GENL_EVENT_TZ_DELETE) {
+ LOG(INFO) << "THERMAL_GENL_EVENT_TZ_DELETE";
+ if (attrs[THERMAL_GENL_ATTR_TZ_ID]) {
+ LOG(INFO) << "Thermal zone id: " << nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]);
+ *tz_id = nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]);
+ }
+ }
+
+ if (glh->cmd == THERMAL_GENL_EVENT_TZ_DISABLE) {
+ LOG(INFO) << "THERMAL_GENL_EVENT_TZ_DISABLE";
+ if (attrs[THERMAL_GENL_ATTR_TZ_ID]) {
+ LOG(INFO) << "Thermal zone id: " << nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]);
+ *tz_id = nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]);
+ }
+ }
+
+ if (glh->cmd == THERMAL_GENL_EVENT_TZ_ENABLE) {
+ LOG(INFO) << "THERMAL_GENL_EVENT_TZ_ENABLE";
+ if (attrs[THERMAL_GENL_ATTR_TZ_ID]) {
+ LOG(INFO) << "Thermal zone id: " << nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]);
+ *tz_id = nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]);
+ }
+ }
+
+ if (glh->cmd == THERMAL_GENL_EVENT_TZ_TRIP_CHANGE) {
+ LOG(INFO) << "THERMAL_GENL_EVENT_TZ_TRIP_CHANGE";
+ if (attrs[THERMAL_GENL_ATTR_TZ_ID]) {
+ LOG(INFO) << "Thermal zone id: " << nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]);
+ *tz_id = nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]);
+ }
+ if (attrs[THERMAL_GENL_ATTR_TZ_TRIP_ID])
+ LOG(INFO) << "Trip id:: " << nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_ID]);
+ if (attrs[THERMAL_GENL_ATTR_TZ_TRIP_TYPE])
+ LOG(INFO) << "Trip type: " << nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_TYPE]);
+ if (attrs[THERMAL_GENL_ATTR_TZ_TRIP_TEMP])
+ LOG(INFO) << "Trip temp: " << nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_TEMP]);
+ if (attrs[THERMAL_GENL_ATTR_TZ_TRIP_HYST])
+ LOG(INFO) << "Trip hyst: " << nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_HYST]);
+ }
+
+ if (glh->cmd == THERMAL_GENL_EVENT_TZ_TRIP_ADD) {
+ LOG(INFO) << "THERMAL_GENL_EVENT_TZ_TRIP_ADD";
+ if (attrs[THERMAL_GENL_ATTR_TZ_ID])
+ LOG(INFO) << "Thermal zone id: " << nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]);
+ if (attrs[THERMAL_GENL_ATTR_TZ_TRIP_ID])
+ LOG(INFO) << "Trip id:: " << nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_ID]);
+ if (attrs[THERMAL_GENL_ATTR_TZ_TRIP_TYPE])
+ LOG(INFO) << "Trip type: " << nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_TYPE]);
+ if (attrs[THERMAL_GENL_ATTR_TZ_TRIP_TEMP])
+ LOG(INFO) << "Trip temp: " << nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_TEMP]);
+ if (attrs[THERMAL_GENL_ATTR_TZ_TRIP_HYST])
+ LOG(INFO) << "Trip hyst: " << nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_HYST]);
+ }
+
+ if (glh->cmd == THERMAL_GENL_EVENT_TZ_TRIP_DELETE) {
+ LOG(INFO) << "THERMAL_GENL_EVENT_TZ_TRIP_DELETE";
+ if (attrs[THERMAL_GENL_ATTR_TZ_ID]) {
+ LOG(INFO) << "Thermal zone id: " << nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]);
+ *tz_id = nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]);
+ }
+ if (attrs[THERMAL_GENL_ATTR_TZ_TRIP_ID])
+ LOG(INFO) << "Trip id:: " << nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TRIP_ID]);
+ }
+
+ if (glh->cmd == THERMAL_GENL_EVENT_CDEV_STATE_UPDATE) {
+ LOG(INFO) << "THERMAL_GENL_EVENT_CDEV_STATE_UPDATE";
+ if (attrs[THERMAL_GENL_ATTR_CDEV_ID])
+ LOG(INFO) << "Cooling device id: " << nla_get_u32(attrs[THERMAL_GENL_ATTR_CDEV_ID]);
+ if (attrs[THERMAL_GENL_ATTR_CDEV_CUR_STATE])
+ LOG(INFO) << "Cooling device current state: "
+ << nla_get_u32(attrs[THERMAL_GENL_ATTR_CDEV_CUR_STATE]);
+ }
+
+ if (glh->cmd == THERMAL_GENL_EVENT_CDEV_ADD) {
+ LOG(INFO) << "THERMAL_GENL_EVENT_CDEV_ADD";
+ if (attrs[THERMAL_GENL_ATTR_CDEV_NAME])
+ LOG(INFO) << "Cooling device name: " << nla_get_u32(attrs[THERMAL_GENL_ATTR_CDEV_NAME]);
+ if (attrs[THERMAL_GENL_ATTR_CDEV_ID])
+ LOG(INFO) << "Cooling device id: " << nla_get_u32(attrs[THERMAL_GENL_ATTR_CDEV_ID]);
+ if (attrs[THERMAL_GENL_ATTR_CDEV_MAX_STATE])
+ LOG(INFO) << "Cooling device max state: "
+ << nla_get_u32(attrs[THERMAL_GENL_ATTR_CDEV_MAX_STATE]);
+ }
+
+ if (glh->cmd == THERMAL_GENL_EVENT_CDEV_DELETE) {
+ LOG(INFO) << "THERMAL_GENL_EVENT_CDEV_DELETE";
+ if (attrs[THERMAL_GENL_ATTR_CDEV_ID])
+ LOG(INFO) << "Cooling device id: " << nla_get_u32(attrs[THERMAL_GENL_ATTR_CDEV_ID]);
+ }
+
+ if (glh->cmd == THERMAL_GENL_SAMPLING_TEMP) {
+ LOG(INFO) << "THERMAL_GENL_SAMPLING_TEMP";
+ if (attrs[THERMAL_GENL_ATTR_TZ_ID]) {
+ LOG(INFO) << "Thermal zone id: " << nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]);
+ *tz_id = nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_ID]);
+ }
+ if (attrs[THERMAL_GENL_ATTR_TZ_TEMP])
+ LOG(INFO) << "Thermal zone temp: " << nla_get_u32(attrs[THERMAL_GENL_ATTR_TZ_TEMP]);
+ }
+
+ return 0;
+}
+
+} // namespace
+
void ThermalWatcher::registerFilesToWatch(const std::set<std::string> &sensors_to_watch) {
monitored_sensors_.insert(sensors_to_watch.begin(), sensors_to_watch.end());
@@ -47,6 +353,40 @@ void ThermalWatcher::registerFilesToWatch(const std::set<std::string> &sensors_t
fcntl(uevent_fd_, F_SETFL, O_NONBLOCK);
looper_->addFd(uevent_fd_.get(), 0, Looper::EVENT_INPUT, nullptr, nullptr);
+
+ sk_thermal = nl_socket_alloc();
+ if (!sk_thermal) {
+ LOG(ERROR) << "nl_socket_alloc failed";
+ return;
+ }
+
+ if (genl_connect(sk_thermal)) {
+ LOG(ERROR) << "genl_connect failed: sk_thermal";
+ return;
+ }
+
+ thermal_genl_fd_.reset(nl_socket_get_fd(sk_thermal));
+ if (thermal_genl_fd_.get() < 0) {
+ LOG(ERROR) << "Failed to create thermal netlink socket";
+ return;
+ }
+
+ if (!socketAddMembership(sk_thermal, THERMAL_GENL_EVENT_GROUP_NAME)) {
+ return;
+ }
+
+ /*
+ * Currently, only the update_temperature() will send thermal genl samlping events
+ * from kernel. To avoid thermal-hal busy because samlping events are sent
+ * too frequently, ignore thermal genl samlping events until we figure out how to use it.
+ *
+ if (!socketAddMembership(sk_thermal, THERMAL_GENL_SAMPLING_GROUP_NAME)) {
+ return;
+ }
+ */
+
+ fcntl(thermal_genl_fd_, F_SETFL, O_NONBLOCK);
+ looper_->addFd(thermal_genl_fd_.get(), 0, Looper::EVENT_INPUT, nullptr, nullptr);
sleep_ms_ = std::chrono::milliseconds(0);
last_update_time_ = boot_clock::now();
}
@@ -116,6 +456,35 @@ void ThermalWatcher::parseUevent(std::set<std::string> *sensors_set) {
}
}
+// TODO(b/175367921): Consider for potentially adding more type of event in the function
+// instead of just add the sensors to the list.
+void ThermalWatcher::parseGenlink(std::set<std::string> *sensors_set) {
+ int err = 0, done = 0, tz_id = -1;
+
+ std::unique_ptr<nl_cb, decltype(&nl_cb_put)> cb(nl_cb_alloc(NL_CB_DEFAULT), nl_cb_put);
+
+ nl_cb_err(cb.get(), NL_CB_CUSTOM, nlErrorHandle, &err);
+ nl_cb_set(cb.get(), NL_CB_FINISH, NL_CB_CUSTOM, nlFinishHandle, &done);
+ nl_cb_set(cb.get(), NL_CB_ACK, NL_CB_CUSTOM, nlAckHandle, &done);
+ nl_cb_set(cb.get(), NL_CB_SEQ_CHECK, NL_CB_CUSTOM, nlSeqCheckHandle, &done);
+ nl_cb_set(cb.get(), NL_CB_VALID, NL_CB_CUSTOM, handleEvent, &tz_id);
+
+ while (!done && !err) {
+ nl_recvmsgs(sk_thermal, cb.get());
+
+ if (tz_id < 0) {
+ break;
+ }
+
+ std::string name;
+ if (getThermalZoneTypeById(tz_id, &name) &&
+ std::find(monitored_sensors_.begin(), monitored_sensors_.end(), name) !=
+ monitored_sensors_.end()) {
+ sensors_set->insert(name);
+ }
+ }
+}
+
void ThermalWatcher::wake() {
looper_->wake();
}
@@ -131,10 +500,13 @@ bool ThermalWatcher::threadLoop() {
if (time_elapsed_ms < sleep_ms_ &&
looper_->pollOnce(sleep_ms_.count(), &fd, nullptr, nullptr) >= 0) {
- if (fd != uevent_fd_.get()) {
+ if (fd != uevent_fd_.get() && fd != thermal_genl_fd_.get()) {
return true;
+ } else if (fd == thermal_genl_fd_.get()) {
+ parseGenlink(&sensors);
+ } else if (fd == uevent_fd_.get()) {
+ parseUevent(&sensors);
}
- parseUevent(&sensors);
// Ignore cb_ if uevent is not from monitored sensors
if (sensors.size() == 0) {
return true;
diff --git a/thermal/utils/thermal_watcher.h b/thermal/utils/thermal_watcher.h
index 76c38403..7cf46f6c 100644
--- a/thermal/utils/thermal_watcher.h
+++ b/thermal/utils/thermal_watcher.h
@@ -73,6 +73,9 @@ class ThermalWatcher : public ::android::Thread {
// Parse uevent message
void parseUevent(std::set<std::string> *sensor_name);
+ // Parse thermal netlink message
+ void parseGenlink(std::set<std::string> *sensor_name);
+
// Maps watcher filer descriptor to watched file path.
std::unordered_map<int, std::string> watch_to_file_path_map_;
@@ -86,12 +89,16 @@ class ThermalWatcher : public ::android::Thread {
// For uevent socket registration.
android::base::unique_fd uevent_fd_;
+ // For thermal genl socket registration.
+ android::base::unique_fd thermal_genl_fd_;
// Sensor list which monitor flag is enabled.
std::set<std::string> monitored_sensors_;
// Sleep interval voting result
std::chrono::milliseconds sleep_ms_;
// Timestamp for last thermal update
boot_clock::time_point last_update_time_;
+ // For thermal genl socket object.
+ struct nl_sock *sk_thermal;
};
} // namespace implementation