1 /*
2 * Copyright 2008, 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 "wifi"
18
19 #include "jni.h"
20 #include <ScopedUtfChars.h>
21 #include <utils/misc.h>
22 #include <android_runtime/AndroidRuntime.h>
23 #include <utils/Log.h>
24 #include <utils/String16.h>
25
26 #include "wifi.h"
27 #include "wifi_hal.h"
28 #include "jni_helper.h"
29
30 namespace android {
31
32 /* JNI Helpers for wifi_hal implementation */
33
JNIHelper(JavaVM * vm)34 JNIHelper::JNIHelper(JavaVM *vm)
35 {
36 vm->AttachCurrentThread(&mEnv, NULL);
37 mVM = vm;
38 }
39
JNIHelper(JNIEnv * env)40 JNIHelper::JNIHelper(JNIEnv *env)
41 {
42 mVM = NULL;
43 mEnv = env;
44 }
45
~JNIHelper()46 JNIHelper::~JNIHelper()
47 {
48 if (mVM != NULL) {
49 // mVM->DetachCurrentThread(); /* 'attempting to detach while still running code' */
50 mVM = NULL; /* not really required; but may help debugging */
51 mEnv = NULL; /* not really required; but may help debugging */
52 }
53 }
54
newGlobalRef(jobject obj)55 jobject JNIHelper::newGlobalRef(jobject obj) {
56 return mEnv->NewGlobalRef(obj);
57 }
58
deleteGlobalRef(jobject obj)59 void JNIHelper::deleteGlobalRef(jobject obj) {
60 mEnv->DeleteGlobalRef(obj);
61 }
62
newLocalRef(jobject obj)63 jobject JNIHelper::newLocalRef(jobject obj) {
64 return mEnv->NewLocalRef(obj);
65 }
66
deleteLocalRef(jobject obj)67 void JNIHelper::deleteLocalRef(jobject obj) {
68 mEnv->DeleteLocalRef(obj);
69 }
70
throwException(const char * message,int line)71 void JNIHelper::throwException(const char *message, int line)
72 {
73 ALOGE("error at line %d: %s", line, message);
74
75 const char *className = "java/lang/Exception";
76
77 jclass exClass = mEnv->FindClass(className );
78 if ( exClass == NULL ) {
79 ALOGE("Could not find exception class to throw error");
80 ALOGE("error at line %d: %s", line, message);
81 return;
82 }
83
84 mEnv->ThrowNew(exClass, message);
85 }
86
getBoolField(jobject obj,const char * name)87 jboolean JNIHelper::getBoolField(jobject obj, const char *name)
88 {
89 JNIObject<jclass> cls(*this, mEnv->GetObjectClass(obj));
90 jfieldID field = mEnv->GetFieldID(cls, name, "Z");
91 if (field == 0) {
92 THROW(*this, "Error in accessing field");
93 return 0;
94 }
95
96 return mEnv->GetBooleanField(obj, field);
97 }
98
getIntField(jobject obj,const char * name)99 jint JNIHelper::getIntField(jobject obj, const char *name)
100 {
101 JNIObject<jclass> cls(*this, mEnv->GetObjectClass(obj));
102 jfieldID field = mEnv->GetFieldID(cls, name, "I");
103 if (field == 0) {
104 THROW(*this, "Error in accessing field");
105 return 0;
106 }
107
108 return mEnv->GetIntField(obj, field);
109 }
110
getByteField(jobject obj,const char * name)111 jbyte JNIHelper::getByteField(jobject obj, const char *name)
112 {
113 JNIObject<jclass> cls(*this, mEnv->GetObjectClass(obj));
114 jfieldID field = mEnv->GetFieldID(cls, name, "B");
115 if (field == 0) {
116 THROW(*this, "Error in accessing field");
117 return 0;
118 }
119
120 return mEnv->GetByteField(obj, field);
121 }
122
getLongField(jobject obj,const char * name)123 jlong JNIHelper::getLongField(jobject obj, const char *name)
124 {
125 JNIObject<jclass> cls(*this, mEnv->GetObjectClass(obj));
126 jfieldID field = mEnv->GetFieldID(cls, name, "J");
127 if (field == 0) {
128 THROW(*this, "Error in accessing field");
129 return 0;
130 }
131
132 return mEnv->GetLongField(obj, field);
133 }
134
getStringField(jobject obj,const char * name)135 JNIObject<jstring> JNIHelper::getStringField(jobject obj, const char *name)
136 {
137 JNIObject<jobject> m = getObjectField(obj, name, "Ljava/lang/String;");
138 if (m == NULL) {
139 THROW(*this, "Error in accessing field");
140 return JNIObject<jstring>(*this, NULL);
141 }
142
143 return JNIObject<jstring>(*this, (jstring)m.detach());
144 }
145
getStringFieldValue(jobject obj,const char * name,char * buf,int size)146 bool JNIHelper::getStringFieldValue(jobject obj, const char *name, char *buf, int size)
147 {
148 JNIObject<jclass> cls(*this, mEnv->GetObjectClass(obj));
149 jfieldID field = mEnv->GetFieldID(cls, name, "Ljava/lang/String;");
150 if (field == 0) {
151 THROW(*this, "Error in accessing field");
152 return 0;
153 }
154
155 JNIObject<jobject> value(*this, mEnv->GetObjectField(obj, field));
156 JNIObject<jstring> string(*this, (jstring)value.clone());
157 ScopedUtfChars chars(mEnv, string);
158
159 const char *utf = chars.c_str();
160 if (utf == NULL) {
161 THROW(*this, "Error in accessing value");
162 return false;
163 }
164
165 if (*utf != 0 && size < 1) {
166 return false;
167 }
168
169 strncpy(buf, utf, size);
170 if (size > 0) {
171 buf[size - 1] = 0;
172 }
173
174 return true;
175 }
176
getStaticLongField(jobject obj,const char * name)177 jlong JNIHelper::getStaticLongField(jobject obj, const char *name)
178 {
179 JNIObject<jclass> cls(*this, mEnv->GetObjectClass(obj));
180 return getStaticLongField(cls, name);
181 }
182
getStaticLongField(jclass cls,const char * name)183 jlong JNIHelper::getStaticLongField(jclass cls, const char *name)
184 {
185 jfieldID field = mEnv->GetStaticFieldID(cls, name, "J");
186 if (field == 0) {
187 THROW(*this, "Error in accessing field");
188 return 0;
189 }
190 //ALOGE("getStaticLongField %s %p", name, cls);
191 return mEnv->GetStaticLongField(cls, field);
192 }
193
getObjectField(jobject obj,const char * name,const char * type)194 JNIObject<jobject> JNIHelper::getObjectField(jobject obj, const char *name, const char *type)
195 {
196 JNIObject<jclass> cls(*this, mEnv->GetObjectClass(obj));
197 jfieldID field = mEnv->GetFieldID(cls, name, type);
198 if (field == 0) {
199 THROW(*this, "Error in accessing field");
200 return JNIObject<jobject>(*this, NULL);
201 }
202
203 return JNIObject<jobject>(*this, mEnv->GetObjectField(obj, field));
204 }
205
getArrayField(jobject obj,const char * name,const char * type)206 JNIObject<jobjectArray> JNIHelper::getArrayField(jobject obj, const char *name, const char *type)
207 {
208 JNIObject<jclass> cls(*this, mEnv->GetObjectClass(obj));
209 jfieldID field = mEnv->GetFieldID(cls, name, type);
210 if (field == 0) {
211 THROW(*this, "Error in accessing field");
212 return JNIObject<jobjectArray>(*this, NULL);
213 }
214
215 return JNIObject<jobjectArray>(*this, (jobjectArray)mEnv->GetObjectField(obj, field));
216 }
217
getLongArrayField(jobject obj,const char * name,int index)218 jlong JNIHelper::getLongArrayField(jobject obj, const char *name, int index)
219 {
220 JNIObject<jclass> cls(*this, mEnv->GetObjectClass(obj));
221 jfieldID field = mEnv->GetFieldID(cls, name, "[J");
222 if (field == 0) {
223 THROW(*this, "Error in accessing field definition");
224 return 0;
225 }
226
227 JNIObject<jlongArray> array(*this, (jlongArray)mEnv->GetObjectField(obj, field));
228 if (array == NULL) {
229 THROW(*this, "Error in accessing array");
230 return 0;
231 }
232
233 jlong *elem = mEnv->GetLongArrayElements(array, 0);
234 if (elem == NULL) {
235 THROW(*this, "Error in accessing index element");
236 return 0;
237 }
238
239 jlong value = elem[index];
240 mEnv->ReleaseLongArrayElements(array, elem, 0);
241 return value;
242 }
243
getStaticLongArrayField(jobject obj,const char * name,int index)244 jlong JNIHelper::getStaticLongArrayField(jobject obj, const char *name, int index)
245 {
246 JNIObject<jclass> cls(*this, mEnv->GetObjectClass(obj));
247 return getStaticLongArrayField(cls, name, index);
248 }
249
getStaticLongArrayField(jclass cls,const char * name,int index)250 jlong JNIHelper::getStaticLongArrayField(jclass cls, const char *name, int index)
251 {
252 jfieldID field = mEnv->GetStaticFieldID(cls, name, "[J");
253 if (field == 0) {
254 THROW(*this, "Error in accessing field definition");
255 return 0;
256 }
257
258 JNIObject<jlongArray> array(*this, (jlongArray)mEnv->GetStaticObjectField(cls, field));
259 jlong *elem = mEnv->GetLongArrayElements(array, 0);
260 if (elem == NULL) {
261 THROW(*this, "Error in accessing index element");
262 return 0;
263 }
264
265 jlong value = elem[index];
266 mEnv->ReleaseLongArrayElements(array, elem, 0);
267 return value;
268 }
269
getObjectArrayField(jobject obj,const char * name,const char * type,int index)270 JNIObject<jobject> JNIHelper::getObjectArrayField(jobject obj, const char *name, const char *type,
271 int index)
272 {
273 JNIObject<jclass> cls(*this, mEnv->GetObjectClass(obj));
274 jfieldID field = mEnv->GetFieldID(cls, name, type);
275 if (field == 0) {
276 THROW(*this, "Error in accessing field definition");
277 return JNIObject<jobject>(*this, NULL);
278 }
279
280 JNIObject<jobjectArray> array(*this, (jobjectArray)mEnv->GetObjectField(obj, field));
281 JNIObject<jobject> elem(*this, mEnv->GetObjectArrayElement(array, index));
282 if (elem.isNull()) {
283 THROW(*this, "Error in accessing index element");
284 return JNIObject<jobject>(*this, NULL);
285 }
286 return elem;
287 }
288
setIntField(jobject obj,const char * name,jint value)289 void JNIHelper::setIntField(jobject obj, const char *name, jint value)
290 {
291 JNIObject<jclass> cls(*this, mEnv->GetObjectClass(obj));
292 if (cls == NULL) {
293 THROW(*this, "Error in accessing class");
294 return;
295 }
296
297 jfieldID field = mEnv->GetFieldID(cls, name, "I");
298 if (field == NULL) {
299 THROW(*this, "Error in accessing field");
300 return;
301 }
302
303 mEnv->SetIntField(obj, field, value);
304 }
305
setByteField(jobject obj,const char * name,jbyte value)306 void JNIHelper::setByteField(jobject obj, const char *name, jbyte value)
307 {
308 JNIObject<jclass> cls(*this, mEnv->GetObjectClass(obj));
309 if (cls == NULL) {
310 THROW(*this, "Error in accessing class");
311 return;
312 }
313
314 jfieldID field = mEnv->GetFieldID(cls, name, "B");
315 if (field == NULL) {
316 THROW(*this, "Error in accessing field");
317 return;
318 }
319
320 mEnv->SetByteField(obj, field, value);
321 }
322
setBooleanField(jobject obj,const char * name,jboolean value)323 void JNIHelper::setBooleanField(jobject obj, const char *name, jboolean value)
324 {
325 JNIObject<jclass> cls(*this, mEnv->GetObjectClass(obj));
326 if (cls == NULL) {
327 THROW(*this, "Error in accessing class");
328 return;
329 }
330
331 jfieldID field = mEnv->GetFieldID(cls, name, "Z");
332 if (field == NULL) {
333 THROW(*this, "Error in accessing field");
334 return;
335 }
336
337 mEnv->SetBooleanField(obj, field, value);
338 }
339
setLongField(jobject obj,const char * name,jlong value)340 void JNIHelper::setLongField(jobject obj, const char *name, jlong value)
341 {
342 JNIObject<jclass> cls(*this, mEnv->GetObjectClass(obj));
343 if (cls == NULL) {
344 THROW(*this, "Error in accessing class");
345 return;
346 }
347
348 jfieldID field = mEnv->GetFieldID(cls, name, "J");
349 if (field == NULL) {
350 THROW(*this, "Error in accessing field");
351 return;
352 }
353
354 mEnv->SetLongField(obj, field, value);
355 }
356
setStaticLongField(jobject obj,const char * name,jlong value)357 void JNIHelper::setStaticLongField(jobject obj, const char *name, jlong value)
358 {
359 JNIObject<jclass> cls(*this, mEnv->GetObjectClass(obj));
360 if (cls == NULL) {
361 THROW(*this, "Error in accessing class");
362 return;
363 }
364
365 setStaticLongField(cls, name, value);
366 }
367
setStaticLongField(jclass cls,const char * name,jlong value)368 void JNIHelper::setStaticLongField(jclass cls, const char *name, jlong value)
369 {
370 jfieldID field = mEnv->GetStaticFieldID(cls, name, "J");
371 if (field == NULL) {
372 THROW(*this, "Error in accessing field");
373 return;
374 }
375
376 mEnv->SetStaticLongField(cls, field, value);
377 }
378
setLongArrayField(jobject obj,const char * name,jlongArray value)379 void JNIHelper::setLongArrayField(jobject obj, const char *name, jlongArray value)
380 {
381 JNIObject<jclass> cls(*this, mEnv->GetObjectClass(obj));
382 if (cls == NULL) {
383 THROW(*this, "Error in accessing field");
384 return;
385 }
386
387 jfieldID field = mEnv->GetFieldID(cls, name, "[J");
388 if (field == NULL) {
389 THROW(*this, "Error in accessing field");
390 return;
391 }
392
393 mEnv->SetObjectField(obj, field, value);
394 }
395
setStaticLongArrayField(jobject obj,const char * name,jlongArray value)396 void JNIHelper::setStaticLongArrayField(jobject obj, const char *name, jlongArray value)
397 {
398 JNIObject<jclass> cls(*this, mEnv->GetObjectClass(obj));
399 if (cls == NULL) {
400 THROW(*this, "Error in accessing field");
401 return;
402 }
403
404 setStaticLongArrayField(cls, name, value);
405 }
406
setStaticLongArrayField(jclass cls,const char * name,jlongArray value)407 void JNIHelper::setStaticLongArrayField(jclass cls, const char *name, jlongArray value)
408 {
409 jfieldID field = mEnv->GetStaticFieldID(cls, name, "[J");
410 if (field == NULL) {
411 THROW(*this, "Error in accessing field");
412 return;
413 }
414
415 mEnv->SetStaticObjectField(cls, field, value);
416 ALOGD("array field set");
417 }
418
setLongArrayElement(jobject obj,const char * name,int index,jlong value)419 void JNIHelper::setLongArrayElement(jobject obj, const char *name, int index, jlong value)
420 {
421 JNIObject<jclass> cls(*this, mEnv->GetObjectClass(obj));
422 if (cls == NULL) {
423 THROW(*this, "Error in accessing field");
424 return;
425 }
426
427 jfieldID field = mEnv->GetFieldID(cls, name, "[J");
428 if (field == NULL) {
429 THROW(*this, "Error in accessing field");
430 return;
431 }
432
433 JNIObject<jlongArray> array(*this, (jlongArray)mEnv->GetObjectField(obj, field));
434 if (array == NULL) {
435 THROW(*this, "Error in accessing array");
436 return;
437 }
438
439 jlong *elem = mEnv->GetLongArrayElements(array, NULL);
440 if (elem == NULL) {
441 THROW(*this, "Error in accessing index element");
442 return;
443 }
444
445 elem[index] = value;
446 mEnv->ReleaseLongArrayElements(array, elem, 0);
447 }
448
setObjectField(jobject obj,const char * name,const char * type,jobject value)449 void JNIHelper::setObjectField(jobject obj, const char *name, const char *type, jobject value)
450 {
451 JNIObject<jclass> cls(*this, mEnv->GetObjectClass(obj));
452 if (cls == NULL) {
453 THROW(*this, "Error in accessing class");
454 return;
455 }
456
457 jfieldID field = mEnv->GetFieldID(cls, name, type);
458 if (field == NULL) {
459 THROW(*this, "Error in accessing field");
460 return;
461 }
462
463 mEnv->SetObjectField(obj, field, value);
464 }
465
setStringField(jobject obj,const char * name,const char * value)466 jboolean JNIHelper::setStringField(jobject obj, const char *name, const char *value)
467 {
468 JNIObject<jstring> str(*this, mEnv->NewStringUTF(value));
469
470 if (mEnv->ExceptionCheck()) {
471 mEnv->ExceptionDescribe();
472 mEnv->ExceptionClear();
473 return false;
474 }
475
476 if (str == NULL) {
477 THROW(*this, "Error creating string");
478 return false;
479 }
480
481 setObjectField(obj, name, "Ljava/lang/String;", str);
482 return true;
483 }
484
reportEvent(jclass cls,const char * method,const char * signature,...)485 void JNIHelper::reportEvent(jclass cls, const char *method, const char *signature, ...)
486 {
487 va_list params;
488 va_start(params, signature);
489
490 jmethodID methodID = mEnv->GetStaticMethodID(cls, method, signature);
491 if (methodID == 0) {
492 ALOGE("Error in getting method ID");
493 return;
494 }
495
496 mEnv->CallStaticVoidMethodV(cls, methodID, params);
497 if (mEnv->ExceptionCheck()) {
498 mEnv->ExceptionDescribe();
499 mEnv->ExceptionClear();
500 }
501
502 va_end(params);
503 }
504
callStaticMethod(jclass cls,const char * method,const char * signature,...)505 jboolean JNIHelper::callStaticMethod(jclass cls, const char *method, const char *signature, ...)
506 {
507 va_list params;
508 va_start(params, signature);
509
510 jmethodID methodID = mEnv->GetStaticMethodID(cls, method, signature);
511 if (methodID == 0) {
512 ALOGE("Error in getting method ID");
513 return false;
514 }
515
516 jboolean result = mEnv->CallStaticBooleanMethodV(cls, methodID, params);
517 if (mEnv->ExceptionCheck()) {
518 mEnv->ExceptionDescribe();
519 mEnv->ExceptionClear();
520 return false;
521 }
522
523 va_end(params);
524 return result;
525 }
526
createObject(const char * className)527 JNIObject<jobject> JNIHelper::createObject(const char *className)
528 {
529 JNIObject<jclass> cls(*this, mEnv->FindClass(className));
530 if (cls == NULL) {
531 ALOGE("Error in finding class %s", className);
532 return JNIObject<jobject>(*this, NULL);
533 }
534
535 jmethodID constructor = mEnv->GetMethodID(cls, "<init>", "()V");
536 if (constructor == 0) {
537 ALOGE("Error in constructor ID for %s", className);
538 return JNIObject<jobject>(*this, NULL);
539 }
540
541 JNIObject<jobject> obj(*this, mEnv->NewObject(cls, constructor));
542 if (obj == NULL) {
543 ALOGE("Could not create new object of %s", className);
544 return JNIObject<jobject>(*this, NULL);
545 }
546
547 return obj;
548 }
549
createObjectArray(const char * className,int num)550 JNIObject<jobjectArray> JNIHelper::createObjectArray(const char *className, int num)
551 {
552 JNIObject<jclass> cls(*this, mEnv->FindClass(className));
553 if (cls == NULL) {
554 ALOGE("Error in finding class %s", className);
555 return JNIObject<jobjectArray>(*this, NULL);
556 }
557
558 JNIObject<jobject> array(*this, mEnv->NewObjectArray(num, cls.get(), NULL));
559 if (array.get() == NULL) {
560 ALOGE("Error in creating array of class %s", className);
561 return JNIObject<jobjectArray>(*this, NULL);
562 }
563
564 return JNIObject<jobjectArray>(*this, (jobjectArray)array.detach());
565 }
566
getObjectArrayElement(jobjectArray array,int index)567 JNIObject<jobject> JNIHelper::getObjectArrayElement(jobjectArray array, int index)
568 {
569 return JNIObject<jobject>(*this, mEnv->GetObjectArrayElement(array, index));
570 }
571
getObjectArrayElement(jobject array,int index)572 JNIObject<jobject> JNIHelper::getObjectArrayElement(jobject array, int index)
573 {
574 return getObjectArrayElement((jobjectArray)array, index);
575 }
576
getArrayLength(jarray array)577 int JNIHelper::getArrayLength(jarray array) {
578 return mEnv->GetArrayLength(array);
579 }
580
newObjectArray(int num,const char * className,jobject val)581 JNIObject<jobjectArray> JNIHelper::newObjectArray(int num, const char *className, jobject val) {
582 JNIObject<jclass> cls(*this, mEnv->FindClass(className));
583 if (cls == NULL) {
584 ALOGE("Error in finding class %s", className);
585 return JNIObject<jobjectArray>(*this, NULL);
586 }
587
588 return JNIObject<jobjectArray>(*this, mEnv->NewObjectArray(num, cls, val));
589 }
590
newByteArray(int num)591 JNIObject<jbyteArray> JNIHelper::newByteArray(int num) {
592 return JNIObject<jbyteArray>(*this, mEnv->NewByteArray(num));
593 }
594
newIntArray(int num)595 JNIObject<jintArray> JNIHelper::newIntArray(int num) {
596 return JNIObject<jintArray>(*this, mEnv->NewIntArray(num));
597 }
598
newLongArray(int num)599 JNIObject<jlongArray> JNIHelper::newLongArray(int num) {
600 return JNIObject<jlongArray>(*this, mEnv->NewLongArray(num));
601 }
602
newStringUTF(const char * utf)603 JNIObject<jstring> JNIHelper::newStringUTF(const char *utf) {
604 return JNIObject<jstring>(*this, mEnv->NewStringUTF(utf));
605 }
606
setObjectArrayElement(jobjectArray array,int index,jobject obj)607 void JNIHelper::setObjectArrayElement(jobjectArray array, int index, jobject obj) {
608 mEnv->SetObjectArrayElement(array, index, obj);
609 }
610
setByteArrayRegion(jbyteArray array,int from,int to,jbyte * bytes)611 void JNIHelper::setByteArrayRegion(jbyteArray array, int from, int to, jbyte *bytes) {
612 mEnv->SetByteArrayRegion(array, from, to, bytes);
613 }
614
setIntArrayRegion(jintArray array,int from,int to,jint * ints)615 void JNIHelper::setIntArrayRegion(jintArray array, int from, int to, jint *ints) {
616 mEnv->SetIntArrayRegion(array, from, to, ints);
617 }
618
setLongArrayRegion(jlongArray array,int from,int to,jlong * longs)619 void JNIHelper::setLongArrayRegion(jlongArray array, int from, int to, jlong *longs) {
620 mEnv->SetLongArrayRegion(array, from, to, longs);
621 }
622
623 }; // namespace android
624
625
626