[go: nahoru, domu]

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
30namespace android {
31
32// ---------------------------------------------------------------------------
33
34// 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    TEMPERATURE_THROTTLING_BELOW_VR_MIN = 3
41};
42
43static struct {
44    jclass clazz;
45    jmethodID initMethod;
46} gCpuUsageInfoClassInfo;
47
48jfloat gUndefinedTemperature;
49
50static struct thermal_module* gThermalModule;
51
52// ----------------------------------------------------------------------------
53
54static 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
61static 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
92static 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
153static 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
182static 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
194int 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