1 /* 2 * Copyright 2016, 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 34 JNIHelper::JNIHelper(JavaVM *vm) 35 { 36 vm->AttachCurrentThread(&mEnv, NULL); 37 mVM = vm; 38 } 39 40 JNIHelper::JNIHelper(JNIEnv *env) 41 { 42 mVM = NULL; 43 mEnv = env; 44 } 45 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 55 jobject JNIHelper::newGlobalRef(jobject obj) { 56 return mEnv->NewGlobalRef(obj); 57 } 58 59 void JNIHelper::deleteGlobalRef(jobject obj) { 60 mEnv->DeleteGlobalRef(obj); 61 } 62 63 jobject JNIHelper::newLocalRef(jobject obj) { 64 return mEnv->NewLocalRef(obj); 65 } 66 67 void JNIHelper::deleteLocalRef(jobject obj) { 68 mEnv->DeleteLocalRef(obj); 69 } 70 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 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 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 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 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 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 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 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 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 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 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 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 244 void JNIHelper::getByteArrayField(jobject obj, const char *name, byte* buf, int size) { 245 JNIObject<jclass> cls(*this, mEnv->GetObjectClass(obj)); 246 jfieldID field = mEnv->GetFieldID(cls, name, "[B"); 247 if (field == 0) { 248 THROW(*this, "Error in accessing field definition"); 249 return; 250 } 251 252 JNIObject<jbyteArray> array(*this, (jbyteArray)mEnv->GetObjectField(obj, field)); 253 if (array == NULL) { 254 THROW(*this, "Error in accessing array"); 255 return; 256 } 257 258 jbyte *elem = mEnv->GetByteArrayElements(array, 0); 259 if (elem == NULL) { 260 THROW(*this, "Error in accessing index element"); 261 return; 262 } 263 264 memcpy(buf, elem, size); 265 mEnv->ReleaseByteArrayElements(array, elem, 0); 266 } 267 268 jlong JNIHelper::getStaticLongArrayField(jobject obj, const char *name, int index) 269 { 270 JNIObject<jclass> cls(*this, mEnv->GetObjectClass(obj)); 271 return getStaticLongArrayField(cls, name, index); 272 } 273 274 jlong JNIHelper::getStaticLongArrayField(jclass cls, const char *name, int index) 275 { 276 jfieldID field = mEnv->GetStaticFieldID(cls, name, "[J"); 277 if (field == 0) { 278 THROW(*this, "Error in accessing field definition"); 279 return 0; 280 } 281 282 JNIObject<jlongArray> array(*this, (jlongArray)mEnv->GetStaticObjectField(cls, field)); 283 jlong *elem = mEnv->GetLongArrayElements(array, 0); 284 if (elem == NULL) { 285 THROW(*this, "Error in accessing index element"); 286 return 0; 287 } 288 289 jlong value = elem[index]; 290 mEnv->ReleaseLongArrayElements(array, elem, 0); 291 return value; 292 } 293 294 JNIObject<jobject> JNIHelper::getObjectArrayField(jobject obj, const char *name, const char *type, 295 int index) 296 { 297 JNIObject<jclass> cls(*this, mEnv->GetObjectClass(obj)); 298 jfieldID field = mEnv->GetFieldID(cls, name, type); 299 if (field == 0) { 300 THROW(*this, "Error in accessing field definition"); 301 return JNIObject<jobject>(*this, NULL); 302 } 303 304 JNIObject<jobjectArray> array(*this, (jobjectArray)mEnv->GetObjectField(obj, field)); 305 JNIObject<jobject> elem(*this, mEnv->GetObjectArrayElement(array, index)); 306 if (elem.isNull()) { 307 THROW(*this, "Error in accessing index element"); 308 return JNIObject<jobject>(*this, NULL); 309 } 310 return elem; 311 } 312 313 void JNIHelper::setIntField(jobject obj, const char *name, jint value) 314 { 315 JNIObject<jclass> cls(*this, mEnv->GetObjectClass(obj)); 316 if (cls == NULL) { 317 THROW(*this, "Error in accessing class"); 318 return; 319 } 320 321 jfieldID field = mEnv->GetFieldID(cls, name, "I"); 322 if (field == NULL) { 323 THROW(*this, "Error in accessing field"); 324 return; 325 } 326 327 mEnv->SetIntField(obj, field, value); 328 } 329 330 void JNIHelper::setByteField(jobject obj, const char *name, jbyte value) 331 { 332 JNIObject<jclass> cls(*this, mEnv->GetObjectClass(obj)); 333 if (cls == NULL) { 334 THROW(*this, "Error in accessing class"); 335 return; 336 } 337 338 jfieldID field = mEnv->GetFieldID(cls, name, "B"); 339 if (field == NULL) { 340 THROW(*this, "Error in accessing field"); 341 return; 342 } 343 344 mEnv->SetByteField(obj, field, value); 345 } 346 347 void JNIHelper::setBooleanField(jobject obj, const char *name, jboolean value) 348 { 349 JNIObject<jclass> cls(*this, mEnv->GetObjectClass(obj)); 350 if (cls == NULL) { 351 THROW(*this, "Error in accessing class"); 352 return; 353 } 354 355 jfieldID field = mEnv->GetFieldID(cls, name, "Z"); 356 if (field == NULL) { 357 THROW(*this, "Error in accessing field"); 358 return; 359 } 360 361 mEnv->SetBooleanField(obj, field, value); 362 } 363 364 void JNIHelper::setLongField(jobject obj, const char *name, jlong value) 365 { 366 JNIObject<jclass> cls(*this, mEnv->GetObjectClass(obj)); 367 if (cls == NULL) { 368 THROW(*this, "Error in accessing class"); 369 return; 370 } 371 372 jfieldID field = mEnv->GetFieldID(cls, name, "J"); 373 if (field == NULL) { 374 THROW(*this, "Error in accessing field"); 375 return; 376 } 377 378 mEnv->SetLongField(obj, field, value); 379 } 380 381 void JNIHelper::setStaticLongField(jobject obj, const char *name, jlong value) 382 { 383 JNIObject<jclass> cls(*this, mEnv->GetObjectClass(obj)); 384 if (cls == NULL) { 385 THROW(*this, "Error in accessing class"); 386 return; 387 } 388 389 setStaticLongField(cls, name, value); 390 } 391 392 void JNIHelper::setStaticLongField(jclass cls, const char *name, jlong value) 393 { 394 jfieldID field = mEnv->GetStaticFieldID(cls, name, "J"); 395 if (field == NULL) { 396 THROW(*this, "Error in accessing field"); 397 return; 398 } 399 400 mEnv->SetStaticLongField(cls, field, value); 401 } 402 403 void JNIHelper::setLongArrayField(jobject obj, const char *name, jlongArray value) 404 { 405 JNIObject<jclass> cls(*this, mEnv->GetObjectClass(obj)); 406 if (cls == NULL) { 407 THROW(*this, "Error in accessing field"); 408 return; 409 } 410 411 jfieldID field = mEnv->GetFieldID(cls, name, "[J"); 412 if (field == NULL) { 413 THROW(*this, "Error in accessing field"); 414 return; 415 } 416 417 mEnv->SetObjectField(obj, field, value); 418 } 419 420 void JNIHelper::setStaticLongArrayField(jobject obj, const char *name, jlongArray value) 421 { 422 JNIObject<jclass> cls(*this, mEnv->GetObjectClass(obj)); 423 if (cls == NULL) { 424 THROW(*this, "Error in accessing field"); 425 return; 426 } 427 428 setStaticLongArrayField(cls, name, value); 429 } 430 431 void JNIHelper::setStaticLongArrayField(jclass cls, const char *name, jlongArray value) 432 { 433 jfieldID field = mEnv->GetStaticFieldID(cls, name, "[J"); 434 if (field == NULL) { 435 THROW(*this, "Error in accessing field"); 436 return; 437 } 438 439 mEnv->SetStaticObjectField(cls, field, value); 440 ALOGD("array field set"); 441 } 442 443 void JNIHelper::setLongArrayElement(jobject obj, const char *name, int index, jlong value) 444 { 445 JNIObject<jclass> cls(*this, mEnv->GetObjectClass(obj)); 446 if (cls == NULL) { 447 THROW(*this, "Error in accessing field"); 448 return; 449 } 450 451 jfieldID field = mEnv->GetFieldID(cls, name, "[J"); 452 if (field == NULL) { 453 THROW(*this, "Error in accessing field"); 454 return; 455 } 456 457 JNIObject<jlongArray> array(*this, (jlongArray)mEnv->GetObjectField(obj, field)); 458 if (array == NULL) { 459 THROW(*this, "Error in accessing array"); 460 return; 461 } 462 463 jlong *elem = mEnv->GetLongArrayElements(array, NULL); 464 if (elem == NULL) { 465 THROW(*this, "Error in accessing index element"); 466 return; 467 } 468 469 elem[index] = value; 470 mEnv->ReleaseLongArrayElements(array, elem, 0); 471 } 472 473 void JNIHelper::setObjectField(jobject obj, const char *name, const char *type, jobject value) 474 { 475 JNIObject<jclass> cls(*this, mEnv->GetObjectClass(obj)); 476 if (cls == NULL) { 477 THROW(*this, "Error in accessing class"); 478 return; 479 } 480 481 jfieldID field = mEnv->GetFieldID(cls, name, type); 482 if (field == NULL) { 483 THROW(*this, "Error in accessing field"); 484 return; 485 } 486 487 mEnv->SetObjectField(obj, field, value); 488 } 489 490 jboolean JNIHelper::setStringField(jobject obj, const char *name, const char *value) 491 { 492 JNIObject<jstring> str(*this, mEnv->NewStringUTF(value)); 493 494 if (mEnv->ExceptionCheck()) { 495 mEnv->ExceptionDescribe(); 496 mEnv->ExceptionClear(); 497 return false; 498 } 499 500 if (str == NULL) { 501 THROW(*this, "Error creating string"); 502 return false; 503 } 504 505 setObjectField(obj, name, "Ljava/lang/String;", str); 506 return true; 507 } 508 509 void JNIHelper::reportEvent(jclass cls, const char *method, const char *signature, ...) 510 { 511 va_list params; 512 va_start(params, signature); 513 514 jmethodID methodID = mEnv->GetStaticMethodID(cls, method, signature); 515 if (methodID == 0) { 516 ALOGE("Error in getting method ID"); 517 return; 518 } 519 520 mEnv->CallStaticVoidMethodV(cls, methodID, params); 521 if (mEnv->ExceptionCheck()) { 522 mEnv->ExceptionDescribe(); 523 mEnv->ExceptionClear(); 524 } 525 526 va_end(params); 527 } 528 529 void JNIHelper::callMethod(jobject obj, const char *method, const char *signature, ...) 530 { 531 va_list params; 532 va_start(params, signature); 533 534 jclass cls = mEnv->GetObjectClass(obj); 535 jmethodID methodID = mEnv->GetMethodID(cls, method, signature); 536 if (methodID == 0) { 537 ALOGE("Error in getting method ID"); 538 return; 539 } 540 541 mEnv->CallVoidMethodV(obj, methodID, params); 542 if (mEnv->ExceptionCheck()) { 543 mEnv->ExceptionDescribe(); 544 mEnv->ExceptionClear(); 545 } 546 547 va_end(params); 548 } 549 550 jboolean JNIHelper::callStaticMethod(jclass cls, const char *method, const char *signature, ...) 551 { 552 va_list params; 553 va_start(params, signature); 554 555 jmethodID methodID = mEnv->GetStaticMethodID(cls, method, signature); 556 if (methodID == 0) { 557 ALOGE("Error in getting method ID"); 558 return false; 559 } 560 561 jboolean result = mEnv->CallStaticBooleanMethodV(cls, methodID, params); 562 if (mEnv->ExceptionCheck()) { 563 mEnv->ExceptionDescribe(); 564 mEnv->ExceptionClear(); 565 return false; 566 } 567 568 va_end(params); 569 return result; 570 } 571 572 JNIObject<jobject> JNIHelper::createObject(const char *className) { 573 return createObjectWithArgs(className, "()V"); 574 } 575 576 JNIObject<jobject> JNIHelper::createObjectWithArgs( 577 const char *className, const char *signature, ...) 578 { 579 va_list params; 580 va_start(params, signature); 581 582 JNIObject<jclass> cls(*this, mEnv->FindClass(className)); 583 if (cls == NULL) { 584 ALOGE("Error in finding class %s", className); 585 return JNIObject<jobject>(*this, NULL); 586 } 587 588 jmethodID constructor = mEnv->GetMethodID(cls, "<init>", signature); 589 if (constructor == 0) { 590 ALOGE("Error in constructor ID for %s", className); 591 return JNIObject<jobject>(*this, NULL); 592 } 593 594 JNIObject<jobject> obj(*this, mEnv->NewObjectV(cls, constructor, params)); 595 if (obj == NULL) { 596 ALOGE("Could not create new object of %s", className); 597 return JNIObject<jobject>(*this, NULL); 598 } 599 600 va_end(params); 601 return obj; 602 } 603 604 JNIObject<jobjectArray> JNIHelper::createObjectArray(const char *className, int num) 605 { 606 JNIObject<jclass> cls(*this, mEnv->FindClass(className)); 607 if (cls == NULL) { 608 ALOGE("Error in finding class %s", className); 609 return JNIObject<jobjectArray>(*this, NULL); 610 } 611 612 JNIObject<jobject> array(*this, mEnv->NewObjectArray(num, cls.get(), NULL)); 613 if (array.get() == NULL) { 614 ALOGE("Error in creating array of class %s", className); 615 return JNIObject<jobjectArray>(*this, NULL); 616 } 617 618 return JNIObject<jobjectArray>(*this, (jobjectArray)array.detach()); 619 } 620 621 JNIObject<jobject> JNIHelper::getObjectArrayElement(jobjectArray array, int index) 622 { 623 return JNIObject<jobject>(*this, mEnv->GetObjectArrayElement(array, index)); 624 } 625 626 JNIObject<jobject> JNIHelper::getObjectArrayElement(jobject array, int index) 627 { 628 return getObjectArrayElement((jobjectArray)array, index); 629 } 630 631 int JNIHelper::getArrayLength(jarray array) { 632 return mEnv->GetArrayLength(array); 633 } 634 635 JNIObject<jobjectArray> JNIHelper::newObjectArray(int num, const char *className, jobject val) { 636 JNIObject<jclass> cls(*this, mEnv->FindClass(className)); 637 if (cls == NULL) { 638 ALOGE("Error in finding class %s", className); 639 return JNIObject<jobjectArray>(*this, NULL); 640 } 641 642 return JNIObject<jobjectArray>(*this, mEnv->NewObjectArray(num, cls, val)); 643 } 644 645 JNIObject<jbyteArray> JNIHelper::newByteArray(int num) { 646 return JNIObject<jbyteArray>(*this, mEnv->NewByteArray(num)); 647 } 648 649 JNIObject<jintArray> JNIHelper::newIntArray(int num) { 650 return JNIObject<jintArray>(*this, mEnv->NewIntArray(num)); 651 } 652 653 JNIObject<jlongArray> JNIHelper::newLongArray(int num) { 654 return JNIObject<jlongArray>(*this, mEnv->NewLongArray(num)); 655 } 656 657 JNIObject<jstring> JNIHelper::newStringUTF(const char *utf) { 658 return JNIObject<jstring>(*this, mEnv->NewStringUTF(utf)); 659 } 660 661 void JNIHelper::setObjectArrayElement(jobjectArray array, int index, jobject obj) { 662 mEnv->SetObjectArrayElement(array, index, obj); 663 } 664 665 void JNIHelper::setByteArrayRegion(jbyteArray array, int from, int to, const jbyte *bytes) { 666 mEnv->SetByteArrayRegion(array, from, to, bytes); 667 } 668 669 void JNIHelper::setIntArrayRegion(jintArray array, int from, int to, const jint *ints) { 670 mEnv->SetIntArrayRegion(array, from, to, ints); 671 } 672 673 void JNIHelper::setLongArrayRegion(jlongArray array, int from, int to, const jlong *longs) { 674 mEnv->SetLongArrayRegion(array, from, to, longs); 675 } 676 677 }; // namespace android 678 679 680