1 /* 2 * Copyright (C) 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_NDEBUG 0 18 #define LOG_TAG "android_os_HwParcel" 19 #include <android-base/logging.h> 20 21 #include "android_os_HwParcel.h" 22 23 #include "android_os_HwBinder.h" 24 #include "android_os_HwBlob.h" 25 #include "android_os_HwRemoteBinder.h" 26 27 #include <JNIHelp.h> 28 #include <android_runtime/AndroidRuntime.h> 29 #include <hidl/HidlTransportSupport.h> 30 #include <hidl/Status.h> 31 #include <nativehelper/ScopedLocalRef.h> 32 33 #include "core_jni_helpers.h" 34 35 using android::AndroidRuntime; 36 37 using ::android::hardware::hidl_string; 38 using ::android::hardware::hidl_vec; 39 40 #define PACKAGE_PATH "android/os" 41 #define CLASS_NAME "HwParcel" 42 #define CLASS_PATH PACKAGE_PATH "/" CLASS_NAME 43 44 namespace android { 45 46 static struct fields_t { 47 jfieldID contextID; 48 jmethodID constructID; 49 50 } gFields; 51 52 void signalExceptionForError(JNIEnv *env, status_t err, bool canThrowRemoteException) { 53 switch (err) { 54 case OK: 55 break; 56 57 case NO_MEMORY: 58 { 59 jniThrowException(env, "java/lang/OutOfMemoryError", NULL); 60 break; 61 } 62 63 case INVALID_OPERATION: 64 { 65 jniThrowException( 66 env, "java/lang/UnsupportedOperationException", NULL); 67 break; 68 } 69 70 case BAD_VALUE: 71 { 72 jniThrowException(env, "java/lang/IllegalArgumentException", NULL); 73 break; 74 } 75 76 case -ERANGE: 77 case BAD_INDEX: 78 { 79 jniThrowException(env, "java/lang/IndexOutOfBoundsException", NULL); 80 break; 81 } 82 83 case BAD_TYPE: 84 { 85 jniThrowException(env, "java/lang/IllegalArgumentException", NULL); 86 break; 87 } 88 89 case NAME_NOT_FOUND: 90 { 91 jniThrowException(env, "java/util/NoSuchElementException", NULL); 92 break; 93 } 94 95 case PERMISSION_DENIED: 96 { 97 jniThrowException(env, "java/lang/SecurityException", NULL); 98 break; 99 } 100 101 case NO_INIT: 102 { 103 jniThrowException( 104 env, "java/lang/RuntimeException", "Not initialized"); 105 break; 106 } 107 108 case ALREADY_EXISTS: 109 { 110 jniThrowException( 111 env, "java/lang/RuntimeException", "Item already exists"); 112 break; 113 } 114 115 default: 116 { 117 std::stringstream ss; 118 ss << "HwBinder Error: (" << err << ")"; 119 120 jniThrowException( 121 env, 122 canThrowRemoteException ? "android/os/RemoteException" : "java/lang/RuntimeException", 123 ss.str().c_str()); 124 125 break; 126 } 127 } 128 } 129 130 // static 131 void JHwParcel::InitClass(JNIEnv *env) { 132 ScopedLocalRef<jclass> clazz( 133 env, FindClassOrDie(env, CLASS_PATH)); 134 135 gFields.contextID = 136 GetFieldIDOrDie(env, clazz.get(), "mNativeContext", "J"); 137 138 gFields.constructID = GetMethodIDOrDie(env, clazz.get(), "<init>", "(Z)V"); 139 } 140 141 // static 142 sp<JHwParcel> JHwParcel::SetNativeContext( 143 JNIEnv *env, jobject thiz, const sp<JHwParcel> &context) { 144 sp<JHwParcel> old = (JHwParcel *)env->GetLongField(thiz, gFields.contextID); 145 146 if (context != NULL) { 147 context->incStrong(NULL /* id */); 148 } 149 150 if (old != NULL) { 151 old->decStrong(NULL /* id */); 152 } 153 154 env->SetLongField(thiz, gFields.contextID, (long)context.get()); 155 156 return old; 157 } 158 159 // static 160 sp<JHwParcel> JHwParcel::GetNativeContext(JNIEnv *env, jobject thiz) { 161 return (JHwParcel *)env->GetLongField(thiz, gFields.contextID); 162 } 163 164 JHwParcel::JHwParcel(JNIEnv *env, jobject thiz) 165 : mParcel(NULL), 166 mOwnsParcel(false), 167 mTransactCallback(nullptr), 168 mWasSent(false) { 169 jclass clazz = env->GetObjectClass(thiz); 170 CHECK(clazz != NULL); 171 172 mClass = (jclass)env->NewGlobalRef(clazz); 173 mObject = env->NewWeakGlobalRef(thiz); 174 } 175 176 JHwParcel::~JHwParcel() { 177 JNIEnv *env = AndroidRuntime::getJNIEnv(); 178 179 mStorage.release(env); 180 181 setParcel(NULL, false /* assumeOwnership */); 182 183 env->DeleteWeakGlobalRef(mObject); 184 mObject = NULL; 185 186 env->DeleteGlobalRef(mClass); 187 mClass = NULL; 188 } 189 190 hardware::Parcel *JHwParcel::getParcel() { 191 return mParcel; 192 } 193 194 EphemeralStorage *JHwParcel::getStorage() { 195 return &mStorage; 196 } 197 198 void JHwParcel::setParcel(hardware::Parcel *parcel, bool assumeOwnership) { 199 if (mParcel && mOwnsParcel) { 200 delete mParcel; 201 } 202 203 mParcel = parcel; 204 mOwnsParcel = assumeOwnership; 205 } 206 207 // static 208 jobject JHwParcel::NewObject(JNIEnv *env) { 209 ScopedLocalRef<jclass> clazz(env, FindClassOrDie(env, CLASS_PATH)); 210 211 jmethodID constructID = 212 GetMethodIDOrDie(env, clazz.get(), "<init>", "(Z)V"); 213 214 return env->NewObject(clazz.get(), constructID, false /* allocate */); 215 } 216 217 void JHwParcel::setTransactCallback( 218 ::android::hardware::IBinder::TransactCallback cb) { 219 mTransactCallback = cb; 220 } 221 222 void JHwParcel::send() { 223 CHECK(mTransactCallback != nullptr); 224 CHECK(mParcel != nullptr); 225 226 mTransactCallback(*mParcel); 227 mTransactCallback = nullptr; 228 229 mWasSent = true; 230 } 231 232 bool JHwParcel::wasSent() const { 233 return mWasSent; 234 } 235 236 } // namespace android 237 238 //////////////////////////////////////////////////////////////////////////////// 239 240 using namespace android; 241 242 static void releaseNativeContext(void *nativeContext) { 243 sp<JHwParcel> parcel = (JHwParcel *)nativeContext; 244 245 if (parcel != NULL) { 246 parcel->decStrong(NULL /* id */); 247 } 248 } 249 250 static jlong JHwParcel_native_init(JNIEnv *env) { 251 JHwParcel::InitClass(env); 252 253 return reinterpret_cast<jlong>(&releaseNativeContext); 254 } 255 256 static void JHwParcel_native_setup( 257 JNIEnv *env, jobject thiz, jboolean allocate) { 258 sp<JHwParcel> context = new JHwParcel(env, thiz); 259 260 if (allocate) { 261 context->setParcel(new hardware::Parcel, true /* assumeOwnership */); 262 } 263 264 JHwParcel::SetNativeContext(env, thiz, context); 265 } 266 267 static void JHwParcel_native_writeInterfaceToken( 268 JNIEnv *env, jobject thiz, jstring interfaceNameObj) { 269 if (interfaceNameObj == NULL) { 270 jniThrowException(env, "java/lang/NullPointerException", NULL); 271 return; 272 } 273 274 const jchar *interfaceName = env->GetStringCritical(interfaceNameObj, NULL); 275 if (interfaceName) { 276 String8 nameCopy = String8(String16( 277 reinterpret_cast<const char16_t *>(interfaceName), 278 env->GetStringLength(interfaceNameObj))); 279 280 env->ReleaseStringCritical(interfaceNameObj, interfaceName); 281 interfaceName = NULL; 282 283 hardware::Parcel *parcel = 284 JHwParcel::GetNativeContext(env, thiz)->getParcel(); 285 286 status_t err = parcel->writeInterfaceToken(nameCopy.string()); 287 signalExceptionForError(env, err); 288 } 289 } 290 291 static void JHwParcel_native_enforceInterface( 292 JNIEnv *env, jobject thiz, jstring interfaceNameObj) { 293 // XXX original binder Parcel enforceInterface implementation does some 294 // mysterious things regarding strictModePolicy(), figure out if we need 295 // that here as well. 296 if (interfaceNameObj == NULL) { 297 jniThrowException(env, "java/lang/NullPointerException", NULL); 298 return; 299 } 300 301 const jchar *interfaceName = env->GetStringCritical(interfaceNameObj, NULL); 302 if (interfaceName) { 303 String8 interfaceNameCopy = String8(String16( 304 reinterpret_cast<const char16_t *>(interfaceName), 305 env->GetStringLength(interfaceNameObj))); 306 307 env->ReleaseStringCritical(interfaceNameObj, interfaceName); 308 interfaceName = NULL; 309 310 hardware::Parcel *parcel = 311 JHwParcel::GetNativeContext(env, thiz)->getParcel(); 312 313 bool valid = parcel->enforceInterface(interfaceNameCopy.string()); 314 315 if (!valid) { 316 jniThrowException( 317 env, 318 "java/lang/SecurityException", 319 "HWBinder invocation to an incorrect interface"); 320 } 321 } 322 } 323 324 #define DEFINE_PARCEL_WRITER(Suffix,Type) \ 325 static void JHwParcel_native_write ## Suffix( \ 326 JNIEnv *env, jobject thiz, Type val) { \ 327 hardware::Parcel *parcel = \ 328 JHwParcel::GetNativeContext(env, thiz)->getParcel(); \ 329 \ 330 status_t err = parcel->write ## Suffix(val); \ 331 signalExceptionForError(env, err); \ 332 } 333 334 #define DEFINE_PARCEL_READER(Suffix,Type) \ 335 static Type JHwParcel_native_read ## Suffix( \ 336 JNIEnv *env, jobject thiz) { \ 337 hardware::Parcel *parcel = \ 338 JHwParcel::GetNativeContext(env, thiz)->getParcel(); \ 339 \ 340 Type val; \ 341 status_t err = parcel->read ## Suffix(&val); \ 342 signalExceptionForError(env, err); \ 343 \ 344 return val; \ 345 } 346 347 DEFINE_PARCEL_WRITER(Bool,jboolean) 348 DEFINE_PARCEL_WRITER(Int8,jbyte) 349 DEFINE_PARCEL_WRITER(Int16,jshort) 350 DEFINE_PARCEL_WRITER(Int32,jint) 351 DEFINE_PARCEL_WRITER(Int64,jlong) 352 DEFINE_PARCEL_WRITER(Float,jfloat) 353 DEFINE_PARCEL_WRITER(Double,jdouble) 354 355 DEFINE_PARCEL_READER(Int8,jbyte) 356 DEFINE_PARCEL_READER(Int16,jshort) 357 DEFINE_PARCEL_READER(Int32,jint) 358 DEFINE_PARCEL_READER(Int64,jlong) 359 DEFINE_PARCEL_READER(Float,jfloat) 360 DEFINE_PARCEL_READER(Double,jdouble) 361 362 static jboolean JHwParcel_native_readBool(JNIEnv *env, jobject thiz) { 363 hardware::Parcel *parcel = 364 JHwParcel::GetNativeContext(env, thiz)->getParcel(); 365 366 bool val; 367 status_t err = parcel->readBool(&val); 368 signalExceptionForError(env, err); 369 370 return (jboolean)val; 371 } 372 373 static void JHwParcel_native_writeStatus( 374 JNIEnv *env, jobject thiz, jint statusCode) { 375 using hardware::Status; 376 377 Status status; 378 switch (statusCode) { 379 case 0: // kStatusSuccess 380 status = Status::ok(); 381 break; 382 case -1: // kStatusError 383 status = Status::fromStatusT(UNKNOWN_ERROR); 384 break; 385 default: 386 CHECK(!"Should not be here"); 387 } 388 389 hardware::Parcel *parcel = 390 JHwParcel::GetNativeContext(env, thiz)->getParcel(); 391 392 status_t err = ::android::hardware::writeToParcel(status, parcel); 393 signalExceptionForError(env, err); 394 } 395 396 static void JHwParcel_native_verifySuccess(JNIEnv *env, jobject thiz) { 397 using hardware::Status; 398 399 hardware::Parcel *parcel = 400 JHwParcel::GetNativeContext(env, thiz)->getParcel(); 401 402 Status status; 403 status_t err = ::android::hardware::readFromParcel(&status, *parcel); 404 signalExceptionForError(env, err); 405 } 406 407 static void JHwParcel_native_release( 408 JNIEnv *env, jobject thiz) { 409 JHwParcel::GetNativeContext(env, thiz)->setParcel(NULL, false /* assumeOwnership */); 410 } 411 412 static void JHwParcel_native_releaseTemporaryStorage( 413 JNIEnv *env, jobject thiz) { 414 JHwParcel::GetNativeContext(env, thiz)->getStorage()->release(env); 415 } 416 417 static void JHwParcel_native_send(JNIEnv *env, jobject thiz) { 418 JHwParcel::GetNativeContext(env, thiz)->send(); 419 } 420 421 static void JHwParcel_native_writeString( 422 JNIEnv *env, jobject thiz, jstring valObj) { 423 if (valObj == NULL) { 424 jniThrowException(env, "java/lang/NullPointerException", NULL); 425 return; 426 } 427 428 sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz); 429 430 const hidl_string *s = 431 impl->getStorage()->allocTemporaryString(env, valObj); 432 433 hardware::Parcel *parcel = impl->getParcel(); 434 435 size_t parentHandle; 436 status_t err = parcel->writeBuffer(s, sizeof(*s), &parentHandle); 437 438 if (err == OK) { 439 err = ::android::hardware::writeEmbeddedToParcel( 440 *s, parcel, parentHandle, 0 /* parentOffset */); 441 } 442 443 signalExceptionForError(env, err); 444 } 445 446 #define DEFINE_PARCEL_VECTOR_WRITER(Suffix,Type) \ 447 static void JHwParcel_native_write ## Suffix ## Vector( \ 448 JNIEnv *env, jobject thiz, Type ## Array valObj) { \ 449 if (valObj == NULL) { \ 450 jniThrowException(env, "java/lang/NullPointerException", NULL); \ 451 return; \ 452 } \ 453 \ 454 sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz); \ 455 \ 456 const hidl_vec<Type> *vec = \ 457 impl->getStorage()->allocTemporary ## Suffix ## Vector(env, valObj); \ 458 \ 459 hardware::Parcel *parcel = impl->getParcel(); \ 460 \ 461 size_t parentHandle; \ 462 status_t err = parcel->writeBuffer(vec, sizeof(*vec), &parentHandle); \ 463 \ 464 if (err == OK) { \ 465 size_t childHandle; \ 466 \ 467 err = ::android::hardware::writeEmbeddedToParcel( \ 468 *vec, \ 469 parcel, \ 470 parentHandle, \ 471 0 /* parentOffset */, \ 472 &childHandle); \ 473 } \ 474 \ 475 signalExceptionForError(env, err); \ 476 } 477 478 DEFINE_PARCEL_VECTOR_WRITER(Int8,jbyte) 479 DEFINE_PARCEL_VECTOR_WRITER(Int16,jshort) 480 DEFINE_PARCEL_VECTOR_WRITER(Int32,jint) 481 DEFINE_PARCEL_VECTOR_WRITER(Int64,jlong) 482 DEFINE_PARCEL_VECTOR_WRITER(Float,jfloat) 483 DEFINE_PARCEL_VECTOR_WRITER(Double,jdouble) 484 485 static void JHwParcel_native_writeBoolVector( 486 JNIEnv *env, jobject thiz, jbooleanArray valObj) { 487 if (valObj == NULL) { 488 jniThrowException(env, "java/lang/NullPointerException", NULL); 489 return; 490 } 491 492 sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz); 493 494 void *vecPtr = 495 impl->getStorage()->allocTemporaryStorage(sizeof(hidl_vec<bool>)); 496 497 hidl_vec<bool> *vec = new (vecPtr) hidl_vec<bool>; 498 499 jsize len = env->GetArrayLength(valObj); 500 501 jboolean *src = env->GetBooleanArrayElements(valObj, nullptr); 502 503 bool *dst = 504 (bool *)impl->getStorage()->allocTemporaryStorage(len * sizeof(bool)); 505 506 for (jsize i = 0; i < len; ++i) { 507 dst[i] = src[i]; 508 } 509 510 env->ReleaseBooleanArrayElements(valObj, src, 0 /* mode */); 511 src = nullptr; 512 513 vec->setToExternal(dst, len); 514 515 hardware::Parcel *parcel = impl->getParcel(); 516 517 size_t parentHandle; 518 status_t err = parcel->writeBuffer(vec, sizeof(*vec), &parentHandle); 519 520 if (err == OK) { 521 size_t childHandle; 522 523 err = ::android::hardware::writeEmbeddedToParcel( 524 *vec, 525 parcel, 526 parentHandle, 527 0 /* parentOffset */, 528 &childHandle); 529 } 530 531 signalExceptionForError(env, err); 532 } 533 534 static void JHwParcel_native_writeStrongBinder( 535 JNIEnv *env, jobject thiz, jobject binderObj) { 536 sp<hardware::IBinder> binder; 537 if (binderObj != NULL) { 538 ScopedLocalRef<jclass> hwBinderKlass( 539 env, FindClassOrDie(env, PACKAGE_PATH "/HwBinder")); 540 541 ScopedLocalRef<jclass> hwRemoteBinderKlass( 542 env, FindClassOrDie(env, PACKAGE_PATH "/HwRemoteBinder")); 543 544 if (env->IsInstanceOf(binderObj, hwBinderKlass.get())) { 545 binder = JHwBinder::GetNativeContext(env, binderObj); 546 } else if (env->IsInstanceOf(binderObj, hwRemoteBinderKlass.get())) { 547 binder = JHwRemoteBinder::GetNativeContext( 548 env, binderObj)->getBinder(); 549 } else { 550 signalExceptionForError(env, INVALID_OPERATION); 551 return; 552 } 553 } 554 555 hardware::Parcel *parcel = 556 JHwParcel::GetNativeContext(env, thiz)->getParcel(); 557 558 status_t err = parcel->writeStrongBinder(binder); 559 signalExceptionForError(env, err); 560 } 561 562 static jstring MakeStringObjFromHidlString(JNIEnv *env, const hidl_string &s) { 563 String16 utf16String(s.c_str(), s.size()); 564 565 return env->NewString( 566 reinterpret_cast<const jchar *>(utf16String.string()), 567 utf16String.size()); 568 } 569 570 static jstring JHwParcel_native_readString(JNIEnv *env, jobject thiz) { 571 hardware::Parcel *parcel = 572 JHwParcel::GetNativeContext(env, thiz)->getParcel(); 573 574 size_t parentHandle; 575 576 const hidl_string *s; 577 status_t err = parcel->readBuffer(sizeof(*s), &parentHandle, 578 reinterpret_cast<const void**>(&s)); 579 580 if (err != OK) { 581 signalExceptionForError(env, err); 582 return NULL; 583 } 584 585 err = ::android::hardware::readEmbeddedFromParcel( 586 const_cast<hidl_string &>(*s), 587 *parcel, parentHandle, 0 /* parentOffset */); 588 589 if (err != OK) { 590 signalExceptionForError(env, err); 591 return NULL; 592 } 593 594 return MakeStringObjFromHidlString(env, *s); 595 } 596 597 #define DEFINE_PARCEL_VECTOR_READER(Suffix,Type,NewType) \ 598 static Type ## Array JHwParcel_native_read ## Suffix ## Vector( \ 599 JNIEnv *env, jobject thiz) { \ 600 hardware::Parcel *parcel = \ 601 JHwParcel::GetNativeContext(env, thiz)->getParcel(); \ 602 size_t parentHandle; \ 603 \ 604 const hidl_vec<Type> *vec; \ 605 status_t err = parcel->readBuffer(sizeof(*vec), &parentHandle, \ 606 reinterpret_cast<const void**>(&vec)); \ 607 \ 608 if (err != OK) { \ 609 signalExceptionForError(env, err); \ 610 return NULL; \ 611 } \ 612 \ 613 size_t childHandle; \ 614 \ 615 err = ::android::hardware::readEmbeddedFromParcel( \ 616 const_cast<hidl_vec<Type> &>(*vec), \ 617 *parcel, \ 618 parentHandle, \ 619 0 /* parentOffset */, \ 620 &childHandle); \ 621 \ 622 if (err != OK) { \ 623 signalExceptionForError(env, err); \ 624 return NULL; \ 625 } \ 626 \ 627 Type ## Array valObj = env->New ## NewType ## Array(vec->size()); \ 628 env->Set ## NewType ## ArrayRegion(valObj, 0, vec->size(), &(*vec)[0]); \ 629 \ 630 return valObj; \ 631 } 632 633 DEFINE_PARCEL_VECTOR_READER(Int8,jbyte,Byte) 634 DEFINE_PARCEL_VECTOR_READER(Int16,jshort,Short) 635 DEFINE_PARCEL_VECTOR_READER(Int32,jint,Int) 636 DEFINE_PARCEL_VECTOR_READER(Int64,jlong,Long) 637 DEFINE_PARCEL_VECTOR_READER(Float,jfloat,Float) 638 DEFINE_PARCEL_VECTOR_READER(Double,jdouble,Double) 639 640 static jbooleanArray JHwParcel_native_readBoolVector( 641 JNIEnv *env, jobject thiz) { 642 hardware::Parcel *parcel = 643 JHwParcel::GetNativeContext(env, thiz)->getParcel(); 644 645 size_t parentHandle; 646 647 const hidl_vec<bool> *vec; 648 status_t err = parcel->readBuffer(sizeof(*vec), &parentHandle, 649 reinterpret_cast<const void**>(&vec)); 650 651 if (err != OK) { 652 signalExceptionForError(env, err); 653 return NULL; 654 } 655 656 size_t childHandle; 657 658 err = ::android::hardware::readEmbeddedFromParcel( 659 const_cast<hidl_vec<bool> &>(*vec), 660 *parcel, 661 parentHandle, 662 0 /* parentOffset */, 663 &childHandle); 664 665 if (err != OK) { 666 signalExceptionForError(env, err); 667 return NULL; 668 } 669 670 jbooleanArray valObj = env->NewBooleanArray(vec->size()); 671 672 for (size_t i = 0; i < vec->size(); ++i) { 673 jboolean x = (*vec)[i]; 674 env->SetBooleanArrayRegion(valObj, i, 1, &x); 675 } 676 677 return valObj; 678 } 679 680 static jobjectArray MakeStringArray( 681 JNIEnv *env, const hidl_string *array, size_t size) { 682 ScopedLocalRef<jclass> stringKlass( 683 env, 684 env->FindClass("java/lang/String")); 685 686 // XXX Why can't I use ScopedLocalRef<> for the arrayObj and the stringObjs? 687 688 jobjectArray arrayObj = env->NewObjectArray(size, stringKlass.get(), NULL); 689 690 for (size_t i = 0; i < size; ++i) { 691 jstring stringObj = MakeStringObjFromHidlString(env, array[i]); 692 693 env->SetObjectArrayElement( 694 arrayObj, 695 i, 696 stringObj); 697 } 698 699 return arrayObj; 700 } 701 702 static jobjectArray JHwParcel_native_readStringVector( 703 JNIEnv *env, jobject thiz) { 704 typedef hidl_vec<hidl_string> string_vec; 705 706 hardware::Parcel *parcel = 707 JHwParcel::GetNativeContext(env, thiz)->getParcel(); 708 709 size_t parentHandle; 710 711 const string_vec *vec; 712 status_t err = parcel->readBuffer(sizeof(*vec), &parentHandle, 713 reinterpret_cast<const void **>(&vec)); 714 715 if (err != OK) { 716 signalExceptionForError(env, err); 717 return NULL; 718 } 719 720 size_t childHandle; 721 err = ::android::hardware::readEmbeddedFromParcel( 722 const_cast<string_vec &>(*vec), 723 *parcel, parentHandle, 0 /* parentOffset */, &childHandle); 724 725 for (size_t i = 0; (err == OK) && (i < vec->size()); ++i) { 726 err = android::hardware::readEmbeddedFromParcel( 727 const_cast<hidl_string &>((*vec)[i]), 728 *parcel, 729 childHandle, 730 i * sizeof(hidl_string) /* parentOffset */); 731 } 732 733 if (err != OK) { 734 signalExceptionForError(env, err); 735 return NULL; 736 } 737 738 return MakeStringArray(env, &(*vec)[0], vec->size()); 739 } 740 741 static void JHwParcel_native_writeStringVector( 742 JNIEnv *env, jobject thiz, jobjectArray arrayObj) { 743 typedef hidl_vec<hidl_string> string_vec; 744 745 if (arrayObj == NULL) { 746 jniThrowException(env, "java/lang/NullPointerException", NULL); 747 return; 748 } 749 750 jsize len = env->GetArrayLength(arrayObj); 751 752 sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz); 753 754 void *vecPtr = 755 impl->getStorage()->allocTemporaryStorage(sizeof(string_vec)); 756 757 string_vec *vec = new (vecPtr) string_vec; 758 759 hidl_string *strings = impl->getStorage()->allocStringArray(len); 760 vec->setToExternal(strings, len); 761 762 for (jsize i = 0; i < len; ++i) { 763 ScopedLocalRef<jstring> stringObj( 764 env, 765 (jstring)env->GetObjectArrayElement(arrayObj, i)); 766 767 const hidl_string *s = 768 impl->getStorage()->allocTemporaryString(env, stringObj.get()); 769 770 strings[i].setToExternal(s->c_str(), s->size()); 771 } 772 773 hardware::Parcel *parcel = impl->getParcel(); 774 775 size_t parentHandle; 776 status_t err = parcel->writeBuffer(vec, sizeof(*vec), &parentHandle); 777 778 if (err == OK) { 779 size_t childHandle; 780 err = ::android::hardware::writeEmbeddedToParcel( 781 *vec, 782 parcel, 783 parentHandle, 784 0 /* parentOffset */, 785 &childHandle); 786 787 for (size_t i = 0; (err == OK) && (i < vec->size()); ++i) { 788 err = ::android::hardware::writeEmbeddedToParcel( 789 (*vec)[i], 790 parcel, 791 childHandle, 792 i * sizeof(hidl_string)); 793 } 794 } 795 796 signalExceptionForError(env, err); 797 } 798 799 static jobject JHwParcel_native_readStrongBinder(JNIEnv *env, jobject thiz) { 800 hardware::Parcel *parcel = 801 JHwParcel::GetNativeContext(env, thiz)->getParcel(); 802 803 sp<hardware::IBinder> binder = parcel->readStrongBinder(); 804 805 if (binder == NULL) { 806 return NULL; 807 } 808 809 return JHwRemoteBinder::NewObject(env, binder); 810 } 811 812 static jobject JHwParcel_native_readBuffer(JNIEnv *env, jobject thiz, 813 jlong expectedSize) { 814 hardware::Parcel *parcel = 815 JHwParcel::GetNativeContext(env, thiz)->getParcel(); 816 817 size_t handle; 818 const void *ptr; 819 820 if (expectedSize < 0) { 821 jniThrowException(env, "java/lang/IllegalArgumentException", NULL); 822 return nullptr; 823 } 824 825 status_t status = parcel->readBuffer(expectedSize, &handle, &ptr); 826 827 if (status != OK) { 828 jniThrowException(env, "java/util/NoSuchElementException", NULL); 829 return nullptr; 830 } 831 832 return JHwBlob::NewObject(env, ptr, handle); 833 } 834 835 static jobject JHwParcel_native_readEmbeddedBuffer( 836 JNIEnv *env, jobject thiz, jlong expectedSize, 837 jlong parentHandle, jlong offset, jboolean nullable) { 838 hardware::Parcel *parcel = 839 JHwParcel::GetNativeContext(env, thiz)->getParcel(); 840 841 size_t childHandle; 842 843 const void *ptr; 844 status_t status = 845 parcel->readNullableEmbeddedBuffer(expectedSize, 846 &childHandle, parentHandle, offset, &ptr); 847 848 if (expectedSize < 0) { 849 jniThrowException(env, "java/lang/IllegalArgumentException", NULL); 850 return nullptr; 851 } 852 853 if (status != OK) { 854 jniThrowException(env, "java/util/NoSuchElementException", NULL); 855 return 0; 856 } else if (status == OK && !nullable && ptr == nullptr) { 857 jniThrowException(env, "java/lang/NullPointerException", NULL); 858 return 0; 859 } 860 861 return JHwBlob::NewObject(env, ptr, childHandle); 862 } 863 864 static void JHwParcel_native_writeBuffer( 865 JNIEnv *env, jobject thiz, jobject blobObj) { 866 if (blobObj == nullptr) { 867 jniThrowException(env, "java/lang/NullPointerException", NULL); 868 return; 869 } 870 871 hardware::Parcel *parcel = 872 JHwParcel::GetNativeContext(env, thiz)->getParcel(); 873 874 sp<JHwBlob> blob = JHwBlob::GetNativeContext(env, blobObj); 875 status_t err = blob->writeToParcel(parcel); 876 877 if (err != OK) { 878 signalExceptionForError(env, err); 879 } 880 } 881 882 static JNINativeMethod gMethods[] = { 883 { "native_init", "()J", (void *)JHwParcel_native_init }, 884 { "native_setup", "(Z)V", (void *)JHwParcel_native_setup }, 885 886 { "writeInterfaceToken", "(Ljava/lang/String;)V", 887 (void *)JHwParcel_native_writeInterfaceToken }, 888 889 { "writeBool", "(Z)V", (void *)JHwParcel_native_writeBool }, 890 { "writeInt8", "(B)V", (void *)JHwParcel_native_writeInt8 }, 891 { "writeInt16", "(S)V", (void *)JHwParcel_native_writeInt16 }, 892 { "writeInt32", "(I)V", (void *)JHwParcel_native_writeInt32 }, 893 { "writeInt64", "(J)V", (void *)JHwParcel_native_writeInt64 }, 894 { "writeFloat", "(F)V", (void *)JHwParcel_native_writeFloat }, 895 { "writeDouble", "(D)V", (void *)JHwParcel_native_writeDouble }, 896 897 { "writeString", "(Ljava/lang/String;)V", 898 (void *)JHwParcel_native_writeString }, 899 900 { "writeBoolVector", "([Z)V", (void *)JHwParcel_native_writeBoolVector }, 901 { "writeInt8Vector", "([B)V", (void *)JHwParcel_native_writeInt8Vector }, 902 { "writeInt16Vector", "([S)V", (void *)JHwParcel_native_writeInt16Vector }, 903 { "writeInt32Vector", "([I)V", (void *)JHwParcel_native_writeInt32Vector }, 904 { "writeInt64Vector", "([J)V", (void *)JHwParcel_native_writeInt64Vector }, 905 { "writeFloatVector", "([F)V", (void *)JHwParcel_native_writeFloatVector }, 906 907 { "writeDoubleVector", "([D)V", 908 (void *)JHwParcel_native_writeDoubleVector }, 909 910 { "writeStringVector", "([Ljava/lang/String;)V", 911 (void *)JHwParcel_native_writeStringVector }, 912 913 { "writeStrongBinder", "(L" PACKAGE_PATH "/IHwBinder;)V", 914 (void *)JHwParcel_native_writeStrongBinder }, 915 916 { "enforceInterface", "(Ljava/lang/String;)V", 917 (void *)JHwParcel_native_enforceInterface }, 918 919 { "readBool", "()Z", (void *)JHwParcel_native_readBool }, 920 { "readInt8", "()B", (void *)JHwParcel_native_readInt8 }, 921 { "readInt16", "()S", (void *)JHwParcel_native_readInt16 }, 922 { "readInt32", "()I", (void *)JHwParcel_native_readInt32 }, 923 { "readInt64", "()J", (void *)JHwParcel_native_readInt64 }, 924 { "readFloat", "()F", (void *)JHwParcel_native_readFloat }, 925 { "readDouble", "()D", (void *)JHwParcel_native_readDouble }, 926 927 { "readString", "()Ljava/lang/String;", 928 (void *)JHwParcel_native_readString }, 929 930 { "readBoolVectorAsArray", "()[Z", 931 (void *)JHwParcel_native_readBoolVector }, 932 933 { "readInt8VectorAsArray", "()[B", 934 (void *)JHwParcel_native_readInt8Vector }, 935 936 { "readInt16VectorAsArray", "()[S", 937 (void *)JHwParcel_native_readInt16Vector }, 938 939 { "readInt32VectorAsArray", "()[I", 940 (void *)JHwParcel_native_readInt32Vector }, 941 942 { "readInt64VectorAsArray", "()[J", 943 (void *)JHwParcel_native_readInt64Vector }, 944 945 { "readFloatVectorAsArray", "()[F", 946 (void *)JHwParcel_native_readFloatVector }, 947 948 { "readDoubleVectorAsArray", "()[D", 949 (void *)JHwParcel_native_readDoubleVector }, 950 951 { "readStringVectorAsArray", "()[Ljava/lang/String;", 952 (void *)JHwParcel_native_readStringVector }, 953 954 { "readStrongBinder", "()L" PACKAGE_PATH "/IHwBinder;", 955 (void *)JHwParcel_native_readStrongBinder }, 956 957 { "writeStatus", "(I)V", (void *)JHwParcel_native_writeStatus }, 958 959 { "verifySuccess", "()V", (void *)JHwParcel_native_verifySuccess }, 960 961 { "releaseTemporaryStorage", "()V", 962 (void *)JHwParcel_native_releaseTemporaryStorage }, 963 964 { "send", "()V", (void *)JHwParcel_native_send }, 965 966 { "readBuffer", "(J)L" PACKAGE_PATH "/HwBlob;", 967 (void *)JHwParcel_native_readBuffer }, 968 969 { "readEmbeddedBuffer", "(JJJZ)L" PACKAGE_PATH "/HwBlob;", 970 (void *)JHwParcel_native_readEmbeddedBuffer }, 971 972 { "writeBuffer", "(L" PACKAGE_PATH "/HwBlob;)V", 973 (void *)JHwParcel_native_writeBuffer }, 974 975 { "release", "()V", 976 (void *)JHwParcel_native_release }, 977 978 }; 979 980 namespace android { 981 982 int register_android_os_HwParcel(JNIEnv *env) { 983 return RegisterMethodsOrDie(env, CLASS_PATH, gMethods, NELEM(gMethods)); 984 } 985 986 } // namespace android 987