Home | History | Annotate | Download | only in jni
      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