• 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 <math.h>
23 #include <stdlib.h>
24 
25 #include <android/hardware/thermal/1.0/IThermal.h>
26 #include <utils/Log.h>
27 #include <utils/String8.h>
28 
29 #include "core_jni_helpers.h"
30 
31 namespace android {
32 
33 using hardware::hidl_vec;
34 using hardware::thermal::V1_0::CoolingDevice;
35 using hardware::thermal::V1_0::CpuUsage;
36 using hardware::thermal::V1_0::IThermal;
37 using hardware::thermal::V1_0::Temperature;
38 using hardware::thermal::V1_0::ThermalStatus;
39 using hardware::thermal::V1_0::ThermalStatusCode;
40 template<typename T>
41 using Return = hardware::Return<T>;
42 
43 // ---------------------------------------------------------------------------
44 
45 // These values must be kept in sync with the temperature source constants in
46 // HardwarePropertiesManager.java
47 enum {
48     TEMPERATURE_CURRENT = 0,
49     TEMPERATURE_THROTTLING = 1,
50     TEMPERATURE_SHUTDOWN = 2,
51     TEMPERATURE_THROTTLING_BELOW_VR_MIN = 3
52 };
53 
54 static struct {
55     jclass clazz;
56     jmethodID initMethod;
57 } gCpuUsageInfoClassInfo;
58 
59 jfloat gUndefinedTemperature;
60 
61 static sp<IThermal> gThermalModule;
62 
63 // ----------------------------------------------------------------------------
64 
finalizeTemperature(float temperature)65 float finalizeTemperature(float temperature) {
66     return isnan(temperature) ? gUndefinedTemperature : temperature;
67 }
68 
nativeInit(JNIEnv * env,jobject obj)69 static void nativeInit(JNIEnv* env, jobject obj) {
70     // TODO(b/31632518)
71     if (gThermalModule == nullptr) {
72         gThermalModule = IThermal::getService();
73     }
74 
75     if (gThermalModule == nullptr) {
76         ALOGE("Unable to get Thermal service.");
77     }
78 }
79 
nativeGetFanSpeeds(JNIEnv * env,jclass)80 static jfloatArray nativeGetFanSpeeds(JNIEnv *env, jclass /* clazz */) {
81     if (gThermalModule == nullptr) {
82         ALOGE("Couldn't get fan speeds because of HAL error.");
83         return env->NewFloatArray(0);
84     }
85 
86     hidl_vec<CoolingDevice> list;
87     Return<void> ret = gThermalModule->getCoolingDevices(
88             [&list](ThermalStatus status, hidl_vec<CoolingDevice> devices) {
89                 if (status.code == ThermalStatusCode::SUCCESS) {
90                     list = std::move(devices);
91                 } else {
92                     ALOGE("Couldn't get fan speeds because of HAL error: %s",
93                           status.debugMessage.c_str());
94                 }
95             });
96 
97     if (!ret.isOk()) {
98         ALOGE("getCoolingDevices failed status: %s", ret.description().c_str());
99     }
100 
101     float values[list.size()];
102     for (size_t i = 0; i < list.size(); ++i) {
103         values[i] = list[i].currentValue;
104     }
105     jfloatArray fanSpeeds = env->NewFloatArray(list.size());
106     env->SetFloatArrayRegion(fanSpeeds, 0, list.size(), values);
107     return fanSpeeds;
108 }
109 
nativeGetDeviceTemperatures(JNIEnv * env,jclass,int type,int source)110 static jfloatArray nativeGetDeviceTemperatures(JNIEnv *env, jclass /* clazz */, int type,
111                                                int source) {
112     if (gThermalModule == nullptr) {
113         ALOGE("Couldn't get device temperatures because of HAL error.");
114         return env->NewFloatArray(0);
115     }
116     hidl_vec<Temperature> list;
117     Return<void> ret = gThermalModule->getTemperatures(
118             [&list](ThermalStatus status, hidl_vec<Temperature> temperatures) {
119                 if (status.code == ThermalStatusCode::SUCCESS) {
120                     list = std::move(temperatures);
121                 } else {
122                     ALOGE("Couldn't get temperatures because of HAL error: %s",
123                           status.debugMessage.c_str());
124                 }
125             });
126 
127     if (!ret.isOk()) {
128         ALOGE("getDeviceTemperatures failed status: %s", ret.description().c_str());
129     }
130 
131     jfloat values[list.size()];
132     size_t length = 0;
133     for (size_t i = 0; i < list.size(); ++i) {
134         if (static_cast<int>(list[i].type) == type) {
135             switch (source) {
136                 case TEMPERATURE_CURRENT:
137                     values[length++] = finalizeTemperature(list[i].currentValue);
138                     break;
139                 case TEMPERATURE_THROTTLING:
140                     values[length++] = finalizeTemperature(list[i].throttlingThreshold);
141                     break;
142                 case TEMPERATURE_SHUTDOWN:
143                     values[length++] = finalizeTemperature(list[i].shutdownThreshold);
144                     break;
145                 case TEMPERATURE_THROTTLING_BELOW_VR_MIN:
146                     values[length++] = finalizeTemperature(list[i].vrThrottlingThreshold);
147                     break;
148             }
149         }
150     }
151     jfloatArray deviceTemps = env->NewFloatArray(length);
152     env->SetFloatArrayRegion(deviceTemps, 0, length, values);
153     return deviceTemps;
154 }
155 
nativeGetCpuUsages(JNIEnv * env,jclass)156 static jobjectArray nativeGetCpuUsages(JNIEnv *env, jclass /* clazz */) {
157     if (gThermalModule == nullptr || !gCpuUsageInfoClassInfo.initMethod) {
158         ALOGE("Couldn't get CPU usages because of HAL error.");
159         return env->NewObjectArray(0, gCpuUsageInfoClassInfo.clazz, nullptr);
160     }
161     hidl_vec<CpuUsage> list;
162     Return<void> ret = gThermalModule->getCpuUsages(
163             [&list](ThermalStatus status, hidl_vec<CpuUsage> cpuUsages) {
164                 if (status.code == ThermalStatusCode::SUCCESS) {
165                     list = std::move(cpuUsages);
166                 } else {
167                     ALOGE("Couldn't get CPU usages because of HAL error: %s",
168                           status.debugMessage.c_str());
169                 }
170             });
171 
172     if (!ret.isOk()) {
173         ALOGE("getCpuUsages failed status: %s", ret.description().c_str());
174     }
175 
176     jobjectArray cpuUsages = env->NewObjectArray(list.size(), gCpuUsageInfoClassInfo.clazz,
177                                                  nullptr);
178     for (size_t i = 0; i < list.size(); ++i) {
179         if (list[i].isOnline) {
180             jobject cpuUsage = env->NewObject(gCpuUsageInfoClassInfo.clazz,
181                                               gCpuUsageInfoClassInfo.initMethod,
182                                               list[i].active,
183                                               list[i].total);
184             env->SetObjectArrayElement(cpuUsages, i, cpuUsage);
185         }
186     }
187     return cpuUsages;
188 }
189 
190 // ----------------------------------------------------------------------------
191 
192 static const JNINativeMethod gHardwarePropertiesManagerServiceMethods[] = {
193     /* name, signature, funcPtr */
194     { "nativeInit", "()V",
195             (void*) nativeInit },
196     { "nativeGetFanSpeeds", "()[F",
197             (void*) nativeGetFanSpeeds },
198     { "nativeGetDeviceTemperatures", "(II)[F",
199             (void*) nativeGetDeviceTemperatures },
200     { "nativeGetCpuUsages", "()[Landroid/os/CpuUsageInfo;",
201             (void*) nativeGetCpuUsages }
202 };
203 
register_android_server_HardwarePropertiesManagerService(JNIEnv * env)204 int register_android_server_HardwarePropertiesManagerService(JNIEnv* env) {
205     gThermalModule = nullptr;
206     int res = jniRegisterNativeMethods(env, "com/android/server/HardwarePropertiesManagerService",
207                                        gHardwarePropertiesManagerServiceMethods,
208                                        NELEM(gHardwarePropertiesManagerServiceMethods));
209     jclass clazz = env->FindClass("android/os/CpuUsageInfo");
210     gCpuUsageInfoClassInfo.clazz = MakeGlobalRefOrDie(env, clazz);
211     gCpuUsageInfoClassInfo.initMethod = GetMethodIDOrDie(env, gCpuUsageInfoClassInfo.clazz,
212                                                          "<init>", "(JJ)V");
213 
214     clazz = env->FindClass("android/os/HardwarePropertiesManager");
215     jfieldID undefined_temperature_field = GetStaticFieldIDOrDie(env, clazz,
216                                                                  "UNDEFINED_TEMPERATURE", "F");
217     gUndefinedTemperature = env->GetStaticFloatField(clazz, undefined_temperature_field);
218 
219     return res;
220 }
221 
222 } /* namespace android */
223