/* * Copyright (c) 2020, The Linux Foundation. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * Neither the name of The Linux Foundation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Changes from Qualcomm Innovation Center are provided under the following license: * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted (subject to the limitations in the * disclaimer below) provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * * Neither the name of Qualcomm Innovation Center, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE * GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include "thermal.h" namespace android { namespace hardware { namespace thermal { namespace V2_0 { namespace implementation { using ::android::hardware::interfacesEqual; static const Temperature_1_0 dummy_temp_1_0 = { .type = TemperatureType_1_0::SKIN, .name = "test sensor", .currentValue = 30, .throttlingThreshold = 40, .shutdownThreshold = 60, .vrThrottlingThreshold = 40, }; static const Temperature dummy_temp_2_0 = { .type = TemperatureType::SKIN, .name = "test sensor", .value = 25.0, .throttlingStatus = ThrottlingSeverity::NONE, }; template Return exit_hal(A _cb, hidl_vec _data, std::string_view _msg) { ThermalStatus _status; _status.code = ThermalStatusCode::FAILURE; _status.debugMessage = _msg.data(); LOG(ERROR) << _msg; _cb(_status, _data); return Void(); } template Return exit_hal(A _cb, std::string_view _msg) { ThermalStatus _status; _status.code = ThermalStatusCode::FAILURE; _status.debugMessage = _msg.data(); LOG(ERROR) << _msg; _cb(_status); return Void(); } Thermal::Thermal(): utils(std::bind(&Thermal::sendThrottlingChangeCB, this, std::placeholders::_1)) { } Return Thermal::getTemperatures(getTemperatures_cb _hidl_cb) { ThermalStatus status; hidl_vec temperatures; status.code = ThermalStatusCode::SUCCESS; if (!utils.isSensorInitialized()) { std::vector _temp = {dummy_temp_1_0}; LOG(INFO) << "Returning Dummy Value" << std::endl; _hidl_cb(status, _temp); return Void(); } if (utils.readTemperatures(temperatures) <= 0) return exit_hal(_hidl_cb, temperatures, "Sensor Temperature read failure."); _hidl_cb(status, temperatures); return Void(); } Return Thermal::getCpuUsages(getCpuUsages_cb _hidl_cb) { ThermalStatus status; hidl_vec cpu_usages; status.code = ThermalStatusCode::SUCCESS; if (utils.fetchCpuUsages(cpu_usages) <= 0) return exit_hal(_hidl_cb, cpu_usages, "CPU usage read failure."); _hidl_cb(status, cpu_usages); return Void(); } Return Thermal::getCoolingDevices(getCoolingDevices_cb _hidl_cb) { ThermalStatus status; hidl_vec cdev; status.code = ThermalStatusCode::SUCCESS; /* V1 Cdev requires only Fan Support. */ _hidl_cb(status, cdev); return Void(); } Return Thermal::getCurrentCoolingDevices( bool filterType, cdevType type, getCurrentCoolingDevices_cb _hidl_cb) { ThermalStatus status; hidl_vec cdev; status.code = ThermalStatusCode::SUCCESS; if (!utils.isCdevInitialized()) return exit_hal(_hidl_cb, cdev, "ThermalHAL not initialized properly."); if (utils.readCdevStates(filterType, type, cdev) <= 0) return exit_hal(_hidl_cb, cdev, "Failed to read thermal cooling devices."); _hidl_cb(status, cdev); return Void(); } Return Thermal::getCurrentTemperatures( bool filterType, TemperatureType type, getCurrentTemperatures_cb _hidl_cb) { ThermalStatus status; hidl_vec temperatures; status.code = ThermalStatusCode::SUCCESS; if (!utils.isSensorInitialized()) return exit_hal(_hidl_cb, temperatures, "ThermalHAL not initialized properly."); if (utils.readTemperatures(filterType, type, temperatures) <= 0) { if (filterType && type != dummy_temp_2_0.type) { status.code = ThermalStatusCode::FAILURE; status.debugMessage = "Failed to read dummy temperature value"; } else { temperatures = {dummy_temp_2_0}; LOG(INFO) << "Returning Dummy Temperature Value" << std::endl; } } _hidl_cb(status, temperatures); return Void(); } Return Thermal::getTemperatureThresholds( bool filterType, TemperatureType type, getTemperatureThresholds_cb _hidl_cb) { ThermalStatus status; hidl_vec thresh; status.code = ThermalStatusCode::SUCCESS; if (!utils.isSensorInitialized()) return exit_hal(_hidl_cb, thresh, "ThermalHAL not initialized properly."); if (utils.readTemperatureThreshold(filterType, type, thresh) <= 0) return exit_hal(_hidl_cb, thresh, "Sensor Threshold read failure or type not supported."); _hidl_cb(status, thresh); return Void(); } Return Thermal::registerThermalChangedCallback( const sp &callback, bool filterType, TemperatureType type, registerThermalChangedCallback_cb _hidl_cb) { ThermalStatus status; std::lock_guard _lock(thermal_cb_mutex); status.code = ThermalStatusCode::SUCCESS; if (callback == nullptr) return exit_hal(_hidl_cb, "Invalid nullptr callback"); if (type == TemperatureType::BCL_VOLTAGE || type == TemperatureType::BCL_CURRENT) return exit_hal(_hidl_cb, "BCL current and voltage notification not supported"); for (CallbackSetting _cb: cb) { if (interfacesEqual(_cb.callback, callback)) return exit_hal(_hidl_cb, "Same callback interface registered already"); } cb.emplace_back(callback, filterType, type); LOG(DEBUG) << "A callback has been registered to ThermalHAL, isFilter: " << filterType << " Type: " << android::hardware::thermal::V2_0::toString(type); _hidl_cb(status); return Void(); } Return Thermal::unregisterThermalChangedCallback( const sp &callback, unregisterThermalChangedCallback_cb _hidl_cb) { ThermalStatus status; bool removed = false; std::lock_guard _lock(thermal_cb_mutex); std::vector::iterator it; status.code = ThermalStatusCode::SUCCESS; if (callback == nullptr) return exit_hal(_hidl_cb, "Invalid nullptr callback"); for (it = cb.begin(); it != cb.end(); it++) { if (interfacesEqual(it->callback, callback)) { cb.erase(it); LOG(DEBUG) << "callback unregistered. isFilter: " << it->is_filter_type << " Type: " << android::hardware::thermal::V2_0::toString(it->type); removed = true; break; } } if (!removed) return exit_hal(_hidl_cb, "The callback was not registered before"); _hidl_cb(status); return Void(); } void Thermal::sendThrottlingChangeCB(const Temperature &t) { std::lock_guard _lock(thermal_cb_mutex); std::vector::iterator it; LOG(DEBUG) << "Throttle Severity change: " << " Type: " << (int)t.type << " Name: " << t.name << " Value: " << t.value << " ThrottlingStatus: " << (int)t.throttlingStatus; it = cb.begin(); while (it != cb.end()) { if (!it->is_filter_type || it->type == t.type) { Return ret = it->callback->notifyThrottling(t); if (!ret.isOk()) { LOG(ERROR) << "Notify callback execution error. Removing"; it = cb.erase(it); continue; } } it++; } } } // namespace implementation } // namespace V2_0 } // namespace thermal } // namespace hardware } // namespace android