302 lines
7.8 KiB
C++
302 lines
7.8 KiB
C++
/*
|
|
* Copyright (C) 2014 Intel Corporation
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#define LOG_TAG "ThermalManagerJNI"
|
|
|
|
#include "JNIHelp.h"
|
|
#include "jni.h"
|
|
#include <utils/Log.h>
|
|
#include <utils/misc.h>
|
|
|
|
#include <fcntl.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <sys/types.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
|
|
namespace android {
|
|
|
|
#define THERMAL_ZONE_PATH "/sys/class/thermal/thermal_zone"
|
|
#define COOLING_DEV_PATH "/sys/class/thermal/cooling_device"
|
|
|
|
static int readFromFile(const char *path, char* buf, size_t size, bool throwError)
|
|
{
|
|
if (!path)
|
|
return -1;
|
|
|
|
int fd = open(path, O_RDONLY, 0);
|
|
if (fd < 0) {
|
|
if (throwError) {
|
|
ALOGE("Could not open '%s'", path);
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
ssize_t count = read(fd, buf, size);
|
|
if (count > 0) {
|
|
while (count > 0 && buf[count-1] == '\n')
|
|
count--;
|
|
buf[count] = '\0';
|
|
} else {
|
|
buf[0] = '\0';
|
|
}
|
|
|
|
close(fd);
|
|
return count;
|
|
}
|
|
|
|
static int writeToFile(const char *path, int val)
|
|
{
|
|
const int SIZE = 20;
|
|
int ret, fd, len;
|
|
char value[SIZE];
|
|
|
|
if (!path)
|
|
return -1;
|
|
|
|
fd = open(path, O_WRONLY, 0);
|
|
if (fd < 0) {
|
|
ALOGE("writeToFile: Could not open '%s' err: %d", path, errno);
|
|
return -1;
|
|
}
|
|
|
|
len = snprintf(value, SIZE, "%d\n", val);
|
|
ret = write(fd, value, len);
|
|
|
|
close(fd);
|
|
return (ret == len) ? 0 : -1;
|
|
}
|
|
|
|
static int lookup(const char *base_path, const char *name)
|
|
{
|
|
const int SIZE = 128;
|
|
char buf[SIZE];
|
|
char full_path[SIZE];
|
|
int count = 0;
|
|
|
|
do {
|
|
snprintf(full_path, SIZE, "%s%d/type", base_path, count);
|
|
// Loop through all thermal_zones or cooling_devices until we
|
|
// find a first match. We call it a match when the given
|
|
// 'name' of the thermal_zone (or a cooling_device) matches
|
|
// with the value of 'type' sysfs interface of a thermal_zone
|
|
// (or cooling_device).
|
|
if (readFromFile(full_path, buf, SIZE, false) < 0) break;
|
|
|
|
if (!strcmp(name, buf)) return count;
|
|
|
|
count++;
|
|
} while(1);
|
|
|
|
// lookup failed.
|
|
return -1;
|
|
}
|
|
|
|
static int lookup_contains(const char *base_path, const char *name)
|
|
{
|
|
const int SIZE = 128;
|
|
char buf[SIZE];
|
|
char full_path[SIZE];
|
|
int count = 0;
|
|
|
|
do {
|
|
snprintf(full_path, SIZE, "%s%d/type", base_path, count);
|
|
if (readFromFile(full_path, buf, SIZE, false) < 0) break;
|
|
// Check if 'buf' contains 'name'
|
|
if (strstr(buf, name) != NULL) return count;
|
|
|
|
count++;
|
|
} while(1);
|
|
|
|
// lookup failed.
|
|
return -1;
|
|
}
|
|
|
|
static jboolean isFileExists(JNIEnv* env, jobject obj, jstring jPath)
|
|
{
|
|
const char *path = NULL;
|
|
jboolean ret = true;
|
|
|
|
path = jPath ? env->GetStringUTFChars(jPath, NULL) : NULL;
|
|
if (!path) {
|
|
return false;
|
|
}
|
|
|
|
int fd = open(path, O_RDONLY, 0);
|
|
|
|
if (fd < 0) {
|
|
ret = false;
|
|
} else {
|
|
close(fd);
|
|
}
|
|
env->ReleaseStringUTFChars(jPath, path);
|
|
return ret;
|
|
}
|
|
|
|
static jint getThermalZoneIndex(JNIEnv* env, jobject obj, jstring jType)
|
|
{
|
|
int ret;
|
|
const char *type = NULL;
|
|
|
|
type = jType ? env->GetStringUTFChars(jType, NULL) : NULL;
|
|
if (!type) {
|
|
jniThrowNullPointerException(env, "Type");
|
|
return -1;
|
|
}
|
|
|
|
ret = lookup(THERMAL_ZONE_PATH, type);
|
|
env->ReleaseStringUTFChars(jType, type);
|
|
return ret;
|
|
}
|
|
|
|
static jint getThermalZoneIndexContains(JNIEnv* env, jobject obj, jstring jType)
|
|
{
|
|
int ret;
|
|
const char *type = NULL;
|
|
|
|
type = jType ? env->GetStringUTFChars(jType, NULL) : NULL;
|
|
if (!type) {
|
|
jniThrowNullPointerException(env, "Type");
|
|
return -1;
|
|
}
|
|
|
|
ret = lookup_contains(THERMAL_ZONE_PATH, type);
|
|
env->ReleaseStringUTFChars(jType, type);
|
|
return ret;
|
|
}
|
|
|
|
static jint getCoolingDeviceIndex(JNIEnv* env, jobject obj, jstring jType)
|
|
{
|
|
int ret;
|
|
const char *type = NULL;
|
|
|
|
type = jType ? env->GetStringUTFChars(jType, NULL) : NULL;
|
|
if (!type) {
|
|
jniThrowNullPointerException(env, "Type");
|
|
return -1;
|
|
}
|
|
|
|
ret = lookup(COOLING_DEV_PATH, type);
|
|
env->ReleaseStringUTFChars(jType, type);
|
|
return ret;
|
|
}
|
|
|
|
static jint getCoolingDeviceIndexContains(JNIEnv* env, jobject obj, jstring jType)
|
|
{
|
|
int ret;
|
|
const char *type = NULL;
|
|
|
|
type = jType ? env->GetStringUTFChars(jType, NULL) : NULL;
|
|
if (!type) {
|
|
jniThrowNullPointerException(env, "Type");
|
|
return -1;
|
|
}
|
|
|
|
ret = lookup_contains(COOLING_DEV_PATH, type);
|
|
env->ReleaseStringUTFChars(jType, type);
|
|
return ret;
|
|
}
|
|
|
|
static jint writeSysfs(JNIEnv* env, jobject obj, jstring jPath, jint jVal)
|
|
{
|
|
int ret;
|
|
const char *path = NULL;
|
|
|
|
path = jPath ? env->GetStringUTFChars(jPath, NULL) : NULL;
|
|
if (!path) {
|
|
jniThrowNullPointerException(env, "path");
|
|
return -EINVAL;
|
|
}
|
|
|
|
ret = writeToFile(path, jVal);
|
|
env->ReleaseStringUTFChars(jPath, path);
|
|
return ret;
|
|
}
|
|
|
|
static jstring readSysfs(JNIEnv* env, jobject obj, jstring jPath)
|
|
{
|
|
const char *path = NULL;
|
|
const int SIZE = 512;
|
|
char buf[SIZE];
|
|
|
|
path = jPath ? env->GetStringUTFChars(jPath, NULL) : NULL;
|
|
if (!path) {
|
|
jniThrowNullPointerException(env, "path");
|
|
return NULL;
|
|
}
|
|
|
|
if (readFromFile(path, buf, SIZE, true) > 0) {
|
|
env->ReleaseStringUTFChars(jPath, path);
|
|
return env->NewStringUTF(buf);
|
|
} else {
|
|
env->ReleaseStringUTFChars(jPath, path);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
static jint readSysfsTemp(JNIEnv* env, jobject obj, jstring jPath)
|
|
{
|
|
const char *path = NULL;
|
|
const int SIZE = 64;
|
|
char buf[SIZE];
|
|
// Convention: To allow returning of normal negative temperatures
|
|
// (say -10C), let us return errno as a negative offset from
|
|
// absolute zero millidegree C.
|
|
const int ABS_ZERO = -273000;
|
|
int ret;
|
|
|
|
path = jPath ? env->GetStringUTFChars(jPath, NULL) : NULL;
|
|
if (!path) {
|
|
jniThrowNullPointerException(env, "path");
|
|
return (ABS_ZERO - ENOENT);
|
|
}
|
|
|
|
ret = readFromFile(path, buf, SIZE, true);
|
|
env->ReleaseStringUTFChars(jPath, path);
|
|
if (ret > 0) {
|
|
return atoi(buf);
|
|
}
|
|
return (ret + ABS_ZERO);
|
|
}
|
|
|
|
static JNINativeMethod sMethods[] = {
|
|
/* name, signature, funcPtr */
|
|
{"native_readSysfs", "(Ljava/lang/String;)Ljava/lang/String;", (void*)readSysfs},
|
|
{"native_readSysfsTemp", "(Ljava/lang/String;)I", (void*)readSysfsTemp},
|
|
{"native_writeSysfs", "(Ljava/lang/String;I)I", (void*)writeSysfs},
|
|
{"native_getThermalZoneIndex", "(Ljava/lang/String;)I", (void*)getThermalZoneIndex},
|
|
{"native_getThermalZoneIndexContains", "(Ljava/lang/String;)I",
|
|
(void*)getThermalZoneIndexContains},
|
|
{"native_getCoolingDeviceIndex", "(Ljava/lang/String;)I", (void*)getCoolingDeviceIndex},
|
|
{"native_getCoolingDeviceIndexContains", "(Ljava/lang/String;)I",
|
|
(void*)getCoolingDeviceIndexContains},
|
|
{"native_isFileExists", "(Ljava/lang/String;)Z", (void*)isFileExists},
|
|
};
|
|
|
|
int register_intel_thermal_ituxd(JNIEnv* env)
|
|
{
|
|
jclass clazz = env->FindClass("com/intel/thermal/ThermalUtils");
|
|
if (clazz == NULL) {
|
|
ALOGE("Can't find com/intel/thermal/ThermalUtils");
|
|
return -1;
|
|
}
|
|
|
|
return jniRegisterNativeMethods(env, "com/intel/thermal/ThermalUtils",
|
|
sMethods, NELEM(sMethods));
|
|
}
|
|
|
|
} /* namespace android */
|