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