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