1 /*
2 * Copyright (C) 2023 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 #include "include/thermalutils/ThermalHidlWrapper.h"
18
19 #include <hidl/HidlTransportSupport.h>
20
21 #include <cmath>
22
23 namespace aidl {
24 namespace android {
25 namespace hardware {
26 namespace thermal {
27
28 using ::android::hardware::Void;
29
30 namespace {
31
32 template <typename T, typename U>
setFailureAndCallback(T _hidl_cb,hidl_vec<U> data,std::string_view debug_msg)33 Return<void> setFailureAndCallback(T _hidl_cb, hidl_vec<U> data, std::string_view debug_msg) {
34 ThermalStatus status;
35 status.code = ThermalStatusCode::FAILURE;
36 status.debugMessage = debug_msg.data();
37 _hidl_cb(status, data);
38 return Void();
39 }
40
41 template <typename T>
setFailureAndCallback(T _hidl_cb,std::string_view debug_msg)42 Return<void> setFailureAndCallback(T _hidl_cb, std::string_view debug_msg) {
43 ThermalStatus status;
44 status.code = ThermalStatusCode::FAILURE;
45 status.debugMessage = debug_msg.data();
46 _hidl_cb(status);
47 return Void();
48 }
49
50 template <typename T, typename U>
setInitFailureAndCallback(T _hidl_cb,hidl_vec<U> data)51 Return<void> setInitFailureAndCallback(T _hidl_cb, hidl_vec<U> data) {
52 return setFailureAndCallback(
53 _hidl_cb, data, "Thermal AIDL HAL client used by HIDL wrapper was not initialized");
54 }
55
56 template <typename T>
setInitFailureAndCallback(T _hidl_cb)57 Return<void> setInitFailureAndCallback(T _hidl_cb) {
58 return setFailureAndCallback(
59 _hidl_cb, "Thermal AIDL HAL client used by HIDL wrapper was not initialized");
60 }
61
62 template <typename T, typename U>
setUnsupportedFailureAndCallback(T _hidl_cb,hidl_vec<U> data)63 Return<void> setUnsupportedFailureAndCallback(T _hidl_cb, hidl_vec<U> data) {
64 return setFailureAndCallback(_hidl_cb, data, "Operation unsupported by Thermal HIDL wrapper");
65 }
66
convertAidlTemperatureType(const TemperatureType & type)67 TemperatureType_2_0 convertAidlTemperatureType(const TemperatureType& type) {
68 if (type < TemperatureType::CPU || type > TemperatureType::NPU) {
69 return TemperatureType_2_0::UNKNOWN;
70 }
71 return static_cast<TemperatureType_2_0>(type);
72 }
73
convertAidlCoolingType(const CoolingType & type)74 CoolingType_2_0 convertAidlCoolingType(const CoolingType& type) {
75 if (type < CoolingType::FAN || type > CoolingType::COMPONENT) {
76 return CoolingType_2_0::COMPONENT;
77 }
78 return static_cast<CoolingType_2_0>(type);
79 }
80
convertAidlTemperature(const Temperature & temperature)81 Temperature_2_0 convertAidlTemperature(const Temperature& temperature) {
82 Temperature_2_0 t = Temperature_2_0{
83 convertAidlTemperatureType(temperature.type), temperature.name, temperature.value,
84 static_cast<ThrottlingSeverity_2_0>(temperature.throttlingStatus)};
85 return t;
86 }
87
convertAidlCoolingDevice(const CoolingDevice & cooling_device)88 CoolingDevice_2_0 convertAidlCoolingDevice(const CoolingDevice& cooling_device) {
89 CoolingDevice_2_0 t =
90 CoolingDevice_2_0{convertAidlCoolingType(cooling_device.type), cooling_device.name,
91 static_cast<uint64_t>(cooling_device.value)};
92 return t;
93 }
convertAidlTemperatureThreshold(const TemperatureThreshold & threshold)94 TemperatureThreshold_2_0 convertAidlTemperatureThreshold(const TemperatureThreshold& threshold) {
95 TemperatureThreshold_2_0 t =
96 TemperatureThreshold_2_0{convertAidlTemperatureType(threshold.type), threshold.name,
97 threshold.hotThrottlingThresholds.data(),
98 threshold.coldThrottlingThresholds.data(), NAN};
99 return t;
100 }
101
102 } // namespace
103
104 // Methods from ::android::hardware::thermal::V1_0::IThermal follow.
getTemperatures(getTemperatures_cb _hidl_cb)105 Return<void> ThermalHidlWrapper::getTemperatures(getTemperatures_cb _hidl_cb) {
106 hidl_vec<Temperature_1_0> ret_1_0;
107 setUnsupportedFailureAndCallback(_hidl_cb, ret_1_0);
108 return Void();
109 }
110
getCpuUsages(std::function<void (const ThermalStatus &,const hidl_vec<CpuUsage> &)> _hidl_cb)111 Return<void> ThermalHidlWrapper::getCpuUsages(
112 std::function<void(const ThermalStatus&, const hidl_vec<CpuUsage>&)> _hidl_cb) {
113 hidl_vec<CpuUsage> ret_1_0;
114 setUnsupportedFailureAndCallback(_hidl_cb, ret_1_0);
115 return Void();
116 }
117
getCoolingDevices(std::function<void (const ThermalStatus &,const hidl_vec<CoolingDevice_1_0> &)> _hidl_cb)118 Return<void> ThermalHidlWrapper::getCoolingDevices(
119 std::function<void(const ThermalStatus&, const hidl_vec<CoolingDevice_1_0>&)> _hidl_cb) {
120 hidl_vec<CoolingDevice_1_0> ret_1_0;
121 setUnsupportedFailureAndCallback(_hidl_cb, ret_1_0);
122 return Void();
123 }
124
125 // Methods from ::android::hardware::thermal::V2_0::IThermal follow.
getCurrentTemperatures(bool filterType,TemperatureType_2_0 type,std::function<void (const ThermalStatus &,const hidl_vec<Temperature_2_0> &)> _hidl_cb)126 Return<void> ThermalHidlWrapper::getCurrentTemperatures(
127 bool filterType, TemperatureType_2_0 type,
128 std::function<void(const ThermalStatus&, const hidl_vec<Temperature_2_0>&)> _hidl_cb) {
129 hidl_vec<Temperature_2_0> ret_2_0;
130 if (!thermal_service_) {
131 setInitFailureAndCallback(_hidl_cb, ret_2_0);
132 }
133
134 std::vector<Temperature> ret_aidl;
135 ThermalStatus status;
136 ::ndk::ScopedAStatus a_status;
137 if (filterType) {
138 a_status = thermal_service_->getTemperaturesWithType(static_cast<TemperatureType>(type),
139 &ret_aidl);
140 } else {
141 a_status = thermal_service_->getTemperatures(&ret_aidl);
142 }
143 if (a_status.isOk()) {
144 std::vector<Temperature_2_0> ret;
145 for (const auto& temperature : ret_aidl) {
146 ret.push_back(convertAidlTemperature(temperature));
147 }
148 _hidl_cb(status, hidl_vec<Temperature_2_0>(ret));
149 } else {
150 setFailureAndCallback(_hidl_cb, ret_2_0, a_status.getMessage());
151 }
152 return Void();
153 }
154
getTemperatureThresholds(bool filterType,TemperatureType_2_0 type,std::function<void (const ThermalStatus &,const hidl_vec<TemperatureThreshold_2_0> &)> _hidl_cb)155 Return<void> ThermalHidlWrapper::getTemperatureThresholds(
156 bool filterType, TemperatureType_2_0 type,
157 std::function<void(const ThermalStatus&, const hidl_vec<TemperatureThreshold_2_0>&)>
158 _hidl_cb) {
159 hidl_vec<TemperatureThreshold_2_0> ret_2_0;
160 if (!thermal_service_) {
161 setInitFailureAndCallback(_hidl_cb, ret_2_0);
162 }
163
164 std::vector<TemperatureThreshold> ret_aidl;
165 ThermalStatus status;
166 ::ndk::ScopedAStatus a_status;
167 if (filterType) {
168 a_status = thermal_service_->getTemperatureThresholdsWithType(
169 static_cast<TemperatureType>(type), &ret_aidl);
170 } else {
171 a_status = thermal_service_->getTemperatureThresholds(&ret_aidl);
172 }
173 if (a_status.isOk()) {
174 std::vector<TemperatureThreshold_2_0> ret;
175 for (const auto& threshold : ret_aidl) {
176 ret.push_back(convertAidlTemperatureThreshold(threshold));
177 }
178 _hidl_cb(status, hidl_vec<TemperatureThreshold_2_0>(ret));
179 } else {
180 setFailureAndCallback(_hidl_cb, ret_2_0, a_status.getMessage());
181 }
182 return Void();
183 }
184
registerThermalChangedCallback(const sp<IThermalChangedCallback_2_0> & callback,bool filterType,TemperatureType_2_0 type,std::function<void (const ThermalStatus &)> _hidl_cb)185 Return<void> ThermalHidlWrapper::registerThermalChangedCallback(
186 const sp<IThermalChangedCallback_2_0>& callback, bool filterType, TemperatureType_2_0 type,
187 std::function<void(const ThermalStatus&)> _hidl_cb) {
188 if (!thermal_service_) {
189 setInitFailureAndCallback(_hidl_cb);
190 }
191 if (callback == nullptr) {
192 setFailureAndCallback(_hidl_cb, "Invalid nullptr callback");
193 return Void();
194 }
195 std::lock_guard<std::mutex> _lock(callback_wrappers_mutex_);
196 for (const auto& callback_wrapper : callback_wrappers_) {
197 if (::android::hardware::interfacesEqual(callback_wrapper->callback_2_0_.get(),
198 callback.get())) {
199 setFailureAndCallback(_hidl_cb, "The callback was already registered through wrapper");
200 return Void();
201 }
202 }
203 std::shared_ptr<IThermalChangedCallbackWrapper> callback_wrapper =
204 ndk::SharedRefBase::make<IThermalChangedCallbackWrapper>(callback);
205 ::ndk::ScopedAStatus a_status;
206 ThermalStatus status;
207 if (filterType) {
208 a_status = thermal_service_->registerThermalChangedCallbackWithType(
209 callback_wrapper, static_cast<TemperatureType>(type));
210 } else {
211 a_status = thermal_service_->registerThermalChangedCallback(callback_wrapper);
212 }
213 if (a_status.isOk()) {
214 callback_wrappers_.push_back(callback_wrapper);
215 _hidl_cb(status);
216 } else {
217 setFailureAndCallback(_hidl_cb, a_status.getMessage());
218 }
219 return Void();
220 }
221
unregisterThermalChangedCallback(const sp<IThermalChangedCallback_2_0> & callback,std::function<void (const ThermalStatus &)> _hidl_cb)222 Return<void> ThermalHidlWrapper::unregisterThermalChangedCallback(
223 const sp<IThermalChangedCallback_2_0>& callback,
224 std::function<void(const ThermalStatus&)> _hidl_cb) {
225 if (!thermal_service_) {
226 setInitFailureAndCallback(_hidl_cb);
227 }
228 if (callback == nullptr) {
229 setFailureAndCallback(_hidl_cb, "Invalid nullptr callback");
230 return Void();
231 }
232 std::lock_guard<std::mutex> _lock(callback_wrappers_mutex_);
233 for (auto it = callback_wrappers_.begin(); it != callback_wrappers_.end(); it++) {
234 auto callback_wrapper = *it;
235 if (::android::hardware::interfacesEqual(callback_wrapper->callback_2_0_.get(),
236 callback.get())) {
237 ::ndk::ScopedAStatus a_status;
238 ThermalStatus status;
239 a_status = thermal_service_->unregisterThermalChangedCallback(callback_wrapper);
240 if (a_status.isOk()) {
241 callback_wrappers_.erase(it);
242 _hidl_cb(status);
243 } else {
244 setFailureAndCallback(_hidl_cb, a_status.getMessage());
245 }
246 return Void();
247 }
248 }
249 setFailureAndCallback(_hidl_cb, "The callback was not registered through wrapper before");
250 return Void();
251 }
252
getCurrentCoolingDevices(bool filterType,CoolingType_2_0 type,std::function<void (const ThermalStatus &,const hidl_vec<CoolingDevice_2_0> &)> _hidl_cb)253 Return<void> ThermalHidlWrapper::getCurrentCoolingDevices(
254 bool filterType, CoolingType_2_0 type,
255 std::function<void(const ThermalStatus&, const hidl_vec<CoolingDevice_2_0>&)> _hidl_cb) {
256 hidl_vec<CoolingDevice_2_0> ret_2_0;
257 if (!thermal_service_) {
258 setInitFailureAndCallback(_hidl_cb, ret_2_0);
259 }
260
261 std::vector<CoolingDevice> ret_aidl;
262 ThermalStatus status;
263 ::ndk::ScopedAStatus a_status;
264 if (filterType) {
265 a_status = thermal_service_->getCoolingDevicesWithType(static_cast<CoolingType>(type),
266 &ret_aidl);
267 } else {
268 a_status = thermal_service_->getCoolingDevices(&ret_aidl);
269 }
270 if (a_status.isOk()) {
271 std::vector<CoolingDevice_2_0> ret;
272 for (const auto& cooling_device : ret_aidl) {
273 ret.push_back(convertAidlCoolingDevice(cooling_device));
274 }
275 _hidl_cb(status, hidl_vec<CoolingDevice_2_0>(ret));
276 } else {
277 setFailureAndCallback(_hidl_cb, ret_2_0, a_status.getMessage());
278 }
279 return Void();
280 }
281
282 // Methods from ::android::hidl::base::V1_0::IBase follow.
debug(const hidl_handle & handle,const hidl_vec<hidl_string> & args)283 Return<void> ThermalHidlWrapper::debug(const hidl_handle& handle,
284 const hidl_vec<hidl_string>& args) {
285 if (handle != nullptr && handle->numFds >= 1) {
286 int fd = handle->data[0];
287 char** arr = new char*[args.size()];
288 for (size_t i = 0; i < args.size(); i++) {
289 arr[i] = strdup(args[i].c_str());
290 }
291 thermal_service_->dump(fd, (const char**)arr, args.size());
292 }
293 return Void();
294 }
295
notifyThrottling(const Temperature & temperature)296 ::ndk::ScopedAStatus ThermalHidlWrapper::IThermalChangedCallbackWrapper::notifyThrottling(
297 const Temperature& temperature) {
298 callback_2_0_->notifyThrottling(convertAidlTemperature(temperature));
299 return ::ndk::ScopedAStatus::ok();
300 }
301
302 } // namespace thermal
303 } // namespace hardware
304 } // namespace android
305 } // namespace aidl
306