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 <math.h> 23#include <stdlib.h> 24 25#include <android/hardware/thermal/1.0/IThermal.h> 26#include <utils/Log.h> 27#include <utils/String8.h> 28 29#include "core_jni_helpers.h" 30 31namespace android { 32 33using hardware::hidl_vec; 34using hardware::thermal::V1_0::CoolingDevice; 35using hardware::thermal::V1_0::CpuUsage; 36using hardware::thermal::V1_0::IThermal; 37using hardware::thermal::V1_0::Temperature; 38using hardware::thermal::V1_0::ThermalStatus; 39using hardware::thermal::V1_0::ThermalStatusCode; 40template<typename T> 41using Return = hardware::Return<T>; 42 43// --------------------------------------------------------------------------- 44 45// These values must be kept in sync with the temperature source constants in 46// HardwarePropertiesManager.java 47enum { 48 TEMPERATURE_CURRENT = 0, 49 TEMPERATURE_THROTTLING = 1, 50 TEMPERATURE_SHUTDOWN = 2, 51 TEMPERATURE_THROTTLING_BELOW_VR_MIN = 3 52}; 53 54static struct { 55 jclass clazz; 56 jmethodID initMethod; 57} gCpuUsageInfoClassInfo; 58 59jfloat gUndefinedTemperature; 60 61static sp<IThermal> gThermalModule; 62 63// ---------------------------------------------------------------------------- 64 65float finalizeTemperature(float temperature) { 66 return isnan(temperature) ? gUndefinedTemperature : temperature; 67} 68 69static void nativeInit(JNIEnv* env, jobject obj) { 70 // TODO(b/31632518) 71 if (gThermalModule == nullptr) { 72 gThermalModule = IThermal::getService(); 73 } 74 75 if (gThermalModule == nullptr) { 76 ALOGE("Unable to get Thermal service."); 77 } 78} 79 80static jfloatArray nativeGetFanSpeeds(JNIEnv *env, jclass /* clazz */) { 81 if (gThermalModule == nullptr) { 82 ALOGE("Couldn't get fan speeds because of HAL error."); 83 return env->NewFloatArray(0); 84 } 85 86 hidl_vec<CoolingDevice> list; 87 Return<void> ret = gThermalModule->getCoolingDevices( 88 [&list](ThermalStatus status, hidl_vec<CoolingDevice> devices) { 89 if (status.code == ThermalStatusCode::SUCCESS) { 90 list = std::move(devices); 91 } else { 92 ALOGE("Couldn't get fan speeds because of HAL error: %s", 93 status.debugMessage.c_str()); 94 } 95 }); 96 97 if (!ret.isOk()) { 98 ALOGE("getCoolingDevices failed status: %s", ret.description().c_str()); 99 } 100 101 float values[list.size()]; 102 for (size_t i = 0; i < list.size(); ++i) { 103 values[i] = list[i].currentValue; 104 } 105 jfloatArray fanSpeeds = env->NewFloatArray(list.size()); 106 env->SetFloatArrayRegion(fanSpeeds, 0, list.size(), values); 107 return fanSpeeds; 108} 109 110static jfloatArray nativeGetDeviceTemperatures(JNIEnv *env, jclass /* clazz */, int type, 111 int source) { 112 if (gThermalModule == nullptr) { 113 ALOGE("Couldn't get device temperatures because of HAL error."); 114 return env->NewFloatArray(0); 115 } 116 hidl_vec<Temperature> list; 117 Return<void> ret = gThermalModule->getTemperatures( 118 [&list](ThermalStatus status, hidl_vec<Temperature> temperatures) { 119 if (status.code == ThermalStatusCode::SUCCESS) { 120 list = std::move(temperatures); 121 } else { 122 ALOGE("Couldn't get temperatures because of HAL error: %s", 123 status.debugMessage.c_str()); 124 } 125 }); 126 127 if (!ret.isOk()) { 128 ALOGE("getDeviceTemperatures failed status: %s", ret.description().c_str()); 129 } 130 131 jfloat values[list.size()]; 132 size_t length = 0; 133 for (size_t i = 0; i < list.size(); ++i) { 134 if (static_cast<int>(list[i].type) == type) { 135 switch (source) { 136 case TEMPERATURE_CURRENT: 137 values[length++] = finalizeTemperature(list[i].currentValue); 138 break; 139 case TEMPERATURE_THROTTLING: 140 values[length++] = finalizeTemperature(list[i].throttlingThreshold); 141 break; 142 case TEMPERATURE_SHUTDOWN: 143 values[length++] = finalizeTemperature(list[i].shutdownThreshold); 144 break; 145 case TEMPERATURE_THROTTLING_BELOW_VR_MIN: 146 values[length++] = finalizeTemperature(list[i].vrThrottlingThreshold); 147 break; 148 } 149 } 150 } 151 jfloatArray deviceTemps = env->NewFloatArray(length); 152 env->SetFloatArrayRegion(deviceTemps, 0, length, values); 153 return deviceTemps; 154} 155 156static jobjectArray nativeGetCpuUsages(JNIEnv *env, jclass /* clazz */) { 157 if (gThermalModule == nullptr || !gCpuUsageInfoClassInfo.initMethod) { 158 ALOGE("Couldn't get CPU usages because of HAL error."); 159 return env->NewObjectArray(0, gCpuUsageInfoClassInfo.clazz, nullptr); 160 } 161 hidl_vec<CpuUsage> list; 162 Return<void> ret = gThermalModule->getCpuUsages( 163 [&list](ThermalStatus status, hidl_vec<CpuUsage> cpuUsages) { 164 if (status.code == ThermalStatusCode::SUCCESS) { 165 list = std::move(cpuUsages); 166 } else { 167 ALOGE("Couldn't get CPU usages because of HAL error: %s", 168 status.debugMessage.c_str()); 169 } 170 }); 171 172 if (!ret.isOk()) { 173 ALOGE("getCpuUsages failed status: %s", ret.description().c_str()); 174 } 175 176 jobjectArray cpuUsages = env->NewObjectArray(list.size(), gCpuUsageInfoClassInfo.clazz, 177 nullptr); 178 for (size_t i = 0; i < list.size(); ++i) { 179 if (list[i].isOnline) { 180 jobject cpuUsage = env->NewObject(gCpuUsageInfoClassInfo.clazz, 181 gCpuUsageInfoClassInfo.initMethod, 182 list[i].active, 183 list[i].total); 184 env->SetObjectArrayElement(cpuUsages, i, cpuUsage); 185 } 186 } 187 return cpuUsages; 188} 189 190// ---------------------------------------------------------------------------- 191 192static const JNINativeMethod gHardwarePropertiesManagerServiceMethods[] = { 193 /* name, signature, funcPtr */ 194 { "nativeInit", "()V", 195 (void*) nativeInit }, 196 { "nativeGetFanSpeeds", "()[F", 197 (void*) nativeGetFanSpeeds }, 198 { "nativeGetDeviceTemperatures", "(II)[F", 199 (void*) nativeGetDeviceTemperatures }, 200 { "nativeGetCpuUsages", "()[Landroid/os/CpuUsageInfo;", 201 (void*) nativeGetCpuUsages } 202}; 203 204int register_android_server_HardwarePropertiesManagerService(JNIEnv* env) { 205 gThermalModule = nullptr; 206 int res = jniRegisterNativeMethods(env, "com/android/server/HardwarePropertiesManagerService", 207 gHardwarePropertiesManagerServiceMethods, 208 NELEM(gHardwarePropertiesManagerServiceMethods)); 209 jclass clazz = env->FindClass("android/os/CpuUsageInfo"); 210 gCpuUsageInfoClassInfo.clazz = MakeGlobalRefOrDie(env, clazz); 211 gCpuUsageInfoClassInfo.initMethod = GetMethodIDOrDie(env, gCpuUsageInfoClassInfo.clazz, 212 "<init>", "(JJ)V"); 213 214 clazz = env->FindClass("android/os/HardwarePropertiesManager"); 215 jfieldID undefined_temperature_field = GetStaticFieldIDOrDie(env, clazz, 216 "UNDEFINED_TEMPERATURE", "F"); 217 gUndefinedTemperature = env->GetStaticFloatField(clazz, undefined_temperature_field); 218 219 return res; 220} 221 222} /* namespace android */ 223