blob: d453b29c0663e0779dccd686069d5c13d6ee0a91 [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"
Andreas Huberdab5fc62016-08-15 09:25:02 -070025#include "android_os_HwRemoteBinder.h"
26
27#include <JNIHelp.h>
28#include <android_runtime/AndroidRuntime.h>
Martijn Coenenaa2c32f2016-09-01 01:37:05 +020029#include <hidl/Status.h>
Andreas Huberdab5fc62016-08-15 09:25:02 -070030#include <nativehelper/ScopedLocalRef.h>
31
32#include "core_jni_helpers.h"
33
34using android::AndroidRuntime;
35
36using ::android::hardware::hidl_string;
37using ::android::hardware::hidl_vec;
38
39#define PACKAGE_PATH "android/os"
40#define CLASS_NAME "HwParcel"
41#define CLASS_PATH PACKAGE_PATH "/" CLASS_NAME
42
43namespace android {
44
45static struct fields_t {
46 jfieldID contextID;
47 jmethodID constructID;
48
49} gFields;
50
51void signalExceptionForError(JNIEnv *env, status_t err) {
52 switch (err) {
53 case OK:
54 break;
55
56 case NO_MEMORY:
57 {
58 jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
59 break;
60 }
61
62 case INVALID_OPERATION:
63 {
64 jniThrowException(
65 env, "java/lang/UnsupportedOperationException", NULL);
66 break;
67 }
68
69 case BAD_VALUE:
70 {
71 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
72 break;
73 }
74
Andreas Huber9266f992016-08-25 11:21:21 -070075 case -ERANGE:
Andreas Huberdab5fc62016-08-15 09:25:02 -070076 case BAD_INDEX:
77 {
78 jniThrowException(env, "java/lang/IndexOutOfBoundsException", NULL);
79 break;
80 }
81
82 case BAD_TYPE:
83 {
84 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
85 break;
86 }
87
88 case NAME_NOT_FOUND:
89 {
90 jniThrowException(env, "java/util/NoSuchElementException", NULL);
91 break;
92 }
93
94 case PERMISSION_DENIED:
95 {
96 jniThrowException(env, "java/lang/SecurityException", NULL);
97 break;
98 }
99
100 case NO_INIT:
101 {
102 jniThrowException(
103 env, "java/lang/RuntimeException", "Not initialized");
104 break;
105 }
106
107 case ALREADY_EXISTS:
108 {
109 jniThrowException(
110 env, "java/lang/RuntimeException", "Item already exists");
111 break;
112 }
113
114 default:
115 {
116 jniThrowException(
117 env, "java/lang/RuntimeException", "Unknown error");
118
119 break;
120 }
121 }
122}
123
124// static
125void JHwParcel::InitClass(JNIEnv *env) {
126 ScopedLocalRef<jclass> clazz(
127 env, FindClassOrDie(env, CLASS_PATH));
128
129 gFields.contextID =
130 GetFieldIDOrDie(env, clazz.get(), "mNativeContext", "J");
131
132 gFields.constructID = GetMethodIDOrDie(env, clazz.get(), "<init>", "(Z)V");
133}
134
135// static
136sp<JHwParcel> JHwParcel::SetNativeContext(
137 JNIEnv *env, jobject thiz, const sp<JHwParcel> &context) {
138 sp<JHwParcel> old = (JHwParcel *)env->GetLongField(thiz, gFields.contextID);
139
140 if (context != NULL) {
141 context->incStrong(NULL /* id */);
142 }
143
144 if (old != NULL) {
145 old->decStrong(NULL /* id */);
146 }
147
148 env->SetLongField(thiz, gFields.contextID, (long)context.get());
149
150 return old;
151}
152
153// static
154sp<JHwParcel> JHwParcel::GetNativeContext(JNIEnv *env, jobject thiz) {
155 return (JHwParcel *)env->GetLongField(thiz, gFields.contextID);
156}
157
158JHwParcel::JHwParcel(JNIEnv *env, jobject thiz)
159 : mParcel(NULL),
160 mOwnsParcel(false),
161 mTransactCallback(nullptr),
162 mWasSent(false) {
163 jclass clazz = env->GetObjectClass(thiz);
164 CHECK(clazz != NULL);
165
166 mClass = (jclass)env->NewGlobalRef(clazz);
167 mObject = env->NewWeakGlobalRef(thiz);
168}
169
170JHwParcel::~JHwParcel() {
171 JNIEnv *env = AndroidRuntime::getJNIEnv();
172
173 mStorage.release(env);
174
175 setParcel(NULL, false /* assumeOwnership */);
176
177 env->DeleteWeakGlobalRef(mObject);
178 mObject = NULL;
179
180 env->DeleteGlobalRef(mClass);
181 mClass = NULL;
182}
183
184hardware::Parcel *JHwParcel::getParcel() {
185 return mParcel;
186}
187
188EphemeralStorage *JHwParcel::getStorage() {
189 return &mStorage;
190}
191
192void 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
202jobject JHwParcel::NewObject(JNIEnv *env) {
203 ScopedLocalRef<jclass> clazz(env, FindClassOrDie(env, CLASS_PATH));
204
Andreas Huber9266f992016-08-25 11:21:21 -0700205 jmethodID constructID =
206 GetMethodIDOrDie(env, clazz.get(), "<init>", "(Z)V");
207
208 return env->NewObject(clazz.get(), constructID, false /* allocate */);
Andreas Huberdab5fc62016-08-15 09:25:02 -0700209}
210
211void JHwParcel::setTransactCallback(
212 ::android::hardware::IBinder::TransactCallback cb) {
213 mTransactCallback = cb;
214}
215
216void JHwParcel::send() {
217 CHECK(mTransactCallback != nullptr);
218 CHECK(mParcel != nullptr);
219
220 mTransactCallback(*mParcel);
221 mTransactCallback = nullptr;
222
223 mWasSent = true;
224}
225
226bool JHwParcel::wasSent() const {
227 return mWasSent;
228}
229
230} // namespace android
231
232////////////////////////////////////////////////////////////////////////////////
233
234using namespace android;
235
236static void releaseNativeContext(void *nativeContext) {
237 sp<JHwParcel> parcel = (JHwParcel *)nativeContext;
238
239 if (parcel != NULL) {
240 parcel->decStrong(NULL /* id */);
241 }
242}
243
244static jlong JHwParcel_native_init(JNIEnv *env) {
245 JHwParcel::InitClass(env);
246
247 return reinterpret_cast<jlong>(&releaseNativeContext);
248}
249
250static 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
261static 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 hardware::Parcel *parcel =
271 JHwParcel::GetNativeContext(env, thiz)->getParcel();
272
273 status_t err = parcel->writeInterfaceToken(
274 String16(
275 reinterpret_cast<const char16_t *>(interfaceName),
276 env->GetStringLength(interfaceNameObj)));
277
278 env->ReleaseStringCritical(interfaceNameObj, interfaceName);
279 interfaceName = NULL;
280
281 signalExceptionForError(env, err);
282 }
283}
284
285static 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 hardware::Parcel *parcel =
298 JHwParcel::GetNativeContext(env, thiz)->getParcel();
299
300 bool valid = parcel->enforceInterface(
301 String16(
302 reinterpret_cast<const char16_t *>(interfaceName),
303 env->GetStringLength(interfaceNameObj)));
304
305 env->ReleaseStringCritical(interfaceNameObj, interfaceName);
306 interfaceName = NULL;
307
308 if (!valid) {
309 jniThrowException(
310 env,
311 "java/lang/SecurityException",
312 "HWBinder invocation to an incorrect interface");
313 }
314 }
315}
316
317#define DEFINE_PARCEL_WRITER(Suffix,Type) \
318static void JHwParcel_native_write ## Suffix( \
319 JNIEnv *env, jobject thiz, Type val) { \
320 hardware::Parcel *parcel = \
321 JHwParcel::GetNativeContext(env, thiz)->getParcel(); \
322 \
323 status_t err = parcel->write ## Suffix(val); \
324 signalExceptionForError(env, err); \
325}
326
327#define DEFINE_PARCEL_READER(Suffix,Type) \
328static Type JHwParcel_native_read ## Suffix( \
329 JNIEnv *env, jobject thiz) { \
330 hardware::Parcel *parcel = \
331 JHwParcel::GetNativeContext(env, thiz)->getParcel(); \
332 \
333 Type val; \
334 status_t err = parcel->read ## Suffix(&val); \
335 signalExceptionForError(env, err); \
336 \
337 return val; \
338}
339
Andreas Huber86635bb2016-08-24 16:19:03 -0700340DEFINE_PARCEL_WRITER(Bool,jboolean)
Andreas Huberdab5fc62016-08-15 09:25:02 -0700341DEFINE_PARCEL_WRITER(Int8,jbyte)
342DEFINE_PARCEL_WRITER(Int16,jshort)
343DEFINE_PARCEL_WRITER(Int32,jint)
344DEFINE_PARCEL_WRITER(Int64,jlong)
345DEFINE_PARCEL_WRITER(Float,jfloat)
346DEFINE_PARCEL_WRITER(Double,jdouble)
347
348DEFINE_PARCEL_READER(Int8,jbyte)
349DEFINE_PARCEL_READER(Int16,jshort)
350DEFINE_PARCEL_READER(Int32,jint)
351DEFINE_PARCEL_READER(Int64,jlong)
352DEFINE_PARCEL_READER(Float,jfloat)
353DEFINE_PARCEL_READER(Double,jdouble)
354
Andreas Huber86635bb2016-08-24 16:19:03 -0700355static jboolean JHwParcel_native_readBool(JNIEnv *env, jobject thiz) {
356 hardware::Parcel *parcel =
357 JHwParcel::GetNativeContext(env, thiz)->getParcel();
358
359 bool val;
360 status_t err = parcel->readBool(&val);
361 signalExceptionForError(env, err);
362
363 return (jboolean)val;
364}
365
Andreas Huberdab5fc62016-08-15 09:25:02 -0700366static void JHwParcel_native_writeStatus(
367 JNIEnv *env, jobject thiz, jint statusCode) {
368 using hardware::Status;
369
370 Status status;
371 switch (statusCode) {
372 case 0: // kStatusSuccess
373 status = Status::ok();
374 break;
375 case -1: // kStatusError
376 status = Status::fromStatusT(UNKNOWN_ERROR);
377 break;
378 default:
379 CHECK(!"Should not be here");
380 }
381
382 hardware::Parcel *parcel =
383 JHwParcel::GetNativeContext(env, thiz)->getParcel();
384
385 status_t err = status.writeToParcel(parcel);
386 signalExceptionForError(env, err);
387}
388
389static void JHwParcel_native_verifySuccess(JNIEnv *env, jobject thiz) {
390 using hardware::Status;
391
392 hardware::Parcel *parcel =
393 JHwParcel::GetNativeContext(env, thiz)->getParcel();
394
395 Status status;
396 status_t err = status.readFromParcel(*parcel);
397 signalExceptionForError(env, err);
398}
399
400static void JHwParcel_native_releaseTemporaryStorage(
401 JNIEnv *env, jobject thiz) {
402 JHwParcel::GetNativeContext(env, thiz)->getStorage()->release(env);
403}
404
405static void JHwParcel_native_send(JNIEnv *env, jobject thiz) {
406 JHwParcel::GetNativeContext(env, thiz)->send();
407}
408
409static void JHwParcel_native_writeString(
410 JNIEnv *env, jobject thiz, jstring valObj) {
411 if (valObj == NULL) {
412 jniThrowException(env, "java/lang/NullPointerException", NULL);
413 return;
414 }
415
416 sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz);
417
418 const hidl_string *s =
419 impl->getStorage()->allocTemporaryString(env, valObj);
420
421 hardware::Parcel *parcel = impl->getParcel();
422
423 size_t parentHandle;
424 status_t err = parcel->writeBuffer(s, sizeof(*s), &parentHandle);
425
426 if (err == OK) {
427 err = s->writeEmbeddedToParcel(
428 parcel, parentHandle, 0 /* parentOffset */);
429 }
430
431 signalExceptionForError(env, err);
432}
433
434#define DEFINE_PARCEL_ARRAY_WRITER(Suffix,Type) \
435static void JHwParcel_native_write ## Suffix ## Array( \
436 JNIEnv *env, jobject thiz, jint size, Type ## Array valObj) { \
437 if (valObj == NULL) { \
438 jniThrowException(env, "java/lang/NullPointerException", NULL); \
439 return; \
440 } \
441 \
442 jsize len = env->GetArrayLength(valObj); \
443 \
444 if (len != size) { \
445 jniThrowException(env, "java/lang/IllegalArgumentException", NULL); \
446 return; \
447 } \
448 \
449 sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz); \
450 \
451 const Type *val = \
452 impl->getStorage()->allocTemporary ## Suffix ## Array(env, valObj); \
453 \
454 hardware::Parcel *parcel = impl->getParcel(); \
455 \
456 size_t parentHandle; \
457 status_t err = parcel->writeBuffer( \
458 val, size * sizeof(*val), &parentHandle); \
459 \
460 signalExceptionForError(env, err); \
461}
462
463#define DEFINE_PARCEL_VECTOR_WRITER(Suffix,Type) \
464static void JHwParcel_native_write ## Suffix ## Vector( \
465 JNIEnv *env, jobject thiz, Type ## Array valObj) { \
466 if (valObj == NULL) { \
467 jniThrowException(env, "java/lang/NullPointerException", NULL); \
468 return; \
469 } \
470 \
471 sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz); \
472 \
473 const hidl_vec<Type> *vec = \
474 impl->getStorage()->allocTemporary ## Suffix ## Vector(env, valObj); \
475 \
476 hardware::Parcel *parcel = impl->getParcel(); \
477 \
478 size_t parentHandle; \
479 status_t err = parcel->writeBuffer(vec, sizeof(*vec), &parentHandle); \
480 \
481 if (err == OK) { \
482 size_t childHandle; \
483 \
484 err = vec->writeEmbeddedToParcel( \
485 parcel, \
486 parentHandle, \
487 0 /* parentOffset */, \
488 &childHandle); \
489 } \
490 \
491 signalExceptionForError(env, err); \
492}
493
494DEFINE_PARCEL_ARRAY_WRITER(Int8,jbyte)
495DEFINE_PARCEL_ARRAY_WRITER(Int16,jshort)
496DEFINE_PARCEL_ARRAY_WRITER(Int32,jint)
497DEFINE_PARCEL_ARRAY_WRITER(Int64,jlong)
498DEFINE_PARCEL_ARRAY_WRITER(Float,jfloat)
499DEFINE_PARCEL_ARRAY_WRITER(Double,jdouble)
500
501DEFINE_PARCEL_VECTOR_WRITER(Int8,jbyte)
502DEFINE_PARCEL_VECTOR_WRITER(Int16,jshort)
503DEFINE_PARCEL_VECTOR_WRITER(Int32,jint)
504DEFINE_PARCEL_VECTOR_WRITER(Int64,jlong)
505DEFINE_PARCEL_VECTOR_WRITER(Float,jfloat)
506DEFINE_PARCEL_VECTOR_WRITER(Double,jdouble)
507
Andreas Huber86635bb2016-08-24 16:19:03 -0700508static void JHwParcel_native_writeBoolArray(
509 JNIEnv *env, jobject thiz, jint size, jbooleanArray valObj) {
510 if (valObj == NULL) {
511 jniThrowException(env, "java/lang/NullPointerException", NULL);
512 return;
513 }
514
515 jsize len = env->GetArrayLength(valObj);
516
517 if (len != size) {
518 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
519 return;
520 }
521
522 sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz);
523
524 jboolean *src = env->GetBooleanArrayElements(valObj, nullptr);
525
526 bool *dst =
527 (bool *)impl->getStorage()->allocTemporaryStorage(size * sizeof(bool));
528
529 for (jint i = 0; i < size; ++i) {
530 dst[i] = src[i];
531 }
532
533 env->ReleaseBooleanArrayElements(valObj, src, 0 /* mode */);
534 src = nullptr;
535
536 hardware::Parcel *parcel = impl->getParcel();
537
538 size_t parentHandle;
539 status_t err = parcel->writeBuffer(
540 dst, size * sizeof(*dst), &parentHandle);
541
542 signalExceptionForError(env, err);
543}
544
545static void JHwParcel_native_writeBoolVector(
546 JNIEnv *env, jobject thiz, jbooleanArray valObj) {
547 if (valObj == NULL) {
548 jniThrowException(env, "java/lang/NullPointerException", NULL);
549 return;
550 }
551
552 sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz);
553
Andreas Huber9266f992016-08-25 11:21:21 -0700554 void *vecPtr =
555 impl->getStorage()->allocTemporaryStorage(sizeof(hidl_vec<bool>));
556
557 hidl_vec<bool> *vec = new (vecPtr) hidl_vec<bool>;
Andreas Huber86635bb2016-08-24 16:19:03 -0700558
559 jsize len = env->GetArrayLength(valObj);
560
561 jboolean *src = env->GetBooleanArrayElements(valObj, nullptr);
562
563 bool *dst =
564 (bool *)impl->getStorage()->allocTemporaryStorage(len * sizeof(bool));
565
566 for (jsize i = 0; i < len; ++i) {
567 dst[i] = src[i];
568 }
569
570 env->ReleaseBooleanArrayElements(valObj, src, 0 /* mode */);
571 src = nullptr;
572
573 vec->setToExternal(dst, len);
574
575 hardware::Parcel *parcel = impl->getParcel();
576
577 size_t parentHandle;
578 status_t err = parcel->writeBuffer(vec, sizeof(*vec), &parentHandle);
579
580 if (err == OK) {
581 size_t childHandle;
582
583 err = vec->writeEmbeddedToParcel(
584 parcel,
585 parentHandle,
586 0 /* parentOffset */,
587 &childHandle);
588 }
589
590 signalExceptionForError(env, err);
591}
592
Andreas Huberdab5fc62016-08-15 09:25:02 -0700593static void JHwParcel_native_writeStrongBinder(
594 JNIEnv *env, jobject thiz, jobject binderObj) {
595 sp<hardware::IBinder> binder;
596 if (binderObj != NULL) {
597 ScopedLocalRef<jclass> hwBinderKlass(
598 env, FindClassOrDie(env, PACKAGE_PATH "/HwBinder"));
599
600 ScopedLocalRef<jclass> hwRemoteBinderKlass(
601 env, FindClassOrDie(env, PACKAGE_PATH "/HwRemoteBinder"));
602
603 if (env->IsInstanceOf(binderObj, hwBinderKlass.get())) {
604 binder = JHwBinder::GetNativeContext(env, binderObj);
605 } else if (env->IsInstanceOf(binderObj, hwRemoteBinderKlass.get())) {
606 binder = JHwRemoteBinder::GetNativeContext(
607 env, binderObj)->getBinder();
608 } else {
609 signalExceptionForError(env, INVALID_OPERATION);
610 return;
611 }
612 }
613
614 hardware::Parcel *parcel =
615 JHwParcel::GetNativeContext(env, thiz)->getParcel();
616
617 status_t err = parcel->writeStrongBinder(binder);
618 signalExceptionForError(env, err);
619}
620
621static jstring MakeStringObjFromHidlString(JNIEnv *env, const hidl_string &s) {
622 String16 utf16String(s.c_str(), s.size());
623
624 return env->NewString(
625 reinterpret_cast<const jchar *>(utf16String.string()),
626 utf16String.size());
627}
628
629static jstring JHwParcel_native_readString(JNIEnv *env, jobject thiz) {
630 hardware::Parcel *parcel =
631 JHwParcel::GetNativeContext(env, thiz)->getParcel();
632
633 size_t parentHandle;
634
635 const hidl_string *s = static_cast<const hidl_string *>(
636 parcel->readBuffer(&parentHandle));
637
638 if (s == NULL) {
639 signalExceptionForError(env, UNKNOWN_ERROR);
640 return NULL;
641 }
642
643 status_t err = const_cast<hidl_string *>(s)->readEmbeddedFromParcel(
644 *parcel, parentHandle, 0 /* parentOffset */);
645
646 if (err != OK) {
647 signalExceptionForError(env, err);
648 return NULL;
649 }
650
651 return MakeStringObjFromHidlString(env, *s);
652}
653
654#define DEFINE_PARCEL_ARRAY_READER(Suffix,Type,NewType) \
655static Type ## Array JHwParcel_native_read ## Suffix ## Array( \
656 JNIEnv *env, jobject thiz, jint size) { \
657 hardware::Parcel *parcel = \
658 JHwParcel::GetNativeContext(env, thiz)->getParcel(); \
659 \
660 size_t parentHandle; \
661 const Type *val = static_cast<const Type *>( \
662 parcel->readBuffer(&parentHandle)); \
663 \
664 Type ## Array valObj = env->New ## NewType ## Array(size); \
665 env->Set ## NewType ## ArrayRegion(valObj, 0, size, val); \
666 \
667 return valObj; \
668}
669
670#define DEFINE_PARCEL_VECTOR_READER(Suffix,Type,NewType) \
671static Type ## Array JHwParcel_native_read ## Suffix ## Vector( \
672 JNIEnv *env, jobject thiz) { \
673 hardware::Parcel *parcel = \
674 JHwParcel::GetNativeContext(env, thiz)->getParcel(); \
675 \
676 size_t parentHandle; \
677 \
678 const hidl_vec<Type> *vec = \
679 (const hidl_vec<Type> *)parcel->readBuffer(&parentHandle); \
680 \
681 if (vec == NULL) { \
682 signalExceptionForError(env, UNKNOWN_ERROR); \
683 return NULL; \
684 } \
685 \
686 size_t childHandle; \
687 \
688 status_t err = const_cast<hidl_vec<Type> *>(vec) \
689 ->readEmbeddedFromParcel( \
690 *parcel, \
691 parentHandle, \
692 0 /* parentOffset */, \
693 &childHandle); \
694 \
695 if (err != OK) { \
696 signalExceptionForError(env, err); \
697 return NULL; \
698 } \
699 \
700 Type ## Array valObj = env->New ## NewType ## Array(vec->size()); \
701 env->Set ## NewType ## ArrayRegion(valObj, 0, vec->size(), &(*vec)[0]); \
702 \
703 return valObj; \
704}
705
706DEFINE_PARCEL_ARRAY_READER(Int8,jbyte,Byte)
707DEFINE_PARCEL_ARRAY_READER(Int16,jshort,Short)
708DEFINE_PARCEL_ARRAY_READER(Int32,jint,Int)
709DEFINE_PARCEL_ARRAY_READER(Int64,jlong,Long)
710DEFINE_PARCEL_ARRAY_READER(Float,jfloat,Float)
711DEFINE_PARCEL_ARRAY_READER(Double,jdouble,Double)
712
713DEFINE_PARCEL_VECTOR_READER(Int8,jbyte,Byte)
714DEFINE_PARCEL_VECTOR_READER(Int16,jshort,Short)
715DEFINE_PARCEL_VECTOR_READER(Int32,jint,Int)
716DEFINE_PARCEL_VECTOR_READER(Int64,jlong,Long)
717DEFINE_PARCEL_VECTOR_READER(Float,jfloat,Float)
718DEFINE_PARCEL_VECTOR_READER(Double,jdouble,Double)
719
Andreas Huber86635bb2016-08-24 16:19:03 -0700720static jbooleanArray JHwParcel_native_readBoolArray(
721 JNIEnv *env, jobject thiz, jint size) {
722 hardware::Parcel *parcel =
723 JHwParcel::GetNativeContext(env, thiz)->getParcel();
724
725 size_t parentHandle;
726 const bool *val = static_cast<const bool *>(
727 parcel->readBuffer(&parentHandle));
728
729 jbooleanArray valObj = env->NewBooleanArray(size);
730
731 for (jint i = 0; i < size; ++i) {
732 jboolean x = val[i];
733 env->SetBooleanArrayRegion(valObj, i, 1, &x);
734 }
735
736 return valObj;
737}
738
739static jbooleanArray JHwParcel_native_readBoolVector(
740 JNIEnv *env, jobject thiz) {
741 hardware::Parcel *parcel =
742 JHwParcel::GetNativeContext(env, thiz)->getParcel();
743
744 size_t parentHandle;
745
746 const hidl_vec<bool> *vec =
747 (const hidl_vec<bool> *)parcel->readBuffer(&parentHandle);
748
749 if (vec == NULL) {
750 signalExceptionForError(env, UNKNOWN_ERROR);
751 return NULL;
752 }
753
754 size_t childHandle;
755
756 status_t err = const_cast<hidl_vec<bool> *>(vec)
757 ->readEmbeddedFromParcel(
758 *parcel,
759 parentHandle,
760 0 /* parentOffset */,
761 &childHandle);
762
763 if (err != OK) {
764 signalExceptionForError(env, err);
765 return NULL;
766 }
767
768 jbooleanArray valObj = env->NewBooleanArray(vec->size());
769
770 for (size_t i = 0; i < vec->size(); ++i) {
771 jboolean x = (*vec)[i];
772 env->SetBooleanArrayRegion(valObj, i, 1, &x);
773 }
774
775 return valObj;
776}
777
Andreas Huberdab5fc62016-08-15 09:25:02 -0700778static jobjectArray MakeStringArray(
779 JNIEnv *env, const hidl_string *array, size_t size) {
780 ScopedLocalRef<jclass> stringKlass(
781 env,
782 env->FindClass("java/lang/String"));
783
784 // XXX Why can't I use ScopedLocalRef<> for the arrayObj and the stringObjs?
785
786 jobjectArray arrayObj = env->NewObjectArray(size, stringKlass.get(), NULL);
787
788 for (size_t i = 0; i < size; ++i) {
789 jstring stringObj = MakeStringObjFromHidlString(env, array[i]);
790
791 env->SetObjectArrayElement(
792 arrayObj,
793 i,
794 stringObj);
795 }
796
797 return arrayObj;
798}
799
800static jobjectArray JHwParcel_native_readStringArray(
801 JNIEnv *env, jobject thiz, jint size) {
802 hardware::Parcel *parcel =
803 JHwParcel::GetNativeContext(env, thiz)->getParcel();
804
805 size_t parentHandle;
806 const hidl_string *val = static_cast<const hidl_string *>(
807 parcel->readBuffer(&parentHandle));
808
809 if (val == NULL) {
810 signalExceptionForError(env, UNKNOWN_ERROR);
811 return NULL;
812 }
813
814 status_t err = OK;
815 for (jint i = 0; (err == OK) && (i < size); ++i) {
816 err = const_cast<hidl_string *>(&val[i])
817 ->readEmbeddedFromParcel(
818 *parcel,
819 parentHandle,
820 i * sizeof(hidl_string));
821 }
822
823 if (err != OK) {
824 signalExceptionForError(env, err);
825 return NULL;
826 }
827
828 return MakeStringArray(env, val, size);
829}
830
831static void JHwParcel_native_writeStringArray(
832 JNIEnv *env, jobject thiz, jint size, jobjectArray arrayObj) {
833 if (arrayObj == NULL) {
834 jniThrowException(env, "java/lang/NullPointerException", NULL);
835 return;
836 }
837
838 jsize len = env->GetArrayLength(arrayObj);
839
840 if (len != size) {
841 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
842 return;
843 }
844
845 sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz);
846
847 hidl_string *strings = impl->getStorage()->allocStringArray(len);
848
849 for (jsize i = 0; i < len; ++i) {
850 ScopedLocalRef<jstring> stringObj(
851 env,
852 (jstring)env->GetObjectArrayElement(arrayObj, i));
853
854 const hidl_string *s =
855 impl->getStorage()->allocTemporaryString(env, stringObj.get());
856
857 strings[i].setToExternal(s->c_str(), s->size());
858 }
859
860 hardware::Parcel *parcel = impl->getParcel();
861
862 size_t parentHandle;
863 status_t err = parcel->writeBuffer(
864 strings, sizeof(hidl_string) * len, &parentHandle);
865
866 for (jsize i = 0; (err == OK) && (i < len); ++i) {
867 err = strings[i].writeEmbeddedToParcel(
868 parcel, parentHandle, i * sizeof(hidl_string));
869 }
870
871 signalExceptionForError(env, err);
872}
873
874static jobjectArray JHwParcel_native_readStringVector(
875 JNIEnv *env, jobject thiz) {
876 typedef hidl_vec<hidl_string> string_vec;
877
878 hardware::Parcel *parcel =
879 JHwParcel::GetNativeContext(env, thiz)->getParcel();
880
881 size_t parentHandle;
882
883 const string_vec *vec=
884 (const string_vec *)parcel->readBuffer(&parentHandle);
885
886 if (vec == NULL) {
887 signalExceptionForError(env, UNKNOWN_ERROR);
888 return NULL;
889 }
890
891 size_t childHandle;
892 status_t err = const_cast<string_vec *>(vec)->readEmbeddedFromParcel(
893 *parcel, parentHandle, 0 /* parentOffset */, &childHandle);
894
895 for (size_t i = 0; (err == OK) && (i < vec->size()); ++i) {
896 err = const_cast<hidl_vec<hidl_string> *>(vec)
897 ->readEmbeddedFromParcel(
898 *parcel,
899 childHandle,
900 i * sizeof(hidl_string),
901 nullptr /* childHandle */);
902 }
903
904 if (err != OK) {
905 signalExceptionForError(env, err);
906 return NULL;
907 }
908
909 return MakeStringArray(env, &(*vec)[0], vec->size());
910}
911
912static void JHwParcel_native_writeStringVector(
913 JNIEnv *env, jobject thiz, jobjectArray arrayObj) {
914 typedef hidl_vec<hidl_string> string_vec;
915
916 if (arrayObj == NULL) {
917 jniThrowException(env, "java/lang/NullPointerException", NULL);
918 return;
919 }
920
921 jsize len = env->GetArrayLength(arrayObj);
922
923 sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz);
924
Andreas Huber9266f992016-08-25 11:21:21 -0700925 void *vecPtr =
926 impl->getStorage()->allocTemporaryStorage(sizeof(string_vec));
927
928 string_vec *vec = new (vecPtr) string_vec;
Andreas Huberdab5fc62016-08-15 09:25:02 -0700929
930 hidl_string *strings = impl->getStorage()->allocStringArray(len);
931 vec->setToExternal(strings, len);
932
933 for (jsize i = 0; i < len; ++i) {
934 ScopedLocalRef<jstring> stringObj(
935 env,
936 (jstring)env->GetObjectArrayElement(arrayObj, i));
937
938 const hidl_string *s =
939 impl->getStorage()->allocTemporaryString(env, stringObj.get());
940
941 strings[i].setToExternal(s->c_str(), s->size());
942 }
943
944 hardware::Parcel *parcel = impl->getParcel();
945
946 size_t parentHandle;
947 status_t err = parcel->writeBuffer(vec, sizeof(*vec), &parentHandle);
948
949 if (err == OK) {
950 size_t childHandle;
951 err = vec->writeEmbeddedToParcel(
952 parcel,
953 parentHandle,
954 0 /* parentOffset */,
955 &childHandle);
956
957 for (size_t i = 0; (err == OK) && (i < vec->size()); ++i) {
958 err = (*vec)[i].writeEmbeddedToParcel(
959 parcel,
960 childHandle,
961 i * sizeof(hidl_string));
962 }
963 }
964
965 signalExceptionForError(env, err);
966}
967
968static jobject JHwParcel_native_readStrongBinder(JNIEnv *env, jobject thiz) {
969 hardware::Parcel *parcel =
970 JHwParcel::GetNativeContext(env, thiz)->getParcel();
971
972 sp<hardware::IBinder> binder = parcel->readStrongBinder();
973
974 if (binder == NULL) {
975 return NULL;
976 }
977
978 return JHwRemoteBinder::NewObject(env, binder);
979}
980
Andreas Huber9266f992016-08-25 11:21:21 -0700981static jobject JHwParcel_native_readBuffer(JNIEnv *env, jobject thiz) {
982 hardware::Parcel *parcel =
983 JHwParcel::GetNativeContext(env, thiz)->getParcel();
984
985 size_t handle;
986 const void *ptr = parcel->readBuffer(&handle);
987
988 if (ptr == nullptr) {
989 jniThrowException(env, "java/util/NoSuchElementException", NULL);
990 return nullptr;
991 }
992
993 return JHwBlob::NewObject(env, ptr, handle);
994}
995
996static jobject JHwParcel_native_readEmbeddedBuffer(
997 JNIEnv *env, jobject thiz, jlong parentHandle, jlong offset) {
998 hardware::Parcel *parcel =
999 JHwParcel::GetNativeContext(env, thiz)->getParcel();
1000
1001 size_t childHandle;
1002
1003 const void *ptr =
1004 parcel->readEmbeddedBuffer(&childHandle, parentHandle, offset);
1005
1006 if (ptr == nullptr) {
1007 jniThrowException(env, "java/util/NoSuchElementException", NULL);
1008 return 0;
1009 }
1010
1011 return JHwBlob::NewObject(env, ptr, childHandle);
1012}
1013
1014static void JHwParcel_native_writeBuffer(
1015 JNIEnv *env, jobject thiz, jobject blobObj) {
1016 if (blobObj == nullptr) {
1017 jniThrowException(env, "java/lang/NullPointerException", NULL);
1018 return;
1019 }
1020
1021 hardware::Parcel *parcel =
1022 JHwParcel::GetNativeContext(env, thiz)->getParcel();
1023
1024 sp<JHwBlob> blob = JHwBlob::GetNativeContext(env, blobObj);
1025 status_t err = blob->writeToParcel(parcel);
1026
1027 if (err != OK) {
1028 signalExceptionForError(env, err);
1029 }
1030}
1031
Andreas Huberdab5fc62016-08-15 09:25:02 -07001032static JNINativeMethod gMethods[] = {
1033 { "native_init", "()J", (void *)JHwParcel_native_init },
1034 { "native_setup", "(Z)V", (void *)JHwParcel_native_setup },
1035
1036 { "writeInterfaceToken", "(Ljava/lang/String;)V",
1037 (void *)JHwParcel_native_writeInterfaceToken },
1038
Andreas Huber86635bb2016-08-24 16:19:03 -07001039 { "writeBool", "(Z)V", (void *)JHwParcel_native_writeBool },
Andreas Huberdab5fc62016-08-15 09:25:02 -07001040 { "writeInt8", "(B)V", (void *)JHwParcel_native_writeInt8 },
1041 { "writeInt16", "(S)V", (void *)JHwParcel_native_writeInt16 },
1042 { "writeInt32", "(I)V", (void *)JHwParcel_native_writeInt32 },
1043 { "writeInt64", "(J)V", (void *)JHwParcel_native_writeInt64 },
1044 { "writeFloat", "(F)V", (void *)JHwParcel_native_writeFloat },
1045 { "writeDouble", "(D)V", (void *)JHwParcel_native_writeDouble },
1046
1047 { "writeString", "(Ljava/lang/String;)V",
1048 (void *)JHwParcel_native_writeString },
1049
Andreas Huber86635bb2016-08-24 16:19:03 -07001050 { "writeBoolArray", "(I[Z)V", (void *)JHwParcel_native_writeBoolArray },
1051 { "writeBoolVector", "([Z)V", (void *)JHwParcel_native_writeBoolVector },
Andreas Huberdab5fc62016-08-15 09:25:02 -07001052 { "writeInt8Array", "(I[B)V", (void *)JHwParcel_native_writeInt8Array },
1053 { "writeInt8Vector", "([B)V", (void *)JHwParcel_native_writeInt8Vector },
1054 { "writeInt16Array", "(I[S)V", (void *)JHwParcel_native_writeInt16Array },
1055 { "writeInt16Vector", "([S)V", (void *)JHwParcel_native_writeInt16Vector },
1056 { "writeInt32Array", "(I[I)V", (void *)JHwParcel_native_writeInt32Array },
1057 { "writeInt32Vector", "([I)V", (void *)JHwParcel_native_writeInt32Vector },
1058 { "writeInt64Array", "(I[J)V", (void *)JHwParcel_native_writeInt64Array },
1059 { "writeInt64Vector", "([J)V", (void *)JHwParcel_native_writeInt64Vector },
1060 { "writeFloatArray", "(I[F)V", (void *)JHwParcel_native_writeFloatArray },
1061 { "writeFloatVector", "([F)V", (void *)JHwParcel_native_writeFloatVector },
1062 { "writeDoubleArray", "(I[D)V", (void *)JHwParcel_native_writeDoubleArray },
1063
1064 { "writeDoubleVector", "([D)V",
1065 (void *)JHwParcel_native_writeDoubleVector },
1066
1067 { "writeStringArray", "(I[Ljava/lang/String;)V",
1068 (void *)JHwParcel_native_writeStringArray },
1069
1070 { "writeStringVector", "([Ljava/lang/String;)V",
1071 (void *)JHwParcel_native_writeStringVector },
1072
1073 { "writeStrongBinder", "(L" PACKAGE_PATH "/IHwBinder;)V",
1074 (void *)JHwParcel_native_writeStrongBinder },
1075
1076 { "enforceInterface", "(Ljava/lang/String;)V",
1077 (void *)JHwParcel_native_enforceInterface },
1078
Andreas Huber86635bb2016-08-24 16:19:03 -07001079 { "readBool", "()Z", (void *)JHwParcel_native_readBool },
Andreas Huberdab5fc62016-08-15 09:25:02 -07001080 { "readInt8", "()B", (void *)JHwParcel_native_readInt8 },
1081 { "readInt16", "()S", (void *)JHwParcel_native_readInt16 },
1082 { "readInt32", "()I", (void *)JHwParcel_native_readInt32 },
1083 { "readInt64", "()J", (void *)JHwParcel_native_readInt64 },
1084 { "readFloat", "()F", (void *)JHwParcel_native_readFloat },
1085 { "readDouble", "()D", (void *)JHwParcel_native_readDouble },
1086
1087 { "readString", "()Ljava/lang/String;",
1088 (void *)JHwParcel_native_readString },
1089
Andreas Huber86635bb2016-08-24 16:19:03 -07001090 { "readBoolArray", "(I)[Z", (void *)JHwParcel_native_readBoolArray },
1091 { "readBoolVector", "()[Z", (void *)JHwParcel_native_readBoolVector },
Andreas Huberdab5fc62016-08-15 09:25:02 -07001092 { "readInt8Array", "(I)[B", (void *)JHwParcel_native_readInt8Array },
1093 { "readInt8Vector", "()[B", (void *)JHwParcel_native_readInt8Vector },
1094 { "readInt16Array", "(I)[S", (void *)JHwParcel_native_readInt16Array },
1095 { "readInt16Vector", "()[S", (void *)JHwParcel_native_readInt16Vector },
1096 { "readInt32Array", "(I)[I", (void *)JHwParcel_native_readInt32Array },
1097 { "readInt32Vector", "()[I", (void *)JHwParcel_native_readInt32Vector },
1098 { "readInt64Array", "(I)[J", (void *)JHwParcel_native_readInt64Array },
1099 { "readInt64Vector", "()[J", (void *)JHwParcel_native_readInt64Vector },
1100 { "readFloatArray", "(I)[F", (void *)JHwParcel_native_readFloatArray },
1101 { "readFloatVector", "()[F", (void *)JHwParcel_native_readFloatVector },
1102 { "readDoubleArray", "(I)[D", (void *)JHwParcel_native_readDoubleArray },
1103 { "readDoubleVector", "()[D", (void *)JHwParcel_native_readDoubleVector },
1104
1105 { "readStringArray", "(I)[Ljava/lang/String;",
1106 (void *)JHwParcel_native_readStringArray },
1107
1108 { "readStringVector", "()[Ljava/lang/String;",
1109 (void *)JHwParcel_native_readStringVector },
1110
1111 { "readStrongBinder", "()L" PACKAGE_PATH "/IHwBinder;",
1112 (void *)JHwParcel_native_readStrongBinder },
1113
1114 { "writeStatus", "(I)V", (void *)JHwParcel_native_writeStatus },
1115
1116 { "verifySuccess", "()V", (void *)JHwParcel_native_verifySuccess },
1117
1118 { "releaseTemporaryStorage", "()V",
1119 (void *)JHwParcel_native_releaseTemporaryStorage },
1120
1121 { "send", "()V", (void *)JHwParcel_native_send },
Andreas Huber9266f992016-08-25 11:21:21 -07001122
1123 { "readBuffer", "()L" PACKAGE_PATH "/HwBlob;",
1124 (void *)JHwParcel_native_readBuffer },
1125
1126 { "readEmbeddedBuffer", "(JJ)L" PACKAGE_PATH "/HwBlob;",
1127 (void *)JHwParcel_native_readEmbeddedBuffer },
1128
1129 { "writeBuffer", "(L" PACKAGE_PATH "/HwBlob;)V",
1130 (void *)JHwParcel_native_writeBuffer },
Andreas Huberdab5fc62016-08-15 09:25:02 -07001131};
1132
1133namespace android {
1134
1135int register_android_os_HwParcel(JNIEnv *env) {
1136 return RegisterMethodsOrDie(env, CLASS_PATH, gMethods, NELEM(gMethods));
1137}
1138
1139} // namespace android