blob: 7221ca11cc00a89a62a41cd2c78f9fd83ce59502 [file] [log] [blame]
Andreas Huberdab5fc62016-08-15 09:25:02 -07001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//#define LOG_NDEBUG 0
18#define LOG_TAG "android_os_HwParcel"
19#include <android-base/logging.h>
20
21#include "android_os_HwParcel.h"
22
23#include "android_os_HwBinder.h"
Andreas Huber9266f992016-08-25 11:21:21 -070024#include "android_os_HwBlob.h"
Nirav Atre9850dd92018-07-24 17:03:44 -070025#include "android_os_NativeHandle.h"
Andreas Huberdab5fc62016-08-15 09:25:02 -070026#include "android_os_HwRemoteBinder.h"
27
Steven Moreland2279b252017-07-19 09:50:45 -070028#include <nativehelper/JNIHelp.h>
Andreas Huberdab5fc62016-08-15 09:25:02 -070029#include <android_runtime/AndroidRuntime.h>
Yifan Hongddf31f62016-11-15 16:02:40 -080030#include <hidl/HidlTransportSupport.h>
Martijn Coenenaa2c32f2016-09-01 01:37:05 +020031#include <hidl/Status.h>
Andreas Huberdab5fc62016-08-15 09:25:02 -070032#include <nativehelper/ScopedLocalRef.h>
33
34#include "core_jni_helpers.h"
35
36using android::AndroidRuntime;
37
Nirav Atre9850dd92018-07-24 17:03:44 -070038using ::android::hardware::hidl_handle;
Andreas Huberdab5fc62016-08-15 09:25:02 -070039using ::android::hardware::hidl_string;
40using ::android::hardware::hidl_vec;
41
42#define PACKAGE_PATH "android/os"
43#define CLASS_NAME "HwParcel"
44#define CLASS_PATH PACKAGE_PATH "/" CLASS_NAME
45
46namespace android {
47
48static struct fields_t {
49 jfieldID contextID;
50 jmethodID constructID;
51
52} gFields;
53
Steven Morelande62b1f32016-12-20 15:55:48 -080054void signalExceptionForError(JNIEnv *env, status_t err, bool canThrowRemoteException) {
Andreas Huberdab5fc62016-08-15 09:25:02 -070055 switch (err) {
56 case OK:
57 break;
58
59 case NO_MEMORY:
60 {
61 jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
62 break;
63 }
64
65 case INVALID_OPERATION:
66 {
67 jniThrowException(
68 env, "java/lang/UnsupportedOperationException", NULL);
69 break;
70 }
71
72 case BAD_VALUE:
73 {
74 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
75 break;
76 }
77
Andreas Huber9266f992016-08-25 11:21:21 -070078 case -ERANGE:
Andreas Huberdab5fc62016-08-15 09:25:02 -070079 case BAD_INDEX:
80 {
81 jniThrowException(env, "java/lang/IndexOutOfBoundsException", NULL);
82 break;
83 }
84
85 case BAD_TYPE:
86 {
87 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
88 break;
89 }
90
91 case NAME_NOT_FOUND:
92 {
93 jniThrowException(env, "java/util/NoSuchElementException", NULL);
94 break;
95 }
96
97 case PERMISSION_DENIED:
98 {
99 jniThrowException(env, "java/lang/SecurityException", NULL);
100 break;
101 }
102
103 case NO_INIT:
104 {
105 jniThrowException(
106 env, "java/lang/RuntimeException", "Not initialized");
107 break;
108 }
109
110 case ALREADY_EXISTS:
111 {
112 jniThrowException(
113 env, "java/lang/RuntimeException", "Item already exists");
114 break;
115 }
116
117 default:
118 {
Steven Morelande62b1f32016-12-20 15:55:48 -0800119 std::stringstream ss;
120 ss << "HwBinder Error: (" << err << ")";
121
Andreas Huberdab5fc62016-08-15 09:25:02 -0700122 jniThrowException(
Steven Morelande62b1f32016-12-20 15:55:48 -0800123 env,
124 canThrowRemoteException ? "android/os/RemoteException" : "java/lang/RuntimeException",
125 ss.str().c_str());
Andreas Huberdab5fc62016-08-15 09:25:02 -0700126
127 break;
128 }
129 }
130}
131
132// static
133void JHwParcel::InitClass(JNIEnv *env) {
134 ScopedLocalRef<jclass> clazz(
135 env, FindClassOrDie(env, CLASS_PATH));
136
137 gFields.contextID =
138 GetFieldIDOrDie(env, clazz.get(), "mNativeContext", "J");
139
140 gFields.constructID = GetMethodIDOrDie(env, clazz.get(), "<init>", "(Z)V");
141}
142
143// static
144sp<JHwParcel> JHwParcel::SetNativeContext(
145 JNIEnv *env, jobject thiz, const sp<JHwParcel> &context) {
146 sp<JHwParcel> old = (JHwParcel *)env->GetLongField(thiz, gFields.contextID);
147
148 if (context != NULL) {
149 context->incStrong(NULL /* id */);
150 }
151
152 if (old != NULL) {
153 old->decStrong(NULL /* id */);
154 }
155
156 env->SetLongField(thiz, gFields.contextID, (long)context.get());
157
158 return old;
159}
160
161// static
162sp<JHwParcel> JHwParcel::GetNativeContext(JNIEnv *env, jobject thiz) {
163 return (JHwParcel *)env->GetLongField(thiz, gFields.contextID);
164}
165
166JHwParcel::JHwParcel(JNIEnv *env, jobject thiz)
167 : mParcel(NULL),
168 mOwnsParcel(false),
169 mTransactCallback(nullptr),
170 mWasSent(false) {
Andreas Huberdab5fc62016-08-15 09:25:02 -0700171}
172
173JHwParcel::~JHwParcel() {
174 JNIEnv *env = AndroidRuntime::getJNIEnv();
175
176 mStorage.release(env);
177
178 setParcel(NULL, false /* assumeOwnership */);
Andreas Huberdab5fc62016-08-15 09:25:02 -0700179}
180
181hardware::Parcel *JHwParcel::getParcel() {
182 return mParcel;
183}
184
185EphemeralStorage *JHwParcel::getStorage() {
186 return &mStorage;
187}
188
189void JHwParcel::setParcel(hardware::Parcel *parcel, bool assumeOwnership) {
190 if (mParcel && mOwnsParcel) {
191 delete mParcel;
192 }
193
194 mParcel = parcel;
195 mOwnsParcel = assumeOwnership;
196}
197
198// static
199jobject JHwParcel::NewObject(JNIEnv *env) {
200 ScopedLocalRef<jclass> clazz(env, FindClassOrDie(env, CLASS_PATH));
201
Andreas Huber9266f992016-08-25 11:21:21 -0700202 jmethodID constructID =
203 GetMethodIDOrDie(env, clazz.get(), "<init>", "(Z)V");
204
205 return env->NewObject(clazz.get(), constructID, false /* allocate */);
Andreas Huberdab5fc62016-08-15 09:25:02 -0700206}
207
208void JHwParcel::setTransactCallback(
209 ::android::hardware::IBinder::TransactCallback cb) {
210 mTransactCallback = cb;
211}
212
213void JHwParcel::send() {
214 CHECK(mTransactCallback != nullptr);
215 CHECK(mParcel != nullptr);
216
217 mTransactCallback(*mParcel);
218 mTransactCallback = nullptr;
219
220 mWasSent = true;
221}
222
223bool JHwParcel::wasSent() const {
224 return mWasSent;
225}
226
227} // namespace android
228
229////////////////////////////////////////////////////////////////////////////////
230
231using namespace android;
232
233static void releaseNativeContext(void *nativeContext) {
234 sp<JHwParcel> parcel = (JHwParcel *)nativeContext;
235
236 if (parcel != NULL) {
237 parcel->decStrong(NULL /* id */);
238 }
239}
240
241static jlong JHwParcel_native_init(JNIEnv *env) {
242 JHwParcel::InitClass(env);
243
244 return reinterpret_cast<jlong>(&releaseNativeContext);
245}
246
247static void JHwParcel_native_setup(
248 JNIEnv *env, jobject thiz, jboolean allocate) {
249 sp<JHwParcel> context = new JHwParcel(env, thiz);
250
251 if (allocate) {
252 context->setParcel(new hardware::Parcel, true /* assumeOwnership */);
253 }
254
255 JHwParcel::SetNativeContext(env, thiz, context);
256}
257
258static void JHwParcel_native_writeInterfaceToken(
259 JNIEnv *env, jobject thiz, jstring interfaceNameObj) {
260 if (interfaceNameObj == NULL) {
261 jniThrowException(env, "java/lang/NullPointerException", NULL);
262 return;
263 }
264
265 const jchar *interfaceName = env->GetStringCritical(interfaceNameObj, NULL);
266 if (interfaceName) {
Steven Morelandab2fca22016-11-11 12:33:41 -0800267 String8 nameCopy = String8(String16(
Andreas Huber9f026862016-11-03 15:46:04 -0700268 reinterpret_cast<const char16_t *>(interfaceName),
Steven Morelandab2fca22016-11-11 12:33:41 -0800269 env->GetStringLength(interfaceNameObj)));
Andreas Huberdab5fc62016-08-15 09:25:02 -0700270
271 env->ReleaseStringCritical(interfaceNameObj, interfaceName);
272 interfaceName = NULL;
273
Andreas Huber9f026862016-11-03 15:46:04 -0700274 hardware::Parcel *parcel =
275 JHwParcel::GetNativeContext(env, thiz)->getParcel();
276
Steven Morelandab2fca22016-11-11 12:33:41 -0800277 status_t err = parcel->writeInterfaceToken(nameCopy.string());
Andreas Huberdab5fc62016-08-15 09:25:02 -0700278 signalExceptionForError(env, err);
279 }
280}
281
282static void JHwParcel_native_enforceInterface(
283 JNIEnv *env, jobject thiz, jstring interfaceNameObj) {
284 // XXX original binder Parcel enforceInterface implementation does some
285 // mysterious things regarding strictModePolicy(), figure out if we need
286 // that here as well.
287 if (interfaceNameObj == NULL) {
288 jniThrowException(env, "java/lang/NullPointerException", NULL);
289 return;
290 }
291
292 const jchar *interfaceName = env->GetStringCritical(interfaceNameObj, NULL);
293 if (interfaceName) {
Steven Morelandab2fca22016-11-11 12:33:41 -0800294 String8 interfaceNameCopy = String8(String16(
Andreas Huber9f026862016-11-03 15:46:04 -0700295 reinterpret_cast<const char16_t *>(interfaceName),
Steven Morelandab2fca22016-11-11 12:33:41 -0800296 env->GetStringLength(interfaceNameObj)));
Andreas Huberdab5fc62016-08-15 09:25:02 -0700297
298 env->ReleaseStringCritical(interfaceNameObj, interfaceName);
299 interfaceName = NULL;
300
Andreas Huber9f026862016-11-03 15:46:04 -0700301 hardware::Parcel *parcel =
302 JHwParcel::GetNativeContext(env, thiz)->getParcel();
303
Steven Morelandab2fca22016-11-11 12:33:41 -0800304 bool valid = parcel->enforceInterface(interfaceNameCopy.string());
Andreas Huber9f026862016-11-03 15:46:04 -0700305
Andreas Huberdab5fc62016-08-15 09:25:02 -0700306 if (!valid) {
307 jniThrowException(
308 env,
309 "java/lang/SecurityException",
310 "HWBinder invocation to an incorrect interface");
311 }
312 }
313}
314
315#define DEFINE_PARCEL_WRITER(Suffix,Type) \
316static void JHwParcel_native_write ## Suffix( \
317 JNIEnv *env, jobject thiz, Type val) { \
318 hardware::Parcel *parcel = \
319 JHwParcel::GetNativeContext(env, thiz)->getParcel(); \
320 \
321 status_t err = parcel->write ## Suffix(val); \
322 signalExceptionForError(env, err); \
323}
324
325#define DEFINE_PARCEL_READER(Suffix,Type) \
326static Type JHwParcel_native_read ## Suffix( \
327 JNIEnv *env, jobject thiz) { \
328 hardware::Parcel *parcel = \
329 JHwParcel::GetNativeContext(env, thiz)->getParcel(); \
330 \
331 Type val; \
332 status_t err = parcel->read ## Suffix(&val); \
333 signalExceptionForError(env, err); \
334 \
335 return val; \
336}
337
Andreas Huber86635bb2016-08-24 16:19:03 -0700338DEFINE_PARCEL_WRITER(Bool,jboolean)
Andreas Huberdab5fc62016-08-15 09:25:02 -0700339DEFINE_PARCEL_WRITER(Int8,jbyte)
340DEFINE_PARCEL_WRITER(Int16,jshort)
341DEFINE_PARCEL_WRITER(Int32,jint)
342DEFINE_PARCEL_WRITER(Int64,jlong)
343DEFINE_PARCEL_WRITER(Float,jfloat)
344DEFINE_PARCEL_WRITER(Double,jdouble)
345
346DEFINE_PARCEL_READER(Int8,jbyte)
347DEFINE_PARCEL_READER(Int16,jshort)
348DEFINE_PARCEL_READER(Int32,jint)
349DEFINE_PARCEL_READER(Int64,jlong)
350DEFINE_PARCEL_READER(Float,jfloat)
351DEFINE_PARCEL_READER(Double,jdouble)
352
Andreas Huber86635bb2016-08-24 16:19:03 -0700353static jboolean JHwParcel_native_readBool(JNIEnv *env, jobject thiz) {
354 hardware::Parcel *parcel =
355 JHwParcel::GetNativeContext(env, thiz)->getParcel();
356
357 bool val;
358 status_t err = parcel->readBool(&val);
359 signalExceptionForError(env, err);
360
361 return (jboolean)val;
362}
363
Andreas Huberdab5fc62016-08-15 09:25:02 -0700364static void JHwParcel_native_writeStatus(
365 JNIEnv *env, jobject thiz, jint statusCode) {
366 using hardware::Status;
367
368 Status status;
369 switch (statusCode) {
370 case 0: // kStatusSuccess
371 status = Status::ok();
372 break;
373 case -1: // kStatusError
374 status = Status::fromStatusT(UNKNOWN_ERROR);
375 break;
376 default:
377 CHECK(!"Should not be here");
378 }
379
380 hardware::Parcel *parcel =
381 JHwParcel::GetNativeContext(env, thiz)->getParcel();
382
Yifan Hongddf31f62016-11-15 16:02:40 -0800383 status_t err = ::android::hardware::writeToParcel(status, parcel);
Andreas Huberdab5fc62016-08-15 09:25:02 -0700384 signalExceptionForError(env, err);
385}
386
387static void JHwParcel_native_verifySuccess(JNIEnv *env, jobject thiz) {
388 using hardware::Status;
389
390 hardware::Parcel *parcel =
391 JHwParcel::GetNativeContext(env, thiz)->getParcel();
392
393 Status status;
Yifan Hongddf31f62016-11-15 16:02:40 -0800394 status_t err = ::android::hardware::readFromParcel(&status, *parcel);
Andreas Huberdab5fc62016-08-15 09:25:02 -0700395 signalExceptionForError(env, err);
Steven Moreland2ef0cbd2018-01-17 13:26:35 -0800396
397 if (!status.isOk()) {
398 signalExceptionForError(env, UNKNOWN_ERROR, true /* canThrowRemoteException */);
399 }
Andreas Huberdab5fc62016-08-15 09:25:02 -0700400}
401
Martijn Coenen3d726d12017-03-16 18:46:42 +0100402static void JHwParcel_native_release(
403 JNIEnv *env, jobject thiz) {
404 JHwParcel::GetNativeContext(env, thiz)->setParcel(NULL, false /* assumeOwnership */);
405}
406
Andreas Huberdab5fc62016-08-15 09:25:02 -0700407static void JHwParcel_native_releaseTemporaryStorage(
408 JNIEnv *env, jobject thiz) {
409 JHwParcel::GetNativeContext(env, thiz)->getStorage()->release(env);
410}
411
412static void JHwParcel_native_send(JNIEnv *env, jobject thiz) {
413 JHwParcel::GetNativeContext(env, thiz)->send();
414}
415
416static void JHwParcel_native_writeString(
417 JNIEnv *env, jobject thiz, jstring valObj) {
418 if (valObj == NULL) {
419 jniThrowException(env, "java/lang/NullPointerException", NULL);
420 return;
421 }
422
423 sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz);
424
425 const hidl_string *s =
426 impl->getStorage()->allocTemporaryString(env, valObj);
427
428 hardware::Parcel *parcel = impl->getParcel();
429
430 size_t parentHandle;
431 status_t err = parcel->writeBuffer(s, sizeof(*s), &parentHandle);
432
433 if (err == OK) {
Yifan Hong3bb65782016-11-11 17:20:54 -0800434 err = ::android::hardware::writeEmbeddedToParcel(
435 *s, parcel, parentHandle, 0 /* parentOffset */);
Andreas Huberdab5fc62016-08-15 09:25:02 -0700436 }
437
438 signalExceptionForError(env, err);
439}
440
Nirav Atre9850dd92018-07-24 17:03:44 -0700441static void JHwParcel_native_writeNativeHandle(JNIEnv *env, jobject thiz, jobject valObj) {
442 sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz);
443
444 EphemeralStorage *storage = impl->getStorage();
445 native_handle_t *handle = JNativeHandle::MakeCppNativeHandle(env, valObj, storage);
446
447 hardware::Parcel *parcel = impl->getParcel();
448 status_t err = parcel->writeNativeHandleNoDup(handle);
449
450 signalExceptionForError(env, err);
451}
452
Andreas Huberdab5fc62016-08-15 09:25:02 -0700453#define DEFINE_PARCEL_VECTOR_WRITER(Suffix,Type) \
454static void JHwParcel_native_write ## Suffix ## Vector( \
455 JNIEnv *env, jobject thiz, Type ## Array valObj) { \
456 if (valObj == NULL) { \
457 jniThrowException(env, "java/lang/NullPointerException", NULL); \
458 return; \
459 } \
460 \
461 sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz); \
462 \
463 const hidl_vec<Type> *vec = \
464 impl->getStorage()->allocTemporary ## Suffix ## Vector(env, valObj); \
465 \
466 hardware::Parcel *parcel = impl->getParcel(); \
467 \
468 size_t parentHandle; \
469 status_t err = parcel->writeBuffer(vec, sizeof(*vec), &parentHandle); \
470 \
471 if (err == OK) { \
472 size_t childHandle; \
473 \
Yifan Hong3bb65782016-11-11 17:20:54 -0800474 err = ::android::hardware::writeEmbeddedToParcel( \
475 *vec, \
Andreas Huberdab5fc62016-08-15 09:25:02 -0700476 parcel, \
477 parentHandle, \
478 0 /* parentOffset */, \
479 &childHandle); \
480 } \
481 \
482 signalExceptionForError(env, err); \
483}
484
Andreas Huberdab5fc62016-08-15 09:25:02 -0700485DEFINE_PARCEL_VECTOR_WRITER(Int8,jbyte)
486DEFINE_PARCEL_VECTOR_WRITER(Int16,jshort)
487DEFINE_PARCEL_VECTOR_WRITER(Int32,jint)
488DEFINE_PARCEL_VECTOR_WRITER(Int64,jlong)
489DEFINE_PARCEL_VECTOR_WRITER(Float,jfloat)
490DEFINE_PARCEL_VECTOR_WRITER(Double,jdouble)
491
Andreas Huber86635bb2016-08-24 16:19:03 -0700492static void JHwParcel_native_writeBoolVector(
493 JNIEnv *env, jobject thiz, jbooleanArray valObj) {
494 if (valObj == NULL) {
495 jniThrowException(env, "java/lang/NullPointerException", NULL);
496 return;
497 }
498
499 sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz);
500
Andreas Huber9266f992016-08-25 11:21:21 -0700501 void *vecPtr =
502 impl->getStorage()->allocTemporaryStorage(sizeof(hidl_vec<bool>));
503
504 hidl_vec<bool> *vec = new (vecPtr) hidl_vec<bool>;
Andreas Huber86635bb2016-08-24 16:19:03 -0700505
506 jsize len = env->GetArrayLength(valObj);
507
508 jboolean *src = env->GetBooleanArrayElements(valObj, nullptr);
509
510 bool *dst =
511 (bool *)impl->getStorage()->allocTemporaryStorage(len * sizeof(bool));
512
513 for (jsize i = 0; i < len; ++i) {
514 dst[i] = src[i];
515 }
516
517 env->ReleaseBooleanArrayElements(valObj, src, 0 /* mode */);
518 src = nullptr;
519
520 vec->setToExternal(dst, len);
521
522 hardware::Parcel *parcel = impl->getParcel();
523
524 size_t parentHandle;
525 status_t err = parcel->writeBuffer(vec, sizeof(*vec), &parentHandle);
526
527 if (err == OK) {
528 size_t childHandle;
529
Yifan Hong3bb65782016-11-11 17:20:54 -0800530 err = ::android::hardware::writeEmbeddedToParcel(
531 *vec,
Andreas Huber86635bb2016-08-24 16:19:03 -0700532 parcel,
533 parentHandle,
534 0 /* parentOffset */,
535 &childHandle);
536 }
537
538 signalExceptionForError(env, err);
539}
540
Nirav Atre9850dd92018-07-24 17:03:44 -0700541template<typename T>
542static void WriteHidlVector(JNIEnv *env, jobject thiz, const hidl_vec<T> &vec) {
543 hardware::Parcel *parcel = JHwParcel::GetNativeContext(env, thiz)->getParcel();
544
545 size_t parentHandle;
546 status_t err = parcel->writeBuffer(&vec, sizeof(vec), &parentHandle);
547
548 if (err == OK) {
549 size_t childHandle;
550 err = ::android::hardware::writeEmbeddedToParcel(
551 vec,
552 parcel,
553 parentHandle,
554 0 /* parentOffset */,
555 &childHandle);
556
557 for (size_t i = 0; (err == OK) && (i < vec.size()); ++i) {
558 err = ::android::hardware::writeEmbeddedToParcel(
559 vec[i],
560 parcel,
561 childHandle,
562 i * sizeof(T));
563 }
564 }
565
566 signalExceptionForError(env, err);
567}
568
569static void JHwParcel_native_writeStringVector(
570 JNIEnv *env, jobject thiz, jobjectArray arrayObj) {
571 if (arrayObj == nullptr) {
572 jniThrowException(env, "java/lang/NullPointerException", nullptr);
573 return;
574 }
575
576 sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz);
577 EphemeralStorage *storage = impl->getStorage();
578
579 void *vecPtr = storage->allocTemporaryStorage(sizeof(hidl_vec<hidl_string>));
580 hidl_vec<hidl_string> *vec = new (vecPtr) hidl_vec<hidl_string>();
581
582 jsize len = env->GetArrayLength(arrayObj);
583 hidl_string *strings = storage->allocStringArray(len);
584 vec->setToExternal(strings, len, false /* shouldOwn */);
585
586 for (jsize i = 0; i < len; ++i) {
587 ScopedLocalRef<jstring> stringObj(env, (jstring) env->GetObjectArrayElement(arrayObj, i));
588
589 const hidl_string *s = storage->allocTemporaryString(env, stringObj.get());
590 strings[i].setToExternal(s->c_str(), s->size());
591 }
592
593 WriteHidlVector(env, thiz, *vec);
594}
595
596static void JHwParcel_native_writeNativeHandleVector(
597 JNIEnv *env, jobject thiz, jobjectArray jHandleArray) {
598 if (jHandleArray == nullptr) {
599 jniThrowException(env, "java/lang/NullPointerException", nullptr);
600 return;
601 }
602
603 sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz);
604 EphemeralStorage *storage = impl->getStorage();
605
606 void *vecPtr = storage->allocTemporaryStorage(sizeof(hidl_vec<hidl_handle>));
607 hidl_vec<hidl_handle> *vec = new (vecPtr) hidl_vec<hidl_handle>();
608
609 jsize len = env->GetArrayLength(jHandleArray);
610 hidl_handle *handles = static_cast<hidl_handle *>(
611 storage->allocTemporaryStorage(len * sizeof(hidl_handle)));
612
613 vec->setToExternal(handles, len, false /* shouldOwn */);
614 for (jsize i = 0; i < len; i++) {
615 ScopedLocalRef<jobject> jHandle(env, env->GetObjectArrayElement(jHandleArray, i));
616
617 native_handle_t* handle = JNativeHandle::MakeCppNativeHandle(env, jHandle.get(), storage);
618
619 new (&(handles[i])) hidl_handle();
620 handles[i].setTo(handle, false /* shouldOwn */);
621 }
622
623 WriteHidlVector(env, thiz, *vec);
624}
625
Andreas Huberdab5fc62016-08-15 09:25:02 -0700626static void JHwParcel_native_writeStrongBinder(
627 JNIEnv *env, jobject thiz, jobject binderObj) {
628 sp<hardware::IBinder> binder;
629 if (binderObj != NULL) {
Nirav Atre9850dd92018-07-24 17:03:44 -0700630 ScopedLocalRef<jclass> hwBinderKlass(env, FindClassOrDie(env, PACKAGE_PATH "/HwBinder"));
Andreas Huberdab5fc62016-08-15 09:25:02 -0700631
632 ScopedLocalRef<jclass> hwRemoteBinderKlass(
633 env, FindClassOrDie(env, PACKAGE_PATH "/HwRemoteBinder"));
634
635 if (env->IsInstanceOf(binderObj, hwBinderKlass.get())) {
Andreas Huber56bdb8a2017-06-16 14:56:12 -0700636 binder = JHwBinder::GetNativeBinder(env, binderObj);
Andreas Huberdab5fc62016-08-15 09:25:02 -0700637 } else if (env->IsInstanceOf(binderObj, hwRemoteBinderKlass.get())) {
638 binder = JHwRemoteBinder::GetNativeContext(
639 env, binderObj)->getBinder();
640 } else {
641 signalExceptionForError(env, INVALID_OPERATION);
642 return;
643 }
644 }
645
646 hardware::Parcel *parcel =
647 JHwParcel::GetNativeContext(env, thiz)->getParcel();
648
649 status_t err = parcel->writeStrongBinder(binder);
650 signalExceptionForError(env, err);
651}
652
653static jstring MakeStringObjFromHidlString(JNIEnv *env, const hidl_string &s) {
654 String16 utf16String(s.c_str(), s.size());
655
656 return env->NewString(
657 reinterpret_cast<const jchar *>(utf16String.string()),
658 utf16String.size());
659}
660
661static jstring JHwParcel_native_readString(JNIEnv *env, jobject thiz) {
662 hardware::Parcel *parcel =
663 JHwParcel::GetNativeContext(env, thiz)->getParcel();
664
665 size_t parentHandle;
666
Martijn Coenen24c82272017-01-11 12:35:56 +0100667 const hidl_string *s;
Martijn Coenen7c006392017-04-18 15:54:43 -0700668 status_t err = parcel->readBuffer(sizeof(*s), &parentHandle,
Martijn Coenen24c82272017-01-11 12:35:56 +0100669 reinterpret_cast<const void**>(&s));
Andreas Huberdab5fc62016-08-15 09:25:02 -0700670
Martijn Coenen24c82272017-01-11 12:35:56 +0100671 if (err != OK) {
672 signalExceptionForError(env, err);
Andreas Huberdab5fc62016-08-15 09:25:02 -0700673 return NULL;
674 }
675
Martijn Coenen24c82272017-01-11 12:35:56 +0100676 err = ::android::hardware::readEmbeddedFromParcel(
Martijn Coenen7c006392017-04-18 15:54:43 -0700677 const_cast<hidl_string &>(*s),
Andreas Huberdab5fc62016-08-15 09:25:02 -0700678 *parcel, parentHandle, 0 /* parentOffset */);
679
680 if (err != OK) {
681 signalExceptionForError(env, err);
682 return NULL;
683 }
684
685 return MakeStringObjFromHidlString(env, *s);
686}
687
Nirav Atre9850dd92018-07-24 17:03:44 -0700688static jobject ReadNativeHandle(JNIEnv *env, jobject thiz, jboolean embedded,
689 jlong parentHandle, jlong offset) {
690 hardware::Parcel *parcel =
691 JHwParcel::GetNativeContext(env, thiz)->getParcel();
692
693 const native_handle_t *handle = nullptr;
694 status_t err = OK;
695
696 if (embedded) {
697 err = parcel->readNullableEmbeddedNativeHandle(parentHandle, offset, &handle);
698 } else {
699 err = parcel->readNullableNativeHandleNoDup(&handle);
700 }
701
702 if (err != OK) {
703 signalExceptionForError(env, err);
704 return nullptr;
705 }
706
707 return JNativeHandle::MakeJavaNativeHandleObj(env, handle);
708}
709
710static jobject JHwParcel_native_readNativeHandle(JNIEnv *env, jobject thiz) {
711 return ReadNativeHandle(env, thiz, false /*embedded*/, 0L /*parentHandle*/, 0L /*offset*/);
712}
713
714static jobject JHwParcel_native_readEmbeddedNativeHandle(
715 JNIEnv *env, jobject thiz, jlong parentHandle, jlong offset) {
716 return ReadNativeHandle(env, thiz, true /*embedded*/, parentHandle, offset);
717}
718
Andreas Huberdab5fc62016-08-15 09:25:02 -0700719#define DEFINE_PARCEL_VECTOR_READER(Suffix,Type,NewType) \
720static Type ## Array JHwParcel_native_read ## Suffix ## Vector( \
721 JNIEnv *env, jobject thiz) { \
722 hardware::Parcel *parcel = \
723 JHwParcel::GetNativeContext(env, thiz)->getParcel(); \
Andreas Huberdab5fc62016-08-15 09:25:02 -0700724 size_t parentHandle; \
725 \
Martijn Coenen24c82272017-01-11 12:35:56 +0100726 const hidl_vec<Type> *vec; \
Martijn Coenen7c006392017-04-18 15:54:43 -0700727 status_t err = parcel->readBuffer(sizeof(*vec), &parentHandle, \
Martijn Coenen24c82272017-01-11 12:35:56 +0100728 reinterpret_cast<const void**>(&vec)); \
Andreas Huberdab5fc62016-08-15 09:25:02 -0700729 \
Martijn Coenen24c82272017-01-11 12:35:56 +0100730 if (err != OK) { \
731 signalExceptionForError(env, err); \
Andreas Huberdab5fc62016-08-15 09:25:02 -0700732 return NULL; \
733 } \
734 \
735 size_t childHandle; \
736 \
Martijn Coenen24c82272017-01-11 12:35:56 +0100737 err = ::android::hardware::readEmbeddedFromParcel( \
Martijn Coenen7c006392017-04-18 15:54:43 -0700738 const_cast<hidl_vec<Type> &>(*vec), \
Andreas Huberdab5fc62016-08-15 09:25:02 -0700739 *parcel, \
740 parentHandle, \
741 0 /* parentOffset */, \
742 &childHandle); \
743 \
744 if (err != OK) { \
745 signalExceptionForError(env, err); \
746 return NULL; \
747 } \
748 \
749 Type ## Array valObj = env->New ## NewType ## Array(vec->size()); \
750 env->Set ## NewType ## ArrayRegion(valObj, 0, vec->size(), &(*vec)[0]); \
751 \
752 return valObj; \
753}
754
Andreas Huberdab5fc62016-08-15 09:25:02 -0700755DEFINE_PARCEL_VECTOR_READER(Int8,jbyte,Byte)
756DEFINE_PARCEL_VECTOR_READER(Int16,jshort,Short)
757DEFINE_PARCEL_VECTOR_READER(Int32,jint,Int)
758DEFINE_PARCEL_VECTOR_READER(Int64,jlong,Long)
759DEFINE_PARCEL_VECTOR_READER(Float,jfloat,Float)
760DEFINE_PARCEL_VECTOR_READER(Double,jdouble,Double)
761
Nirav Atre9850dd92018-07-24 17:03:44 -0700762static jbooleanArray JHwParcel_native_readBoolVector(JNIEnv *env, jobject thiz) {
763 hardware::Parcel *parcel = JHwParcel::GetNativeContext(env, thiz)->getParcel();
Andreas Huber86635bb2016-08-24 16:19:03 -0700764
765 size_t parentHandle;
766
Martijn Coenen24c82272017-01-11 12:35:56 +0100767 const hidl_vec<bool> *vec;
Martijn Coenen7c006392017-04-18 15:54:43 -0700768 status_t err = parcel->readBuffer(sizeof(*vec), &parentHandle,
Martijn Coenen24c82272017-01-11 12:35:56 +0100769 reinterpret_cast<const void**>(&vec));
Andreas Huber86635bb2016-08-24 16:19:03 -0700770
Martijn Coenen24c82272017-01-11 12:35:56 +0100771 if (err != OK) {
772 signalExceptionForError(env, err);
Andreas Huber86635bb2016-08-24 16:19:03 -0700773 return NULL;
774 }
775
776 size_t childHandle;
777
Martijn Coenen24c82272017-01-11 12:35:56 +0100778 err = ::android::hardware::readEmbeddedFromParcel(
Martijn Coenen7c006392017-04-18 15:54:43 -0700779 const_cast<hidl_vec<bool> &>(*vec),
Andreas Huber86635bb2016-08-24 16:19:03 -0700780 *parcel,
781 parentHandle,
782 0 /* parentOffset */,
783 &childHandle);
784
785 if (err != OK) {
786 signalExceptionForError(env, err);
787 return NULL;
788 }
789
790 jbooleanArray valObj = env->NewBooleanArray(vec->size());
791
792 for (size_t i = 0; i < vec->size(); ++i) {
793 jboolean x = (*vec)[i];
794 env->SetBooleanArrayRegion(valObj, i, 1, &x);
795 }
796
797 return valObj;
798}
799
Andreas Huberdab5fc62016-08-15 09:25:02 -0700800static jobjectArray MakeStringArray(
801 JNIEnv *env, const hidl_string *array, size_t size) {
802 ScopedLocalRef<jclass> stringKlass(
803 env,
804 env->FindClass("java/lang/String"));
805
806 // XXX Why can't I use ScopedLocalRef<> for the arrayObj and the stringObjs?
807
808 jobjectArray arrayObj = env->NewObjectArray(size, stringKlass.get(), NULL);
809
810 for (size_t i = 0; i < size; ++i) {
811 jstring stringObj = MakeStringObjFromHidlString(env, array[i]);
812
813 env->SetObjectArrayElement(
814 arrayObj,
815 i,
816 stringObj);
817 }
818
819 return arrayObj;
820}
821
Nirav Atre9850dd92018-07-24 17:03:44 -0700822template<typename T>
823static const hidl_vec<T> *ReadHidlVector(JNIEnv *env, jobject thiz) {
824 const hidl_vec<T> *vec;
Andreas Huberdab5fc62016-08-15 09:25:02 -0700825
Nirav Atre9850dd92018-07-24 17:03:44 -0700826 hardware::Parcel *parcel = JHwParcel::GetNativeContext(env, thiz)->getParcel();
Andreas Huberdab5fc62016-08-15 09:25:02 -0700827
828 size_t parentHandle;
Nirav Atre9850dd92018-07-24 17:03:44 -0700829 status_t err = parcel->readBuffer(sizeof(hidl_vec<T>),
830 &parentHandle, reinterpret_cast<const void **>(&vec));
Andreas Huberdab5fc62016-08-15 09:25:02 -0700831
832 if (err == OK) {
833 size_t childHandle;
Nirav Atre9850dd92018-07-24 17:03:44 -0700834 err = ::android::hardware::readEmbeddedFromParcel(
835 const_cast<hidl_vec<T> &>(*vec),
836 *parcel, parentHandle,
Andreas Huberdab5fc62016-08-15 09:25:02 -0700837 0 /* parentOffset */,
838 &childHandle);
839
Nirav Atre9850dd92018-07-24 17:03:44 -0700840 for (size_t i = 0; (err == OK) && (i < vec->size()); i++) {
841 err = android::hardware::readEmbeddedFromParcel(
842 const_cast<T &>((*vec)[i]),
843 *parcel,
Andreas Huberdab5fc62016-08-15 09:25:02 -0700844 childHandle,
Nirav Atre9850dd92018-07-24 17:03:44 -0700845 i * sizeof(T) /* parentOffset */);
Andreas Huberdab5fc62016-08-15 09:25:02 -0700846 }
847 }
848
Nirav Atre9850dd92018-07-24 17:03:44 -0700849 if (err != OK) {
850 signalExceptionForError(env, err);
851 return nullptr;
852 }
853
854 return vec;
855}
856
857static jobjectArray JHwParcel_native_readStringVector(
858 JNIEnv *env, jobject thiz) {
859 const hidl_vec<hidl_string> *vec = ReadHidlVector<hidl_string>(env, thiz);
860 return MakeStringArray(env, &(*vec)[0], vec->size());
861}
862
863static jobjectArray JHwParcel_native_readNativeHandleVector(
864 JNIEnv *env, jobject thiz) {
865 const hidl_vec<hidl_handle> *vec = ReadHidlVector<hidl_handle>(env, thiz);
866
867 jsize length = vec->size();
868 jobjectArray objArray = JNativeHandle::AllocJavaNativeHandleObjArray(
869 env, length);
870
871 for (jsize i = 0; i < length; i++) {
872 jobject jHandle = JNativeHandle::MakeJavaNativeHandleObj(env, (*vec)[i].getNativeHandle());
873
874 env->SetObjectArrayElement(objArray, i, jHandle);
875 }
876
877 return objArray;
Andreas Huberdab5fc62016-08-15 09:25:02 -0700878}
879
880static jobject JHwParcel_native_readStrongBinder(JNIEnv *env, jobject thiz) {
881 hardware::Parcel *parcel =
882 JHwParcel::GetNativeContext(env, thiz)->getParcel();
883
884 sp<hardware::IBinder> binder = parcel->readStrongBinder();
885
886 if (binder == NULL) {
887 return NULL;
888 }
889
890 return JHwRemoteBinder::NewObject(env, binder);
891}
892
Martijn Coenen7c006392017-04-18 15:54:43 -0700893static jobject JHwParcel_native_readBuffer(JNIEnv *env, jobject thiz,
894 jlong expectedSize) {
Andreas Huber9266f992016-08-25 11:21:21 -0700895 hardware::Parcel *parcel =
896 JHwParcel::GetNativeContext(env, thiz)->getParcel();
897
898 size_t handle;
Martijn Coenen24c82272017-01-11 12:35:56 +0100899 const void *ptr;
Martijn Coenen7c006392017-04-18 15:54:43 -0700900
901 if (expectedSize < 0) {
902 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
903 return nullptr;
904 }
905
906 status_t status = parcel->readBuffer(expectedSize, &handle, &ptr);
Andreas Huber9266f992016-08-25 11:21:21 -0700907
Martijn Coenen24c82272017-01-11 12:35:56 +0100908 if (status != OK) {
Andreas Huber9266f992016-08-25 11:21:21 -0700909 jniThrowException(env, "java/util/NoSuchElementException", NULL);
910 return nullptr;
911 }
912
913 return JHwBlob::NewObject(env, ptr, handle);
914}
915
916static jobject JHwParcel_native_readEmbeddedBuffer(
Martijn Coenen7c006392017-04-18 15:54:43 -0700917 JNIEnv *env, jobject thiz, jlong expectedSize,
918 jlong parentHandle, jlong offset, jboolean nullable) {
Andreas Huber9266f992016-08-25 11:21:21 -0700919 hardware::Parcel *parcel =
920 JHwParcel::GetNativeContext(env, thiz)->getParcel();
921
922 size_t childHandle;
923
Martijn Coenen24c82272017-01-11 12:35:56 +0100924 const void *ptr;
925 status_t status =
Martijn Coenen7c006392017-04-18 15:54:43 -0700926 parcel->readNullableEmbeddedBuffer(expectedSize,
927 &childHandle, parentHandle, offset, &ptr);
928
929 if (expectedSize < 0) {
930 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
931 return nullptr;
932 }
Andreas Huber9266f992016-08-25 11:21:21 -0700933
Martijn Coenen24c82272017-01-11 12:35:56 +0100934 if (status != OK) {
Andreas Huber9266f992016-08-25 11:21:21 -0700935 jniThrowException(env, "java/util/NoSuchElementException", NULL);
936 return 0;
Martijn Coenen14fae062017-01-13 11:08:51 +0100937 } else if (status == OK && !nullable && ptr == nullptr) {
938 jniThrowException(env, "java/lang/NullPointerException", NULL);
939 return 0;
Andreas Huber9266f992016-08-25 11:21:21 -0700940 }
941
942 return JHwBlob::NewObject(env, ptr, childHandle);
943}
944
945static void JHwParcel_native_writeBuffer(
946 JNIEnv *env, jobject thiz, jobject blobObj) {
947 if (blobObj == nullptr) {
948 jniThrowException(env, "java/lang/NullPointerException", NULL);
949 return;
950 }
951
952 hardware::Parcel *parcel =
953 JHwParcel::GetNativeContext(env, thiz)->getParcel();
954
955 sp<JHwBlob> blob = JHwBlob::GetNativeContext(env, blobObj);
956 status_t err = blob->writeToParcel(parcel);
957
958 if (err != OK) {
959 signalExceptionForError(env, err);
960 }
961}
962
Andreas Huberdab5fc62016-08-15 09:25:02 -0700963static JNINativeMethod gMethods[] = {
964 { "native_init", "()J", (void *)JHwParcel_native_init },
965 { "native_setup", "(Z)V", (void *)JHwParcel_native_setup },
966
967 { "writeInterfaceToken", "(Ljava/lang/String;)V",
968 (void *)JHwParcel_native_writeInterfaceToken },
969
Andreas Huber86635bb2016-08-24 16:19:03 -0700970 { "writeBool", "(Z)V", (void *)JHwParcel_native_writeBool },
Andreas Huberdab5fc62016-08-15 09:25:02 -0700971 { "writeInt8", "(B)V", (void *)JHwParcel_native_writeInt8 },
972 { "writeInt16", "(S)V", (void *)JHwParcel_native_writeInt16 },
973 { "writeInt32", "(I)V", (void *)JHwParcel_native_writeInt32 },
974 { "writeInt64", "(J)V", (void *)JHwParcel_native_writeInt64 },
975 { "writeFloat", "(F)V", (void *)JHwParcel_native_writeFloat },
976 { "writeDouble", "(D)V", (void *)JHwParcel_native_writeDouble },
977
978 { "writeString", "(Ljava/lang/String;)V",
979 (void *)JHwParcel_native_writeString },
980
Nirav Atre9850dd92018-07-24 17:03:44 -0700981 { "writeNativeHandle", "(L" PACKAGE_PATH "/NativeHandle;)V",
982 (void *)JHwParcel_native_writeNativeHandle },
983
Andreas Huber86635bb2016-08-24 16:19:03 -0700984 { "writeBoolVector", "([Z)V", (void *)JHwParcel_native_writeBoolVector },
Andreas Huberdab5fc62016-08-15 09:25:02 -0700985 { "writeInt8Vector", "([B)V", (void *)JHwParcel_native_writeInt8Vector },
Andreas Huberdab5fc62016-08-15 09:25:02 -0700986 { "writeInt16Vector", "([S)V", (void *)JHwParcel_native_writeInt16Vector },
Andreas Huberdab5fc62016-08-15 09:25:02 -0700987 { "writeInt32Vector", "([I)V", (void *)JHwParcel_native_writeInt32Vector },
Andreas Huberdab5fc62016-08-15 09:25:02 -0700988 { "writeInt64Vector", "([J)V", (void *)JHwParcel_native_writeInt64Vector },
Andreas Huberdab5fc62016-08-15 09:25:02 -0700989 { "writeFloatVector", "([F)V", (void *)JHwParcel_native_writeFloatVector },
Andreas Huberdab5fc62016-08-15 09:25:02 -0700990
991 { "writeDoubleVector", "([D)V",
992 (void *)JHwParcel_native_writeDoubleVector },
993
Andreas Huberdab5fc62016-08-15 09:25:02 -0700994 { "writeStringVector", "([Ljava/lang/String;)V",
995 (void *)JHwParcel_native_writeStringVector },
996
Nirav Atre9850dd92018-07-24 17:03:44 -0700997 { "writeNativeHandleVector", "([L" PACKAGE_PATH "/NativeHandle;)V",
998 (void *)JHwParcel_native_writeNativeHandleVector },
999
Andreas Huberdab5fc62016-08-15 09:25:02 -07001000 { "writeStrongBinder", "(L" PACKAGE_PATH "/IHwBinder;)V",
1001 (void *)JHwParcel_native_writeStrongBinder },
1002
1003 { "enforceInterface", "(Ljava/lang/String;)V",
1004 (void *)JHwParcel_native_enforceInterface },
1005
Andreas Huber86635bb2016-08-24 16:19:03 -07001006 { "readBool", "()Z", (void *)JHwParcel_native_readBool },
Andreas Huberdab5fc62016-08-15 09:25:02 -07001007 { "readInt8", "()B", (void *)JHwParcel_native_readInt8 },
1008 { "readInt16", "()S", (void *)JHwParcel_native_readInt16 },
1009 { "readInt32", "()I", (void *)JHwParcel_native_readInt32 },
1010 { "readInt64", "()J", (void *)JHwParcel_native_readInt64 },
1011 { "readFloat", "()F", (void *)JHwParcel_native_readFloat },
1012 { "readDouble", "()D", (void *)JHwParcel_native_readDouble },
1013
1014 { "readString", "()Ljava/lang/String;",
1015 (void *)JHwParcel_native_readString },
1016
Nirav Atre9850dd92018-07-24 17:03:44 -07001017 { "readNativeHandle", "()L" PACKAGE_PATH "/NativeHandle;",
1018 (void *)JHwParcel_native_readNativeHandle },
1019
1020 { "readEmbeddedNativeHandle", "(JJ)L" PACKAGE_PATH "/NativeHandle;",
1021 (void *)JHwParcel_native_readEmbeddedNativeHandle },
1022
Andreas Huberef1a5652016-10-18 09:24:04 -07001023 { "readBoolVectorAsArray", "()[Z",
1024 (void *)JHwParcel_native_readBoolVector },
Andreas Huberdab5fc62016-08-15 09:25:02 -07001025
Andreas Huberef1a5652016-10-18 09:24:04 -07001026 { "readInt8VectorAsArray", "()[B",
1027 (void *)JHwParcel_native_readInt8Vector },
1028
1029 { "readInt16VectorAsArray", "()[S",
1030 (void *)JHwParcel_native_readInt16Vector },
1031
1032 { "readInt32VectorAsArray", "()[I",
1033 (void *)JHwParcel_native_readInt32Vector },
1034
1035 { "readInt64VectorAsArray", "()[J",
1036 (void *)JHwParcel_native_readInt64Vector },
1037
1038 { "readFloatVectorAsArray", "()[F",
1039 (void *)JHwParcel_native_readFloatVector },
1040
1041 { "readDoubleVectorAsArray", "()[D",
1042 (void *)JHwParcel_native_readDoubleVector },
1043
1044 { "readStringVectorAsArray", "()[Ljava/lang/String;",
Andreas Huberdab5fc62016-08-15 09:25:02 -07001045 (void *)JHwParcel_native_readStringVector },
1046
Nirav Atre9850dd92018-07-24 17:03:44 -07001047 { "readNativeHandleAsArray", "()[L" PACKAGE_PATH "/NativeHandle;",
1048 (void *)JHwParcel_native_readNativeHandleVector },
1049
Andreas Huberdab5fc62016-08-15 09:25:02 -07001050 { "readStrongBinder", "()L" PACKAGE_PATH "/IHwBinder;",
1051 (void *)JHwParcel_native_readStrongBinder },
1052
1053 { "writeStatus", "(I)V", (void *)JHwParcel_native_writeStatus },
1054
1055 { "verifySuccess", "()V", (void *)JHwParcel_native_verifySuccess },
1056
1057 { "releaseTemporaryStorage", "()V",
1058 (void *)JHwParcel_native_releaseTemporaryStorage },
1059
1060 { "send", "()V", (void *)JHwParcel_native_send },
Andreas Huber9266f992016-08-25 11:21:21 -07001061
Martijn Coenen7c006392017-04-18 15:54:43 -07001062 { "readBuffer", "(J)L" PACKAGE_PATH "/HwBlob;",
Andreas Huber9266f992016-08-25 11:21:21 -07001063 (void *)JHwParcel_native_readBuffer },
1064
Martijn Coenen7c006392017-04-18 15:54:43 -07001065 { "readEmbeddedBuffer", "(JJJZ)L" PACKAGE_PATH "/HwBlob;",
Andreas Huber9266f992016-08-25 11:21:21 -07001066 (void *)JHwParcel_native_readEmbeddedBuffer },
1067
1068 { "writeBuffer", "(L" PACKAGE_PATH "/HwBlob;)V",
1069 (void *)JHwParcel_native_writeBuffer },
Martijn Coenen3d726d12017-03-16 18:46:42 +01001070
1071 { "release", "()V",
1072 (void *)JHwParcel_native_release },
1073
Andreas Huberdab5fc62016-08-15 09:25:02 -07001074};
1075
1076namespace android {
1077
1078int register_android_os_HwParcel(JNIEnv *env) {
1079 return RegisterMethodsOrDie(env, CLASS_PATH, gMethods, NELEM(gMethods));
1080}
1081
1082} // namespace android