diff options
author | Ram Chandrasekar <rkumbako@codeaurora.org> | 2020-06-10 12:23:28 -0700 |
---|---|---|
committer | Ram Chandrasekar <rkumbako@codeaurora.org> | 2020-07-09 15:23:36 -0700 |
commit | dac8f7dd5a799e95196072ac7ac0ff6b944867b0 (patch) | |
tree | bb9f3e1ebda0512db3fd68f8d2cd86e49f8ae654 | |
parent | 95b571040fc5c15dfc9361458391eceb86dd95a5 (diff) |
thermal-hal: Add support for HAL2.0
Add support for thermal HAL 2.0 interfaces. Also add support for HAL 1.0
interfaces to be backward compatible.
Change-Id: Ib0be008605db2751bda21f537ea694b3f9849800
-rw-r--r-- | Android.bp | 36 | ||||
-rw-r--r-- | Android.mk | 39 | ||||
-rw-r--r-- | android.hardware.thermal@2.0-service.qti.rc | 34 | ||||
-rw-r--r-- | android.hardware.thermal@2.0-service.qti.xml | 42 | ||||
-rw-r--r-- | service.cpp | 65 | ||||
-rw-r--r-- | thermal-845.c | 100 | ||||
-rw-r--r-- | thermal-8998.c | 100 | ||||
-rw-r--r-- | thermal.c | 187 | ||||
-rw-r--r-- | thermal.cpp | 277 | ||||
-rw-r--r-- | thermal.h | 114 | ||||
-rw-r--r-- | thermalCommon.cpp | 595 | ||||
-rw-r--r-- | thermalCommon.h | 83 | ||||
-rw-r--r-- | thermalConfig.cpp | 345 | ||||
-rw-r--r-- | thermalConfig.h | 67 | ||||
-rw-r--r-- | thermalData.h | 96 | ||||
-rw-r--r-- | thermalMonitor.cpp | 192 | ||||
-rw-r--r-- | thermalMonitor.h | 69 | ||||
-rw-r--r-- | thermalUtils.cpp | 224 | ||||
-rw-r--r-- | thermalUtils.h | 91 | ||||
-rw-r--r-- | thermal_common.c | 385 | ||||
-rw-r--r-- | thermal_common.h | 76 | ||||
-rw-r--r-- | thermal_target.c | 877 |
22 files changed, 2330 insertions, 1764 deletions
diff --git a/Android.bp b/Android.bp new file mode 100644 index 0000000..284f473 --- /dev/null +++ b/Android.bp @@ -0,0 +1,36 @@ +cc_binary { + name: "android.hardware.thermal@2.0-service.qti", + defaults: [ + "hidl_defaults", + ], + vendor: true, + relative_install_path: "hw", + init_rc: ["android.hardware.thermal@2.0-service.qti.rc"], + vintf_fragments: ["android.hardware.thermal@2.0-service.qti.xml"], + srcs: [ + "service.cpp", + "thermal.cpp", + "thermalConfig.cpp", + "thermalCommon.cpp", + "thermalUtils.cpp", + "thermalMonitor.cpp", + ], + shared_libs: [ + "libbase", + "libcutils", + "libhidlbase", + "libhidltransport", + "libutils", + "liblog", + "android.hardware.thermal@1.0", + "android.hardware.thermal@2.0", + ], + header_libs: [ + "liblog_headers", + "libcutils_headers" + ], + cflags: [ + "-Wno-unused-parameter", + "-Wno-unused-variable", + ], +} diff --git a/Android.mk b/Android.mk deleted file mode 100644 index 1a14500..0000000 --- a/Android.mk +++ /dev/null @@ -1,39 +0,0 @@ -# Copyright (C) 2015 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -LOCAL_PATH := $(call my-dir) - -include $(CLEAR_VARS) - -LOCAL_MODULE := thermal.$(TARGET_BOARD_PLATFORM) -LOCAL_MODULE_RELATIVE_PATH := hw -LOCAL_PROPRIETARY_MODULE := true - -LOCAL_SRC_FILES := thermal.c -LOCAL_SRC_FILES += thermal_common.c - -ifeq ($(call is-board-platform-in-list,msm8998), true) -LOCAL_SRC_FILES += thermal-8998.c -else ifeq ($(call is-board-platform-in-list,sdm845), true) -LOCAL_SRC_FILES += thermal-845.c -else -LOCAL_SRC_FILES += thermal_target.c -endif - -LOCAL_HEADER_LIBRARIES := libutils_headers libhardware_headers -LOCAL_SHARED_LIBRARIES := liblog libcutils -LOCAL_MODULE_TAGS := optional -LOCAL_CFLAGS := -Wno-unused-parameter - -include $(BUILD_SHARED_LIBRARY) diff --git a/android.hardware.thermal@2.0-service.qti.rc b/android.hardware.thermal@2.0-service.qti.rc new file mode 100644 index 0000000..4c9186c --- /dev/null +++ b/android.hardware.thermal@2.0-service.qti.rc @@ -0,0 +1,34 @@ +# 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. + +service android.thermal-hal /vendor/bin/hw/android.hardware.thermal@2.0-service.qti + interface android.hardware.thermal@1.0::IThermal default + interface android.hardware.thermal@2.0::IThermal default + class hal + user root + group root diff --git a/android.hardware.thermal@2.0-service.qti.xml b/android.hardware.thermal@2.0-service.qti.xml new file mode 100644 index 0000000..26c3e56 --- /dev/null +++ b/android.hardware.thermal@2.0-service.qti.xml @@ -0,0 +1,42 @@ +<!-- +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. +--> + +<manifest version="1.0" type="device"> + <hal format="hidl"> + <name>android.hardware.thermal</name> + <transport>hwbinder</transport> + <version>1.0</version> + <version>2.0</version> + <interface> + <name>IThermal</name> + <instance>default</instance> + </interface> + </hal> +</manifest> diff --git a/service.cpp b/service.cpp new file mode 100644 index 0000000..f1350ec --- /dev/null +++ b/service.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + * Not a contribution + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "thermal_hal" + +#include <android-base/logging.h> +#include <hidl/HidlTransportSupport.h> +#include "thermal.h" + +using ::android::OK; +using ::android::status_t; + +// libhwbinder: +using ::android::hardware::configureRpcThreadpool; +using ::android::hardware::joinRpcThreadpool; + +// Generated HIDL files: +using ::android::hardware::thermal::V2_0::IThermal; +using ::android::hardware::thermal::V2_0::implementation::Thermal; + +static int shutdown() { + LOG(ERROR) << "Thermal HAL Service is shutting down."; + return 1; +} + +int main(int /* argc */, char ** /* argv */) { + status_t status; + android::sp<IThermal> service = nullptr; + + LOG(INFO) << "Thermal HAL Service 2.0 starting..."; + + service = new Thermal(); + if (service == nullptr) { + LOG(ERROR) << "Error creating an instance of Thermal HAL. Exiting..."; + return shutdown(); + } + + configureRpcThreadpool(1, true /* callerWillJoin */); + + status = service->registerAsService(); + if (status != OK) { + LOG(ERROR) << "Could not register service for ThermalHAL (" << status << ")"; + return shutdown(); + } + + LOG(INFO) << "Thermal HAL Service 2.0 started successfully."; + joinRpcThreadpool(); + // We should not get past the joinRpcThreadpool(). + return shutdown(); +} diff --git a/thermal-845.c b/thermal-845.c deleted file mode 100644 index 59925b5..0000000 --- a/thermal-845.c +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved. - * Not a contribution - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -#define LOG_TAG "ThermalHAL-845" -#include <utils/Log.h> - -#include <hardware/hardware.h> -#include <hardware/thermal.h> -#include "thermal_common.h" - -static char *cpu_sensors_845[] = -{ - "cpu0-silver-usr", - "cpu1-silver-usr", - "cpu2-silver-usr", - "cpu3-silver-usr", - "cpu0-gold-usr", - "cpu1-gold-usr", - "cpu2-gold-usr", - "cpu3-gold-usr", -}; - -static char *misc_sensors_845[] = -{ - "gpu0-usr", - "battery", - "xo-therm-adc" -}; - -static struct target_therm_cfg sensor_cfg_845[] = { - { - .type = DEVICE_TEMPERATURE_CPU, - .sensor_list = cpu_sensors_845, - .sens_cnt = ARRAY_SIZE(cpu_sensors_845), - .mult = 0.001, - .throt_thresh = 60, - .shutdwn_thresh = 115, - }, - { - .type = DEVICE_TEMPERATURE_GPU, - .sensor_list = &misc_sensors_845[0], - .sens_cnt = 1, - .mult = 0.001, - .label = "GPU", - }, - { - .type = DEVICE_TEMPERATURE_BATTERY, - .sensor_list = &misc_sensors_845[1], - .sens_cnt = 1, - .mult = 0.001, - .shutdwn_thresh = 60, - .label = "battery", - }, - { - .type = DEVICE_TEMPERATURE_SKIN, - .sensor_list = &misc_sensors_845[2], - .sens_cnt = 1, - .mult = 0.001, - .throt_thresh = 44, - .shutdwn_thresh = 70, - .vr_thresh = 58, - .label = "skin", - } -}; - -ssize_t get_temperatures(thermal_module_t *module, temperature_t *list, size_t size) { - ALOGD("Entering %s",__func__); - static int thermal_sens_size; - - if (!thermal_sens_size) { - thermal_sens_size = thermal_zone_init(sensor_cfg_845, - ARRAY_SIZE(sensor_cfg_845)); - if (thermal_sens_size <= 0) { - ALOGE("thermal sensor initialization is failed\n"); - thermal_sens_size = 0; - return 0; - } - } - - if (list == NULL) - return thermal_sens_size; - - return get_temperature_for_all(list, size); -} diff --git a/thermal-8998.c b/thermal-8998.c deleted file mode 100644 index 94bf375..0000000 --- a/thermal-8998.c +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved. - * Not a contribution - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -#define LOG_TAG "ThermalHAL-8998" -#include <utils/Log.h> - -#include <hardware/hardware.h> -#include <hardware/thermal.h> -#include "thermal_common.h" - -static char *cpu_sensors_8998[] = -{ - "tsens_tz_sensor1", - "tsens_tz_sensor2", - "tsens_tz_sensor3", - "tsens_tz_sensor4", - "tsens_tz_sensor7", - "tsens_tz_sensor8", - "tsens_tz_sensor9", - "tsens_tz_sensor10", -}; - -static char *misc_sensors_8998[] = -{ - "tsens_tz_sensor12", - "battery", - "quiet_therm" -}; - -static struct target_therm_cfg sensor_cfg_8998[] = { - { - .type = DEVICE_TEMPERATURE_CPU, - .sensor_list = cpu_sensors_8998, - .sens_cnt = ARRAY_SIZE(cpu_sensors_8998), - .mult = 0.1, - .throt_thresh = 60, - .shutdwn_thresh = 115, - }, - { - .type = DEVICE_TEMPERATURE_GPU, - .sensor_list = &misc_sensors_8998[0], - .sens_cnt = 1, - .mult = 0.1, - .label = "GPU", - }, - { - .type = DEVICE_TEMPERATURE_BATTERY, - .sensor_list = &misc_sensors_8998[1], - .sens_cnt = 1, - .mult = 0.001, - .shutdwn_thresh = 60, - .label = "battery", - }, - { - .type = DEVICE_TEMPERATURE_SKIN, - .sensor_list = &misc_sensors_8998[2], - .sens_cnt = 1, - .mult = 1.0, - .throt_thresh = 44, - .shutdwn_thresh = 70, - .vr_thresh = 58, - .label = "skin", - } -}; - -ssize_t get_temperatures(thermal_module_t *module, temperature_t *list, size_t size) { - ALOGD("Entering %s",__func__); - static int thermal_sens_size; - - if (!thermal_sens_size) { - thermal_sens_size = thermal_zone_init(sensor_cfg_8998, - ARRAY_SIZE(sensor_cfg_8998)); - if (thermal_sens_size <= 0) { - ALOGE("thermal sensor initialization is failed\n"); - thermal_sens_size = 0; - return 0; - } - } - - if (list == NULL) - return thermal_sens_size; - - return get_temperature_for_all(list, size); -} diff --git a/thermal.c b/thermal.c deleted file mode 100644 index 684c52f..0000000 --- a/thermal.c +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Copyright (c) 2017, The Linux Foundation. All rights reserved. - * Not a contribution - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <ctype.h> -#include <errno.h> -#include <inttypes.h> -#include <stdlib.h> -#include <string.h> - -#define LOG_TAG "ThermalHAL" -#include <utils/Log.h> - -#include <hardware/hardware.h> -#include <hardware/thermal.h> - -#define MAX_LENGTH 50 - -#define CPU_USAGE_FILE "/proc/stat" -#define CPU_ONLINE_FILE_FORMAT "/sys/devices/system/cpu/cpu%d/online" -#define CPU_PRESENT_FILE "/sys/devices/system/cpu/present" - -const char * __attribute__ ((weak)) get_cpu_label(unsigned int cpu_num) { - ALOGD("Entering %s",__func__); - static const char * cpu_label = "cpu"; - return cpu_label; -} - -size_t __attribute__ ((weak)) get_num_cpus() { - ALOGD("Entering %s",__func__); - FILE *file; - char *line = NULL; - size_t len = 0; - static size_t cpus = 0; - ssize_t read; - - if(cpus) return cpus; - - file = fopen(CPU_PRESENT_FILE, "r"); - if (file == NULL) { - ALOGE("%s: failed to open: %s", __func__, strerror(errno)); - return 0; - } - - if ((read = getline(&line, &len, file)) != -1) { - if (strnlen(line, read) < 3 || strncmp(line, "0-", 2) != 0 || !isdigit(line[2])) - ALOGE("%s: Incorrect cpu present file format", __func__); - else - cpus = atoi(&line[2]) + 1; - - free(line); - } - else - ALOGE("%s: failed to read cpu present file: %s", __func__, strerror(errno)); - - fclose(file); - return cpus; -} - -ssize_t __attribute__ ((weak)) get_temperatures(thermal_module_t *module, temperature_t *list, size_t size) { - ALOGD("Entering %s",__func__); - return 0; -} - -static ssize_t get_cpu_usages(thermal_module_t *module, cpu_usage_t *list) { - ALOGD("Entering %s",__func__); - int vals, cpu_num, online; - ssize_t read; - uint64_t user, nice, system, idle, active, total; - char *line = NULL; - size_t len = 0; - size_t size = 0; - size_t cpus = 0; - char file_name[MAX_LENGTH]; - FILE *file; - FILE *cpu_file; - - cpus = get_num_cpus(); - if (!cpus) - return errno ? -errno : -EIO; - - if (list == NULL) - return cpus; - - file = fopen(CPU_USAGE_FILE, "r"); - if (file == NULL) { - ALOGE("%s: failed to open: %s", __func__, strerror(errno)); - return -errno; - } - - while ((read = getline(&line, &len, file)) != -1) { - if (strnlen(line, read) < 4 || strncmp(line, "cpu", 3) != 0 || !isdigit(line[3])) { - free(line); - line = NULL; - len = 0; - continue; - } - - vals = sscanf(line, "cpu%d %" SCNu64 " %" SCNu64 " %" SCNu64 " %" SCNu64, &cpu_num, &user, - &nice, &system, &idle); - - free(line); - line = NULL; - len = 0; - - if (vals != 5 || size == cpus) { - if (vals != 5) { - ALOGE("%s: failed to read CPU information from file: %s", __func__, - strerror(errno)); - } else { - ALOGE("/proc/stat file has incorrect format."); - } - fclose(file); - return errno ? -errno : -EIO; - } - - active = user + nice + system; - total = active + idle; - - // Read online CPU information. - snprintf(file_name, MAX_LENGTH, CPU_ONLINE_FILE_FORMAT, cpu_num); - cpu_file = fopen(file_name, "r"); - online = 0; - if (cpu_file == NULL) { - ALOGE("%s: failed to open file: %s (%s)", __func__, file_name, strerror(errno)); - fclose(file); - return -errno; - } - if (1 != fscanf(cpu_file, "%d", &online)) { - ALOGE("%s: failed to read CPU online information from file: %s (%s)", __func__, - file_name, strerror(errno)); - fclose(file); - fclose(cpu_file); - return errno ? -errno : -EIO; - } - fclose(cpu_file); - - list[size] = (cpu_usage_t) { - .name = get_cpu_label(size), - .active = active, - .total = total, - .is_online = online - }; - - size++; - } - fclose(file); - - if (size != cpus) { - ALOGE("/proc/stat file has incorrect format."); - return -EIO; - } - - return cpus; -} - -static struct hw_module_methods_t thermal_module_methods = { - .open = NULL, -}; - -thermal_module_t HAL_MODULE_INFO_SYM = { - .common = { - .tag = HARDWARE_MODULE_TAG, - .module_api_version = THERMAL_HARDWARE_MODULE_API_VERSION_0_1, - .hal_api_version = HARDWARE_HAL_API_VERSION, - .id = THERMAL_HARDWARE_MODULE_ID, - .name = "Thermal HAL", - .author = "The Android Open Source Project", - .methods = &thermal_module_methods, - }, - .getTemperatures = get_temperatures, - .getCpuUsages = get_cpu_usages, -}; diff --git a/thermal.cpp b/thermal.cpp new file mode 100644 index 0000000..c525e8b --- /dev/null +++ b/thermal.cpp @@ -0,0 +1,277 @@ +/* + * 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. + */ + +#include <ctype.h> +#include <errno.h> +#include <inttypes.h> +#include <stdlib.h> +#include <cerrno> +#include <mutex> +#include <string> + +#include <android-base/file.h> +#include <android-base/logging.h> +#include <hidl/HidlTransportSupport.h> + +#include "thermal.h" +#include "thermalUtils.h" + +namespace android { +namespace hardware { +namespace thermal { +namespace V2_0 { +namespace implementation { + +using ::android::hardware::interfacesEqual; + +template <typename A, typename B> +Return<void> exit_hal(A _cb, hidl_vec<B> _data, std::string_view _msg) { + ThermalStatus _status; + + _status.code = ThermalStatusCode::FAILURE; + _status.debugMessage = _msg.data(); + LOG(ERROR) << _msg; + _cb(_status, _data); + + return Void(); +} + +template <typename A> +Return<void> 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<void> Thermal::getTemperatures(getTemperatures_cb _hidl_cb) +{ + ThermalStatus status; + hidl_vec<Temperature_1_0> temperatures; + + status.code = ThermalStatusCode::SUCCESS; + if (!utils.isSensorInitialized()) + return exit_hal(_hidl_cb, temperatures, + "ThermalHAL not initialized properly."); + + if (!utils.readTemperatures(&temperatures)) + return exit_hal(_hidl_cb, temperatures, + "Sensor Temperature read failure."); + + _hidl_cb(status, temperatures); + + return Void(); +} + +Return<void> Thermal::getCpuUsages(getCpuUsages_cb _hidl_cb) +{ + + ThermalStatus status; + hidl_vec<CpuUsage> cpu_usages; + + status.code = ThermalStatusCode::SUCCESS; + if (!utils.isSensorInitialized()) + return exit_hal(_hidl_cb, cpu_usages, + "ThermalHAL not initialized properly."); + 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<void> Thermal::getCoolingDevices(getCoolingDevices_cb _hidl_cb) +{ + ThermalStatus status; + hidl_vec<CoolingDevice_1_0> cdev; + + status.code = ThermalStatusCode::SUCCESS; + if (!utils.isCdevInitialized()) + return exit_hal(_hidl_cb, cdev, + "ThermalHAL not initialized properly."); + /* V1 Cdev requires only Fan Support. */ + _hidl_cb(status, cdev); + return Void(); +} + +Return<void> Thermal::getCurrentCoolingDevices( + bool filterType, + cdevType type, + getCurrentCoolingDevices_cb _hidl_cb) +{ + ThermalStatus status; + hidl_vec<CoolingDevice> cdev; + + status.code = ThermalStatusCode::SUCCESS; + if (!utils.isCdevInitialized()) + return exit_hal(_hidl_cb, cdev, + "ThermalHAL not initialized properly."); + if (!utils.readCdevStates(filterType, type, &cdev)) + return exit_hal(_hidl_cb, cdev, + "Failed to read thermal cooling devices."); + + _hidl_cb(status, cdev); + return Void(); +} + +Return<void> Thermal::getCurrentTemperatures( + bool filterType, + TemperatureType type, + getCurrentTemperatures_cb _hidl_cb) +{ + ThermalStatus status; + hidl_vec<Temperature> temperatures; + + status.code = ThermalStatusCode::SUCCESS; + if (!utils.isSensorInitialized()) + return exit_hal(_hidl_cb, temperatures, + "ThermalHAL not initialized properly."); + + if (!utils.readTemperatures(filterType, type, &temperatures)) + return exit_hal(_hidl_cb, temperatures, + "Sensor Temperature read failure."); + + _hidl_cb(status, temperatures); + + return Void(); +} + +Return<void> Thermal::getTemperatureThresholds( + bool filterType, + TemperatureType type, + getTemperatureThresholds_cb _hidl_cb) +{ + ThermalStatus status; + hidl_vec<TemperatureThreshold> thresh; + + status.code = ThermalStatusCode::SUCCESS; + if (!utils.isSensorInitialized()) + return exit_hal(_hidl_cb, thresh, + "ThermalHAL not initialized properly."); + + if (!utils.readTemperatureThreshold(filterType, type, &thresh)) + return exit_hal(_hidl_cb, thresh, + "Sensor Temperature threshold read failure."); + + _hidl_cb(status, thresh); + + return Void(); +} + +Return<void> Thermal::registerThermalChangedCallback( + const sp<IThermalChangedCallback> &callback, + bool filterType, + TemperatureType type, + registerThermalChangedCallback_cb _hidl_cb) +{ + ThermalStatus status; + std::lock_guard<std::mutex> _lock(thermal_cb_mutex); + std::vector<CallbackSetting>::iterator it; + + 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 (it = cb.begin(); it != cb.end(); it++) { + if (interfacesEqual(it->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<void> Thermal::unregisterThermalChangedCallback( + const sp<IThermalChangedCallback> &callback, + unregisterThermalChangedCallback_cb _hidl_cb) +{ + + ThermalStatus status; + bool removed = false; + std::lock_guard<std::mutex> _lock(thermal_cb_mutex); + std::vector<CallbackSetting>::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<std::mutex> _lock(thermal_cb_mutex); + std::vector<CallbackSetting>::iterator it; + + LOG(DEBUG) << "Throttle Severity change: " << " Type: " << (int)t.type + << " Name: " << t.name << " Value: " << t.value << + " ThrottlingStatus: " << (int)t.throttlingStatus; + for (it = cb.begin(); it != cb.end(); it++) { + if (!it->is_filter_type || it->type == t.type) + it->callback->notifyThrottling(t); + } +} + +} // namespace implementation +} // namespace V2_0 +} // namespace thermal +} // namespace hardware +} // namespace android diff --git a/thermal.h b/thermal.h new file mode 100644 index 0000000..1450ebb --- /dev/null +++ b/thermal.h @@ -0,0 +1,114 @@ +/* + * 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. + */ + +#ifndef ANDROID_QTI_VENDOR_THERMAL_H +#define ANDROID_QTI_VENDOR_THERMAL_H + +#include <mutex> +#include <thread> + +#include <android/hardware/thermal/2.0/IThermal.h> +#include <hidl/MQDescriptor.h> +#include <android/hardware/thermal/2.0/IThermalChangedCallback.h> + +#include <hidl/Status.h> + +#include "thermalUtils.h" +#include "thermalData.h" + +namespace android { +namespace hardware { +namespace thermal { +namespace V2_0 { +namespace implementation { + +struct CallbackSetting { + sp<IThermalChangedCallback> callback; + bool is_filter_type; + TemperatureType type; + + CallbackSetting(sp<IThermalChangedCallback> callback, + bool is_filter_type, TemperatureType type) + : callback(callback), + is_filter_type(is_filter_type), type(type) {} +}; + +class Thermal : public IThermal { + public: + Thermal(); + ~Thermal() = default; + + Thermal(const Thermal &) = delete; + void operator=(const Thermal &) = delete; + + Return<void> getTemperatures( + getTemperatures_cb _hidl_cb) override; + Return<void> getCpuUsages(getCpuUsages_cb _hidl_cb) override; + Return<void> getCoolingDevices( + getCoolingDevices_cb _hidl_cb) override; + + Return<void> getCurrentTemperatures( + bool filterType, + TemperatureType type, + getCurrentTemperatures_cb _hidl_cb) override; + Return<void> getTemperatureThresholds( + bool filterType, + TemperatureType type, + getTemperatureThresholds_cb _hidl_cb) override; + Return<void> registerThermalChangedCallback( + const sp<IThermalChangedCallback> &callback, + bool filterType, + TemperatureType type, + registerThermalChangedCallback_cb _hidl_cb) + override; + Return<void> unregisterThermalChangedCallback( + const sp<IThermalChangedCallback> &callback, + unregisterThermalChangedCallback_cb _hidl_cb) + override; + Return<void> getCurrentCoolingDevices( + bool filterType, + CoolingType type, + getCurrentCoolingDevices_cb _hidl_cb) override; + + void sendThrottlingChangeCB(const Temperature &t); + + private: + std::mutex thermal_cb_mutex; + std::vector<CallbackSetting> cb; + ThermalUtils utils; +}; + +} // namespace implementation +} // namespace V2_0 +} // namespace thermal +} // namespace hardware +} // namespace android + +#endif // ANDROID_QTI_VENDOR_THERMAL_H diff --git a/thermalCommon.cpp b/thermalCommon.cpp new file mode 100644 index 0000000..642573f --- /dev/null +++ b/thermalCommon.cpp @@ -0,0 +1,595 @@ +/* + * 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. + */ + +#include <cstdio> +#include <cinttypes> +#include <string> +#include <dirent.h> +#include <unordered_map> +#include <fstream> + +#include <android-base/logging.h> +#include "thermalCommon.h" + +#define MAX_LENGTH 50 +#define MAX_PATH (256) +#define DEFAULT_HYSTERESIS 5000 +#define THERMAL_SYSFS "/sys/class/thermal/" +#define TZ_DIR_NAME "thermal_zone" +#define TZ_DIR_FMT "thermal_zone%d" +#define TEMPERATURE_FILE_FORMAT "/sys/class/thermal/thermal_zone%d/temp" +#define POLICY_FILE_FORMAT "/sys/class/thermal/thermal_zone%d/policy" +#define TRIP_FILE_FORMAT "/sys/class/thermal/thermal_zone%d/trip_point_1_temp" +#define HYST_FILE_FORMAT "/sys/class/thermal/thermal_zone%d/trip_point_1_hyst" +#define USER_SPACE_POLICY "user_space" +#define TZ_TYPE "type" +#define CDEV_DIR_NAME "cooling_device" +#define CDEV_DIR_FMT "cooling_device%d" +#define CDEV_CUR_STATE_PATH "/sys/class/thermal/cooling_device%d/cur_state" +#define CPU_USAGE_FILE "/proc/stat" +#define CPU_ONLINE_FILE_FORMAT "/sys/devices/system/cpu/cpu%d/online" + +namespace android { +namespace hardware { +namespace thermal { +namespace V2_0 { +namespace implementation { + +static std::unordered_map<std::string, cdevType> cdev_map = { + {"thermal-cpufreq-0", cdevType::CPU}, + {"thermal-cpufreq-1", cdevType::CPU}, + {"thermal-cpufreq-2", cdevType::CPU}, + {"thermal-cpufreq-3", cdevType::CPU}, + {"thermal-cpufreq-4", cdevType::CPU}, + {"thermal-cpufreq-5", cdevType::CPU}, + {"thermal-cpufreq-6", cdevType::CPU}, + {"thermal-cpufreq-7", cdevType::CPU}, + {"thermal-cluster-7-4", cdevType::CPU}, + {"cpu-isolate0", cdevType::CPU}, + {"cpu-isolate1", cdevType::CPU}, + {"cpu-isolate2", cdevType::CPU}, + {"cpu-isolate3", cdevType::CPU}, + {"cpu-isolate4", cdevType::CPU}, + {"cpu-isolate5", cdevType::CPU}, + {"cpu-isolate6", cdevType::CPU}, + {"cpu-isolate7", cdevType::CPU}, + {"thermal-devfreq-0", cdevType::GPU}, + {"modem_tj", cdevType::MODEM}, + {"cdsp", cdevType::NPU}, + {"cdsp_hw", cdevType::NPU}, + {"battery", cdevType::BATTERY}, +}; + +ThermalCommon::ThermalCommon() +{ + LOG(DEBUG) << "Entering " << __func__; + ncpus = (int)sysconf(_SC_NPROCESSORS_CONF); + if (ncpus < 1) + LOG(ERROR) << "Error retrieving number of cores"; +} + +static int writeToFile(std::string_view path, std::string data) +{ + std::fstream outFile; + + outFile.open(std::string(path).c_str(), + std::fstream::binary | std::fstream::out); + if (outFile.is_open()) { + LOG(DEBUG) << "writing: "<< data << " in path:" << path + << std::endl; + outFile << data; + outFile.close(); + return data.length(); + } + + LOG(ERROR) << "Error opening file: "<< path << std::endl; + return -1; +} + +static int readLineFromFile(std::string_view path, std::string *out) +{ + char *fgets_ret; + FILE *fd; + int rv; + char buf[MAX_LENGTH]; + + out->clear(); + + fd = fopen(std::string(path).c_str(), "r"); + if (fd == NULL) { + LOG(ERROR) << "Path:" << std::string(path) << " file open error.err:" + << strerror(errno) << std::endl; + return errno; + } + + fgets_ret = fgets(buf, MAX_LENGTH, fd); + if (NULL != fgets_ret) { + rv = (int)strlen(buf); + out->append(buf, rv); + } else { + rv = ferror(fd); + } + + fclose(fd); + out->erase(std::remove(out->begin(), out->end(), '\n'), out->end()); + LOG(DEBUG) << "Path:" << std::string(path) << " Val:" << *out << std::endl; + + return rv; +} + +int ThermalCommon::readFromFile(std::string_view path, std::string *out) +{ + return readLineFromFile(path, out); +} + +static int get_tzn(std::string sensor_name) +{ + DIR *tdir = NULL; + struct dirent *tdirent = NULL; + int found = -1; + int tzn = 0; + char name[MAX_PATH] = {0}; + char cwd[MAX_PATH] = {0}; + int ret = 0; + + if (!getcwd(cwd, sizeof(cwd))) + return found; + + /* Change dir to read the entries. Doesnt work otherwise */ + ret = chdir(THERMAL_SYSFS); + if (ret) { + LOG(ERROR) << "Unable to change to " << THERMAL_SYSFS << std::endl; + return found; + } + tdir = opendir(THERMAL_SYSFS); + if (!tdir) { + LOG(ERROR) << "Unable to open " << THERMAL_SYSFS << std::endl; + return found; + } + + while ((tdirent = readdir(tdir))) { + std::string buf; + + if (strncmp(tdirent->d_name, TZ_DIR_NAME, + strlen(TZ_DIR_NAME)) != 0) + continue; + + snprintf(name, MAX_PATH, "%s%s/%s", THERMAL_SYSFS, + tdirent->d_name, TZ_TYPE); + ret = readLineFromFile(std::string_view(name), &buf); + if (ret <= 0) { + LOG(ERROR) << + "get_tzn: sensor name read error for tz:" << + tdirent->d_name << std::endl; + continue; + } + if (!strncmp(buf.c_str(), sensor_name.c_str(), + sensor_name.length())) { + found = 1; + break; + } + } + + if (found == 1) { + sscanf(tdirent->d_name, TZ_DIR_FMT, &tzn); + LOG(DEBUG) << "Sensor: " << sensor_name << + " found at tz: " << tzn << std::endl; + found = tzn; + } + + closedir(tdir); + /* Restore current working dir */ + ret = chdir(cwd); + + return found; +} + +int ThermalCommon::initialize_sensor(struct target_therm_cfg cfg, int sens_idx) +{ + struct therm_sensor sensor; + int idx = 0; + + sensor.tzn = get_tzn(cfg.sensor_list[sens_idx]); + if (sensor.tzn < 0) { + LOG(ERROR) << "No thermal zone for sensor: " << + cfg.sensor_list[sens_idx] << ", ret:" << + sensor.tzn << std::endl; + return -1; + } + if (cfg.type == TemperatureType::CPU) + sensor.thresh.name = sensor.t.name = + std::string("CPU") + std::to_string(sens_idx); + else + sensor.thresh.name = sensor.t.name = cfg.label; + + if (cfg.type == TemperatureType::BCL_PERCENTAGE) + sensor.mulFactor = 1; + else + sensor.mulFactor = 1000; + + sensor.sensor_name = cfg.sensor_list[sens_idx]; + sensor.positiveThresh = cfg.positive_thresh_ramp; + sensor.lastThrottleStatus = sensor.t.throttlingStatus = + ThrottlingSeverity::NONE; + sensor.thresh.type = sensor.t.type = cfg.type; + sensor.thresh.vrThrottlingThreshold = + UNKNOWN_TEMPERATURE; + for (idx = 0; idx < (size_t)ThrottlingSeverity::SHUTDOWN; idx++) { + sensor.thresh.hotThrottlingThresholds[idx] = + sensor.thresh.coldThrottlingThresholds[idx] = + UNKNOWN_TEMPERATURE; + } + + if (cfg.throt_thresh != 0 && cfg.positive_thresh_ramp) + sensor.thresh.hotThrottlingThresholds[(size_t)ThrottlingSeverity::SEVERE - 1] = + cfg.throt_thresh; + else if (cfg.throt_thresh != 0 && !cfg.positive_thresh_ramp) + sensor.thresh.coldThrottlingThresholds[(size_t)ThrottlingSeverity::SEVERE - 1] = + cfg.throt_thresh; + + if (cfg.shutdwn_thresh != 0 && cfg.positive_thresh_ramp) + sensor.thresh.hotThrottlingThresholds[(size_t)ThrottlingSeverity::SHUTDOWN - 1] = + cfg.shutdwn_thresh; + else if (cfg.shutdwn_thresh != 0 && !cfg.positive_thresh_ramp) + sensor.thresh.coldThrottlingThresholds[(size_t)ThrottlingSeverity::SHUTDOWN - 1] = + cfg.shutdwn_thresh; + + if (cfg.vr_thresh != 0) + sensor.thresh.vrThrottlingThreshold = + cfg.vr_thresh; + sens.push_back(sensor); + //read_temperature((struct therm_sensor *)sensor); + + return 0; +} + +int ThermalCommon::initializeCpuSensor(struct target_therm_cfg cpu_cfg) +{ + int cpu = 0; + + for (;cpu < ncpus; cpu++) { + if (initialize_sensor(cpu_cfg, cpu) < 0) + return -1; + } + + return 0; +} + +int ThermalCommon::initThermalZones(std::vector<struct target_therm_cfg> cfg) +{ + std::vector<struct target_therm_cfg>::iterator it; + + if (cfg.empty()) { + LOG(ERROR) << std::string(__func__) +":Invalid input"; + return -1; + } + + for (it = cfg.begin(); it != cfg.end(); it++) + { + if (it->type == TemperatureType::CPU) { + if (initializeCpuSensor(*it) < 0) + return -1; + continue; + } + if (initialize_sensor(*it, 0) < 0) { + return -1; + } + } + + return sens.size(); +} + +int ThermalCommon::initCdev() +{ + DIR *tdir = NULL; + struct dirent *tdirent = NULL; + int cdevn = 0; + char name[MAX_PATH] = {0}; + char cwd[MAX_PATH] = {0}; + int ret = 0; + + if (!getcwd(cwd, sizeof(cwd))) + return 0; + + /* Change dir to read the entries. Doesnt work otherwise */ + ret = chdir(THERMAL_SYSFS); + if (ret) { + LOG(ERROR) << "Unable to change to " << THERMAL_SYSFS << std::endl; + return 0; + } + tdir = opendir(THERMAL_SYSFS); + if (!tdir) { + LOG(ERROR) << "Unable to open " << THERMAL_SYSFS << std::endl; + return 0; + } + + while ((tdirent = readdir(tdir))) { + std::string buf; + struct dirent *tzdirent; + std::unordered_map<std::string, cdevType>::iterator it; + struct therm_cdev cdevInst; + + if (strncmp(tdirent->d_name, CDEV_DIR_NAME, + strlen(CDEV_DIR_NAME)) != 0) + continue; + + snprintf(name, MAX_PATH, "%s%s/%s", THERMAL_SYSFS, + tdirent->d_name, TZ_TYPE); + ret = readLineFromFile(std::string_view(name), &buf); + if (ret <= 0) { + LOG(ERROR) << + "init_cdev: cdev type read error for cdev:" << + tdirent->d_name << std::endl; + } + it = cdev_map.find(buf); + if (it == cdev_map.end()) + continue; + sscanf(tdirent->d_name, CDEV_DIR_FMT, &cdevn); + LOG(DEBUG) << "cdev: " << it->first << + " found at cdev number: " << cdevn << std::endl; + cdevInst.c.name = it->first; + cdevInst.c.type = it->second; + cdevInst.cdevn = cdevn; + read_cdev_state(&cdevInst); + cdev.push_back(cdevInst); + } + + closedir(tdir); + /* Restore current working dir */ + ret = chdir(cwd); + + return cdev.size(); +} + +int ThermalCommon::read_cdev_state(struct therm_cdev *cdev) +{ + char file_name[MAX_PATH]; + std::string buf; + int ret = 0; + + LOG(DEBUG) << "Entering " <<__func__; + snprintf(file_name, sizeof(file_name), CDEV_CUR_STATE_PATH, + cdev->cdevn); + ret = readLineFromFile(std::string(file_name), &buf); + if (ret <= 0) { + LOG(ERROR) << "Cdev state read error:"<< ret << + " for cdev: " << cdev->c.name; + return -1; + } + cdev->c.value = std::stoi(buf, nullptr, 0); + LOG(DEBUG) << "cdev Name:" << cdev->c.name << ". state:" << + cdev->c.value << std::endl; + + return cdev->c.value; +} + +int ThermalCommon::estimateSeverity(struct therm_sensor *sensor) +{ + int idx = 0; + ThrottlingSeverity severity = ThrottlingSeverity::NONE; + float temp = sensor->t.value * sensor->mulFactor; + + for (idx = (int)ThrottlingSeverity::SHUTDOWN - 1; idx >= 0; idx--) { + if ((sensor->positiveThresh && + !isnan(sensor->thresh.hotThrottlingThresholds[idx]) && + temp >= + sensor->thresh.hotThrottlingThresholds[idx]) || + (!sensor->positiveThresh && + !isnan(sensor->thresh.coldThrottlingThresholds[idx]) && + temp <= + sensor->thresh.coldThrottlingThresholds[idx])) + break; + } + if (idx >= 0) + severity = (ThrottlingSeverity)(idx + 1); + LOG(DEBUG) << "Sensor Name:" << sensor->t.name << ". old severity:" << + (int)sensor->t.throttlingStatus << " New severity:" << + (int)severity << std::endl; + if (severity == sensor->t.throttlingStatus) + return 0; + sensor->lastThrottleStatus = sensor->t.throttlingStatus; + sensor->t.throttlingStatus = severity; + + return 0; +} + +int ThermalCommon::read_temperature(struct therm_sensor *sensor) +{ + char file_name[MAX_PATH]; + float temp; + std::string buf; + int ret = 0; + + LOG(DEBUG) << "Entering " <<__func__; + snprintf(file_name, sizeof(file_name), TEMPERATURE_FILE_FORMAT, + sensor->tzn); + ret = readLineFromFile(std::string(file_name), &buf); + if (ret <= 0) { + LOG(ERROR) << "Temperature read error:"<< ret << + " for sensor " << sensor->t.name; + return -1; + } + sensor->t.value = (float)std::stoi(buf, nullptr, 0) / (float)sensor->mulFactor; + LOG(DEBUG) << "Sensor Name:" << sensor->t.name << ". Temperature:" << + (float)sensor->t.value << std::endl; + + return estimateSeverity(sensor); +} + +void ThermalCommon::initThreshold(struct therm_sensor sensor) +{ + char file_name[MAX_PATH] = ""; + std::string buf; + int ret = 0, idx; + ThrottlingSeverity severity = ThrottlingSeverity::NONE; + int next_trip, curr_trip, hyst_temp = 0; + + LOG(DEBUG) << "Entering " <<__func__; + if (!sensor.positiveThresh) { + LOG(ERROR) << "negative temperature ramp for sensor:"<< + sensor.t.name; + return; + } + snprintf(file_name, sizeof(file_name), POLICY_FILE_FORMAT, + sensor.tzn); + ret = readLineFromFile(std::string(file_name), &buf); + if (ret <= 0) { + LOG(ERROR) << "Policy read error:"<< ret << + " for sensor " << sensor.t.name; + return; + } + if (buf != std::string(USER_SPACE_POLICY)) { + LOG(ERROR) << "Policy error:"<< buf << " sensor:" << + sensor.t.name << std::endl; + return; + } + + next_trip = UNKNOWN_TEMPERATURE; + for (idx = 0;idx < (int)ThrottlingSeverity::SHUTDOWN; idx++) { + if (isnan(sensor.thresh.hotThrottlingThresholds[idx]) + || idx <= ((int)sensor.t.throttlingStatus) - 1) + continue; + + next_trip = sensor.thresh.hotThrottlingThresholds[idx]; + break; + } + + if (!isnan(next_trip)) { + LOG(DEBUG) << "Sensor: " << sensor.t.name << " high trip:" + << next_trip << std::endl; + snprintf(file_name, sizeof(file_name), TRIP_FILE_FORMAT, + sensor.tzn); + writeToFile(std::string_view(file_name), std::to_string(next_trip)); + } + if (sensor.t.throttlingStatus != ThrottlingSeverity::NONE) { + curr_trip = sensor.thresh.hotThrottlingThresholds[ + (int)sensor.t.throttlingStatus - 1]; + if (!isnan(next_trip)) + hyst_temp = (next_trip - curr_trip) + DEFAULT_HYSTERESIS; + else + hyst_temp = DEFAULT_HYSTERESIS; + LOG(DEBUG) << "Sensor: " << sensor.t.name << " hysteresis:" + << hyst_temp << std::endl; + snprintf(file_name, sizeof(file_name), HYST_FILE_FORMAT, + sensor.tzn); + writeToFile(std::string_view(file_name), std::to_string(hyst_temp)); + } + + return; +} + +int ThermalCommon::get_cpu_usages(hidl_vec<CpuUsage> *list) { + int vals, cpu_num, online; + ssize_t read; + uint64_t user, nice, system, idle, active, total; + char *line = NULL; + size_t len = 0; + size_t cpu = 0; + char file_name[MAX_LENGTH]; + FILE *file; + FILE *cpu_file; + + file = fopen(CPU_USAGE_FILE, "r"); + if (file == NULL) { + LOG(ERROR) << "failed to open:" << CPU_USAGE_FILE << + " err:" << strerror(errno); + return -errno; + } + + while ((read = getline(&line, &len, file)) != -1) { + if (strnlen(line, read) < 4 || strncmp(line, "cpu", 3) != 0 || + !isdigit(line[3])) { + free(line); + line = NULL; + len = 0; + continue; + } + vals = sscanf(line, \ + "cpu%d %" SCNu64 " %" SCNu64 " %" SCNu64 " %" SCNu64, \ + &cpu_num, &user, &nice, &system, &idle); + + free(line); + line = NULL; + len = 0; + + if (vals != 5 || cpu == ncpus) { + if (vals != 5) { + LOG(ERROR) << + "failed to read CPU information from file: " + << strerror(errno); + } else { + LOG(ERROR) << + "/proc/stat file has incorrect format."; + } + fclose(file); + return errno ? -errno : -EIO; + } + + active = user + nice + system; + total = active + idle; + + // Read online CPU information. + snprintf(file_name, MAX_LENGTH, CPU_ONLINE_FILE_FORMAT, + cpu_num); + cpu_file = fopen(file_name, "r"); + online = 0; + if (cpu_file == NULL) { + LOG(ERROR) << "failed to open file:" << file_name << + " err: " << strerror(errno); + fclose(file); + return -errno; + } + if (1 != fscanf(cpu_file, "%d", &online)) { + LOG(ERROR) << "failed to read CPU online information" << strerror(errno); + fclose(file); + fclose(cpu_file); + return errno ? -errno : -EIO; + } + fclose(cpu_file); + + (*list)[cpu_num].name = std::string("CPU") + std::to_string(cpu_num); + (*list)[cpu_num].active = active; + (*list)[cpu_num].total = total; + (*list)[cpu_num].isOnline = online; + cpu++; + } + fclose(file); + if (cpu != ncpus) { + LOG(ERROR) <<"/proc/stat file has incorrect format."; + return -EIO; + } + return ncpus; +} + +} // namespace implementation +} // namespace V2_0 +} // namespace thermal +} // namespace hardware +} // namespace android diff --git a/thermalCommon.h b/thermalCommon.h new file mode 100644 index 0000000..b3c557c --- /dev/null +++ b/thermalCommon.h @@ -0,0 +1,83 @@ +/* + * 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. + */ + +#ifndef THERMAL_THERMAL_COMMON_H__ +#define THERMAL_THERMAL_COMMON_H__ + +#include "thermalData.h" + +namespace android { +namespace hardware { +namespace thermal { +namespace V2_0 { +namespace implementation { + +class ThermalCommon { + public: + ThermalCommon(); + ~ThermalCommon() = default; + + int readFromFile(std::string_view path, std::string *out); + int initThermalZones(std::vector<struct target_therm_cfg> cfg); + void initThreshold(struct therm_sensor sens); + int initCdev(); + + int read_cdev_state(struct therm_cdev *cdev); + int read_temperature(struct therm_sensor *sensor); + int estimateSeverity(struct therm_sensor *sensor); + int get_cpu_usages(hidl_vec<CpuUsage> *list); + + std::vector<struct therm_sensor> fetch_sensor_list() + { + return sens; + }; + std::vector<struct therm_cdev> fetch_cdev_list() + { + return cdev; + }; + + private: + int ncpus; + std::vector<struct target_therm_cfg> cfg; + std::vector<struct therm_sensor> sens; + std::vector<struct therm_cdev> cdev; + + int initializeCpuSensor(struct target_therm_cfg cpu_cfg); + int initialize_sensor(struct target_therm_cfg cfg, + int sens_idx); +}; + +} // namespace implementation +} // namespace V2_0 +} // namespace thermal +} // namespace hardware +} // namespace android + +#endif // THERMAL_THERMAL_COMMON_H__ diff --git a/thermalConfig.cpp b/thermalConfig.cpp new file mode 100644 index 0000000..7525022 --- /dev/null +++ b/thermalConfig.cpp @@ -0,0 +1,345 @@ +/* + * 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. + */ + +#include <unordered_map> +#include <android-base/logging.h> +#include <android/hardware/thermal/2.0/IThermal.h> + +#include "thermalData.h" +#include "thermalConfig.h" + +namespace android { +namespace hardware { +namespace thermal { +namespace V2_0 { +namespace implementation { + constexpr std::string_view socIDPath("/sys/devices/soc0/soc_id"); + + std::vector<std::string> cpu_sensors_lito = + { + "cpu-0-0-usr", + "cpu-0-1-usr", + "cpu-0-2-usr", + "cpu-0-3-usr", + "cpu-0-4-usr", + "cpu-0-5-usr", + "cpu-1-0-usr", + "cpu-1-2-usr", + }; + + std::vector<struct target_therm_cfg> sensor_cfg_lito = + { + { + TemperatureType::CPU, + cpu_sensors_lito, + "", + 95000, + 115000, + 95000, + true, + }, + { + TemperatureType::GPU, + { "gpuss-0-usr" }, + "GPU", + 95000, + 115000, + 95000, + true, + }, + { + TemperatureType::SKIN, + { "xo-therm-usr" }, + "skin", + 40000, + 45000, + 40000, + true, + }, + { + TemperatureType::BCL_CURRENT, + { "pm7250b-ibat-lvl0" }, + "ibat", + 4500, + 5000, + 4500, + true, + }, + { + TemperatureType::BCL_VOLTAGE, + { "pm7250b-vbat-lvl0" }, + "vbat", + 3200, + 3000, + 3200, + false, + }, + { + TemperatureType::BCL_PERCENTAGE, + { "soc" }, + "soc", + 10, + 2, + 10, + false, + }, + }; + + std::vector<std::string> cpu_sensors_kona = + { + "cpu-0-0-usr", + "cpu-0-1-usr", + "cpu-0-2-usr", + "cpu-0-3-usr", + "cpu-1-0-usr", + "cpu-1-1-usr", + "cpu-1-2-usr", + "cpu-1-3-usr", + }; + + std::vector<struct target_therm_cfg> kona_common = { + { + TemperatureType::CPU, + cpu_sensors_kona, + "", + 95000, + 115000, + 95000, + true, + }, + { + TemperatureType::GPU, + { "gpuss-0-usr" }, + "GPU0", + 95000, + 115000, + 95000, + true, + }, + { + TemperatureType::GPU, + { "gpuss-1-usr" }, + "GPU1", + 95000, + 115000, + 95000, + true, + }, + { + TemperatureType::SKIN, + { "skin-msm-therm-usr" }, + "skin", + 40000, + 95000, + 40000, + true, + } + }; + + std::vector<struct target_therm_cfg> kona_specific = { + { + TemperatureType::BCL_CURRENT, + { "pm8150b-ibat-lvl0" }, + "ibat", + 4500, + 5000, + 4500, + true, + }, + { + TemperatureType::BCL_VOLTAGE, + { "pm8150b-vbat-lvl0" }, + "vbat", + 3200, + 3000, + 3200, + false, + }, + { + TemperatureType::BCL_PERCENTAGE, + { "soc" }, + "soc", + 10, + 2, + 10, + false, + }, + { + TemperatureType::NPU, + { "npu-usr" }, + "npu", + 95000, + 105000, + 95000, + true, + }, + }; + + std::vector<struct target_therm_cfg> lahaina_specific = { + { + TemperatureType::BCL_CURRENT, + { "pm8350b-ibat-lvl0" }, + "ibat", + 4500, + 5000, + 4500, + true, + }, + { + TemperatureType::NPU, + { "nspss-0-usr" }, + "nsp0", + 95000, + 105000, + 95000, + true, + }, + { + TemperatureType::NPU, + { "nspss-1-usr" }, + "nsp1", + 95000, + 105000, + 95000, + true, + }, + { + TemperatureType::NPU, + { "nspss-2-usr" }, + "nsp2", + 95000, + 105000, + 95000, + true, + }, + }; + + struct target_therm_cfg bat_conf = { + TemperatureType::BATTERY, + { "battery" }, + "battery", + 80000, + 90000, + 80000, + true, + }; + + std::vector<struct target_therm_cfg> bcl_conf = { + { + TemperatureType::BCL_VOLTAGE, + { "vbat" }, + "vbat", + 3200, + 3000, + 3200, + false, + }, + { + TemperatureType::BCL_PERCENTAGE, + { "socd" }, + "socd", + 90, + 99, + 90, + true, + }, + }; + + const std::unordered_map<int, std::vector<struct target_therm_cfg>> + msm_soc_map = { + {400, sensor_cfg_lito}, // lito + {440, sensor_cfg_lito}, + {407, sensor_cfg_lito}, // atoll + {434, sensor_cfg_lito}, // lagoon + {356, kona_common}, // kona + {415, kona_common}, // lahaina + }; + + const std::unordered_map<int, std::vector<struct target_therm_cfg>> + msm_soc_specific = { + {356, kona_specific}, // kona + {415, lahaina_specific}, // lahaina + }; + + std::vector<struct target_therm_cfg> add_target_config( + int socID, + std::vector<struct target_therm_cfg> conf) + { + std::vector<struct target_therm_cfg> targetConf; + + if (msm_soc_specific.find(socID) == msm_soc_specific.end()) + return conf; + targetConf = (msm_soc_specific.find(socID))->second; + + conf.insert(conf.end(), targetConf.begin(), + targetConf.end()); + return conf; + } + + ThermalConfig::ThermalConfig():cmnInst() + { + std::unordered_map<int, std::vector<struct target_therm_cfg>>::const_iterator it; + std::vector<struct target_therm_cfg>::iterator it_vec; + bool bcl_defined = false; + std::string soc_val; + + if (cmnInst.readFromFile(socIDPath, &soc_val) <= 0) { + LOG(ERROR) <<"soc ID fetch error"; + return; + } + soc_id = std::stoi(soc_val, nullptr, 0); + if (soc_id <= 0) { + LOG(ERROR) << "Invalid soc ID: " << soc_id; + return; + } + it = msm_soc_map.find(soc_id); + if (it == msm_soc_map.end()) { + LOG(ERROR) << "No config for soc ID: " << soc_id; + return; + } + thermalConfig = add_target_config(soc_id, it->second); + for (it_vec = thermalConfig.begin(); + it_vec != thermalConfig.end(); it_vec++) { + if (it_vec->type == TemperatureType::BCL_PERCENTAGE) + bcl_defined = true; + } + + thermalConfig.push_back(bat_conf); + if (!bcl_defined) + thermalConfig.insert(thermalConfig.end(), + bcl_conf.begin(), bcl_conf.end()); + LOG(DEBUG) << "Total sensors:" << thermalConfig.size(); + } +} // namespace implementation +} // namespace V2_0 +} // namespace thermal +} // namespace hardware +} // namespace android + diff --git a/thermalConfig.h b/thermalConfig.h new file mode 100644 index 0000000..07f3375 --- /dev/null +++ b/thermalConfig.h @@ -0,0 +1,67 @@ +/* + * 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. + */ + +#ifndef THERMAL_THERMAL_CONFIG_H__ +#define THERMAL_THERMAL_CONFIG_H__ + +#include <android/hardware/thermal/2.0/IThermal.h> + +#include "thermalData.h" +#include "thermalCommon.h" + +namespace android { +namespace hardware { +namespace thermal { +namespace V2_0 { +namespace implementation { + +class ThermalConfig { + public: + ThermalConfig(); + ~ThermalConfig() = default; + + std::vector<struct target_therm_cfg> fetchConfig(void) + { + return thermalConfig; + } + + private: + std::vector<struct target_therm_cfg> thermalConfig; + int soc_id; + ThermalCommon cmnInst; +}; + +} // namespace implementation +} // namespace V2_0 +} // namespace thermal +} // namespace hardware +} // namespace android + +#endif // THERMAL_THERMAL_CONFIG_H__ diff --git a/thermalData.h b/thermalData.h new file mode 100644 index 0000000..93eb5cc --- /dev/null +++ b/thermalData.h @@ -0,0 +1,96 @@ +/* + * 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. + */ + +#ifndef THERMAL_THERMAL_DATA_H__ +#define THERMAL_THERMAL_DATA_H__ + +#include <vector> +#include <string> +#include <mutex> +#include <cmath> + +#include <android/hardware/thermal/2.0/IThermal.h> + +#define UNKNOWN_TEMPERATURE (NAN) + +namespace android { +namespace hardware { +namespace thermal { +namespace V2_0 { +namespace implementation { + +using ::android::hardware::hidl_vec; +using ::android::hardware::thermal::V1_0::CpuUsage; +using CoolingDevice_1_0 = ::android::hardware::thermal::V1_0::CoolingDevice; +using Temperature_1_0 = ::android::hardware::thermal::V1_0::Temperature; +using TemperatureType_1_0 = ::android::hardware::thermal::V1_0::TemperatureType; +using ::android::hardware::thermal::V1_0::ThermalStatus; +using ::android::hardware::thermal::V1_0::ThermalStatusCode; + +using cdevType = ::android::hardware::thermal::V2_0::CoolingType; +using CoolingDevice = ::android::hardware::thermal::V2_0::CoolingDevice; +using Temperature = ::android::hardware::thermal::V2_0::Temperature; +using TemperatureType = ::android::hardware::thermal::V2_0::TemperatureType; +using TemperatureThreshold = + ::android::hardware::thermal::V2_0::TemperatureThreshold; +using ::android::hardware::thermal::V2_0::ThrottlingSeverity; + + struct target_therm_cfg { + TemperatureType type; + std::vector<std::string> sensor_list; + std::string label; + int throt_thresh; + int shutdwn_thresh; + int vr_thresh; + bool positive_thresh_ramp; + }; + + struct therm_sensor { + int tzn; + int mulFactor; + bool positiveThresh; + std::string sensor_name; + ThrottlingSeverity lastThrottleStatus; + Temperature t; + TemperatureThreshold thresh; + }; + + struct therm_cdev { + int cdevn; + CoolingDevice c; + }; + +} // namespace implementation +} // namespace V2_0 +} // namespace thermal +} // namespace hardware +} // namespace android + +#endif // THERMAL_THERMAL_DATA_H__ diff --git a/thermalMonitor.cpp b/thermalMonitor.cpp new file mode 100644 index 0000000..176d121 --- /dev/null +++ b/thermalMonitor.cpp @@ -0,0 +1,192 @@ +/* + * 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. + */ + +#include <unistd.h> +#include <poll.h> +#include <sys/socket.h> +#include <linux/types.h> +#include <linux/netlink.h> +#include <android-base/logging.h> +#include <android-base/properties.h> +#include <android-base/stringprintf.h> + +#include "thermalMonitor.h" + +#define UEVENT_BUF 1024 + +#define HYST_FMT "change@/devices/virtual/thermal/thermal_zone%d\n\ + ACTION=change\n\ + DEVPATH=/devices/virtual/thermal/thermal_zone%d\n\ + SUBSYSTEM=thermal\n\ + NAME=%s\n\ + TEMP=%d\n\ + HYST=%d\n\ + EVENT=%d\n"\ + +#define TRIP_FMT "change@/devices/virtual/thermal/thermal_zone%d\n\ + ACTION=change\n\ + DEVPATH=/devices/virtual/thermal/thermal_zone%d\n\ + SUBSYSTEM=thermal\n\ + NAME=%s\n\ + TEMP=%d\n\ + TRIP=%d\n\ + EVENT=%d\n"\ + +namespace android { +namespace hardware { +namespace thermal { +namespace V2_0 { +namespace implementation { + +using parseCB = std::function<void(char *inp_buf, ssize_t len)>; +using pollCB = std::function<bool()>; + +void thermal_monitor_uevent(const parseCB &parse_cb, const pollCB &stopPollCB) +{ + struct pollfd pfd; + char buf[UEVENT_BUF] = {0}; + int sz = 64*1024; + struct sockaddr_nl nls; + + memset(&nls, 0, sizeof(nls)); + nls.nl_family = AF_NETLINK; + nls.nl_pid = getpid(); + nls.nl_groups = 0xffffffff; + + pfd.events = POLLIN; + pfd.fd = socket(PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, + NETLINK_KOBJECT_UEVENT); + if (pfd.fd < 0) { + LOG(ERROR) << "socket creation error:" << errno << std::endl; + return; + } + LOG(DEBUG) << "socket creation success" << std::endl; + + setsockopt(pfd.fd, SOL_SOCKET, SO_RCVBUF, &sz, sizeof(sz)); + if (bind(pfd.fd, (struct sockaddr *)&nls, sizeof(nls)) < 0) { + close(pfd.fd); + LOG(ERROR) << "socket bind failed:" << errno << std::endl; + return; + } + LOG(DEBUG) << "Listening for uevent" << std::endl; + + while (!stopPollCB()) { + ssize_t len; + int err; + + err = poll(&pfd, 1, -1); + if (err == -1) { + LOG(ERROR) << "Error in uevent poll."; + break; + } + if (stopPollCB()) { + LOG(INFO) << "Exiting uevent monitor" << std::endl; + return; + } + len = recv(pfd.fd, buf, sizeof(buf) - 1, MSG_DONTWAIT); + if (len == -1) { + LOG(ERROR) << "uevent read failed:" << errno << std::endl; + continue; + } + buf[len] = '\0'; + + parse_cb(buf, len); + } + + return; +} + +ThermalMonitor::ThermalMonitor(const ueventMonitorCB &inp_cb): + cb(inp_cb) +{ + monitor_shutdown = false; +} + +ThermalMonitor::~ThermalMonitor() +{ + monitor_shutdown = true; + th.join(); +} + +void ThermalMonitor::start() +{ + th = std::thread(thermal_monitor_uevent, + std::bind(&ThermalMonitor::parse_and_notify, this, + std::placeholders::_1, std::placeholders::_2), + std::bind(&ThermalMonitor::stopPolling, this)); +} + +void ThermalMonitor::parse_and_notify(char *inp_buf, ssize_t len) +{ + int zone_num, temp, trip, ret = 0, event; + ssize_t i = 0; + char sensor_name[30] = "", buf[UEVENT_BUF] = {0}; + + LOG(DEBUG) << "monitor received thermal uevent: " << inp_buf + << std::endl; + + while (i < len) { + if (i >= UEVENT_BUF) + return; + ret = snprintf(buf + i, UEVENT_BUF - i, "%s ", inp_buf + i); + if (ret == (strlen(inp_buf + i) + 1)) + i += ret; + else + return; + } + + if (!strstr(buf, "SUBSYSTEM=thermal")) + return; + + if (strstr(buf, "TRIP=")) { + ret = sscanf(buf, TRIP_FMT, &zone_num, &zone_num, sensor_name, + &temp, &trip, &event); + LOG(DEBUG) << "zone:" << zone_num << " sensor:" << sensor_name + <<" temp:" << temp << " trip:" << trip << " event:" << + event << std::endl; + } else { + ret = sscanf(buf, HYST_FMT, &zone_num, &zone_num, sensor_name, + &temp, &trip, &event); + LOG(DEBUG) << "zone:" << zone_num << " sensor:" << sensor_name + <<" temp:" << temp << " trip:" << trip << " event:" << + event << std::endl; + } + if (ret <= 0 || ret == EOF) { + LOG(ERROR) << "read error:" << ret <<". buf:" << buf << std::endl; + return; + } + cb(sensor_name, temp); +} + +} // namespace implementation +} // namespace V2_0 +} // namespace thermal +} // namespace hardware +} // namespace android diff --git a/thermalMonitor.h b/thermalMonitor.h new file mode 100644 index 0000000..3b6962f --- /dev/null +++ b/thermalMonitor.h @@ -0,0 +1,69 @@ +/* + * 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. + */ + + +#ifndef THERMAL_THERMAL_MONITOR_H__ +#define THERMAL_THERMAL_MONITOR_H__ + +#include <thread> +#include <android/hardware/thermal/2.0/IThermal.h> + +namespace android { +namespace hardware { +namespace thermal { +namespace V2_0 { +namespace implementation { + +using ueventMonitorCB = std::function<void(std::string sensor_name, int temp)>; + +class ThermalMonitor { + public: + ThermalMonitor(const ueventMonitorCB &inp_cb); + ~ThermalMonitor(); + + void parse_and_notify(char *inp_buf, ssize_t len); + bool stopPolling() + { + return monitor_shutdown; + } + void start(); + private: + std::thread th; + bool monitor_shutdown; + ueventMonitorCB cb; +}; + +} // namespace implementation +} // namespace V2_0 +} // namespace thermal +} // namespace hardware +} // namespace android + +#endif // THERMAL_THERMAL_MONITOR_H__ diff --git a/thermalUtils.cpp b/thermalUtils.cpp new file mode 100644 index 0000000..517b979 --- /dev/null +++ b/thermalUtils.cpp @@ -0,0 +1,224 @@ +/* + * 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. + */ + +#include <android-base/file.h> +#include <android-base/logging.h> +#include <android-base/properties.h> +#include <android-base/stringprintf.h> +#include <android-base/strings.h> +#include <hidl/HidlTransportSupport.h> + +#include "thermalConfig.h" +#include "thermalUtils.h" + +namespace android { +namespace hardware { +namespace thermal { +namespace V2_0 { +namespace implementation { + +ThermalUtils::ThermalUtils(const ueventCB &inp_cb): + cfg(), + cmnInst(), + monitor(std::bind(&ThermalUtils::ueventParse, this, + std::placeholders::_1, + std::placeholders::_2)), + cb(inp_cb) +{ + int ret = 0; + std::vector<struct therm_sensor> sensorList; + std::vector<struct therm_sensor>::iterator it; + + is_sensor_init = false; + is_cdev_init = false; + ret = cmnInst.initThermalZones(cfg.fetchConfig()); + if (ret > 0) { + is_sensor_init = true; + sensorList = cmnInst.fetch_sensor_list(); + std::lock_guard<std::mutex> _lock(sens_cb_mutex); + for (it = sensorList.begin(); it != sensorList.end(); it++) { + thermalConfig[it->sensor_name] = *it; + cmnInst.read_temperature(&(*it)); + cmnInst.initThreshold(*it); + } + monitor.start(); + } + ret = cmnInst.initCdev(); + if (ret > 0) { + is_cdev_init = true; + cdevList = cmnInst.fetch_cdev_list(); + } +} + +void ThermalUtils::ueventParse(std::string sensor_name, int temp) +{ + std::unordered_map<std::string, struct therm_sensor>::iterator it; + struct therm_sensor sens; + + LOG(INFO) << "uevent triggered for sensor: " << sensor_name + << std::endl; + it = thermalConfig.find(sensor_name); + if (it == thermalConfig.end()) { + LOG(DEBUG) << "sensor is not monitored:" << sensor_name + << std::endl; + return; + } + sens = it->second; + std::lock_guard<std::mutex> _lock(sens_cb_mutex); + sens.t.value = (float)temp / (float)sens.mulFactor; + cmnInst.estimateSeverity(&sens); + if (sens.lastThrottleStatus != sens.t.throttlingStatus) { + LOG(INFO) << "sensor: " << sensor_name <<" old: " << + (int)sens.lastThrottleStatus << " new: " << + (int)sens.t.throttlingStatus << std::endl; + cb(sens.t); + cmnInst.initThreshold(sens); + } +} + +int ThermalUtils::readTemperatures(hidl_vec<Temperature_1_0> *temp) +{ + std::unordered_map<std::string, struct therm_sensor>::iterator it; + int ret = 0, idx = 0; + + if (!is_sensor_init) + return 0; + temp->resize(thermalConfig.size()); + for (it = thermalConfig.begin(); it != thermalConfig.end(); + it++, idx++) { + struct therm_sensor sens = it->second; + ret = cmnInst.read_temperature(&sens); + if (ret < 0) + return ret; + (*temp)[idx].currentValue = sens.t.value; + (*temp)[idx].name = sens.t.name; + (*temp)[idx].type = (TemperatureType_1_0)sens.t.type; + } + + return temp->size(); +} + +int ThermalUtils::readTemperatures(bool filterType, TemperatureType type, + hidl_vec<Temperature> *temperatures) +{ + std::vector<Temperature> local_temp; + std::unordered_map<std::string, struct therm_sensor>::iterator it; + int ret = 0; + Temperature nantemp; + + for (it = thermalConfig.begin(); it != thermalConfig.end(); it++) { + struct therm_sensor sens = it->second; + + if (filterType && sens.t.type != type) + continue; + ret = cmnInst.read_temperature(&sens); + if (ret < 0) + return ret; + local_temp.push_back(sens.t); + } + if (local_temp.empty()) { + nantemp.type = type; + nantemp.value = UNKNOWN_TEMPERATURE; + local_temp.push_back(nantemp); + } + *temperatures = local_temp; + + return temperatures->size(); +} + +int ThermalUtils::readTemperatureThreshold(bool filterType, TemperatureType type, + hidl_vec<TemperatureThreshold> *thresh) +{ + std::vector<TemperatureThreshold> local_thresh; + std::unordered_map<std::string, struct therm_sensor>::iterator it; + int idx = 0; + TemperatureThreshold nanthresh; + + for (it = thermalConfig.begin(); it != thermalConfig.end(); it++) { + struct therm_sensor sens = it->second; + + if (filterType && sens.t.type != type) + continue; + local_thresh.push_back(sens.thresh); + } + if (local_thresh.empty()) { + nanthresh.type = type; + nanthresh.vrThrottlingThreshold = UNKNOWN_TEMPERATURE; + for (idx = 0; idx < (size_t)ThrottlingSeverity::SHUTDOWN; + idx++) { + nanthresh.hotThrottlingThresholds[idx] = + nanthresh.coldThrottlingThresholds[idx] = + UNKNOWN_TEMPERATURE; + } + local_thresh.push_back(nanthresh); + } + *thresh = local_thresh; + + return thresh->size(); +} + +int ThermalUtils::readCdevStates(bool filterType, cdevType type, + hidl_vec<CoolingDevice> *cdev_out) +{ + std::vector<CoolingDevice> local_cdev; + std::vector<struct therm_cdev>::iterator it; + int ret = 0; + CoolingDevice nanCdev; + + for (it = cdevList.begin(); it != cdevList.end(); it++) { + struct therm_cdev cdev = *it; + + if (filterType && cdev.c.type != type) + continue; + ret = cmnInst.read_cdev_state(&cdev); + if (ret < 0) + return ret; + local_cdev.push_back(cdev.c); + } + if (local_cdev.empty()) { + nanCdev.type = type; + nanCdev.value = UNKNOWN_TEMPERATURE; + local_cdev.push_back(nanCdev); + } + *cdev_out = local_cdev; + + return cdev_out->size(); +} + +int ThermalUtils::fetchCpuUsages(hidl_vec<CpuUsage> *cpu_usages) +{ + return cmnInst.get_cpu_usages(cpu_usages); +} + +} // namespace implementation +} // namespace V2_0 +} // namespace thermal +} // namespace hardware +} // namespace android diff --git a/thermalUtils.h b/thermalUtils.h new file mode 100644 index 0000000..8cf4a41 --- /dev/null +++ b/thermalUtils.h @@ -0,0 +1,91 @@ +/* + * 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. + */ + +#ifndef THERMAL_THERMAL_UTILS_H__ +#define THERMAL_THERMAL_UTILS_H__ + +#include <unordered_map> +#include <mutex> +#include <android/hardware/thermal/2.0/IThermal.h> +#include "thermalConfig.h" +#include "thermalMonitor.h" +#include "thermalCommon.h" +#include "thermalData.h" + +namespace android { +namespace hardware { +namespace thermal { +namespace V2_0 { +namespace implementation { + +using ueventCB = std::function<void(Temperature &t)>; + +class ThermalUtils { + public: + ThermalUtils(const ueventCB &inp_cb); + ~ThermalUtils() = default; + bool isSensorInitialized() + { + return is_sensor_init; + }; + bool isCdevInitialized() + { + return is_cdev_init; + }; + int readTemperatures(hidl_vec<Temperature_1_0> *temp); + int readTemperatures(bool filterType, TemperatureType type, + hidl_vec<Temperature> *temperatures); + int readTemperatureThreshold(bool filterType, TemperatureType type, + hidl_vec<TemperatureThreshold> *thresh); + int readCdevStates(bool filterType, cdevType type, + hidl_vec<CoolingDevice> *cdev); + int fetchCpuUsages(hidl_vec<CpuUsage> *cpu_usages); + private: + bool is_sensor_init; + bool is_cdev_init; + ThermalConfig cfg; + ThermalCommon cmnInst; + ThermalMonitor monitor; + std::unordered_map<std::string, struct therm_sensor> + thermalConfig; + std::vector<struct therm_cdev> cdevList; + std::mutex sens_cb_mutex; + ueventCB cb; + + void ueventParse(std::string sensor_name, int temp); +}; + +} // namespace implementation +} // namespace V2_0 +} // namespace thermal +} // namespace hardware +} // namespace android + +#endif // THERMAL_THERMAL_UTILS_H__ diff --git a/thermal_common.c b/thermal_common.c deleted file mode 100644 index 9374929..0000000 --- a/thermal_common.c +++ /dev/null @@ -1,385 +0,0 @@ -/* - * Copyright (c) 2018, The Linux Foundation. All rights reserved. - * Not a contribution - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <errno.h> -#include <stdlib.h> -#include <unistd.h> -#include <string.h> -#include <dirent.h> - -#define LOG_TAG "ThermalHAL-UTIL" -#include <utils/Log.h> - -#include <hardware/hardware.h> -#include <hardware/thermal.h> -#include "thermal_common.h" - -#define MAX_LENGTH 50 -#define MAX_PATH (256) -#define CPU_LABEL "CPU%d" -#define THERMAL_SYSFS "/sys/devices/virtual/thermal" -#define TZ_DIR_NAME "thermal_zone" -#define TZ_DIR_FMT "thermal_zone%d" -#define THERMAL_TYPE "/sys/devices/virtual/thermal/%s/type" -#define TEMPERATURE_FILE_FORMAT "/sys/class/thermal/thermal_zone%d/temp" - -static char **cpu_label; -static struct vendor_temperature *sensors; -static unsigned int sensor_cnt; - -/** - * Get number of cpus of target. - * - * @return number of cpus on success or 0 on error. - */ -size_t get_num_cpus() { - ALOGD("Entering %s",__func__); - static int ncpus; - - if (!ncpus) { - ncpus = (int)sysconf(_SC_NPROCESSORS_CONF); - if (ncpus < 1) - ALOGE("%s: Error retrieving number of cores", __func__); - } - return ncpus; -} - -/** - * Get cpu label for a given cpu. - * - * @param cpu_num: cpu number. - * - * @return cpu label string on success or NULL on error. - */ -const char *get_cpu_label(unsigned int cpu_num) { - ALOGD("Entering %s",__func__); - unsigned int cpu = 0; - - if (cpu_label == NULL) { - cpu_label= (char**)calloc(get_num_cpus(), sizeof(char *)); - if (!cpu_label) - return NULL; - for(cpu = 0; cpu < get_num_cpus(); cpu++) { - cpu_label[cpu] = (char *)calloc(sizeof("CPUN"), sizeof(char)); - if(!cpu_label[cpu]) - return NULL; - snprintf(cpu_label[cpu], sizeof("CPUN"), CPU_LABEL, cpu); - } - } - if(cpu_num >= get_num_cpus()) - return NULL; - - return cpu_label[cpu_num]; -} - -/** - * Read data from a target sysfs file. - * - * @param path: Absolute path for a file to be read. - * @param buf: Char buffer to store data from file. - * @param count: Size of data buffer. - * - * @return number of bytes read on success or negative value on error. - */ -int read_line_from_file(const char *path, char *buf, size_t count) -{ - char * fgets_ret; - FILE * fd; - int rv; - - fd = fopen(path, "r"); - if (fd == NULL) - return -1; - - fgets_ret = fgets(buf, (int)count, fd); - if (NULL != fgets_ret) { - rv = (int)strlen(buf); - } else { - rv = ferror(fd); - } - - fclose(fd); - - return rv; -} - -/** - * Function to get thermal zone id from sensor name. - * - * @param sensor_name: Name of sensor. - * - * @return positive integer on success or negative value on error. - */ -static int get_tzn(const char *sensor_name) -{ - DIR *tdir = NULL; - struct dirent *tdirent = NULL; - int found = -1; - int tzn = 0; - char name[MAX_PATH] = {0}; - char cwd[MAX_PATH] = {0}; - int ret = 0; - - if (!getcwd(cwd, sizeof(cwd))) - return found; - - /* Change dir to read the entries. Doesnt work otherwise */ - ret = chdir(THERMAL_SYSFS); - if (ret) { - ALOGE("Unable to change to %s\n", THERMAL_SYSFS); - return found; - } - tdir = opendir(THERMAL_SYSFS); - if (!tdir) { - ALOGE("Unable to open %s\n", THERMAL_SYSFS); - return found; - } - - while ((tdirent = readdir(tdir))) { - char buf[50]; - struct dirent *tzdirent; - DIR *tzdir = NULL; - - if (strncmp(tdirent->d_name, TZ_DIR_NAME, - strlen(TZ_DIR_NAME)) != 0) - continue; - - tzdir = opendir(tdirent->d_name); - if (!tzdir) - continue; - while ((tzdirent = readdir(tzdir))) { - if (strcmp(tzdirent->d_name, "type")) - continue; - snprintf(name, MAX_PATH, THERMAL_TYPE, - tdirent->d_name); - ret = read_line_from_file(name, buf, sizeof(buf)); - if (ret <= 0) { - ALOGE("%s: sensor name read error for tz:%s\n", - __func__, tdirent->d_name); - break; - } - if (buf[ret - 1] == '\n') - buf[ret - 1] = '\0'; - else - buf[ret] = '\0'; - - if (!strcmp(buf, sensor_name)) { - found = 1; - break; - } - } - closedir(tzdir); - if (found == 1) - break; - } - - if (found == 1) { - sscanf(tdirent->d_name, TZ_DIR_FMT, &tzn); - ALOGD("Sensor %s found at tz: %d\n", - sensor_name, tzn); - found = tzn; - } - - closedir(tdir); - /* Restore current working dir */ - ret = chdir(cwd); - - return found; -} - -/** - * Helper function for sensor intialization. - * - * @param v_sen_t: pointer to a sensor static config. - * @param sensor: pointer to a sensor vendor_temperature structure. - * @param type: Type of sensor ie cpu, battery, gpu, skin etc. - * @param sens_idx: Index for sensor of same type. - * - * @return 0 on success or negative value -errno on error. - */ -static int initialize_sensor(struct target_therm_cfg *v_sen_t, - struct vendor_temperature *sensor, - enum temperature_type type, - int sens_idx) -{ - if (v_sen_t == NULL || sensor == NULL || - sens_idx < 0) { - ALOGE("%s:Invalid input, sens_idx%d\n", __func__, sens_idx); - return -1; - } - - sensor->tzn = get_tzn(v_sen_t->sensor_list[sens_idx]); - if (sensor->tzn < 0) { - ALOGE("No thermal zone for sensor: %s, ret:%d\n", - v_sen_t->sensor_list[sens_idx], sensor->tzn); - return -1; - } - if (type == DEVICE_TEMPERATURE_CPU) - sensor->t.name = get_cpu_label(sens_idx); - else - sensor->t.name = v_sen_t->label; - - sensor->t.type = v_sen_t->type; - sensor->mult = v_sen_t->mult; - - if (v_sen_t->throt_thresh != 0) - sensor->t.throttling_threshold = v_sen_t->throt_thresh; - else - sensor->t.throttling_threshold = UNKNOWN_TEMPERATURE; - - if (v_sen_t->shutdwn_thresh != 0) - sensor->t.shutdown_threshold = v_sen_t->shutdwn_thresh; - else - sensor->t.shutdown_threshold = UNKNOWN_TEMPERATURE; - - if (v_sen_t->vr_thresh != 0) - sensor->t.vr_throttling_threshold = v_sen_t->vr_thresh; - else - sensor->t.vr_throttling_threshold = UNKNOWN_TEMPERATURE; - - return 0; -} - -/** - * Initialize all sensors. - * - * @param v_sen_t: Base pointer to array of target specific sensor configs. - * @param cfg_cnt: Number of set of config for a given target. - * - * @return number of sensor on success or negative value or zero on error. - */ -int thermal_zone_init(struct target_therm_cfg *v_sen_t, int cfg_cnt) -{ - unsigned int idx = 0, cpu = 0; - int j = 0; - - if (sensors != NULL && sensor_cnt != 0) - return sensor_cnt; - - if (v_sen_t == NULL || cfg_cnt == 0) { - ALOGE("%s:Invalid input\n", __func__); - return -1; - } - sensors = calloc(get_num_cpus() + cfg_cnt - 1, - sizeof(struct vendor_temperature)); - - for (j = 0, idx = 0; j < cfg_cnt && - idx < (get_num_cpus() + cfg_cnt - 1); j++) { - if (v_sen_t[j].type == DEVICE_TEMPERATURE_CPU) { - /* Initialize cpu thermal zone id */ - for (cpu = 0; cpu < get_num_cpus() && - idx < (get_num_cpus() + cfg_cnt - 1); cpu++, idx++) { - if (initialize_sensor(&v_sen_t[j], &sensors[idx], - v_sen_t[j].type, cpu)) { - free(sensors); - return -1; - } - } - } else { - /* Initialize misc thermal zone id */ - if (initialize_sensor(&v_sen_t[j], &sensors[idx], - v_sen_t[j].type, 0)) { - free(sensors); - return -1; - } - idx++; - } - } - sensor_cnt = idx; - - return sensor_cnt; -} - -/** - * Reads sensor temperature. - * - * @param sensor_num: thermal zone id for the sensor to be read - * @param type: Device temperature type. - * @param name: Device temperature name. - * @param mult: Multiplier used to translate temperature to Celsius. - * @param throttling_threshold: Throttling threshold for the sensor. - * @param shutdown_threshold: Shutdown threshold for the sensor. - * @param out: Pointer to temperature_t structure that will be filled with - * temperature values. - * - * @return 0 on success or negative value -errno on error. - */ -static ssize_t read_temperature(int sensor_num, int type, const char *name, - float mult, float throttling_threshold, float shutdown_threshold, - float vr_throttling_threshold, - temperature_t *out) { - ALOGD("Entering %s",__func__); - char file_name[MAX_LENGTH]; - float temp; - char buf[16] = {0}; - int ret = 0; - - snprintf(file_name, sizeof(file_name), TEMPERATURE_FILE_FORMAT, sensor_num); - ret = read_line_from_file(file_name, buf, sizeof(buf)); - if (ret <= 0) { - ALOGE("Temperature read error: %d for sensor[%d]:%s\n", - ret, sensor_num, name); - return -1; - } - temp = atof(buf); - - (*out) = (temperature_t) { - .type = type, - .name = name, - .current_value = temp * mult, - .throttling_threshold = throttling_threshold, - .shutdown_threshold = shutdown_threshold, - .vr_throttling_threshold = vr_throttling_threshold - }; - - return 0; -} - -/** - * Reads all sensor temperature. - * - * @param list: Base pointer to array of temperature_t structure that will be - * filled with temperature values. - * @param size: Number of sensor temperature needs to be filled in list. - * - * @return number of sensor data filled on success or 0 or negative value - * -errno on error. - */ -ssize_t get_temperature_for_all(temperature_t *list, size_t size) -{ - ALOGD("Entering %s",__func__); - size_t idx; - - if (sensors == NULL) { - ALOGE("No sensor configured\n"); - return 0; - } - - for (idx = 0; idx < sensor_cnt && idx < size; idx++) { - ssize_t result = read_temperature(sensors[idx].tzn, sensors[idx].t.type, - sensors[idx].t.name, sensors[idx].mult, - sensors[idx].t.throttling_threshold, - sensors[idx].t.shutdown_threshold, - sensors[idx].t.vr_throttling_threshold, - &list[idx]); - if (result != 0) - return result; - } - return idx; -} - diff --git a/thermal_common.h b/thermal_common.h deleted file mode 100644 index b6a96fa..0000000 --- a/thermal_common.h +++ /dev/null @@ -1,76 +0,0 @@ -/* Copyright (c) 2018-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. - */ - -#include <hardware/thermal.h> -#define ARRAY_SIZE(x) (int)(sizeof(x)/sizeof(x[0])) - -enum therm_msm_id { - THERM_MSM_UNKNOWN = 0, - THERM_MSM_8953, - THERM_SDM_660, - THERM_SDM_630, - THERM_SDM_710, - THERM_QCS_605, - THERM_SDM_632, - THERM_SDM_439, - THERM_MSMNILE, - THERM_TALOS, - THERM_SDMMAGPIE, - THERM_MSM_8917, - THERM_TRINKET, - THERM_KONA, - THERM_LITO, - THERM_ATOLL, - THERM_BENGAL, - THERM_LAGOON, - THERM_LAHAINA, -}; - -struct target_therm_cfg { - enum temperature_type type; - char **sensor_list; - uint8_t sens_cnt; - char *label; - float mult; - int throt_thresh; - int shutdwn_thresh; - int vr_thresh; -}; - -struct vendor_temperature { - int tzn; - float mult; - temperature_t t; -}; - - -int read_line_from_file(const char *path, char *buf, size_t count); -size_t get_num_cpus(); -const char *get_cpu_label(unsigned int cpu_num); -int thermal_zone_init(struct target_therm_cfg *v_sen_t, int cfg_cnt); -ssize_t get_temperature_for_all(temperature_t *list, size_t size); diff --git a/thermal_target.c b/thermal_target.c deleted file mode 100644 index 51e8b1e..0000000 --- a/thermal_target.c +++ /dev/null @@ -1,877 +0,0 @@ -/* Copyright (c) 2018-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. - */ - -#define LOG_TAG "ThermalHAL-TARGET" -#include <utils/Log.h> - -#include <hardware/hardware.h> -#include <hardware/thermal.h> -#include <stdlib.h> -#include "thermal_common.h" - -#define SYSFS_PLATFORMID "/sys/devices/soc0/soc_id" -#define SOC_INFO_NAME_LEN 15 - -struct therm_msm_soc_type { - enum therm_msm_id msm_id; - int soc_id; -}; - -static struct therm_msm_soc_type msm_soc_table[] = { - {THERM_MSM_8953, 293}, - {THERM_MSM_8953, 304}, - {THERM_MSM_8953, 338}, - {THERM_MSM_8953, 351}, - {THERM_SDM_660, 317}, - {THERM_SDM_660, 324}, - {THERM_SDM_660, 325}, - {THERM_SDM_660, 326}, - {THERM_SDM_660, 345}, - {THERM_SDM_660, 346}, - {THERM_SDM_630, 318}, - {THERM_SDM_630, 327}, - {THERM_SDM_630, 385}, - {THERM_SDM_710, 336}, - {THERM_SDM_710, 337}, - {THERM_SDM_710, 393}, // This SOC ID is for SDM712 - {THERM_QCS_605, 347}, - {THERM_SDM_632, 349}, - {THERM_SDM_632, 350}, - {THERM_SDM_439, 353}, - {THERM_SDM_439, 354}, - {THERM_SDM_439, 363}, - {THERM_SDM_439, 364}, - {THERM_MSMNILE, 339}, - {THERM_MSMNILE, 361}, - {THERM_MSMNILE, 362}, - {THERM_MSMNILE, 367}, - {THERM_KONA, 356}, - {THERM_TALOS, 355}, - {THERM_SDMMAGPIE, 365}, - {THERM_MSM_8917, 303}, - {THERM_MSM_8917, 307}, - {THERM_MSM_8917, 308}, - {THERM_MSM_8917, 309}, - {THERM_MSM_8917, 386}, // This SOC ID is for QM215 - {THERM_MSM_8917, 436}, // This SOC ID is for QCM2150 - {THERM_TRINKET, 394}, - {THERM_LITO, 400}, - {THERM_LITO, 440}, - {THERM_ATOLL, 407}, - {THERM_BENGAL, 417}, - {THERM_BENGAL, 444}, - {THERM_BENGAL, 445}, - {THERM_BENGAL, 420}, - {THERM_LAGOON, 434}, - {THERM_LAHAINA, 415}, -}; - -static char *gen_sensors_list[] = -{ - "gpuss-max-step", - "battery", - "skin-msm-therm-usr" -}; - -static char *cpu_sensors_talos[] = -{ - "cpuss-2-usr", - "cpuss-2-usr", - "cpuss-1-usr", - "cpuss-1-usr", - "cpuss-0-usr", - "cpuss-0-usr", - "cpu-1-0-usr", - "cpu-1-2-usr", -}; - -static char *misc_sensors_talos[] = -{ - "gpu-usr", - "battery", - "xo-therm" -}; - -static struct target_therm_cfg sensor_cfg_talos[] = { - { - .type = DEVICE_TEMPERATURE_CPU, - .sensor_list = cpu_sensors_talos, - .sens_cnt = ARRAY_SIZE(cpu_sensors_talos), - .mult = 0.001, - }, - { - .type = DEVICE_TEMPERATURE_GPU, - .sensor_list = &misc_sensors_talos[0], - .sens_cnt = 1, - .mult = 0.001, - .label = "GPU", - }, - { - .type = DEVICE_TEMPERATURE_BATTERY, - .sensor_list = &misc_sensors_talos[1], - .sens_cnt = 1, - .mult = 0.001, - .label = "battery", - }, - { - .type = DEVICE_TEMPERATURE_SKIN, - .sensor_list = &misc_sensors_talos[2], - .sens_cnt = 1, - .mult = 0.001, - .label = "skin", - } -}; - -static char *cpu_sensors_sdmmagpie[] = -{ - "cpu-0-0-usr", - "cpu-0-1-usr", - "cpu-0-2-usr", - "cpu-0-3-usr", - "cpu-0-4-usr", - "cpu-0-5-usr", - "cpu-1-0-usr", - "cpu-1-2-usr", -}; - -static char *misc_sensors_sdmmagpie[] = -{ - "gpuss-0-usr", - "battery", - "xo-therm-adc" -}; - -static struct target_therm_cfg sensor_cfg_sdmmagpie[] = { - { - .type = DEVICE_TEMPERATURE_CPU, - .sensor_list = cpu_sensors_sdmmagpie, - .sens_cnt = ARRAY_SIZE(cpu_sensors_sdmmagpie), - .mult = 0.001, - }, - { - .type = DEVICE_TEMPERATURE_GPU, - .sensor_list = &misc_sensors_sdmmagpie[0], - .sens_cnt = 1, - .mult = 0.001, - .label = "GPU", - }, - { - .type = DEVICE_TEMPERATURE_BATTERY, - .sensor_list = &misc_sensors_sdmmagpie[1], - .sens_cnt = 1, - .mult = 0.001, - .label = "battery", - }, - { - .type = DEVICE_TEMPERATURE_SKIN, - .sensor_list = &misc_sensors_sdmmagpie[2], - .sens_cnt = 1, - .mult = 0.001, - .label = "skin", - } -}; - -static char *misc_sensors_lito[] = -{ - "gpuss-0-usr", - "battery", - "xo-therm-usr" -}; - -static struct target_therm_cfg sensor_cfg_lito[] = { - { - .type = DEVICE_TEMPERATURE_CPU, - .sensor_list = cpu_sensors_sdmmagpie, - .sens_cnt = ARRAY_SIZE(cpu_sensors_sdmmagpie), - .mult = 0.001, - }, - { - .type = DEVICE_TEMPERATURE_GPU, - .sensor_list = &misc_sensors_lito[0], - .sens_cnt = 1, - .mult = 0.001, - .label = "GPU", - }, - { - .type = DEVICE_TEMPERATURE_BATTERY, - .sensor_list = &misc_sensors_lito[1], - .sens_cnt = 1, - .mult = 0.001, - .label = "battery", - }, - { - .type = DEVICE_TEMPERATURE_SKIN, - .sensor_list = &misc_sensors_lito[2], - .sens_cnt = 1, - .mult = 0.001, - .label = "skin", - } -}; - -static char *cpu_sensors_trinket[] = -{ - "cpuss-0-usr", - "cpuss-0-usr", - "cpuss-0-usr", - "cpuss-0-usr", - "cpu-1-0-usr", - "cpu-1-1-usr", - "cpu-1-2-usr", - "cpu-1-3-usr", -}; - -static char *misc_sensors_trinket[] = -{ - "gpu-usr", - "battery", - "xo-therm-adc" -}; - -static struct target_therm_cfg sensor_cfg_trinket[] = { - { - .type = DEVICE_TEMPERATURE_CPU, - .sensor_list = cpu_sensors_trinket, - .sens_cnt = ARRAY_SIZE(cpu_sensors_trinket), - .mult = 0.001, - }, - { - .type = DEVICE_TEMPERATURE_GPU, - .sensor_list = &misc_sensors_trinket[0], - .sens_cnt = 1, - .mult = 0.001, - .label = "GPU", - }, - { - .type = DEVICE_TEMPERATURE_BATTERY, - .sensor_list = &misc_sensors_trinket[1], - .sens_cnt = 1, - .mult = 0.001, - .label = "battery", - }, - { - .type = DEVICE_TEMPERATURE_SKIN, - .sensor_list = &misc_sensors_trinket[2], - .sens_cnt = 1, - .mult = 0.001, - .label = "skin", - } -}; - -static char *cpu_sensors_bengal[] = -{ - "cpuss-2-usr", - "cpuss-2-usr", - "cpuss-2-usr", - "cpuss-2-usr", - "cpu-1-0-usr", - "cpu-1-1-usr", - "cpu-1-2-usr", - "cpu-1-3-usr", -}; - -static char *misc_sensors_bengal[] = -{ - "gpu-usr", - "battery", - "xo-therm-usr" -}; - -static struct target_therm_cfg sensor_cfg_bengal[] = { - { - .type = DEVICE_TEMPERATURE_CPU, - .sensor_list = cpu_sensors_bengal, - .sens_cnt = ARRAY_SIZE(cpu_sensors_bengal), - .mult = 0.001, - }, - { - .type = DEVICE_TEMPERATURE_GPU, - .sensor_list = &misc_sensors_bengal[0], - .sens_cnt = 1, - .mult = 0.001, - .label = "GPU", - }, - { - .type = DEVICE_TEMPERATURE_BATTERY, - .sensor_list = &misc_sensors_bengal[1], - .sens_cnt = 1, - .mult = 0.001, - .label = "battery", - }, - { - .type = DEVICE_TEMPERATURE_SKIN, - .sensor_list = &misc_sensors_bengal[2], - .sens_cnt = 1, - .mult = 0.001, - .label = "skin", - } -}; - -static char *cpu_sensors_msmnile[] = -{ - "cpu-0-0-usr", - "cpu-0-1-usr", - "cpu-0-2-usr", - "cpu-0-3-usr", - "cpu-1-0-usr", - "cpu-1-1-usr", - "cpu-1-2-usr", - "cpu-1-3-usr", -}; - -static char *misc_sensors_msmnile[] = -{ - "gpuss-0-usr", - "battery", - "xo-therm" -}; - -static struct target_therm_cfg sensor_cfg_msmnile[] = { - { - .type = DEVICE_TEMPERATURE_CPU, - .sensor_list = cpu_sensors_msmnile, - .sens_cnt = ARRAY_SIZE(cpu_sensors_msmnile), - .mult = 0.001, - }, - { - .type = DEVICE_TEMPERATURE_GPU, - .sensor_list = &misc_sensors_msmnile[0], - .sens_cnt = 1, - .mult = 0.001, - .label = "GPU", - }, - { - .type = DEVICE_TEMPERATURE_BATTERY, - .sensor_list = &misc_sensors_msmnile[1], - .sens_cnt = 1, - .mult = 0.001, - .label = "battery", - }, - { - .type = DEVICE_TEMPERATURE_SKIN, - .sensor_list = &misc_sensors_msmnile[2], - .sens_cnt = 1, - .mult = 0.001, - .label = "skin", - } -}; - -static struct target_therm_cfg sensor_cfg_kona[] = { - { - .type = DEVICE_TEMPERATURE_CPU, - .sensor_list = cpu_sensors_msmnile, - .sens_cnt = ARRAY_SIZE(cpu_sensors_msmnile), - .mult = 0.001, - }, - { - .type = DEVICE_TEMPERATURE_GPU, - .sensor_list = &gen_sensors_list[0], - .sens_cnt = 1, - .mult = 0.001, - .label = "GPU", - }, - { - .type = DEVICE_TEMPERATURE_BATTERY, - .sensor_list = &gen_sensors_list[1], - .sens_cnt = 1, - .mult = 0.001, - .label = "battery", - }, - { - .type = DEVICE_TEMPERATURE_SKIN, - .sensor_list = &gen_sensors_list[2], - .sens_cnt = 1, - .mult = 0.001, - .label = "skin", - } -}; - -static char *cpu_sensors_660[] = -{ - "tsens_tz_sensor1", - "tsens_tz_sensor1", - "tsens_tz_sensor1", - "tsens_tz_sensor1", - "tsens_tz_sensor3", - "tsens_tz_sensor4", - "tsens_tz_sensor5", - "tsens_tz_sensor6", -}; - -static char *misc_sensors_660[] = -{ - "tsens_tz_sensor8", - "battery", - "xo_therm" -}; - -static struct target_therm_cfg sensor_cfg_660[] = { - { - .type = DEVICE_TEMPERATURE_CPU, - .sensor_list = cpu_sensors_660, - .sens_cnt = ARRAY_SIZE(cpu_sensors_660), - .mult = 0.1, - }, - { - .type = DEVICE_TEMPERATURE_GPU, - .sensor_list = &misc_sensors_660[0], - .sens_cnt = 1, - .mult = 0.1, - .label = "GPU", - }, - { - .type = DEVICE_TEMPERATURE_BATTERY, - .sensor_list = &misc_sensors_660[1], - .sens_cnt = 1, - .mult = 0.001, - .label = "battery", - }, - { - .type = DEVICE_TEMPERATURE_SKIN, - .sensor_list = &misc_sensors_660[2], - .sens_cnt = 1, - .mult = 1, - .label = "skin", - } -}; - -static char *cpu_sensors_630[] = -{ - "tsens_tz_sensor3", - "tsens_tz_sensor4", - "tsens_tz_sensor5", - "tsens_tz_sensor6", - "tsens_tz_sensor7", - "tsens_tz_sensor7", - "tsens_tz_sensor7", - "tsens_tz_sensor7", -}; - -static struct target_therm_cfg sensor_cfg_630[] = { - { - .type = DEVICE_TEMPERATURE_CPU, - .sensor_list = cpu_sensors_630, - .sens_cnt = ARRAY_SIZE(cpu_sensors_630), - .mult = 0.1, - }, - { - .type = DEVICE_TEMPERATURE_GPU, - .sensor_list = &misc_sensors_660[0], - .sens_cnt = 1, - .mult = 0.1, - .label = "GPU", - }, - { - .type = DEVICE_TEMPERATURE_BATTERY, - .sensor_list = &misc_sensors_660[1], - .sens_cnt = 1, - .mult = 0.001, - .label = "battery", - }, - { - .type = DEVICE_TEMPERATURE_SKIN, - .sensor_list = &misc_sensors_660[2], - .sens_cnt = 1, - .mult = 1, - .label = "skin", - } -}; - -static char *cpu_sensors_8953[] = -{ - "tsens_tz_sensor9", - "tsens_tz_sensor10", - "tsens_tz_sensor11", - "tsens_tz_sensor12", - "tsens_tz_sensor4", - "tsens_tz_sensor5", - "tsens_tz_sensor6", - "tsens_tz_sensor7", -}; - -static char *misc_sensors_8953[] = -{ - "tsens_tz_sensor15", - "battery", - "xo_therm" -}; - -static struct target_therm_cfg sensor_cfg_8953[] = { - { - .type = DEVICE_TEMPERATURE_CPU, - .sensor_list = cpu_sensors_8953, - .sens_cnt = ARRAY_SIZE(cpu_sensors_8953), - .mult = 0.1, - }, - { - .type = DEVICE_TEMPERATURE_GPU, - .sensor_list = &misc_sensors_8953[0], - .sens_cnt = 1, - .mult = 0.1, - .label = "GPU", - }, - { - .type = DEVICE_TEMPERATURE_BATTERY, - .sensor_list = &misc_sensors_8953[1], - .sens_cnt = 1, - .mult = 0.001, - .label = "battery", - }, - { - .type = DEVICE_TEMPERATURE_SKIN, - .sensor_list = &misc_sensors_8953[2], - .sens_cnt = 1, - .mult = 1, - .label = "skin", - } -}; - - -static char *cpu_sensors_710[] = -{ - "cpu0-silver-usr", - "cpu1-silver-usr", - "cpu2-silver-usr", - "cpu3-silver-usr", - "cpu4-silver-usr", - "cpu5-silver-usr", - "cpu0-gold-usr", - "cpu1-gold-usr", -}; - -static char *misc_sensors_710[] = -{ - "gpu0-usr", - "battery", - "xo-therm-adc" -}; - -static struct target_therm_cfg sensor_cfg_710[] = { - { - .type = DEVICE_TEMPERATURE_CPU, - .sensor_list = cpu_sensors_710, - .sens_cnt = ARRAY_SIZE(cpu_sensors_710), - .mult = 0.001, - }, - { - .type = DEVICE_TEMPERATURE_GPU, - .sensor_list = &misc_sensors_710[0], - .sens_cnt = 1, - .mult = 0.001, - .label = "GPU", - }, - { - .type = DEVICE_TEMPERATURE_BATTERY, - .sensor_list = &misc_sensors_710[1], - .sens_cnt = 1, - .mult = 0.001, - .label = "battery", - }, - { - .type = DEVICE_TEMPERATURE_SKIN, - .sensor_list = &misc_sensors_710[2], - .sens_cnt = 1, - .mult = 0.001, - .label = "skin", - } -}; - -static char *cpu_sensors_632[] = -{ - "cpuss0-usr", - "cpuss0-usr", - "cpuss0-usr", - "cpuss0-usr", - "apc1-cpu0-usr", - "apc1-cpu1-usr", - "apc1-cpu2-usr", - "apc1-cpu3-usr", -}; - -static char *misc_sensors_632[] = -{ - "gpu0-usr", - "battery", - "quiet-therm-adc" -}; - -static struct target_therm_cfg sensor_cfg_632[] = { - { - .type = DEVICE_TEMPERATURE_CPU, - .sensor_list = cpu_sensors_632, - .sens_cnt = ARRAY_SIZE(cpu_sensors_632), - .mult = 0.001, - }, - { - .type = DEVICE_TEMPERATURE_GPU, - .sensor_list = &misc_sensors_632[0], - .sens_cnt = 1, - .mult = 0.001, - .label = "GPU", - }, - { - .type = DEVICE_TEMPERATURE_BATTERY, - .sensor_list = &misc_sensors_632[1], - .sens_cnt = 1, - .mult = 0.001, - .label = "battery", - }, - { - .type = DEVICE_TEMPERATURE_SKIN, - .sensor_list = &misc_sensors_632[2], - .sens_cnt = 1, - .mult = 0.001, - .label = "skin", - } -}; - -static char *cpu_sensors_439[] = -{ - "apc1-cpu0-usr", - "apc1-cpu1-usr", - "apc1-cpu2-usr", - "apc1-cpu3-usr", - "cpuss0-usr", - "cpuss0-usr", - "cpuss0-usr", - "cpuss0-usr", -}; - -static char *misc_sensors_439[] = -{ - "gpu-usr", - "battery", - "quiet-therm-adc" -}; - -static struct target_therm_cfg sensor_cfg_439[] = { - { - .type = DEVICE_TEMPERATURE_CPU, - .sensor_list = cpu_sensors_439, - .sens_cnt = ARRAY_SIZE(cpu_sensors_439), - .mult = 0.001, - }, - { - .type = DEVICE_TEMPERATURE_GPU, - .sensor_list = &misc_sensors_439[0], - .sens_cnt = 1, - .mult = 0.001, - .label = "GPU", - }, - { - .type = DEVICE_TEMPERATURE_BATTERY, - .sensor_list = &misc_sensors_439[1], - .sens_cnt = 1, - .mult = 0.001, - .label = "battery", - }, - { - .type = DEVICE_TEMPERATURE_SKIN, - .sensor_list = &misc_sensors_439[2], - .sens_cnt = 1, - .mult = 0.001, - .label = "skin", - } -}; - -static char *cpu_sensors_8917[] = -{ - "apc1-cpu0-usr", - "apc1-cpu1-usr", - "apc1-cpu2-usr", - "apc1-cpu3-usr", -}; - -static char *misc_sensors_8917[] = -{ - "gpu0-usr", - "battery", - "xo-therm-adc" -}; - -static struct target_therm_cfg sensor_cfg_8917[] = { - { - .type = DEVICE_TEMPERATURE_CPU, - .sensor_list = cpu_sensors_8917, - .sens_cnt = ARRAY_SIZE(cpu_sensors_8917), - .mult = 0.001, - }, - { - .type = DEVICE_TEMPERATURE_GPU, - .sensor_list = &misc_sensors_8917[0], - .sens_cnt = 1, - .mult = 0.001, - .label = "GPU", - }, - { - .type = DEVICE_TEMPERATURE_BATTERY, - .sensor_list = &misc_sensors_8917[1], - .sens_cnt = 1, - .mult = 0.001, - .label = "battery", - }, - { - .type = DEVICE_TEMPERATURE_SKIN, - .sensor_list = &misc_sensors_8917[2], - .sens_cnt = 1, - .mult = 0.001, - .label = "skin", - } -}; - -static int get_soc_info(char *buf) -{ - int ret = 0; - - ret = read_line_from_file(SYSFS_PLATFORMID, buf, SOC_INFO_NAME_LEN); - if (ret < 0) { - ALOGE("Error getting platform_id %d", ret); - return ret; - } - if (ret && buf[ret - 1] == '\n') - buf[ret - 1] = '\0'; - - return ret; -} - -enum therm_msm_id therm_get_soc_id(void) -{ - static enum therm_msm_id msm_id; - int soc_id = -1; - - if (!msm_id) { - int idx; - char buf[SOC_INFO_NAME_LEN]; - - if (get_soc_info(buf) <= 0) - return msm_id; - - soc_id = atoi(buf); - for (idx = 0; idx < ARRAY_SIZE(msm_soc_table); idx++) { - if (soc_id == msm_soc_table[idx].soc_id) { - msm_id = msm_soc_table[idx].msm_id; - break; - } - } - if (!msm_id) - ALOGE("Unknown target identified with soc id %d\n", soc_id); - } - - return msm_id; -} - -ssize_t get_temperatures(thermal_module_t *module, temperature_t *list, size_t size) { - ALOGD("Entering %s",__func__); - static int thermal_sens_size; - - if (!thermal_sens_size) { - struct target_therm_cfg *cfg = NULL; - size_t num_cfg = 0; - - switch (therm_get_soc_id()) { - case THERM_MSM_8953: - cfg = sensor_cfg_8953; - num_cfg = ARRAY_SIZE(sensor_cfg_8953); - break; - case THERM_SDM_660: - cfg = sensor_cfg_660; - num_cfg = ARRAY_SIZE(sensor_cfg_660); - break; - case THERM_SDM_630: - cfg = sensor_cfg_630; - num_cfg = ARRAY_SIZE(sensor_cfg_630); - break; - case THERM_SDM_710: - case THERM_QCS_605: - cfg = sensor_cfg_710; - num_cfg = ARRAY_SIZE(sensor_cfg_710); - break; - case THERM_SDM_632: - cfg = sensor_cfg_632; - num_cfg = ARRAY_SIZE(sensor_cfg_632); - break; - case THERM_SDM_439: - cfg = sensor_cfg_439; - num_cfg = ARRAY_SIZE(sensor_cfg_439); - break; - case THERM_MSM_8917: - cfg = sensor_cfg_8917; - num_cfg = ARRAY_SIZE(sensor_cfg_8917); - break; - case THERM_MSMNILE: - cfg = sensor_cfg_msmnile; - num_cfg = ARRAY_SIZE(sensor_cfg_msmnile); - break; - case THERM_KONA: - case THERM_LAHAINA: - cfg = sensor_cfg_kona; - num_cfg = ARRAY_SIZE(sensor_cfg_kona); - break; - case THERM_TALOS: - cfg = sensor_cfg_talos; - num_cfg = ARRAY_SIZE(sensor_cfg_talos); - break; - case THERM_SDMMAGPIE: - cfg = sensor_cfg_sdmmagpie; - num_cfg = ARRAY_SIZE(sensor_cfg_sdmmagpie); - break; - case THERM_TRINKET: - cfg = sensor_cfg_trinket; - num_cfg = ARRAY_SIZE(sensor_cfg_trinket); - break; - case THERM_BENGAL: - cfg = sensor_cfg_bengal; - num_cfg = ARRAY_SIZE(sensor_cfg_bengal); - break; - case THERM_LITO: - case THERM_ATOLL: - case THERM_LAGOON: - cfg = sensor_cfg_lito; - num_cfg = ARRAY_SIZE(sensor_cfg_lito); - break; - default: - cfg = NULL; - num_cfg = 0; - break; - } - if (cfg == NULL || num_cfg == 0) { - ALOGE("No target specific sensor config\n"); - return 0; - } - thermal_sens_size = thermal_zone_init(cfg, num_cfg); - if (thermal_sens_size <= 0) { - ALOGE("thermal sensor initialization is failed\n"); - thermal_sens_size = 0; - return 0; - } - } - - if (list == NULL) - return thermal_sens_size; - - return get_temperature_for_all(list, size); -} |