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