125cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko/* 225cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko * Copyright (C) 2016 The Android Open Source Project 325cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko * 425cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko * Licensed under the Apache License, Version 2.0 (the "License"); 525cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko * you may not use this file except in compliance with the License. 625cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko * You may obtain a copy of the License at 725cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko * 825cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko * http://www.apache.org/licenses/LICENSE-2.0 925cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko * 1025cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko * Unless required by applicable law or agreed to in writing, software 1125cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko * distributed under the License is distributed on an "AS IS" BASIS, 1225cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1325cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko * See the License for the specific language governing permissions and 1425cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko * limitations under the License. 1525cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko */ 1625cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko 1725cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko#include <errno.h> 1825cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko#include <ctype.h> 1925cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko#include <dirent.h> 2025cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko#include <inttypes.h> 2125cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko#include <stdlib.h> 2225cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko#include <string.h> 2325cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko 2425cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko#define LOG_TAG "ThermalHAL" 2525cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko#include <utils/Log.h> 2625cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko 2725cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko#include <hardware/hardware.h> 2825cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko#include <hardware/thermal.h> 2925cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko 3025cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko#define CPU_LABEL "CPU" 3125cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko#define MAX_LENGTH 50 3225cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko 3325cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko#define CPU_USAGE_FILE "/proc/stat" 3425cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko#define TEMPERATURE_DIR "/sys/class/thermal" 3525cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko#define THERMAL_DIR "thermal_zone" 3625cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko#define CPU_ONLINE_FILE_FORMAT "/sys/devices/system/cpu/cpu%d/online" 3725cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko#define UNKNOWN_LABEL "UNKNOWN" 3825cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko 3925cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenkostatic ssize_t get_temperatures(thermal_module_t *module, temperature_t *list, size_t size) { 4025cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko char file_name[MAX_LENGTH]; 4125cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko FILE *file; 4225cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko float temp; 4325cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko size_t idx = 0; 4425cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko DIR *dir; 4525cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko struct dirent *de; 4625cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko 4725cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko /** Read all available temperatures from 4825cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko * /sys/class/thermal/thermal_zone[0-9]+/temp files. 4925cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko * Don't guarantee that all temperatures are in Celsius. */ 5025cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko dir = opendir(TEMPERATURE_DIR); 5125cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko if (dir == 0) { 5225cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko ALOGE("%s: failed to open directory %s: %s", __func__, TEMPERATURE_DIR, strerror(-errno)); 5325cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko return -errno; 5425cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko } 5525cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko 5625cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko while ((de = readdir(dir))) { 5725cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko if (!strncmp(de->d_name, THERMAL_DIR, strlen(THERMAL_DIR))) { 5825cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko snprintf(file_name, MAX_LENGTH, "%s/%s/temp", TEMPERATURE_DIR, de->d_name); 5925cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko file = fopen(file_name, "r"); 6025cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko if (file == NULL) { 6125cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko continue; 6225cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko } 6325cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko if (1 != fscanf(file, "%f", &temp)) { 6425cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko fclose(file); 6525cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko continue; 6625cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko } 6725cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko 6825cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko if (list != NULL && idx < size) { 6925cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko list[idx] = (temperature_t) { 7025cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko .name = UNKNOWN_LABEL, 7125cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko .type = DEVICE_TEMPERATURE_UNKNOWN, 7225cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko .current_value = temp, 7325cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko .throttling_threshold = UNKNOWN_TEMPERATURE, 7425cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko .shutdown_threshold = UNKNOWN_TEMPERATURE, 7553b134045f686972eb0a5ec1d4301fc04e3f095aRuben Brunk .vr_throttling_threshold = UNKNOWN_TEMPERATURE, 7625cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko }; 7725cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko } 7825cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko fclose(file); 7925cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko idx++; 8025cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko } 8125cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko } 8225cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko closedir(dir); 8325cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko return idx; 8425cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko} 8525cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko 8625cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenkostatic ssize_t get_cpu_usages(thermal_module_t *module, cpu_usage_t *list) { 8725cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko int vals, cpu_num, online; 8825cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko ssize_t read; 8925cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko uint64_t user, nice, system, idle, active, total; 9025cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko char *line = NULL; 9125cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko size_t len = 0; 9225cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko size_t size = 0; 9325cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko char file_name[MAX_LENGTH]; 9425cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko FILE *cpu_file; 9525cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko FILE *file = fopen(CPU_USAGE_FILE, "r"); 9625cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko 9725cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko if (file == NULL) { 9825cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko ALOGE("%s: failed to open: %s", __func__, strerror(errno)); 9925cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko return -errno; 10025cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko } 10125cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko 10225cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko while ((read = getline(&line, &len, file)) != -1) { 10325cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko // Skip non "cpu[0-9]" lines. 10425cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko if (strnlen(line, read) < 4 || strncmp(line, "cpu", 3) != 0 || !isdigit(line[3])) { 10525cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko free(line); 10625cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko line = NULL; 10725cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko len = 0; 10825cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko continue; 10925cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko } 11025cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko vals = sscanf(line, "cpu%d %" SCNu64 " %" SCNu64 " %" SCNu64 " %" SCNu64, &cpu_num, &user, 11125cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko &nice, &system, &idle); 11225cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko 11325cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko free(line); 11425cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko line = NULL; 11525cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko len = 0; 11625cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko 11725cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko if (vals != 5) { 11825cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko ALOGE("%s: failed to read CPU information from file: %s", __func__, strerror(errno)); 11925cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko fclose(file); 12025cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko return errno ? -errno : -EIO; 12125cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko } 12225cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko 12325cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko active = user + nice + system; 12425cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko total = active + idle; 12525cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko 12625cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko // Read online CPU information. 12725cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko snprintf(file_name, MAX_LENGTH, CPU_ONLINE_FILE_FORMAT, cpu_num); 12825cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko cpu_file = fopen(file_name, "r"); 12925cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko online = 0; 13025cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko if (cpu_file == NULL) { 13125cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko ALOGE("%s: failed to open file: %s (%s)", __func__, file_name, strerror(errno)); 13225cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko // /sys/devices/system/cpu/cpu0/online is missing on some systems, because cpu0 can't 13325cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko // be offline. 13425cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko online = cpu_num == 0; 13525cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko } else if (1 != fscanf(cpu_file, "%d", &online)) { 13625cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko ALOGE("%s: failed to read CPU online information from file: %s (%s)", __func__, 13725cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko file_name, strerror(errno)); 13825cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko fclose(file); 13925cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko fclose(cpu_file); 14025cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko return errno ? -errno : -EIO; 14125cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko } 14225cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko fclose(cpu_file); 14325cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko 14425cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko if (list != NULL) { 14525cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko list[size] = (cpu_usage_t) { 14625cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko .name = CPU_LABEL, 14725cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko .active = active, 14825cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko .total = total, 14925cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko .is_online = online 15025cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko }; 15125cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko } 15225cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko 15325cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko size++; 15425cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko } 15525cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko 15625cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko fclose(file); 15725cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko return size; 15825cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko} 15925cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko 16025cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenkostatic ssize_t get_cooling_devices(thermal_module_t *module, cooling_device_t *list, size_t size) { 16125cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko return 0; 16225cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko} 16325cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko 16425cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenkostatic struct hw_module_methods_t thermal_module_methods = { 16525cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko .open = NULL, 16625cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko}; 16725cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko 16825cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenkothermal_module_t HAL_MODULE_INFO_SYM = { 16925cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko .common = { 17025cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko .tag = HARDWARE_MODULE_TAG, 17125cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko .module_api_version = THERMAL_HARDWARE_MODULE_API_VERSION_0_1, 17225cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko .hal_api_version = HARDWARE_HAL_API_VERSION, 17325cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko .id = THERMAL_HARDWARE_MODULE_ID, 17425cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko .name = "Default Thermal HAL", 17525cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko .author = "The Android Open Source Project", 17625cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko .methods = &thermal_module_methods, 17725cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko }, 17825cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko 17925cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko .getTemperatures = get_temperatures, 18025cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko .getCpuUsages = get_cpu_usages, 18125cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko .getCoolingDevices = get_cooling_devices, 18225cd7f0fb0969683eceb00c9493e2ba8b80228e9Polina Bondarenko}; 183