blob: ec5e8c92197978184c5384a1bde60528b40ab9df [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,
39 TEMPERATURE_SHUTDOWN = 2
40};
41
Polina Bondarenko965ecbb2015-11-13 15:34:28 +010042static struct {
43 jclass clazz;
44 jmethodID initMethod;
45} gCpuUsageInfoClassInfo;
46
Polina Bondarenkoeb845522016-03-01 14:39:48 +010047jfloat gUndefinedTemperature;
48
Polina Bondarenkocb8ca182016-03-01 12:36:34 +010049static struct thermal_module* gThermalModule;
Polina Bondarenko965ecbb2015-11-13 15:34:28 +010050
51// ----------------------------------------------------------------------------
52
53static void nativeInit(JNIEnv* env, jobject obj) {
Polina Bondarenkocb8ca182016-03-01 12:36:34 +010054 status_t err = hw_get_module(THERMAL_HARDWARE_MODULE_ID, (hw_module_t const**)&gThermalModule);
Polina Bondarenko965ecbb2015-11-13 15:34:28 +010055 if (err) {
Polina Bondarenkocb8ca182016-03-01 12:36:34 +010056 ALOGE("Couldn't load %s module (%s)", THERMAL_HARDWARE_MODULE_ID, strerror(-err));
Polina Bondarenko965ecbb2015-11-13 15:34:28 +010057 }
58}
59
60static jfloatArray nativeGetFanSpeeds(JNIEnv *env, jclass /* clazz */) {
Polina Bondarenkocb8ca182016-03-01 12:36:34 +010061 if (gThermalModule && gThermalModule->getCoolingDevices) {
62 ssize_t list_size = gThermalModule->getCoolingDevices(gThermalModule, nullptr, 0);
Polina Bondarenko965ecbb2015-11-13 15:34:28 +010063
Polina Bondarenkocb8ca182016-03-01 12:36:34 +010064 if (list_size >= 0) {
65 cooling_device_t *list = (cooling_device_t *)
66 malloc(list_size * sizeof(cooling_device_t));
67 ssize_t size = gThermalModule->getCoolingDevices(gThermalModule, list, list_size);
68 if (size >= 0) {
69 if (list_size > size) {
70 list_size = size;
71 }
72 jfloat values[list_size];
73 for (ssize_t i = 0; i < list_size; ++i) {
74 values[i] = list[i].current_value;
75 }
76
77 jfloatArray fanSpeeds = env->NewFloatArray(list_size);
78 env->SetFloatArrayRegion(fanSpeeds, 0, list_size, values);
79 free(list);
80 return fanSpeeds;
81 }
82
83 free(list);
Polina Bondarenko965ecbb2015-11-13 15:34:28 +010084 }
85
Polina Bondarenkocb8ca182016-03-01 12:36:34 +010086 ALOGE("Cloudn't get fan speeds because of HAL error");
Polina Bondarenko965ecbb2015-11-13 15:34:28 +010087 }
88 return env->NewFloatArray(0);
89}
90
Polina Bondarenkoeb845522016-03-01 14:39:48 +010091static jfloatArray nativeGetDeviceTemperatures(JNIEnv *env, jclass /* clazz */, int type,
92 int source) {
Polina Bondarenkocb8ca182016-03-01 12:36:34 +010093 if (gThermalModule && gThermalModule->getTemperatures) {
94 ssize_t list_size = gThermalModule->getTemperatures(gThermalModule, nullptr, 0);
95 if (list_size >= 0) {
96 temperature_t *list = (temperature_t *) malloc(list_size * sizeof(temperature_t));
97 ssize_t size = gThermalModule->getTemperatures(gThermalModule, list, list_size);
98 if (size >= 0) {
99 if (list_size > size) {
100 list_size = size;
101 }
102
103 jfloat values[list_size];
104 size_t length = 0;
105
106 for (ssize_t i = 0; i < list_size; ++i) {
107 if (list[i].type == type) {
Polina Bondarenkoeb845522016-03-01 14:39:48 +0100108 switch (source) {
109 case TEMPERATURE_CURRENT:
110 if (list[i].current_value == UNKNOWN_TEMPERATURE) {
111 values[length++] = gUndefinedTemperature;
112 } else {
113 values[length++] = list[i].current_value;
114 }
115 break;
116 case TEMPERATURE_THROTTLING:
117 if (list[i].throttling_threshold == UNKNOWN_TEMPERATURE) {
118 values[length++] = gUndefinedTemperature;
119 } else {
120 values[length++] = list[i].throttling_threshold;
121 }
122 break;
123 case TEMPERATURE_SHUTDOWN:
124 if (list[i].shutdown_threshold == UNKNOWN_TEMPERATURE) {
125 values[length++] = gUndefinedTemperature;
126 } else {
127 values[length++] = list[i].shutdown_threshold;
128 }
129 break;
130 }
Polina Bondarenkocb8ca182016-03-01 12:36:34 +0100131 }
132 }
133 jfloatArray deviceTemps = env->NewFloatArray(length);
134 env->SetFloatArrayRegion(deviceTemps, 0, length, values);
135 free(list);
136 return deviceTemps;
Polina Bondarenko965ecbb2015-11-13 15:34:28 +0100137 }
Polina Bondarenkocb8ca182016-03-01 12:36:34 +0100138 free(list);
Polina Bondarenko965ecbb2015-11-13 15:34:28 +0100139 }
Polina Bondarenkocb8ca182016-03-01 12:36:34 +0100140 ALOGE("Couldn't get device temperatures because of HAL error");
Polina Bondarenko965ecbb2015-11-13 15:34:28 +0100141 }
142 return env->NewFloatArray(0);
143}
144
145static jobjectArray nativeGetCpuUsages(JNIEnv *env, jclass /* clazz */) {
Polina Bondarenkocb8ca182016-03-01 12:36:34 +0100146 if (gThermalModule && gThermalModule->getCpuUsages
147 && gCpuUsageInfoClassInfo.initMethod) {
148 ssize_t size = gThermalModule->getCpuUsages(gThermalModule, nullptr);
149 if (size >= 0) {
150 cpu_usage_t *list = (cpu_usage_t *) malloc(size * sizeof(cpu_usage_t));
151 size = gThermalModule->getCpuUsages(gThermalModule, list);
152 if (size >= 0) {
153 jobjectArray cpuUsages = env->NewObjectArray(size, gCpuUsageInfoClassInfo.clazz,
154 nullptr);
155 for (ssize_t i = 0; i < size; ++i) {
156 if (list[i].is_online) {
157 jobject cpuUsage = env->NewObject(gCpuUsageInfoClassInfo.clazz,
158 gCpuUsageInfoClassInfo.initMethod, list[i].active, list[i].total);
159 env->SetObjectArrayElement(cpuUsages, i, cpuUsage);
160 }
161 }
162 free(list);
163 return cpuUsages;
Polina Bondarenko965ecbb2015-11-13 15:34:28 +0100164 }
Polina Bondarenkocb8ca182016-03-01 12:36:34 +0100165 free(list);
Polina Bondarenko965ecbb2015-11-13 15:34:28 +0100166 }
Polina Bondarenkocb8ca182016-03-01 12:36:34 +0100167 ALOGE("Couldn't get CPU usages because of HAL error");
Polina Bondarenko965ecbb2015-11-13 15:34:28 +0100168 }
169 return env->NewObjectArray(0, gCpuUsageInfoClassInfo.clazz, nullptr);
170}
171
172// ----------------------------------------------------------------------------
173
Polina Bondarenkof8754ac2016-02-12 20:38:23 +0100174static const JNINativeMethod gHardwarePropertiesManagerServiceMethods[] = {
Polina Bondarenko965ecbb2015-11-13 15:34:28 +0100175 /* name, signature, funcPtr */
176 { "nativeInit", "()V",
177 (void*) nativeInit },
178 { "nativeGetFanSpeeds", "()[F",
179 (void*) nativeGetFanSpeeds },
Polina Bondarenkoeb845522016-03-01 14:39:48 +0100180 { "nativeGetDeviceTemperatures", "(II)[F",
Polina Bondarenko965ecbb2015-11-13 15:34:28 +0100181 (void*) nativeGetDeviceTemperatures },
182 { "nativeGetCpuUsages", "()[Landroid/os/CpuUsageInfo;",
183 (void*) nativeGetCpuUsages }
184};
185
Polina Bondarenkof8754ac2016-02-12 20:38:23 +0100186int register_android_server_HardwarePropertiesManagerService(JNIEnv* env) {
Polina Bondarenkocb8ca182016-03-01 12:36:34 +0100187 gThermalModule = nullptr;
Polina Bondarenkof8754ac2016-02-12 20:38:23 +0100188 int res = jniRegisterNativeMethods(env, "com/android/server/HardwarePropertiesManagerService",
189 gHardwarePropertiesManagerServiceMethods,
190 NELEM(gHardwarePropertiesManagerServiceMethods));
Polina Bondarenko965ecbb2015-11-13 15:34:28 +0100191 jclass clazz = env->FindClass("android/os/CpuUsageInfo");
192 gCpuUsageInfoClassInfo.clazz = MakeGlobalRefOrDie(env, clazz);
193 gCpuUsageInfoClassInfo.initMethod = GetMethodIDOrDie(env, gCpuUsageInfoClassInfo.clazz,
194 "<init>", "(JJ)V");
Polina Bondarenkoeb845522016-03-01 14:39:48 +0100195
196 clazz = env->FindClass("android/os/HardwarePropertiesManager");
197 jfieldID undefined_temperature_field = GetStaticFieldIDOrDie(env, clazz,
198 "UNDEFINED_TEMPERATURE", "F");
199 gUndefinedTemperature = env->GetStaticFloatField(clazz, undefined_temperature_field);
200
Polina Bondarenko965ecbb2015-11-13 15:34:28 +0100201 return res;
202}
203
204} /* namespace android */