• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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