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
30 namespace android {
31
32 // ---------------------------------------------------------------------------
33
34 // These values must be kept in sync with the temperature source constants in
35 // HardwarePropertiesManager.java
36 enum {
37 TEMPERATURE_CURRENT = 0,
38 TEMPERATURE_THROTTLING = 1,
39 TEMPERATURE_SHUTDOWN = 2,
40 TEMPERATURE_THROTTLING_BELOW_VR_MIN = 3
41 };
42
43 static struct {
44 jclass clazz;
45 jmethodID initMethod;
46 } gCpuUsageInfoClassInfo;
47
48 jfloat gUndefinedTemperature;
49
50 static struct thermal_module* gThermalModule;
51
52 // ----------------------------------------------------------------------------
53
nativeInit(JNIEnv * env,jobject obj)54 static 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
nativeGetFanSpeeds(JNIEnv * env,jclass)61 static 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
nativeGetDeviceTemperatures(JNIEnv * env,jclass,int type,int source)92 static 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
nativeGetCpuUsages(JNIEnv * env,jclass)153 static 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
182 static 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
register_android_server_HardwarePropertiesManagerService(JNIEnv * env)194 int 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