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