blob: 57ab90ab79fc014923026e04e691837ffbd5a6bb [file] [log] [blame]
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -07001/*
Bavyasritha Alahari0a344f42023-04-26 17:16:51 -07002 * Copyright (c) 2020,2023, The Linux Foundation. All rights reserved.
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -07003 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above
10 * copyright notice, this list of conditions and the following
11 * disclaimer in the documentation and/or other materials provided
12 * with the distribution.
13 * * Neither the name of The Linux Foundation nor the names of its
14 * contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 *
17 *
18 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
19 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
22 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
25 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
27 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
28 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
Bavyasritha Alahari0a344f42023-04-26 17:16:51 -070031/* Changes from Qualcomm Innovation Center are provided under the following license:
32
33Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
34SPDX-License-Identifier: BSD-3-Clause-Clear */
35
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -070036#include <unistd.h>
37#include <poll.h>
38#include <sys/socket.h>
39#include <linux/types.h>
40#include <linux/netlink.h>
41#include <android-base/logging.h>
42#include <android-base/properties.h>
43#include <android-base/stringprintf.h>
44
45#include "thermalMonitor.h"
46
47#define UEVENT_BUF 1024
48
49#define HYST_FMT "change@/devices/virtual/thermal/thermal_zone%d\n\
50 ACTION=change\n\
51 DEVPATH=/devices/virtual/thermal/thermal_zone%d\n\
52 SUBSYSTEM=thermal\n\
53 NAME=%s\n\
54 TEMP=%d\n\
55 HYST=%d\n\
56 EVENT=%d\n"\
57
58#define TRIP_FMT "change@/devices/virtual/thermal/thermal_zone%d\n\
59 ACTION=change\n\
60 DEVPATH=/devices/virtual/thermal/thermal_zone%d\n\
61 SUBSYSTEM=thermal\n\
62 NAME=%s\n\
63 TEMP=%d\n\
64 TRIP=%d\n\
65 EVENT=%d\n"\
66
Bavyasritha Alahari0a344f42023-04-26 17:16:51 -070067namespace aidl {
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -070068namespace android {
69namespace hardware {
70namespace thermal {
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -070071
72using parseCB = std::function<void(char *inp_buf, ssize_t len)>;
73using pollCB = std::function<bool()>;
74
75void thermal_monitor_uevent(const parseCB &parse_cb, const pollCB &stopPollCB)
76{
77 struct pollfd pfd;
78 char buf[UEVENT_BUF] = {0};
79 int sz = 64*1024;
80 struct sockaddr_nl nls;
81
82 memset(&nls, 0, sizeof(nls));
83 nls.nl_family = AF_NETLINK;
84 nls.nl_pid = getpid();
85 nls.nl_groups = 0xffffffff;
86
87 pfd.events = POLLIN;
88 pfd.fd = socket(PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC,
89 NETLINK_KOBJECT_UEVENT);
90 if (pfd.fd < 0) {
91 LOG(ERROR) << "socket creation error:" << errno << std::endl;
92 return;
93 }
94 LOG(DEBUG) << "socket creation success" << std::endl;
95
96 setsockopt(pfd.fd, SOL_SOCKET, SO_RCVBUF, &sz, sizeof(sz));
97 if (bind(pfd.fd, (struct sockaddr *)&nls, sizeof(nls)) < 0) {
98 close(pfd.fd);
99 LOG(ERROR) << "socket bind failed:" << errno << std::endl;
100 return;
101 }
102 LOG(DEBUG) << "Listening for uevent" << std::endl;
103
104 while (!stopPollCB()) {
105 ssize_t len;
106 int err;
107
108 err = poll(&pfd, 1, -1);
109 if (err == -1) {
110 LOG(ERROR) << "Error in uevent poll.";
111 break;
112 }
113 if (stopPollCB()) {
114 LOG(INFO) << "Exiting uevent monitor" << std::endl;
115 return;
116 }
117 len = recv(pfd.fd, buf, sizeof(buf) - 1, MSG_DONTWAIT);
118 if (len == -1) {
119 LOG(ERROR) << "uevent read failed:" << errno << std::endl;
120 continue;
121 }
122 buf[len] = '\0';
123
124 parse_cb(buf, len);
125 }
126
127 return;
128}
129
130ThermalMonitor::ThermalMonitor(const ueventMonitorCB &inp_cb):
131 cb(inp_cb)
132{
133 monitor_shutdown = false;
134}
135
136ThermalMonitor::~ThermalMonitor()
137{
138 monitor_shutdown = true;
139 th.join();
140}
141
142void ThermalMonitor::start()
143{
144 th = std::thread(thermal_monitor_uevent,
145 std::bind(&ThermalMonitor::parse_and_notify, this,
146 std::placeholders::_1, std::placeholders::_2),
147 std::bind(&ThermalMonitor::stopPolling, this));
148}
149
150void ThermalMonitor::parse_and_notify(char *inp_buf, ssize_t len)
151{
152 int zone_num, temp, trip, ret = 0, event;
153 ssize_t i = 0;
154 char sensor_name[30] = "", buf[UEVENT_BUF] = {0};
155
156 LOG(DEBUG) << "monitor received thermal uevent: " << inp_buf
157 << std::endl;
158
159 while (i < len) {
160 if (i >= UEVENT_BUF)
161 return;
162 ret = snprintf(buf + i, UEVENT_BUF - i, "%s ", inp_buf + i);
163 if (ret == (strlen(inp_buf + i) + 1))
164 i += ret;
165 else
166 return;
167 }
168
169 if (!strstr(buf, "SUBSYSTEM=thermal"))
170 return;
171
172 if (strstr(buf, "TRIP=")) {
173 ret = sscanf(buf, TRIP_FMT, &zone_num, &zone_num, sensor_name,
174 &temp, &trip, &event);
175 LOG(DEBUG) << "zone:" << zone_num << " sensor:" << sensor_name
176 <<" temp:" << temp << " trip:" << trip << " event:" <<
177 event << std::endl;
178 } else {
179 ret = sscanf(buf, HYST_FMT, &zone_num, &zone_num, sensor_name,
180 &temp, &trip, &event);
181 LOG(DEBUG) << "zone:" << zone_num << " sensor:" << sensor_name
182 <<" temp:" << temp << " trip:" << trip << " event:" <<
183 event << std::endl;
184 }
185 if (ret <= 0 || ret == EOF) {
186 LOG(ERROR) << "read error:" << ret <<". buf:" << buf << std::endl;
187 return;
188 }
189 cb(sensor_name, temp);
190}
191
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700192} // namespace thermal
193} // namespace hardware
194} // namespace android
Bavyasritha Alahari0a344f42023-04-26 17:16:51 -0700195} // namespace aidl