Xiang Wang | 0b7c652 | 2023-02-15 15:42:22 -0800 | [diff] [blame] | 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> |
| 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> |
| 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> |
| 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> |
| 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> |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | } |
| 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. |
| 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 | |
| 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 | |
| 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. |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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. |
| 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 | |
| 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 |