summaryrefslogtreecommitdiff
path: root/thermalMonitor.cpp
diff options
context:
space:
mode:
authorRam Chandrasekar <rkumbako@codeaurora.org>2020-06-10 12:23:28 -0700
committerRam Chandrasekar <rkumbako@codeaurora.org>2020-07-09 15:23:36 -0700
commitdac8f7dd5a799e95196072ac7ac0ff6b944867b0 (patch)
treebb9f3e1ebda0512db3fd68f8d2cd86e49f8ae654 /thermalMonitor.cpp
parent95b571040fc5c15dfc9361458391eceb86dd95a5 (diff)
thermal-hal: Add support for HAL2.0
Add support for thermal HAL 2.0 interfaces. Also add support for HAL 1.0 interfaces to be backward compatible. Change-Id: Ib0be008605db2751bda21f537ea694b3f9849800
Diffstat (limited to 'thermalMonitor.cpp')
-rw-r--r--thermalMonitor.cpp192
1 files changed, 192 insertions, 0 deletions
diff --git a/thermalMonitor.cpp b/thermalMonitor.cpp
new file mode 100644
index 0000000..176d121
--- /dev/null
+++ b/thermalMonitor.cpp
@@ -0,0 +1,192 @@
+/*
+ * Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <unistd.h>
+#include <poll.h>
+#include <sys/socket.h>
+#include <linux/types.h>
+#include <linux/netlink.h>
+#include <android-base/logging.h>
+#include <android-base/properties.h>
+#include <android-base/stringprintf.h>
+
+#include "thermalMonitor.h"
+
+#define UEVENT_BUF 1024
+
+#define HYST_FMT "change@/devices/virtual/thermal/thermal_zone%d\n\
+ ACTION=change\n\
+ DEVPATH=/devices/virtual/thermal/thermal_zone%d\n\
+ SUBSYSTEM=thermal\n\
+ NAME=%s\n\
+ TEMP=%d\n\
+ HYST=%d\n\
+ EVENT=%d\n"\
+
+#define TRIP_FMT "change@/devices/virtual/thermal/thermal_zone%d\n\
+ ACTION=change\n\
+ DEVPATH=/devices/virtual/thermal/thermal_zone%d\n\
+ SUBSYSTEM=thermal\n\
+ NAME=%s\n\
+ TEMP=%d\n\
+ TRIP=%d\n\
+ EVENT=%d\n"\
+
+namespace android {
+namespace hardware {
+namespace thermal {
+namespace V2_0 {
+namespace implementation {
+
+using parseCB = std::function<void(char *inp_buf, ssize_t len)>;
+using pollCB = std::function<bool()>;
+
+void thermal_monitor_uevent(const parseCB &parse_cb, const pollCB &stopPollCB)
+{
+ struct pollfd pfd;
+ char buf[UEVENT_BUF] = {0};
+ int sz = 64*1024;
+ struct sockaddr_nl nls;
+
+ memset(&nls, 0, sizeof(nls));
+ nls.nl_family = AF_NETLINK;
+ nls.nl_pid = getpid();
+ nls.nl_groups = 0xffffffff;
+
+ pfd.events = POLLIN;
+ pfd.fd = socket(PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC,
+ NETLINK_KOBJECT_UEVENT);
+ if (pfd.fd < 0) {
+ LOG(ERROR) << "socket creation error:" << errno << std::endl;
+ return;
+ }
+ LOG(DEBUG) << "socket creation success" << std::endl;
+
+ setsockopt(pfd.fd, SOL_SOCKET, SO_RCVBUF, &sz, sizeof(sz));
+ if (bind(pfd.fd, (struct sockaddr *)&nls, sizeof(nls)) < 0) {
+ close(pfd.fd);
+ LOG(ERROR) << "socket bind failed:" << errno << std::endl;
+ return;
+ }
+ LOG(DEBUG) << "Listening for uevent" << std::endl;
+
+ while (!stopPollCB()) {
+ ssize_t len;
+ int err;
+
+ err = poll(&pfd, 1, -1);
+ if (err == -1) {
+ LOG(ERROR) << "Error in uevent poll.";
+ break;
+ }
+ if (stopPollCB()) {
+ LOG(INFO) << "Exiting uevent monitor" << std::endl;
+ return;
+ }
+ len = recv(pfd.fd, buf, sizeof(buf) - 1, MSG_DONTWAIT);
+ if (len == -1) {
+ LOG(ERROR) << "uevent read failed:" << errno << std::endl;
+ continue;
+ }
+ buf[len] = '\0';
+
+ parse_cb(buf, len);
+ }
+
+ return;
+}
+
+ThermalMonitor::ThermalMonitor(const ueventMonitorCB &inp_cb):
+ cb(inp_cb)
+{
+ monitor_shutdown = false;
+}
+
+ThermalMonitor::~ThermalMonitor()
+{
+ monitor_shutdown = true;
+ th.join();
+}
+
+void ThermalMonitor::start()
+{
+ th = std::thread(thermal_monitor_uevent,
+ std::bind(&ThermalMonitor::parse_and_notify, this,
+ std::placeholders::_1, std::placeholders::_2),
+ std::bind(&ThermalMonitor::stopPolling, this));
+}
+
+void ThermalMonitor::parse_and_notify(char *inp_buf, ssize_t len)
+{
+ int zone_num, temp, trip, ret = 0, event;
+ ssize_t i = 0;
+ char sensor_name[30] = "", buf[UEVENT_BUF] = {0};
+
+ LOG(DEBUG) << "monitor received thermal uevent: " << inp_buf
+ << std::endl;
+
+ while (i < len) {
+ if (i >= UEVENT_BUF)
+ return;
+ ret = snprintf(buf + i, UEVENT_BUF - i, "%s ", inp_buf + i);
+ if (ret == (strlen(inp_buf + i) + 1))
+ i += ret;
+ else
+ return;
+ }
+
+ if (!strstr(buf, "SUBSYSTEM=thermal"))
+ return;
+
+ if (strstr(buf, "TRIP=")) {
+ ret = sscanf(buf, TRIP_FMT, &zone_num, &zone_num, sensor_name,
+ &temp, &trip, &event);
+ LOG(DEBUG) << "zone:" << zone_num << " sensor:" << sensor_name
+ <<" temp:" << temp << " trip:" << trip << " event:" <<
+ event << std::endl;
+ } else {
+ ret = sscanf(buf, HYST_FMT, &zone_num, &zone_num, sensor_name,
+ &temp, &trip, &event);
+ LOG(DEBUG) << "zone:" << zone_num << " sensor:" << sensor_name
+ <<" temp:" << temp << " trip:" << trip << " event:" <<
+ event << std::endl;
+ }
+ if (ret <= 0 || ret == EOF) {
+ LOG(ERROR) << "read error:" << ret <<". buf:" << buf << std::endl;
+ return;
+ }
+ cb(sensor_name, temp);
+}
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace thermal
+} // namespace hardware
+} // namespace android