blob: c9b4edd28bb036f419a30b7a8a296f921a766355 [file] [log] [blame]
/*
* Copyright 2016, The Android Open Source Project
*
* 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 "wifi"
#include "jni.h"
#include <ScopedUtfChars.h>
#include <utils/misc.h>
#include <android_runtime/AndroidRuntime.h>
#include <utils/Log.h>
#include <utils/String16.h>
#include "wifi.h"
#include "wifi_hal.h"
#include "jni_helper.h"
namespace android {
/* JNI Helpers for wifi_hal implementation */
JNIHelper::JNIHelper(JavaVM *vm)
{
vm->AttachCurrentThread(&mEnv, NULL);
mVM = vm;
}
JNIHelper::JNIHelper(JNIEnv *env)
{
mVM = NULL;
mEnv = env;
}
JNIHelper::~JNIHelper()
{
if (mVM != NULL) {
// mVM->DetachCurrentThread(); /* 'attempting to detach while still running code' */
mVM = NULL; /* not really required; but may help debugging */
mEnv = NULL; /* not really required; but may help debugging */
}
}
jobject JNIHelper::newGlobalRef(jobject obj) {
return mEnv->NewGlobalRef(obj);
}
void JNIHelper::deleteGlobalRef(jobject obj) {
mEnv->DeleteGlobalRef(obj);
}
jobject JNIHelper::newLocalRef(jobject obj) {
return mEnv->NewLocalRef(obj);
}
void JNIHelper::deleteLocalRef(jobject obj) {
mEnv->DeleteLocalRef(obj);
}
void JNIHelper::throwException(const char *message, int line)
{
ALOGE("error at line %d: %s", line, message);
const char *className = "java/lang/Exception";
jclass exClass = mEnv->FindClass(className );
if ( exClass == NULL ) {
ALOGE("Could not find exception class to throw error");
ALOGE("error at line %d: %s", line, message);
return;
}
mEnv->ThrowNew(exClass, message);
}
jboolean JNIHelper::getBoolField(jobject obj, const char *name)
{
JNIObject<jclass> cls(*this, mEnv->GetObjectClass(obj));
jfieldID field = mEnv->GetFieldID(cls, name, "Z");
if (field == 0) {
THROW(*this, "Error in accessing field");
return 0;
}
return mEnv->GetBooleanField(obj, field);
}
jint JNIHelper::getIntField(jobject obj, const char *name)
{
JNIObject<jclass> cls(*this, mEnv->GetObjectClass(obj));
jfieldID field = mEnv->GetFieldID(cls, name, "I");
if (field == 0) {
THROW(*this, "Error in accessing field");
return 0;
}
return mEnv->GetIntField(obj, field);
}
jbyte JNIHelper::getByteField(jobject obj, const char *name)
{
JNIObject<jclass> cls(*this, mEnv->GetObjectClass(obj));
jfieldID field = mEnv->GetFieldID(cls, name, "B");
if (field == 0) {
THROW(*this, "Error in accessing field");
return 0;
}
return mEnv->GetByteField(obj, field);
}
jlong JNIHelper::getLongField(jobject obj, const char *name)
{
JNIObject<jclass> cls(*this, mEnv->GetObjectClass(obj));
jfieldID field = mEnv->GetFieldID(cls, name, "J");
if (field == 0) {
THROW(*this, "Error in accessing field");
return 0;
}
return mEnv->GetLongField(obj, field);
}
JNIObject<jstring> JNIHelper::getStringField(jobject obj, const char *name)
{
JNIObject<jobject> m = getObjectField(obj, name, "Ljava/lang/String;");
if (m == NULL) {
THROW(*this, "Error in accessing field");
return JNIObject<jstring>(*this, NULL);
}
return JNIObject<jstring>(*this, (jstring)m.detach());
}
bool JNIHelper::getStringFieldValue(jobject obj, const char *name, char *buf, int size)
{
JNIObject<jclass> cls(*this, mEnv->GetObjectClass(obj));
jfieldID field = mEnv->GetFieldID(cls, name, "Ljava/lang/String;");
if (field == 0) {
THROW(*this, "Error in accessing field");
return 0;
}
JNIObject<jobject> value(*this, mEnv->GetObjectField(obj, field));
JNIObject<jstring> string(*this, (jstring)value.clone());
ScopedUtfChars chars(mEnv, string);
const char *utf = chars.c_str();
if (utf == NULL) {
THROW(*this, "Error in accessing value");
return false;
}
if (*utf != 0 && size < 1) {
return false;
}
strncpy(buf, utf, size);
if (size > 0) {
buf[size - 1] = 0;
}
return true;
}
jlong JNIHelper::getStaticLongField(jobject obj, const char *name)
{
JNIObject<jclass> cls(*this, mEnv->GetObjectClass(obj));
return getStaticLongField(cls, name);
}
jlong JNIHelper::getStaticLongField(jclass cls, const char *name)
{
jfieldID field = mEnv->GetStaticFieldID(cls, name, "J");
if (field == 0) {
THROW(*this, "Error in accessing field");
return 0;
}
//ALOGE("getStaticLongField %s %p", name, cls);
return mEnv->GetStaticLongField(cls, field);
}
JNIObject<jobject> JNIHelper::getObjectField(jobject obj, const char *name, const char *type)
{
JNIObject<jclass> cls(*this, mEnv->GetObjectClass(obj));
jfieldID field = mEnv->GetFieldID(cls, name, type);
if (field == 0) {
THROW(*this, "Error in accessing field");
return JNIObject<jobject>(*this, NULL);
}
return JNIObject<jobject>(*this, mEnv->GetObjectField(obj, field));
}
JNIObject<jobjectArray> JNIHelper::getArrayField(jobject obj, const char *name, const char *type)
{
JNIObject<jclass> cls(*this, mEnv->GetObjectClass(obj));
jfieldID field = mEnv->GetFieldID(cls, name, type);
if (field == 0) {
THROW(*this, "Error in accessing field");
return JNIObject<jobjectArray>(*this, NULL);
}
return JNIObject<jobjectArray>(*this, (jobjectArray)mEnv->GetObjectField(obj, field));
}
jlong JNIHelper::getLongArrayField(jobject obj, const char *name, int index)
{
JNIObject<jclass> cls(*this, mEnv->GetObjectClass(obj));
jfieldID field = mEnv->GetFieldID(cls, name, "[J");
if (field == 0) {
THROW(*this, "Error in accessing field definition");
return 0;
}
JNIObject<jlongArray> array(*this, (jlongArray)mEnv->GetObjectField(obj, field));
if (array == NULL) {
THROW(*this, "Error in accessing array");
return 0;
}
jlong *elem = mEnv->GetLongArrayElements(array, 0);
if (elem == NULL) {
THROW(*this, "Error in accessing index element");
return 0;
}
jlong value = elem[index];
mEnv->ReleaseLongArrayElements(array, elem, 0);
return value;
}
void JNIHelper::getByteArrayField(jobject obj, const char *name, byte* buf, int size) {
JNIObject<jclass> cls(*this, mEnv->GetObjectClass(obj));
jfieldID field = mEnv->GetFieldID(cls, name, "[B");
if (field == 0) {
THROW(*this, "Error in accessing field definition");
return;
}
JNIObject<jbyteArray> array(*this, (jbyteArray)mEnv->GetObjectField(obj, field));
if (array == NULL) {
THROW(*this, "Error in accessing array");
return;
}
jbyte *elem = mEnv->GetByteArrayElements(array, 0);
if (elem == NULL) {
THROW(*this, "Error in accessing index element");
return;
}
memcpy(buf, elem, size);
mEnv->ReleaseByteArrayElements(array, elem, 0);
}
jlong JNIHelper::getStaticLongArrayField(jobject obj, const char *name, int index)
{
JNIObject<jclass> cls(*this, mEnv->GetObjectClass(obj));
return getStaticLongArrayField(cls, name, index);
}
jlong JNIHelper::getStaticLongArrayField(jclass cls, const char *name, int index)
{
jfieldID field = mEnv->GetStaticFieldID(cls, name, "[J");
if (field == 0) {
THROW(*this, "Error in accessing field definition");
return 0;
}
JNIObject<jlongArray> array(*this, (jlongArray)mEnv->GetStaticObjectField(cls, field));
jlong *elem = mEnv->GetLongArrayElements(array, 0);
if (elem == NULL) {
THROW(*this, "Error in accessing index element");
return 0;
}
jlong value = elem[index];
mEnv->ReleaseLongArrayElements(array, elem, 0);
return value;
}
JNIObject<jobject> JNIHelper::getObjectArrayField(jobject obj, const char *name, const char *type,
int index)
{
JNIObject<jclass> cls(*this, mEnv->GetObjectClass(obj));
jfieldID field = mEnv->GetFieldID(cls, name, type);
if (field == 0) {
THROW(*this, "Error in accessing field definition");
return JNIObject<jobject>(*this, NULL);
}
JNIObject<jobjectArray> array(*this, (jobjectArray)mEnv->GetObjectField(obj, field));
JNIObject<jobject> elem(*this, mEnv->GetObjectArrayElement(array, index));
if (elem.isNull()) {
THROW(*this, "Error in accessing index element");
return JNIObject<jobject>(*this, NULL);
}
return elem;
}
void JNIHelper::setIntField(jobject obj, const char *name, jint value)
{
JNIObject<jclass> cls(*this, mEnv->GetObjectClass(obj));
if (cls == NULL) {
THROW(*this, "Error in accessing class");
return;
}
jfieldID field = mEnv->GetFieldID(cls, name, "I");
if (field == NULL) {
THROW(*this, "Error in accessing field");
return;
}
mEnv->SetIntField(obj, field, value);
}
void JNIHelper::setByteField(jobject obj, const char *name, jbyte value)
{
JNIObject<jclass> cls(*this, mEnv->GetObjectClass(obj));
if (cls == NULL) {
THROW(*this, "Error in accessing class");
return;
}
jfieldID field = mEnv->GetFieldID(cls, name, "B");
if (field == NULL) {
THROW(*this, "Error in accessing field");
return;
}
mEnv->SetByteField(obj, field, value);
}
void JNIHelper::setBooleanField(jobject obj, const char *name, jboolean value)
{
JNIObject<jclass> cls(*this, mEnv->GetObjectClass(obj));
if (cls == NULL) {
THROW(*this, "Error in accessing class");
return;
}
jfieldID field = mEnv->GetFieldID(cls, name, "Z");
if (field == NULL) {
THROW(*this, "Error in accessing field");
return;
}
mEnv->SetBooleanField(obj, field, value);
}
void JNIHelper::setLongField(jobject obj, const char *name, jlong value)
{
JNIObject<jclass> cls(*this, mEnv->GetObjectClass(obj));
if (cls == NULL) {
THROW(*this, "Error in accessing class");
return;
}
jfieldID field = mEnv->GetFieldID(cls, name, "J");
if (field == NULL) {
THROW(*this, "Error in accessing field");
return;
}
mEnv->SetLongField(obj, field, value);
}
void JNIHelper::setStaticLongField(jobject obj, const char *name, jlong value)
{
JNIObject<jclass> cls(*this, mEnv->GetObjectClass(obj));
if (cls == NULL) {
THROW(*this, "Error in accessing class");
return;
}
setStaticLongField(cls, name, value);
}
void JNIHelper::setStaticLongField(jclass cls, const char *name, jlong value)
{
jfieldID field = mEnv->GetStaticFieldID(cls, name, "J");
if (field == NULL) {
THROW(*this, "Error in accessing field");
return;
}
mEnv->SetStaticLongField(cls, field, value);
}
void JNIHelper::setLongArrayField(jobject obj, const char *name, jlongArray value)
{
JNIObject<jclass> cls(*this, mEnv->GetObjectClass(obj));
if (cls == NULL) {
THROW(*this, "Error in accessing field");
return;
}
jfieldID field = mEnv->GetFieldID(cls, name, "[J");
if (field == NULL) {
THROW(*this, "Error in accessing field");
return;
}
mEnv->SetObjectField(obj, field, value);
}
void JNIHelper::setStaticLongArrayField(jobject obj, const char *name, jlongArray value)
{
JNIObject<jclass> cls(*this, mEnv->GetObjectClass(obj));
if (cls == NULL) {
THROW(*this, "Error in accessing field");
return;
}
setStaticLongArrayField(cls, name, value);
}
void JNIHelper::setStaticLongArrayField(jclass cls, const char *name, jlongArray value)
{
jfieldID field = mEnv->GetStaticFieldID(cls, name, "[J");
if (field == NULL) {
THROW(*this, "Error in accessing field");
return;
}
mEnv->SetStaticObjectField(cls, field, value);
ALOGD("array field set");
}
void JNIHelper::setLongArrayElement(jobject obj, const char *name, int index, jlong value)
{
JNIObject<jclass> cls(*this, mEnv->GetObjectClass(obj));
if (cls == NULL) {
THROW(*this, "Error in accessing field");
return;
}
jfieldID field = mEnv->GetFieldID(cls, name, "[J");
if (field == NULL) {
THROW(*this, "Error in accessing field");
return;
}
JNIObject<jlongArray> array(*this, (jlongArray)mEnv->GetObjectField(obj, field));
if (array == NULL) {
THROW(*this, "Error in accessing array");
return;
}
jlong *elem = mEnv->GetLongArrayElements(array, NULL);
if (elem == NULL) {
THROW(*this, "Error in accessing index element");
return;
}
elem[index] = value;
mEnv->ReleaseLongArrayElements(array, elem, 0);
}
void JNIHelper::setObjectField(jobject obj, const char *name, const char *type, jobject value)
{
JNIObject<jclass> cls(*this, mEnv->GetObjectClass(obj));
if (cls == NULL) {
THROW(*this, "Error in accessing class");
return;
}
jfieldID field = mEnv->GetFieldID(cls, name, type);
if (field == NULL) {
THROW(*this, "Error in accessing field");
return;
}
mEnv->SetObjectField(obj, field, value);
}
jboolean JNIHelper::setStringField(jobject obj, const char *name, const char *value)
{
JNIObject<jstring> str(*this, mEnv->NewStringUTF(value));
if (mEnv->ExceptionCheck()) {
mEnv->ExceptionDescribe();
mEnv->ExceptionClear();
return false;
}
if (str == NULL) {
THROW(*this, "Error creating string");
return false;
}
setObjectField(obj, name, "Ljava/lang/String;", str);
return true;
}
void JNIHelper::reportEvent(jclass cls, const char *method, const char *signature, ...)
{
va_list params;
va_start(params, signature);
jmethodID methodID = mEnv->GetStaticMethodID(cls, method, signature);
if (methodID == 0) {
ALOGE("Error in getting method ID");
return;
}
mEnv->CallStaticVoidMethodV(cls, methodID, params);
if (mEnv->ExceptionCheck()) {
mEnv->ExceptionDescribe();
mEnv->ExceptionClear();
}
va_end(params);
}
void JNIHelper::callMethod(jobject obj, const char *method, const char *signature, ...)
{
va_list params;
va_start(params, signature);
jclass cls = mEnv->GetObjectClass(obj);
jmethodID methodID = mEnv->GetMethodID(cls, method, signature);
if (methodID == 0) {
ALOGE("Error in getting method ID");
return;
}
mEnv->CallVoidMethodV(obj, methodID, params);
if (mEnv->ExceptionCheck()) {
mEnv->ExceptionDescribe();
mEnv->ExceptionClear();
}
va_end(params);
}
jboolean JNIHelper::callStaticMethod(jclass cls, const char *method, const char *signature, ...)
{
va_list params;
va_start(params, signature);
jmethodID methodID = mEnv->GetStaticMethodID(cls, method, signature);
if (methodID == 0) {
ALOGE("Error in getting method ID");
return false;
}
jboolean result = mEnv->CallStaticBooleanMethodV(cls, methodID, params);
if (mEnv->ExceptionCheck()) {
mEnv->ExceptionDescribe();
mEnv->ExceptionClear();
return false;
}
va_end(params);
return result;
}
JNIObject<jobject> JNIHelper::createObject(const char *className) {
return createObjectWithArgs(className, "()V");
}
JNIObject<jobject> JNIHelper::createObjectWithArgs(
const char *className, const char *signature, ...)
{
va_list params;
va_start(params, signature);
JNIObject<jclass> cls(*this, mEnv->FindClass(className));
if (cls == NULL) {
ALOGE("Error in finding class %s", className);
return JNIObject<jobject>(*this, NULL);
}
jmethodID constructor = mEnv->GetMethodID(cls, "<init>", signature);
if (constructor == 0) {
ALOGE("Error in constructor ID for %s", className);
return JNIObject<jobject>(*this, NULL);
}
JNIObject<jobject> obj(*this, mEnv->NewObjectV(cls, constructor, params));
if (obj == NULL) {
ALOGE("Could not create new object of %s", className);
return JNIObject<jobject>(*this, NULL);
}
va_end(params);
return obj;
}
JNIObject<jobjectArray> JNIHelper::createObjectArray(const char *className, int num)
{
JNIObject<jclass> cls(*this, mEnv->FindClass(className));
if (cls == NULL) {
ALOGE("Error in finding class %s", className);
return JNIObject<jobjectArray>(*this, NULL);
}
JNIObject<jobject> array(*this, mEnv->NewObjectArray(num, cls.get(), NULL));
if (array.get() == NULL) {
ALOGE("Error in creating array of class %s", className);
return JNIObject<jobjectArray>(*this, NULL);
}
return JNIObject<jobjectArray>(*this, (jobjectArray)array.detach());
}
JNIObject<jobject> JNIHelper::getObjectArrayElement(jobjectArray array, int index)
{
return JNIObject<jobject>(*this, mEnv->GetObjectArrayElement(array, index));
}
JNIObject<jobject> JNIHelper::getObjectArrayElement(jobject array, int index)
{
return getObjectArrayElement((jobjectArray)array, index);
}
int JNIHelper::getArrayLength(jarray array) {
return mEnv->GetArrayLength(array);
}
JNIObject<jobjectArray> JNIHelper::newObjectArray(int num, const char *className, jobject val) {
JNIObject<jclass> cls(*this, mEnv->FindClass(className));
if (cls == NULL) {
ALOGE("Error in finding class %s", className);
return JNIObject<jobjectArray>(*this, NULL);
}
return JNIObject<jobjectArray>(*this, mEnv->NewObjectArray(num, cls, val));
}
JNIObject<jbyteArray> JNIHelper::newByteArray(int num) {
return JNIObject<jbyteArray>(*this, mEnv->NewByteArray(num));
}
JNIObject<jintArray> JNIHelper::newIntArray(int num) {
return JNIObject<jintArray>(*this, mEnv->NewIntArray(num));
}
JNIObject<jlongArray> JNIHelper::newLongArray(int num) {
return JNIObject<jlongArray>(*this, mEnv->NewLongArray(num));
}
JNIObject<jstring> JNIHelper::newStringUTF(const char *utf) {
return JNIObject<jstring>(*this, mEnv->NewStringUTF(utf));
}
void JNIHelper::setObjectArrayElement(jobjectArray array, int index, jobject obj) {
mEnv->SetObjectArrayElement(array, index, obj);
}
void JNIHelper::setByteArrayRegion(jbyteArray array, int from, int to, const jbyte *bytes) {
mEnv->SetByteArrayRegion(array, from, to, bytes);
}
void JNIHelper::setIntArrayRegion(jintArray array, int from, int to, const jint *ints) {
mEnv->SetIntArrayRegion(array, from, to, ints);
}
void JNIHelper::setLongArrayRegion(jlongArray array, int from, int to, const jlong *longs) {
mEnv->SetLongArrayRegion(array, from, to, longs);
}
}; // namespace android