C++程序  |  303行  |  7.79 KB

/*
 * 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 */