blob: c8408889269a83ed1712c9ba5fcdf1b4d4060f72 [file] [log] [blame]
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -07001/*
2 * Copyright (c) 2020, The Linux Foundation. All rights reserved.
Minghao Zhangd6fbfa12022-03-29 22:00:09 +08003 * Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved.
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -07004 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following
12 * disclaimer in the documentation and/or other materials provided
13 * with the distribution.
14 * * Neither the name of The Linux Foundation nor the names of its
15 * contributors may be used to endorse or promote products derived
16 * from this software without specific prior written permission.
17 *
18 *
19 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
20 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
26 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
28 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
29 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32#include <ctype.h>
33#include <errno.h>
34#include <inttypes.h>
35#include <stdlib.h>
36#include <cerrno>
37#include <mutex>
38#include <string>
39
40#include <android-base/file.h>
41#include <android-base/logging.h>
42#include <hidl/HidlTransportSupport.h>
43
44#include "thermal.h"
45#include "thermalUtils.h"
46
47namespace android {
48namespace hardware {
49namespace thermal {
50namespace V2_0 {
51namespace implementation {
52
53using ::android::hardware::interfacesEqual;
54
Ram Chandrasekara56b9f52020-09-22 12:36:05 -070055static const Temperature_1_0 dummy_temp_1_0 = {
56 .type = TemperatureType_1_0::SKIN,
57 .name = "test sensor",
58 .currentValue = 30,
59 .throttlingThreshold = 40,
60 .shutdownThreshold = 60,
61 .vrThrottlingThreshold = 40,
62};
63
Minghao Zhangd6fbfa12022-03-29 22:00:09 +080064static const Temperature dummy_temp_2_0 = {
65 .type = TemperatureType::SKIN,
66 .name = "test sensor",
67 .value = 25.0,
68 .throttlingStatus = ThrottlingSeverity::NONE,
69};
70
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -070071template <typename A, typename B>
72Return<void> exit_hal(A _cb, hidl_vec<B> _data, std::string_view _msg) {
73 ThermalStatus _status;
74
75 _status.code = ThermalStatusCode::FAILURE;
76 _status.debugMessage = _msg.data();
77 LOG(ERROR) << _msg;
78 _cb(_status, _data);
79
80 return Void();
81}
82
83template <typename A>
84Return<void> exit_hal(A _cb, std::string_view _msg) {
85 ThermalStatus _status;
86
87 _status.code = ThermalStatusCode::FAILURE;
88 _status.debugMessage = _msg.data();
89 LOG(ERROR) << _msg;
90 _cb(_status);
91
92 return Void();
93}
94
95Thermal::Thermal():
96 utils(std::bind(&Thermal::sendThrottlingChangeCB, this,
97 std::placeholders::_1))
98{ }
99
100Return<void> Thermal::getTemperatures(getTemperatures_cb _hidl_cb)
101{
102 ThermalStatus status;
103 hidl_vec<Temperature_1_0> temperatures;
104
105 status.code = ThermalStatusCode::SUCCESS;
Ram Chandrasekara56b9f52020-09-22 12:36:05 -0700106 if (!utils.isSensorInitialized()) {
107 std::vector<Temperature_1_0> _temp = {dummy_temp_1_0};
108 LOG(INFO) << "Returning Dummy Value" << std::endl;
109 _hidl_cb(status, _temp);
110 return Void();
111 }
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700112
Ram Chandrasekarf020a1d2020-08-25 14:25:14 -0700113 if (utils.readTemperatures(temperatures) <= 0)
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700114 return exit_hal(_hidl_cb, temperatures,
115 "Sensor Temperature read failure.");
116
117 _hidl_cb(status, temperatures);
118
119 return Void();
120}
121
122Return<void> Thermal::getCpuUsages(getCpuUsages_cb _hidl_cb)
123{
124
125 ThermalStatus status;
126 hidl_vec<CpuUsage> cpu_usages;
127
128 status.code = ThermalStatusCode::SUCCESS;
Ram Chandrasekar72110b52020-08-06 14:39:40 -0700129 if (utils.fetchCpuUsages(cpu_usages) <= 0)
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700130 return exit_hal(_hidl_cb, cpu_usages,
131 "CPU usage read failure.");
132
133 _hidl_cb(status, cpu_usages);
134 return Void();
135}
136
137Return<void> Thermal::getCoolingDevices(getCoolingDevices_cb _hidl_cb)
138{
139 ThermalStatus status;
140 hidl_vec<CoolingDevice_1_0> cdev;
141
142 status.code = ThermalStatusCode::SUCCESS;
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700143 /* V1 Cdev requires only Fan Support. */
144 _hidl_cb(status, cdev);
145 return Void();
146}
147
148Return<void> Thermal::getCurrentCoolingDevices(
149 bool filterType,
150 cdevType type,
151 getCurrentCoolingDevices_cb _hidl_cb)
152{
153 ThermalStatus status;
154 hidl_vec<CoolingDevice> cdev;
155
156 status.code = ThermalStatusCode::SUCCESS;
157 if (!utils.isCdevInitialized())
158 return exit_hal(_hidl_cb, cdev,
159 "ThermalHAL not initialized properly.");
Ram Chandrasekarf020a1d2020-08-25 14:25:14 -0700160 if (utils.readCdevStates(filterType, type, cdev) <= 0)
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700161 return exit_hal(_hidl_cb, cdev,
162 "Failed to read thermal cooling devices.");
163
164 _hidl_cb(status, cdev);
165 return Void();
166}
167
168Return<void> Thermal::getCurrentTemperatures(
169 bool filterType,
170 TemperatureType type,
171 getCurrentTemperatures_cb _hidl_cb)
172{
173 ThermalStatus status;
174 hidl_vec<Temperature> temperatures;
175
176 status.code = ThermalStatusCode::SUCCESS;
177 if (!utils.isSensorInitialized())
178 return exit_hal(_hidl_cb, temperatures,
179 "ThermalHAL not initialized properly.");
180
Minghao Zhangd6fbfa12022-03-29 22:00:09 +0800181 if (utils.readTemperatures(filterType, type, temperatures) <= 0) {
182 if (filterType && type != dummy_temp_2_0.type) {
183 status.code = ThermalStatusCode::FAILURE;
184 status.debugMessage = "Failed to read dummy temperature value";
185 } else {
186 temperatures = {dummy_temp_2_0};
187 LOG(INFO) << "Returning Dummy Temperature Value" << std::endl;
188 }
189 }
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700190
191 _hidl_cb(status, temperatures);
192
193 return Void();
194}
195
196Return<void> Thermal::getTemperatureThresholds(
197 bool filterType,
198 TemperatureType type,
199 getTemperatureThresholds_cb _hidl_cb)
200{
201 ThermalStatus status;
202 hidl_vec<TemperatureThreshold> thresh;
203
204 status.code = ThermalStatusCode::SUCCESS;
205 if (!utils.isSensorInitialized())
206 return exit_hal(_hidl_cb, thresh,
207 "ThermalHAL not initialized properly.");
208
Ram Chandrasekarf020a1d2020-08-25 14:25:14 -0700209 if (utils.readTemperatureThreshold(filterType, type, thresh) <= 0)
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700210 return exit_hal(_hidl_cb, thresh,
Ram Chandrasekarf020a1d2020-08-25 14:25:14 -0700211 "Sensor Threshold read failure or type not supported.");
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700212
213 _hidl_cb(status, thresh);
214
215 return Void();
216}
217
218Return<void> Thermal::registerThermalChangedCallback(
219 const sp<IThermalChangedCallback> &callback,
220 bool filterType,
221 TemperatureType type,
222 registerThermalChangedCallback_cb _hidl_cb)
223{
224 ThermalStatus status;
225 std::lock_guard<std::mutex> _lock(thermal_cb_mutex);
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700226
227 status.code = ThermalStatusCode::SUCCESS;
228 if (callback == nullptr)
229 return exit_hal(_hidl_cb, "Invalid nullptr callback");
230 if (type == TemperatureType::BCL_VOLTAGE ||
231 type == TemperatureType::BCL_CURRENT)
232 return exit_hal(_hidl_cb,
233 "BCL current and voltage notification not supported");
234
Ram Chandrasekarf020a1d2020-08-25 14:25:14 -0700235 for (CallbackSetting _cb: cb) {
236 if (interfacesEqual(_cb.callback, callback))
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700237 return exit_hal(_hidl_cb,
238 "Same callback interface registered already");
239 }
240 cb.emplace_back(callback, filterType, type);
241 LOG(DEBUG) << "A callback has been registered to ThermalHAL, isFilter: " << filterType
242 << " Type: " << android::hardware::thermal::V2_0::toString(type);
243
244 _hidl_cb(status);
245 return Void();
246}
247
248Return<void> Thermal::unregisterThermalChangedCallback(
249 const sp<IThermalChangedCallback> &callback,
250 unregisterThermalChangedCallback_cb _hidl_cb)
251{
252
253 ThermalStatus status;
254 bool removed = false;
255 std::lock_guard<std::mutex> _lock(thermal_cb_mutex);
256 std::vector<CallbackSetting>::iterator it;
257
258 status.code = ThermalStatusCode::SUCCESS;
259 if (callback == nullptr)
260 return exit_hal(_hidl_cb, "Invalid nullptr callback");
261
262 for (it = cb.begin(); it != cb.end(); it++) {
263 if (interfacesEqual(it->callback, callback)) {
264 cb.erase(it);
265 LOG(DEBUG) << "callback unregistered. isFilter: "
266 << it->is_filter_type << " Type: "
267 << android::hardware::thermal::V2_0::toString(it->type);
268 removed = true;
269 break;
270 }
271 }
272 if (!removed)
273 return exit_hal(_hidl_cb, "The callback was not registered before");
274 _hidl_cb(status);
275 return Void();
276}
277
278void Thermal::sendThrottlingChangeCB(const Temperature &t)
279{
280 std::lock_guard<std::mutex> _lock(thermal_cb_mutex);
281 std::vector<CallbackSetting>::iterator it;
282
283 LOG(DEBUG) << "Throttle Severity change: " << " Type: " << (int)t.type
284 << " Name: " << t.name << " Value: " << t.value <<
285 " ThrottlingStatus: " << (int)t.throttlingStatus;
Ram Chandrasekar1003d372020-08-27 17:18:07 -0700286 it = cb.begin();
287 while (it != cb.end()) {
288 if (!it->is_filter_type || it->type == t.type) {
289 Return<void> ret = it->callback->notifyThrottling(t);
290 if (!ret.isOk()) {
291 LOG(ERROR) << "Notify callback execution error. Removing";
292 it = cb.erase(it);
293 continue;
294 }
295 }
296 it++;
Ram Chandrasekardac8f7d2020-06-10 12:23:28 -0700297 }
298}
299
300} // namespace implementation
301} // namespace V2_0
302} // namespace thermal
303} // namespace hardware
304} // namespace android