blob: 0202303b10ea2fda652695d934312ca8fc9c6ebc [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"
24#include "android_os_HwRemoteBinder.h"
25
26#include <JNIHelp.h>
27#include <android_runtime/AndroidRuntime.h>
28#include <hwbinder/Status.h>
29#include <nativehelper/ScopedLocalRef.h>
30
31#include "core_jni_helpers.h"
32
33using android::AndroidRuntime;
34
35using ::android::hardware::hidl_string;
36using ::android::hardware::hidl_vec;
37
38#define PACKAGE_PATH "android/os"
39#define CLASS_NAME "HwParcel"
40#define CLASS_PATH PACKAGE_PATH "/" CLASS_NAME
41
42namespace android {
43
44static struct fields_t {
45 jfieldID contextID;
46 jmethodID constructID;
47
48} gFields;
49
50void signalExceptionForError(JNIEnv *env, status_t err) {
51 switch (err) {
52 case OK:
53 break;
54
55 case NO_MEMORY:
56 {
57 jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
58 break;
59 }
60
61 case INVALID_OPERATION:
62 {
63 jniThrowException(
64 env, "java/lang/UnsupportedOperationException", NULL);
65 break;
66 }
67
68 case BAD_VALUE:
69 {
70 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
71 break;
72 }
73
74 case BAD_INDEX:
75 {
76 jniThrowException(env, "java/lang/IndexOutOfBoundsException", NULL);
77 break;
78 }
79
80 case BAD_TYPE:
81 {
82 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
83 break;
84 }
85
86 case NAME_NOT_FOUND:
87 {
88 jniThrowException(env, "java/util/NoSuchElementException", NULL);
89 break;
90 }
91
92 case PERMISSION_DENIED:
93 {
94 jniThrowException(env, "java/lang/SecurityException", NULL);
95 break;
96 }
97
98 case NO_INIT:
99 {
100 jniThrowException(
101 env, "java/lang/RuntimeException", "Not initialized");
102 break;
103 }
104
105 case ALREADY_EXISTS:
106 {
107 jniThrowException(
108 env, "java/lang/RuntimeException", "Item already exists");
109 break;
110 }
111
112 default:
113 {
114 jniThrowException(
115 env, "java/lang/RuntimeException", "Unknown error");
116
117 break;
118 }
119 }
120}
121
122// static
123void JHwParcel::InitClass(JNIEnv *env) {
124 ScopedLocalRef<jclass> clazz(
125 env, FindClassOrDie(env, CLASS_PATH));
126
127 gFields.contextID =
128 GetFieldIDOrDie(env, clazz.get(), "mNativeContext", "J");
129
130 gFields.constructID = GetMethodIDOrDie(env, clazz.get(), "<init>", "(Z)V");
131}
132
133// static
134sp<JHwParcel> JHwParcel::SetNativeContext(
135 JNIEnv *env, jobject thiz, const sp<JHwParcel> &context) {
136 sp<JHwParcel> old = (JHwParcel *)env->GetLongField(thiz, gFields.contextID);
137
138 if (context != NULL) {
139 context->incStrong(NULL /* id */);
140 }
141
142 if (old != NULL) {
143 old->decStrong(NULL /* id */);
144 }
145
146 env->SetLongField(thiz, gFields.contextID, (long)context.get());
147
148 return old;
149}
150
151// static
152sp<JHwParcel> JHwParcel::GetNativeContext(JNIEnv *env, jobject thiz) {
153 return (JHwParcel *)env->GetLongField(thiz, gFields.contextID);
154}
155
156JHwParcel::JHwParcel(JNIEnv *env, jobject thiz)
157 : mParcel(NULL),
158 mOwnsParcel(false),
159 mTransactCallback(nullptr),
160 mWasSent(false) {
161 jclass clazz = env->GetObjectClass(thiz);
162 CHECK(clazz != NULL);
163
164 mClass = (jclass)env->NewGlobalRef(clazz);
165 mObject = env->NewWeakGlobalRef(thiz);
166}
167
168JHwParcel::~JHwParcel() {
169 JNIEnv *env = AndroidRuntime::getJNIEnv();
170
171 mStorage.release(env);
172
173 setParcel(NULL, false /* assumeOwnership */);
174
175 env->DeleteWeakGlobalRef(mObject);
176 mObject = NULL;
177
178 env->DeleteGlobalRef(mClass);
179 mClass = NULL;
180}
181
182hardware::Parcel *JHwParcel::getParcel() {
183 return mParcel;
184}
185
186EphemeralStorage *JHwParcel::getStorage() {
187 return &mStorage;
188}
189
190void JHwParcel::setParcel(hardware::Parcel *parcel, bool assumeOwnership) {
191 if (mParcel && mOwnsParcel) {
192 delete mParcel;
193 }
194
195 mParcel = parcel;
196 mOwnsParcel = assumeOwnership;
197}
198
199// static
200jobject JHwParcel::NewObject(JNIEnv *env) {
201 ScopedLocalRef<jclass> clazz(env, FindClassOrDie(env, CLASS_PATH));
202
203 return env->NewObject(
204 clazz.get(), gFields.constructID, false /* allocate */);
205}
206
207void JHwParcel::setTransactCallback(
208 ::android::hardware::IBinder::TransactCallback cb) {
209 mTransactCallback = cb;
210}
211
212void JHwParcel::send() {
213 CHECK(mTransactCallback != nullptr);
214 CHECK(mParcel != nullptr);
215
216 mTransactCallback(*mParcel);
217 mTransactCallback = nullptr;
218
219 mWasSent = true;
220}
221
222bool JHwParcel::wasSent() const {
223 return mWasSent;
224}
225
226} // namespace android
227
228////////////////////////////////////////////////////////////////////////////////
229
230using namespace android;
231
232static void releaseNativeContext(void *nativeContext) {
233 sp<JHwParcel> parcel = (JHwParcel *)nativeContext;
234
235 if (parcel != NULL) {
236 parcel->decStrong(NULL /* id */);
237 }
238}
239
240static jlong JHwParcel_native_init(JNIEnv *env) {
241 JHwParcel::InitClass(env);
242
243 return reinterpret_cast<jlong>(&releaseNativeContext);
244}
245
246static void JHwParcel_native_setup(
247 JNIEnv *env, jobject thiz, jboolean allocate) {
248 sp<JHwParcel> context = new JHwParcel(env, thiz);
249
250 if (allocate) {
251 context->setParcel(new hardware::Parcel, true /* assumeOwnership */);
252 }
253
254 JHwParcel::SetNativeContext(env, thiz, context);
255}
256
257static void JHwParcel_native_writeInterfaceToken(
258 JNIEnv *env, jobject thiz, jstring interfaceNameObj) {
259 if (interfaceNameObj == NULL) {
260 jniThrowException(env, "java/lang/NullPointerException", NULL);
261 return;
262 }
263
264 const jchar *interfaceName = env->GetStringCritical(interfaceNameObj, NULL);
265 if (interfaceName) {
266 hardware::Parcel *parcel =
267 JHwParcel::GetNativeContext(env, thiz)->getParcel();
268
269 status_t err = parcel->writeInterfaceToken(
270 String16(
271 reinterpret_cast<const char16_t *>(interfaceName),
272 env->GetStringLength(interfaceNameObj)));
273
274 env->ReleaseStringCritical(interfaceNameObj, interfaceName);
275 interfaceName = NULL;
276
277 signalExceptionForError(env, err);
278 }
279}
280
281static void JHwParcel_native_enforceInterface(
282 JNIEnv *env, jobject thiz, jstring interfaceNameObj) {
283 // XXX original binder Parcel enforceInterface implementation does some
284 // mysterious things regarding strictModePolicy(), figure out if we need
285 // that here as well.
286 if (interfaceNameObj == NULL) {
287 jniThrowException(env, "java/lang/NullPointerException", NULL);
288 return;
289 }
290
291 const jchar *interfaceName = env->GetStringCritical(interfaceNameObj, NULL);
292 if (interfaceName) {
293 hardware::Parcel *parcel =
294 JHwParcel::GetNativeContext(env, thiz)->getParcel();
295
296 bool valid = parcel->enforceInterface(
297 String16(
298 reinterpret_cast<const char16_t *>(interfaceName),
299 env->GetStringLength(interfaceNameObj)));
300
301 env->ReleaseStringCritical(interfaceNameObj, interfaceName);
302 interfaceName = NULL;
303
304 if (!valid) {
305 jniThrowException(
306 env,
307 "java/lang/SecurityException",
308 "HWBinder invocation to an incorrect interface");
309 }
310 }
311}
312
313#define DEFINE_PARCEL_WRITER(Suffix,Type) \
314static void JHwParcel_native_write ## Suffix( \
315 JNIEnv *env, jobject thiz, Type val) { \
316 hardware::Parcel *parcel = \
317 JHwParcel::GetNativeContext(env, thiz)->getParcel(); \
318 \
319 status_t err = parcel->write ## Suffix(val); \
320 signalExceptionForError(env, err); \
321}
322
323#define DEFINE_PARCEL_READER(Suffix,Type) \
324static Type JHwParcel_native_read ## Suffix( \
325 JNIEnv *env, jobject thiz) { \
326 hardware::Parcel *parcel = \
327 JHwParcel::GetNativeContext(env, thiz)->getParcel(); \
328 \
329 Type val; \
330 status_t err = parcel->read ## Suffix(&val); \
331 signalExceptionForError(env, err); \
332 \
333 return val; \
334}
335
336DEFINE_PARCEL_WRITER(Int8,jbyte)
337DEFINE_PARCEL_WRITER(Int16,jshort)
338DEFINE_PARCEL_WRITER(Int32,jint)
339DEFINE_PARCEL_WRITER(Int64,jlong)
340DEFINE_PARCEL_WRITER(Float,jfloat)
341DEFINE_PARCEL_WRITER(Double,jdouble)
342
343DEFINE_PARCEL_READER(Int8,jbyte)
344DEFINE_PARCEL_READER(Int16,jshort)
345DEFINE_PARCEL_READER(Int32,jint)
346DEFINE_PARCEL_READER(Int64,jlong)
347DEFINE_PARCEL_READER(Float,jfloat)
348DEFINE_PARCEL_READER(Double,jdouble)
349
350static void JHwParcel_native_writeStatus(
351 JNIEnv *env, jobject thiz, jint statusCode) {
352 using hardware::Status;
353
354 Status status;
355 switch (statusCode) {
356 case 0: // kStatusSuccess
357 status = Status::ok();
358 break;
359 case -1: // kStatusError
360 status = Status::fromStatusT(UNKNOWN_ERROR);
361 break;
362 default:
363 CHECK(!"Should not be here");
364 }
365
366 hardware::Parcel *parcel =
367 JHwParcel::GetNativeContext(env, thiz)->getParcel();
368
369 status_t err = status.writeToParcel(parcel);
370 signalExceptionForError(env, err);
371}
372
373static void JHwParcel_native_verifySuccess(JNIEnv *env, jobject thiz) {
374 using hardware::Status;
375
376 hardware::Parcel *parcel =
377 JHwParcel::GetNativeContext(env, thiz)->getParcel();
378
379 Status status;
380 status_t err = status.readFromParcel(*parcel);
381 signalExceptionForError(env, err);
382}
383
384static void JHwParcel_native_releaseTemporaryStorage(
385 JNIEnv *env, jobject thiz) {
386 JHwParcel::GetNativeContext(env, thiz)->getStorage()->release(env);
387}
388
389static void JHwParcel_native_send(JNIEnv *env, jobject thiz) {
390 JHwParcel::GetNativeContext(env, thiz)->send();
391}
392
393static void JHwParcel_native_writeString(
394 JNIEnv *env, jobject thiz, jstring valObj) {
395 if (valObj == NULL) {
396 jniThrowException(env, "java/lang/NullPointerException", NULL);
397 return;
398 }
399
400 sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz);
401
402 const hidl_string *s =
403 impl->getStorage()->allocTemporaryString(env, valObj);
404
405 hardware::Parcel *parcel = impl->getParcel();
406
407 size_t parentHandle;
408 status_t err = parcel->writeBuffer(s, sizeof(*s), &parentHandle);
409
410 if (err == OK) {
411 err = s->writeEmbeddedToParcel(
412 parcel, parentHandle, 0 /* parentOffset */);
413 }
414
415 signalExceptionForError(env, err);
416}
417
418#define DEFINE_PARCEL_ARRAY_WRITER(Suffix,Type) \
419static void JHwParcel_native_write ## Suffix ## Array( \
420 JNIEnv *env, jobject thiz, jint size, Type ## Array valObj) { \
421 if (valObj == NULL) { \
422 jniThrowException(env, "java/lang/NullPointerException", NULL); \
423 return; \
424 } \
425 \
426 jsize len = env->GetArrayLength(valObj); \
427 \
428 if (len != size) { \
429 jniThrowException(env, "java/lang/IllegalArgumentException", NULL); \
430 return; \
431 } \
432 \
433 sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz); \
434 \
435 const Type *val = \
436 impl->getStorage()->allocTemporary ## Suffix ## Array(env, valObj); \
437 \
438 hardware::Parcel *parcel = impl->getParcel(); \
439 \
440 size_t parentHandle; \
441 status_t err = parcel->writeBuffer( \
442 val, size * sizeof(*val), &parentHandle); \
443 \
444 signalExceptionForError(env, err); \
445}
446
447#define DEFINE_PARCEL_VECTOR_WRITER(Suffix,Type) \
448static void JHwParcel_native_write ## Suffix ## Vector( \
449 JNIEnv *env, jobject thiz, Type ## Array valObj) { \
450 if (valObj == NULL) { \
451 jniThrowException(env, "java/lang/NullPointerException", NULL); \
452 return; \
453 } \
454 \
455 sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz); \
456 \
457 const hidl_vec<Type> *vec = \
458 impl->getStorage()->allocTemporary ## Suffix ## Vector(env, valObj); \
459 \
460 hardware::Parcel *parcel = impl->getParcel(); \
461 \
462 size_t parentHandle; \
463 status_t err = parcel->writeBuffer(vec, sizeof(*vec), &parentHandle); \
464 \
465 if (err == OK) { \
466 size_t childHandle; \
467 \
468 err = vec->writeEmbeddedToParcel( \
469 parcel, \
470 parentHandle, \
471 0 /* parentOffset */, \
472 &childHandle); \
473 } \
474 \
475 signalExceptionForError(env, err); \
476}
477
478DEFINE_PARCEL_ARRAY_WRITER(Int8,jbyte)
479DEFINE_PARCEL_ARRAY_WRITER(Int16,jshort)
480DEFINE_PARCEL_ARRAY_WRITER(Int32,jint)
481DEFINE_PARCEL_ARRAY_WRITER(Int64,jlong)
482DEFINE_PARCEL_ARRAY_WRITER(Float,jfloat)
483DEFINE_PARCEL_ARRAY_WRITER(Double,jdouble)
484
485DEFINE_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
492static void JHwParcel_native_writeStrongBinder(
493 JNIEnv *env, jobject thiz, jobject binderObj) {
494 sp<hardware::IBinder> binder;
495 if (binderObj != NULL) {
496 ScopedLocalRef<jclass> hwBinderKlass(
497 env, FindClassOrDie(env, PACKAGE_PATH "/HwBinder"));
498
499 ScopedLocalRef<jclass> hwRemoteBinderKlass(
500 env, FindClassOrDie(env, PACKAGE_PATH "/HwRemoteBinder"));
501
502 if (env->IsInstanceOf(binderObj, hwBinderKlass.get())) {
503 binder = JHwBinder::GetNativeContext(env, binderObj);
504 } else if (env->IsInstanceOf(binderObj, hwRemoteBinderKlass.get())) {
505 binder = JHwRemoteBinder::GetNativeContext(
506 env, binderObj)->getBinder();
507 } else {
508 signalExceptionForError(env, INVALID_OPERATION);
509 return;
510 }
511 }
512
513 hardware::Parcel *parcel =
514 JHwParcel::GetNativeContext(env, thiz)->getParcel();
515
516 status_t err = parcel->writeStrongBinder(binder);
517 signalExceptionForError(env, err);
518}
519
520static jstring MakeStringObjFromHidlString(JNIEnv *env, const hidl_string &s) {
521 String16 utf16String(s.c_str(), s.size());
522
523 return env->NewString(
524 reinterpret_cast<const jchar *>(utf16String.string()),
525 utf16String.size());
526}
527
528static jstring JHwParcel_native_readString(JNIEnv *env, jobject thiz) {
529 hardware::Parcel *parcel =
530 JHwParcel::GetNativeContext(env, thiz)->getParcel();
531
532 size_t parentHandle;
533
534 const hidl_string *s = static_cast<const hidl_string *>(
535 parcel->readBuffer(&parentHandle));
536
537 if (s == NULL) {
538 signalExceptionForError(env, UNKNOWN_ERROR);
539 return NULL;
540 }
541
542 status_t err = const_cast<hidl_string *>(s)->readEmbeddedFromParcel(
543 *parcel, parentHandle, 0 /* parentOffset */);
544
545 if (err != OK) {
546 signalExceptionForError(env, err);
547 return NULL;
548 }
549
550 return MakeStringObjFromHidlString(env, *s);
551}
552
553#define DEFINE_PARCEL_ARRAY_READER(Suffix,Type,NewType) \
554static Type ## Array JHwParcel_native_read ## Suffix ## Array( \
555 JNIEnv *env, jobject thiz, jint size) { \
556 hardware::Parcel *parcel = \
557 JHwParcel::GetNativeContext(env, thiz)->getParcel(); \
558 \
559 size_t parentHandle; \
560 const Type *val = static_cast<const Type *>( \
561 parcel->readBuffer(&parentHandle)); \
562 \
563 Type ## Array valObj = env->New ## NewType ## Array(size); \
564 env->Set ## NewType ## ArrayRegion(valObj, 0, size, val); \
565 \
566 return valObj; \
567}
568
569#define DEFINE_PARCEL_VECTOR_READER(Suffix,Type,NewType) \
570static Type ## Array JHwParcel_native_read ## Suffix ## Vector( \
571 JNIEnv *env, jobject thiz) { \
572 hardware::Parcel *parcel = \
573 JHwParcel::GetNativeContext(env, thiz)->getParcel(); \
574 \
575 size_t parentHandle; \
576 \
577 const hidl_vec<Type> *vec = \
578 (const hidl_vec<Type> *)parcel->readBuffer(&parentHandle); \
579 \
580 if (vec == NULL) { \
581 signalExceptionForError(env, UNKNOWN_ERROR); \
582 return NULL; \
583 } \
584 \
585 size_t childHandle; \
586 \
587 status_t err = const_cast<hidl_vec<Type> *>(vec) \
588 ->readEmbeddedFromParcel( \
589 *parcel, \
590 parentHandle, \
591 0 /* parentOffset */, \
592 &childHandle); \
593 \
594 if (err != OK) { \
595 signalExceptionForError(env, err); \
596 return NULL; \
597 } \
598 \
599 Type ## Array valObj = env->New ## NewType ## Array(vec->size()); \
600 env->Set ## NewType ## ArrayRegion(valObj, 0, vec->size(), &(*vec)[0]); \
601 \
602 return valObj; \
603}
604
605DEFINE_PARCEL_ARRAY_READER(Int8,jbyte,Byte)
606DEFINE_PARCEL_ARRAY_READER(Int16,jshort,Short)
607DEFINE_PARCEL_ARRAY_READER(Int32,jint,Int)
608DEFINE_PARCEL_ARRAY_READER(Int64,jlong,Long)
609DEFINE_PARCEL_ARRAY_READER(Float,jfloat,Float)
610DEFINE_PARCEL_ARRAY_READER(Double,jdouble,Double)
611
612DEFINE_PARCEL_VECTOR_READER(Int8,jbyte,Byte)
613DEFINE_PARCEL_VECTOR_READER(Int16,jshort,Short)
614DEFINE_PARCEL_VECTOR_READER(Int32,jint,Int)
615DEFINE_PARCEL_VECTOR_READER(Int64,jlong,Long)
616DEFINE_PARCEL_VECTOR_READER(Float,jfloat,Float)
617DEFINE_PARCEL_VECTOR_READER(Double,jdouble,Double)
618
619static jobjectArray MakeStringArray(
620 JNIEnv *env, const hidl_string *array, size_t size) {
621 ScopedLocalRef<jclass> stringKlass(
622 env,
623 env->FindClass("java/lang/String"));
624
625 // XXX Why can't I use ScopedLocalRef<> for the arrayObj and the stringObjs?
626
627 jobjectArray arrayObj = env->NewObjectArray(size, stringKlass.get(), NULL);
628
629 for (size_t i = 0; i < size; ++i) {
630 jstring stringObj = MakeStringObjFromHidlString(env, array[i]);
631
632 env->SetObjectArrayElement(
633 arrayObj,
634 i,
635 stringObj);
636 }
637
638 return arrayObj;
639}
640
641static jobjectArray JHwParcel_native_readStringArray(
642 JNIEnv *env, jobject thiz, jint size) {
643 hardware::Parcel *parcel =
644 JHwParcel::GetNativeContext(env, thiz)->getParcel();
645
646 size_t parentHandle;
647 const hidl_string *val = static_cast<const hidl_string *>(
648 parcel->readBuffer(&parentHandle));
649
650 if (val == NULL) {
651 signalExceptionForError(env, UNKNOWN_ERROR);
652 return NULL;
653 }
654
655 status_t err = OK;
656 for (jint i = 0; (err == OK) && (i < size); ++i) {
657 err = const_cast<hidl_string *>(&val[i])
658 ->readEmbeddedFromParcel(
659 *parcel,
660 parentHandle,
661 i * sizeof(hidl_string));
662 }
663
664 if (err != OK) {
665 signalExceptionForError(env, err);
666 return NULL;
667 }
668
669 return MakeStringArray(env, val, size);
670}
671
672static void JHwParcel_native_writeStringArray(
673 JNIEnv *env, jobject thiz, jint size, jobjectArray arrayObj) {
674 if (arrayObj == NULL) {
675 jniThrowException(env, "java/lang/NullPointerException", NULL);
676 return;
677 }
678
679 jsize len = env->GetArrayLength(arrayObj);
680
681 if (len != size) {
682 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
683 return;
684 }
685
686 sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz);
687
688 hidl_string *strings = impl->getStorage()->allocStringArray(len);
689
690 for (jsize i = 0; i < len; ++i) {
691 ScopedLocalRef<jstring> stringObj(
692 env,
693 (jstring)env->GetObjectArrayElement(arrayObj, i));
694
695 const hidl_string *s =
696 impl->getStorage()->allocTemporaryString(env, stringObj.get());
697
698 strings[i].setToExternal(s->c_str(), s->size());
699 }
700
701 hardware::Parcel *parcel = impl->getParcel();
702
703 size_t parentHandle;
704 status_t err = parcel->writeBuffer(
705 strings, sizeof(hidl_string) * len, &parentHandle);
706
707 for (jsize i = 0; (err == OK) && (i < len); ++i) {
708 err = strings[i].writeEmbeddedToParcel(
709 parcel, parentHandle, i * sizeof(hidl_string));
710 }
711
712 signalExceptionForError(env, err);
713}
714
715static jobjectArray JHwParcel_native_readStringVector(
716 JNIEnv *env, jobject thiz) {
717 typedef hidl_vec<hidl_string> string_vec;
718
719 hardware::Parcel *parcel =
720 JHwParcel::GetNativeContext(env, thiz)->getParcel();
721
722 size_t parentHandle;
723
724 const string_vec *vec=
725 (const string_vec *)parcel->readBuffer(&parentHandle);
726
727 if (vec == NULL) {
728 signalExceptionForError(env, UNKNOWN_ERROR);
729 return NULL;
730 }
731
732 size_t childHandle;
733 status_t err = const_cast<string_vec *>(vec)->readEmbeddedFromParcel(
734 *parcel, parentHandle, 0 /* parentOffset */, &childHandle);
735
736 for (size_t i = 0; (err == OK) && (i < vec->size()); ++i) {
737 err = const_cast<hidl_vec<hidl_string> *>(vec)
738 ->readEmbeddedFromParcel(
739 *parcel,
740 childHandle,
741 i * sizeof(hidl_string),
742 nullptr /* childHandle */);
743 }
744
745 if (err != OK) {
746 signalExceptionForError(env, err);
747 return NULL;
748 }
749
750 return MakeStringArray(env, &(*vec)[0], vec->size());
751}
752
753static void JHwParcel_native_writeStringVector(
754 JNIEnv *env, jobject thiz, jobjectArray arrayObj) {
755 typedef hidl_vec<hidl_string> string_vec;
756
757 if (arrayObj == NULL) {
758 jniThrowException(env, "java/lang/NullPointerException", NULL);
759 return;
760 }
761
762 jsize len = env->GetArrayLength(arrayObj);
763
764 sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz);
765
766 string_vec *vec =
767 (string_vec *)impl->getStorage()->allocTemporaryStorage(
768 sizeof(string_vec));
769
770 hidl_string *strings = impl->getStorage()->allocStringArray(len);
771 vec->setToExternal(strings, len);
772
773 for (jsize i = 0; i < len; ++i) {
774 ScopedLocalRef<jstring> stringObj(
775 env,
776 (jstring)env->GetObjectArrayElement(arrayObj, i));
777
778 const hidl_string *s =
779 impl->getStorage()->allocTemporaryString(env, stringObj.get());
780
781 strings[i].setToExternal(s->c_str(), s->size());
782 }
783
784 hardware::Parcel *parcel = impl->getParcel();
785
786 size_t parentHandle;
787 status_t err = parcel->writeBuffer(vec, sizeof(*vec), &parentHandle);
788
789 if (err == OK) {
790 size_t childHandle;
791 err = vec->writeEmbeddedToParcel(
792 parcel,
793 parentHandle,
794 0 /* parentOffset */,
795 &childHandle);
796
797 for (size_t i = 0; (err == OK) && (i < vec->size()); ++i) {
798 err = (*vec)[i].writeEmbeddedToParcel(
799 parcel,
800 childHandle,
801 i * sizeof(hidl_string));
802 }
803 }
804
805 signalExceptionForError(env, err);
806}
807
808static jobject JHwParcel_native_readStrongBinder(JNIEnv *env, jobject thiz) {
809 hardware::Parcel *parcel =
810 JHwParcel::GetNativeContext(env, thiz)->getParcel();
811
812 sp<hardware::IBinder> binder = parcel->readStrongBinder();
813
814 if (binder == NULL) {
815 return NULL;
816 }
817
818 return JHwRemoteBinder::NewObject(env, binder);
819}
820
821static JNINativeMethod gMethods[] = {
822 { "native_init", "()J", (void *)JHwParcel_native_init },
823 { "native_setup", "(Z)V", (void *)JHwParcel_native_setup },
824
825 { "writeInterfaceToken", "(Ljava/lang/String;)V",
826 (void *)JHwParcel_native_writeInterfaceToken },
827
828 { "writeInt8", "(B)V", (void *)JHwParcel_native_writeInt8 },
829 { "writeInt16", "(S)V", (void *)JHwParcel_native_writeInt16 },
830 { "writeInt32", "(I)V", (void *)JHwParcel_native_writeInt32 },
831 { "writeInt64", "(J)V", (void *)JHwParcel_native_writeInt64 },
832 { "writeFloat", "(F)V", (void *)JHwParcel_native_writeFloat },
833 { "writeDouble", "(D)V", (void *)JHwParcel_native_writeDouble },
834
835 { "writeString", "(Ljava/lang/String;)V",
836 (void *)JHwParcel_native_writeString },
837
838 { "writeInt8Array", "(I[B)V", (void *)JHwParcel_native_writeInt8Array },
839 { "writeInt8Vector", "([B)V", (void *)JHwParcel_native_writeInt8Vector },
840 { "writeInt16Array", "(I[S)V", (void *)JHwParcel_native_writeInt16Array },
841 { "writeInt16Vector", "([S)V", (void *)JHwParcel_native_writeInt16Vector },
842 { "writeInt32Array", "(I[I)V", (void *)JHwParcel_native_writeInt32Array },
843 { "writeInt32Vector", "([I)V", (void *)JHwParcel_native_writeInt32Vector },
844 { "writeInt64Array", "(I[J)V", (void *)JHwParcel_native_writeInt64Array },
845 { "writeInt64Vector", "([J)V", (void *)JHwParcel_native_writeInt64Vector },
846 { "writeFloatArray", "(I[F)V", (void *)JHwParcel_native_writeFloatArray },
847 { "writeFloatVector", "([F)V", (void *)JHwParcel_native_writeFloatVector },
848 { "writeDoubleArray", "(I[D)V", (void *)JHwParcel_native_writeDoubleArray },
849
850 { "writeDoubleVector", "([D)V",
851 (void *)JHwParcel_native_writeDoubleVector },
852
853 { "writeStringArray", "(I[Ljava/lang/String;)V",
854 (void *)JHwParcel_native_writeStringArray },
855
856 { "writeStringVector", "([Ljava/lang/String;)V",
857 (void *)JHwParcel_native_writeStringVector },
858
859 { "writeStrongBinder", "(L" PACKAGE_PATH "/IHwBinder;)V",
860 (void *)JHwParcel_native_writeStrongBinder },
861
862 { "enforceInterface", "(Ljava/lang/String;)V",
863 (void *)JHwParcel_native_enforceInterface },
864
865 { "readInt8", "()B", (void *)JHwParcel_native_readInt8 },
866 { "readInt16", "()S", (void *)JHwParcel_native_readInt16 },
867 { "readInt32", "()I", (void *)JHwParcel_native_readInt32 },
868 { "readInt64", "()J", (void *)JHwParcel_native_readInt64 },
869 { "readFloat", "()F", (void *)JHwParcel_native_readFloat },
870 { "readDouble", "()D", (void *)JHwParcel_native_readDouble },
871
872 { "readString", "()Ljava/lang/String;",
873 (void *)JHwParcel_native_readString },
874
875 { "readInt8Array", "(I)[B", (void *)JHwParcel_native_readInt8Array },
876 { "readInt8Vector", "()[B", (void *)JHwParcel_native_readInt8Vector },
877 { "readInt16Array", "(I)[S", (void *)JHwParcel_native_readInt16Array },
878 { "readInt16Vector", "()[S", (void *)JHwParcel_native_readInt16Vector },
879 { "readInt32Array", "(I)[I", (void *)JHwParcel_native_readInt32Array },
880 { "readInt32Vector", "()[I", (void *)JHwParcel_native_readInt32Vector },
881 { "readInt64Array", "(I)[J", (void *)JHwParcel_native_readInt64Array },
882 { "readInt64Vector", "()[J", (void *)JHwParcel_native_readInt64Vector },
883 { "readFloatArray", "(I)[F", (void *)JHwParcel_native_readFloatArray },
884 { "readFloatVector", "()[F", (void *)JHwParcel_native_readFloatVector },
885 { "readDoubleArray", "(I)[D", (void *)JHwParcel_native_readDoubleArray },
886 { "readDoubleVector", "()[D", (void *)JHwParcel_native_readDoubleVector },
887
888 { "readStringArray", "(I)[Ljava/lang/String;",
889 (void *)JHwParcel_native_readStringArray },
890
891 { "readStringVector", "()[Ljava/lang/String;",
892 (void *)JHwParcel_native_readStringVector },
893
894 { "readStrongBinder", "()L" PACKAGE_PATH "/IHwBinder;",
895 (void *)JHwParcel_native_readStrongBinder },
896
897 { "writeStatus", "(I)V", (void *)JHwParcel_native_writeStatus },
898
899 { "verifySuccess", "()V", (void *)JHwParcel_native_verifySuccess },
900
901 { "releaseTemporaryStorage", "()V",
902 (void *)JHwParcel_native_releaseTemporaryStorage },
903
904 { "send", "()V", (void *)JHwParcel_native_send },
905};
906
907namespace android {
908
909int register_android_os_HwParcel(JNIEnv *env) {
910 return RegisterMethodsOrDie(env, CLASS_PATH, gMethods, NELEM(gMethods));
911}
912
913} // namespace android