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