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