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