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 <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 
     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 }
    170 
    171 JHwParcel::~JHwParcel() {
    172     JNIEnv *env = AndroidRuntime::getJNIEnv();
    173 
    174     mStorage.release(env);
    175 
    176     setParcel(NULL, false /* assumeOwnership */);
    177 }
    178 
    179 hardware::Parcel *JHwParcel::getParcel() {
    180     return mParcel;
    181 }
    182 
    183 EphemeralStorage *JHwParcel::getStorage() {
    184     return &mStorage;
    185 }
    186 
    187 void 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
    197 jobject 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 
    206 void JHwParcel::setTransactCallback(
    207         ::android::hardware::IBinder::TransactCallback cb) {
    208     mTransactCallback = cb;
    209 }
    210 
    211 void JHwParcel::send() {
    212     CHECK(mTransactCallback != nullptr);
    213     CHECK(mParcel != nullptr);
    214 
    215     mTransactCallback(*mParcel);
    216     mTransactCallback = nullptr;
    217 
    218     mWasSent = true;
    219 }
    220 
    221 bool JHwParcel::wasSent() const {
    222     return mWasSent;
    223 }
    224 
    225 }  // namespace android
    226 
    227 ////////////////////////////////////////////////////////////////////////////////
    228 
    229 using namespace android;
    230 
    231 static void releaseNativeContext(void *nativeContext) {
    232     sp<JHwParcel> parcel = (JHwParcel *)nativeContext;
    233 
    234     if (parcel != NULL) {
    235         parcel->decStrong(NULL /* id */);
    236     }
    237 }
    238 
    239 static jlong JHwParcel_native_init(JNIEnv *env) {
    240     JHwParcel::InitClass(env);
    241 
    242     return reinterpret_cast<jlong>(&releaseNativeContext);
    243 }
    244 
    245 static 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 
    256 static 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 
    280 static 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)                               \
    314 static 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)                               \
    324 static 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 
    336 DEFINE_PARCEL_WRITER(Bool,jboolean)
    337 DEFINE_PARCEL_WRITER(Int8,jbyte)
    338 DEFINE_PARCEL_WRITER(Int16,jshort)
    339 DEFINE_PARCEL_WRITER(Int32,jint)
    340 DEFINE_PARCEL_WRITER(Int64,jlong)
    341 DEFINE_PARCEL_WRITER(Float,jfloat)
    342 DEFINE_PARCEL_WRITER(Double,jdouble)
    343 
    344 DEFINE_PARCEL_READER(Int8,jbyte)
    345 DEFINE_PARCEL_READER(Int16,jshort)
    346 DEFINE_PARCEL_READER(Int32,jint)
    347 DEFINE_PARCEL_READER(Int64,jlong)
    348 DEFINE_PARCEL_READER(Float,jfloat)
    349 DEFINE_PARCEL_READER(Double,jdouble)
    350 
    351 static 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 
    362 static 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 
    385 static 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 
    400 static void JHwParcel_native_release(
    401         JNIEnv *env, jobject thiz) {
    402     JHwParcel::GetNativeContext(env, thiz)->setParcel(NULL, false /* assumeOwnership */);
    403 }
    404 
    405 static void JHwParcel_native_releaseTemporaryStorage(
    406         JNIEnv *env, jobject thiz) {
    407     JHwParcel::GetNativeContext(env, thiz)->getStorage()->release(env);
    408 }
    409 
    410 static void JHwParcel_native_send(JNIEnv *env, jobject thiz) {
    411     JHwParcel::GetNativeContext(env, thiz)->send();
    412 }
    413 
    414 static 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)                               \
    440 static 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 
    471 DEFINE_PARCEL_VECTOR_WRITER(Int8,jbyte)
    472 DEFINE_PARCEL_VECTOR_WRITER(Int16,jshort)
    473 DEFINE_PARCEL_VECTOR_WRITER(Int32,jint)
    474 DEFINE_PARCEL_VECTOR_WRITER(Int64,jlong)
    475 DEFINE_PARCEL_VECTOR_WRITER(Float,jfloat)
    476 DEFINE_PARCEL_VECTOR_WRITER(Double,jdouble)
    477 
    478 static 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 
    527 static 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 
    555 static 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 
    563 static 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)                       \
    591 static 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 
    626 DEFINE_PARCEL_VECTOR_READER(Int8,jbyte,Byte)
    627 DEFINE_PARCEL_VECTOR_READER(Int16,jshort,Short)
    628 DEFINE_PARCEL_VECTOR_READER(Int32,jint,Int)
    629 DEFINE_PARCEL_VECTOR_READER(Int64,jlong,Long)
    630 DEFINE_PARCEL_VECTOR_READER(Float,jfloat,Float)
    631 DEFINE_PARCEL_VECTOR_READER(Double,jdouble,Double)
    632 
    633 static 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 
    673 static 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 
    695 static 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 
    734 static 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 
    792 static 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 
    805 static 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 
    828 static 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 
    857 static 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 
    875 static 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 
    973 namespace android {
    974 
    975 int register_android_os_HwParcel(JNIEnv *env) {
    976     return RegisterMethodsOrDie(env, CLASS_PATH, gMethods, NELEM(gMethods));
    977 }
    978 
    979 }  // namespace android
    980