1/* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#define LOG_TAG "HardwarePropertiesManagerService-JNI" 18 19#include "JNIHelp.h" 20#include "jni.h" 21 22#include <stdlib.h> 23 24#include <hardware/thermal.h> 25#include <utils/Log.h> 26#include <utils/String8.h> 27 28#include "core_jni_helpers.h" 29 30namespace android { 31 32// --------------------------------------------------------------------------- 33 34// These values must be kept in sync with the temperature source constants in 35// HardwarePropertiesManager.java 36enum { 37 TEMPERATURE_CURRENT = 0, 38 TEMPERATURE_THROTTLING = 1, 39 TEMPERATURE_SHUTDOWN = 2, 40 TEMPERATURE_THROTTLING_BELOW_VR_MIN = 3 41}; 42 43static struct { 44 jclass clazz; 45 jmethodID initMethod; 46} gCpuUsageInfoClassInfo; 47 48jfloat gUndefinedTemperature; 49 50static struct thermal_module* gThermalModule; 51 52// ---------------------------------------------------------------------------- 53 54static void nativeInit(JNIEnv* env, jobject obj) { 55 status_t err = hw_get_module(THERMAL_HARDWARE_MODULE_ID, (hw_module_t const**)&gThermalModule); 56 if (err) { 57 ALOGE("Couldn't load %s module (%s)", THERMAL_HARDWARE_MODULE_ID, strerror(-err)); 58 } 59} 60 61static jfloatArray nativeGetFanSpeeds(JNIEnv *env, jclass /* clazz */) { 62 if (gThermalModule && gThermalModule->getCoolingDevices) { 63 ssize_t list_size = gThermalModule->getCoolingDevices(gThermalModule, nullptr, 0); 64 65 if (list_size >= 0) { 66 cooling_device_t *list = (cooling_device_t *) 67 malloc(list_size * sizeof(cooling_device_t)); 68 ssize_t size = gThermalModule->getCoolingDevices(gThermalModule, list, list_size); 69 if (size >= 0) { 70 if (list_size > size) { 71 list_size = size; 72 } 73 jfloat values[list_size]; 74 for (ssize_t i = 0; i < list_size; ++i) { 75 values[i] = list[i].current_value; 76 } 77 78 jfloatArray fanSpeeds = env->NewFloatArray(list_size); 79 env->SetFloatArrayRegion(fanSpeeds, 0, list_size, values); 80 free(list); 81 return fanSpeeds; 82 } 83 84 free(list); 85 } 86 87 ALOGE("Cloudn't get fan speeds because of HAL error"); 88 } 89 return env->NewFloatArray(0); 90} 91 92static jfloatArray nativeGetDeviceTemperatures(JNIEnv *env, jclass /* clazz */, int type, 93 int source) { 94 if (gThermalModule && gThermalModule->getTemperatures) { 95 ssize_t list_size = gThermalModule->getTemperatures(gThermalModule, nullptr, 0); 96 if (list_size >= 0) { 97 temperature_t *list = (temperature_t *) malloc(list_size * sizeof(temperature_t)); 98 ssize_t size = gThermalModule->getTemperatures(gThermalModule, list, list_size); 99 if (size >= 0) { 100 if (list_size > size) { 101 list_size = size; 102 } 103 104 jfloat values[list_size]; 105 size_t length = 0; 106 107 for (ssize_t i = 0; i < list_size; ++i) { 108 if (list[i].type == type) { 109 switch (source) { 110 case TEMPERATURE_CURRENT: 111 if (list[i].current_value == UNKNOWN_TEMPERATURE) { 112 values[length++] = gUndefinedTemperature; 113 } else { 114 values[length++] = list[i].current_value; 115 } 116 break; 117 case TEMPERATURE_THROTTLING: 118 if (list[i].throttling_threshold == UNKNOWN_TEMPERATURE) { 119 values[length++] = gUndefinedTemperature; 120 } else { 121 values[length++] = list[i].throttling_threshold; 122 } 123 break; 124 case TEMPERATURE_SHUTDOWN: 125 if (list[i].shutdown_threshold == UNKNOWN_TEMPERATURE) { 126 values[length++] = gUndefinedTemperature; 127 } else { 128 values[length++] = list[i].shutdown_threshold; 129 } 130 break; 131 case TEMPERATURE_THROTTLING_BELOW_VR_MIN: 132 if (list[i].vr_throttling_threshold == UNKNOWN_TEMPERATURE) { 133 values[length++] = gUndefinedTemperature; 134 } else { 135 values[length++] = list[i].vr_throttling_threshold; 136 } 137 break; 138 } 139 } 140 } 141 jfloatArray deviceTemps = env->NewFloatArray(length); 142 env->SetFloatArrayRegion(deviceTemps, 0, length, values); 143 free(list); 144 return deviceTemps; 145 } 146 free(list); 147 } 148 ALOGE("Couldn't get device temperatures because of HAL error"); 149 } 150 return env->NewFloatArray(0); 151} 152 153static jobjectArray nativeGetCpuUsages(JNIEnv *env, jclass /* clazz */) { 154 if (gThermalModule && gThermalModule->getCpuUsages 155 && gCpuUsageInfoClassInfo.initMethod) { 156 ssize_t size = gThermalModule->getCpuUsages(gThermalModule, nullptr); 157 if (size >= 0) { 158 cpu_usage_t *list = (cpu_usage_t *) malloc(size * sizeof(cpu_usage_t)); 159 size = gThermalModule->getCpuUsages(gThermalModule, list); 160 if (size >= 0) { 161 jobjectArray cpuUsages = env->NewObjectArray(size, gCpuUsageInfoClassInfo.clazz, 162 nullptr); 163 for (ssize_t i = 0; i < size; ++i) { 164 if (list[i].is_online) { 165 jobject cpuUsage = env->NewObject(gCpuUsageInfoClassInfo.clazz, 166 gCpuUsageInfoClassInfo.initMethod, list[i].active, list[i].total); 167 env->SetObjectArrayElement(cpuUsages, i, cpuUsage); 168 } 169 } 170 free(list); 171 return cpuUsages; 172 } 173 free(list); 174 } 175 ALOGE("Couldn't get CPU usages because of HAL error"); 176 } 177 return env->NewObjectArray(0, gCpuUsageInfoClassInfo.clazz, nullptr); 178} 179 180// ---------------------------------------------------------------------------- 181 182static const JNINativeMethod gHardwarePropertiesManagerServiceMethods[] = { 183 /* name, signature, funcPtr */ 184 { "nativeInit", "()V", 185 (void*) nativeInit }, 186 { "nativeGetFanSpeeds", "()[F", 187 (void*) nativeGetFanSpeeds }, 188 { "nativeGetDeviceTemperatures", "(II)[F", 189 (void*) nativeGetDeviceTemperatures }, 190 { "nativeGetCpuUsages", "()[Landroid/os/CpuUsageInfo;", 191 (void*) nativeGetCpuUsages } 192}; 193 194int register_android_server_HardwarePropertiesManagerService(JNIEnv* env) { 195 gThermalModule = nullptr; 196 int res = jniRegisterNativeMethods(env, "com/android/server/HardwarePropertiesManagerService", 197 gHardwarePropertiesManagerServiceMethods, 198 NELEM(gHardwarePropertiesManagerServiceMethods)); 199 jclass clazz = env->FindClass("android/os/CpuUsageInfo"); 200 gCpuUsageInfoClassInfo.clazz = MakeGlobalRefOrDie(env, clazz); 201 gCpuUsageInfoClassInfo.initMethod = GetMethodIDOrDie(env, gCpuUsageInfoClassInfo.clazz, 202 "<init>", "(JJ)V"); 203 204 clazz = env->FindClass("android/os/HardwarePropertiesManager"); 205 jfieldID undefined_temperature_field = GetStaticFieldIDOrDie(env, clazz, 206 "UNDEFINED_TEMPERATURE", "F"); 207 gUndefinedTemperature = env->GetStaticFloatField(clazz, undefined_temperature_field); 208 209 return res; 210} 211 212} /* namespace android */ 213