blob: 14d50ce957fe7a6d914a5db3a0a3253bf5a49c93 [file] [log] [blame]
Polina Bondarenko965ecbb2015-11-13 15:34:28 +01001/*
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
Polina Bondarenkof8754ac2016-02-12 20:38:23 +010017#define LOG_TAG "HardwarePropertiesManagerService-JNI"
Polina Bondarenko965ecbb2015-11-13 15:34:28 +010018
19#include "JNIHelp.h"
20#include "jni.h"
21
22#include <stdlib.h>
23
Polina Bondarenkocb8ca182016-03-01 12:36:34 +010024#include <hardware/thermal.h>
Polina Bondarenko965ecbb2015-11-13 15:34:28 +010025#include <utils/Log.h>
26#include <utils/String8.h>
27
Polina Bondarenko965ecbb2015-11-13 15:34:28 +010028#include "core_jni_helpers.h"
29
30namespace android {
31
32// ---------------------------------------------------------------------------
33
Polina Bondarenkoeb845522016-03-01 14:39:48 +010034// 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,
Ruben Brunk946ef642016-03-25 13:45:42 -070039 TEMPERATURE_SHUTDOWN = 2,
40 TEMPERATURE_THROTTLING_BELOW_VR_MIN = 3
Polina Bondarenkoeb845522016-03-01 14:39:48 +010041};
42
Polina Bondarenko965ecbb2015-11-13 15:34:28 +010043static struct {
44 jclass clazz;
45 jmethodID initMethod;
46} gCpuUsageInfoClassInfo;
47
Polina Bondarenkoeb845522016-03-01 14:39:48 +010048jfloat gUndefinedTemperature;
49
Polina Bondarenkocb8ca182016-03-01 12:36:34 +010050static struct thermal_module* gThermalModule;
Polina Bondarenko965ecbb2015-11-13 15:34:28 +010051
52// ----------------------------------------------------------------------------
53
54static void nativeInit(JNIEnv* env, jobject obj) {
Polina Bondarenkocb8ca182016-03-01 12:36:34 +010055 status_t err = hw_get_module(THERMAL_HARDWARE_MODULE_ID, (hw_module_t const**)&gThermalModule);
Polina Bondarenko965ecbb2015-11-13 15:34:28 +010056 if (err) {
Polina Bondarenkocb8ca182016-03-01 12:36:34 +010057 ALOGE("Couldn't load %s module (%s)", THERMAL_HARDWARE_MODULE_ID, strerror(-err));
Polina Bondarenko965ecbb2015-11-13 15:34:28 +010058 }
59}
60
61static jfloatArray nativeGetFanSpeeds(JNIEnv *env, jclass /* clazz */) {
Polina Bondarenkocb8ca182016-03-01 12:36:34 +010062 if (gThermalModule && gThermalModule->getCoolingDevices) {
63 ssize_t list_size = gThermalModule->getCoolingDevices(gThermalModule, nullptr, 0);
Polina Bondarenko965ecbb2015-11-13 15:34:28 +010064
Polina Bondarenkocb8ca182016-03-01 12:36:34 +010065 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);
Polina Bondarenko965ecbb2015-11-13 15:34:28 +010085 }
86
Polina Bondarenkocb8ca182016-03-01 12:36:34 +010087 ALOGE("Cloudn't get fan speeds because of HAL error");
Polina Bondarenko965ecbb2015-11-13 15:34:28 +010088 }
89 return env->NewFloatArray(0);
90}
91
Polina Bondarenkoeb845522016-03-01 14:39:48 +010092static jfloatArray nativeGetDeviceTemperatures(JNIEnv *env, jclass /* clazz */, int type,
93 int source) {
Polina Bondarenkocb8ca182016-03-01 12:36:34 +010094 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) {
Polina Bondarenkoeb845522016-03-01 14:39:48 +0100109 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;
Ruben Brunk946ef642016-03-25 13:45:42 -0700131 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;
Polina Bondarenkoeb845522016-03-01 14:39:48 +0100138 }
Polina Bondarenkocb8ca182016-03-01 12:36:34 +0100139 }
140 }
141 jfloatArray deviceTemps = env->NewFloatArray(length);
142 env->SetFloatArrayRegion(deviceTemps, 0, length, values);
143 free(list);
144 return deviceTemps;
Polina Bondarenko965ecbb2015-11-13 15:34:28 +0100145 }
Polina Bondarenkocb8ca182016-03-01 12:36:34 +0100146 free(list);
Polina Bondarenko965ecbb2015-11-13 15:34:28 +0100147 }
Polina Bondarenkocb8ca182016-03-01 12:36:34 +0100148 ALOGE("Couldn't get device temperatures because of HAL error");
Polina Bondarenko965ecbb2015-11-13 15:34:28 +0100149 }
150 return env->NewFloatArray(0);
151}
152
153static jobjectArray nativeGetCpuUsages(JNIEnv *env, jclass /* clazz */) {
Polina Bondarenkocb8ca182016-03-01 12:36:34 +0100154 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;
Polina Bondarenko965ecbb2015-11-13 15:34:28 +0100172 }
Polina Bondarenkocb8ca182016-03-01 12:36:34 +0100173 free(list);
Polina Bondarenko965ecbb2015-11-13 15:34:28 +0100174 }
Polina Bondarenkocb8ca182016-03-01 12:36:34 +0100175 ALOGE("Couldn't get CPU usages because of HAL error");
Polina Bondarenko965ecbb2015-11-13 15:34:28 +0100176 }
177 return env->NewObjectArray(0, gCpuUsageInfoClassInfo.clazz, nullptr);
178}
179
180// ----------------------------------------------------------------------------
181
Polina Bondarenkof8754ac2016-02-12 20:38:23 +0100182static const JNINativeMethod gHardwarePropertiesManagerServiceMethods[] = {
Polina Bondarenko965ecbb2015-11-13 15:34:28 +0100183 /* name, signature, funcPtr */
184 { "nativeInit", "()V",
185 (void*) nativeInit },
186 { "nativeGetFanSpeeds", "()[F",
187 (void*) nativeGetFanSpeeds },
Polina Bondarenkoeb845522016-03-01 14:39:48 +0100188 { "nativeGetDeviceTemperatures", "(II)[F",
Polina Bondarenko965ecbb2015-11-13 15:34:28 +0100189 (void*) nativeGetDeviceTemperatures },
190 { "nativeGetCpuUsages", "()[Landroid/os/CpuUsageInfo;",
191 (void*) nativeGetCpuUsages }
192};
193
Polina Bondarenkof8754ac2016-02-12 20:38:23 +0100194int register_android_server_HardwarePropertiesManagerService(JNIEnv* env) {
Polina Bondarenkocb8ca182016-03-01 12:36:34 +0100195 gThermalModule = nullptr;
Polina Bondarenkof8754ac2016-02-12 20:38:23 +0100196 int res = jniRegisterNativeMethods(env, "com/android/server/HardwarePropertiesManagerService",
197 gHardwarePropertiesManagerServiceMethods,
198 NELEM(gHardwarePropertiesManagerServiceMethods));
Polina Bondarenko965ecbb2015-11-13 15:34:28 +0100199 jclass clazz = env->FindClass("android/os/CpuUsageInfo");
200 gCpuUsageInfoClassInfo.clazz = MakeGlobalRefOrDie(env, clazz);
201 gCpuUsageInfoClassInfo.initMethod = GetMethodIDOrDie(env, gCpuUsageInfoClassInfo.clazz,
202 "<init>", "(JJ)V");
Polina Bondarenkoeb845522016-03-01 14:39:48 +0100203
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
Polina Bondarenko965ecbb2015-11-13 15:34:28 +0100209 return res;
210}
211
212} /* namespace android */