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
238 } // namespace android
239
240 ////////////////////////////////////////////////////////////////////////////////
241
242 using namespace android;
243
releaseNativeContext(void * nativeContext)244 static void releaseNativeContext(void *nativeContext) {
245 sp<JHwParcel> parcel = (JHwParcel *)nativeContext;
246
247 if (parcel != NULL) {
248 parcel->decStrong(NULL /* id */);
249 }
250 }
251
JHwParcel_native_init(JNIEnv * env)252 static jlong JHwParcel_native_init(JNIEnv *env) {
253 JHwParcel::InitClass(env);
254
255 return reinterpret_cast<jlong>(&releaseNativeContext);
256 }
257
JHwParcel_native_setup(JNIEnv * env,jobject thiz,jboolean allocate)258 static void JHwParcel_native_setup(
259 JNIEnv *env, jobject thiz, jboolean allocate) {
260 sp<JHwParcel> context = new JHwParcel(env, thiz);
261
262 if (allocate) {
263 context->setParcel(new hardware::Parcel, true /* assumeOwnership */);
264 }
265
266 JHwParcel::SetNativeContext(env, thiz, context);
267 }
268
JHwParcel_native_writeInterfaceToken(JNIEnv * env,jobject thiz,jstring interfaceNameObj)269 static void JHwParcel_native_writeInterfaceToken(
270 JNIEnv *env, jobject thiz, jstring interfaceNameObj) {
271 if (interfaceNameObj == NULL) {
272 jniThrowException(env, "java/lang/NullPointerException", NULL);
273 return;
274 }
275
276 const jchar *interfaceName = env->GetStringCritical(interfaceNameObj, NULL);
277 if (interfaceName) {
278 String8 nameCopy = String8(String16(
279 reinterpret_cast<const char16_t *>(interfaceName),
280 env->GetStringLength(interfaceNameObj)));
281
282 env->ReleaseStringCritical(interfaceNameObj, interfaceName);
283 interfaceName = NULL;
284
285 hardware::Parcel *parcel =
286 JHwParcel::GetNativeContext(env, thiz)->getParcel();
287
288 status_t err = parcel->writeInterfaceToken(nameCopy.string());
289 signalExceptionForError(env, err);
290 }
291 }
292
JHwParcel_native_enforceInterface(JNIEnv * env,jobject thiz,jstring interfaceNameObj)293 static void JHwParcel_native_enforceInterface(
294 JNIEnv *env, jobject thiz, jstring interfaceNameObj) {
295 // XXX original binder Parcel enforceInterface implementation does some
296 // mysterious things regarding strictModePolicy(), figure out if we need
297 // that here as well.
298 if (interfaceNameObj == NULL) {
299 jniThrowException(env, "java/lang/NullPointerException", NULL);
300 return;
301 }
302
303 const char *interfaceName = env->GetStringUTFChars(interfaceNameObj, NULL);
304 if (interfaceName) {
305 hardware::Parcel *parcel =
306 JHwParcel::GetNativeContext(env, thiz)->getParcel();
307 bool valid = parcel->enforceInterface(interfaceName);
308
309 if (!valid) {
310 jniThrowException(
311 env,
312 "java/lang/SecurityException",
313 "HWBinder invocation to an incorrect interface");
314 }
315 env->ReleaseStringUTFChars(interfaceNameObj, interfaceName);
316 }
317 }
318
319 #define DEFINE_PARCEL_WRITER(Suffix,Type) \
320 static void JHwParcel_native_write ## Suffix( \
321 JNIEnv *env, jobject thiz, Type val) { \
322 hardware::Parcel *parcel = \
323 JHwParcel::GetNativeContext(env, thiz)->getParcel(); \
324 \
325 status_t err = parcel->write ## Suffix(val); \
326 signalExceptionForError(env, err); \
327 }
328
329 #define DEFINE_PARCEL_READER(Suffix,Type) \
330 static Type JHwParcel_native_read ## Suffix( \
331 JNIEnv *env, jobject thiz) { \
332 hardware::Parcel *parcel = \
333 JHwParcel::GetNativeContext(env, thiz)->getParcel(); \
334 \
335 Type val; \
336 status_t err = parcel->read ## Suffix(&val); \
337 signalExceptionForError(env, err); \
338 \
339 return val; \
340 }
341
DEFINE_PARCEL_WRITER(Bool,jboolean)342 DEFINE_PARCEL_WRITER(Bool,jboolean)
343 DEFINE_PARCEL_WRITER(Int8,jbyte)
344 DEFINE_PARCEL_WRITER(Int16,jshort)
345 DEFINE_PARCEL_WRITER(Int32,jint)
346 DEFINE_PARCEL_WRITER(Int64,jlong)
347 DEFINE_PARCEL_WRITER(Float,jfloat)
348 DEFINE_PARCEL_WRITER(Double,jdouble)
349
350 DEFINE_PARCEL_READER(Int8,jbyte)
351 DEFINE_PARCEL_READER(Int16,jshort)
352 DEFINE_PARCEL_READER(Int32,jint)
353 DEFINE_PARCEL_READER(Int64,jlong)
354 DEFINE_PARCEL_READER(Float,jfloat)
355 DEFINE_PARCEL_READER(Double,jdouble)
356
357 static jboolean JHwParcel_native_readBool(JNIEnv *env, jobject thiz) {
358 hardware::Parcel *parcel =
359 JHwParcel::GetNativeContext(env, thiz)->getParcel();
360
361 bool val;
362 status_t err = parcel->readBool(&val);
363 signalExceptionForError(env, err);
364
365 return (jboolean)val;
366 }
367
JHwParcel_native_writeStatus(JNIEnv * env,jobject thiz,jint statusCode)368 static void JHwParcel_native_writeStatus(
369 JNIEnv *env, jobject thiz, jint statusCode) {
370 using hardware::Status;
371
372 Status status;
373 switch (statusCode) {
374 case 0: // kStatusSuccess
375 status = Status::ok();
376 break;
377 case -1: // kStatusError
378 status = Status::fromStatusT(UNKNOWN_ERROR);
379 break;
380 default:
381 CHECK(!"Should not be here");
382 }
383
384 hardware::Parcel *parcel =
385 JHwParcel::GetNativeContext(env, thiz)->getParcel();
386
387 status_t err = ::android::hardware::writeToParcel(status, parcel);
388 signalExceptionForError(env, err);
389 }
390
JHwParcel_native_verifySuccess(JNIEnv * env,jobject thiz)391 static void JHwParcel_native_verifySuccess(JNIEnv *env, jobject thiz) {
392 using hardware::Status;
393
394 hardware::Parcel *parcel =
395 JHwParcel::GetNativeContext(env, thiz)->getParcel();
396
397 Status status;
398 status_t err = ::android::hardware::readFromParcel(&status, *parcel);
399 signalExceptionForError(env, err);
400
401 if (!status.isOk()) {
402 signalExceptionForError(env, UNKNOWN_ERROR, true /* canThrowRemoteException */);
403 }
404 }
405
JHwParcel_native_release(JNIEnv * env,jobject thiz)406 static void JHwParcel_native_release(
407 JNIEnv *env, jobject thiz) {
408 JHwParcel::GetNativeContext(env, thiz)->setParcel(NULL, false /* assumeOwnership */);
409 }
410
JHwParcel_native_releaseTemporaryStorage(JNIEnv * env,jobject thiz)411 static void JHwParcel_native_releaseTemporaryStorage(
412 JNIEnv *env, jobject thiz) {
413 JHwParcel::GetNativeContext(env, thiz)->getStorage()->release(env);
414 }
415
JHwParcel_native_send(JNIEnv * env,jobject thiz)416 static void JHwParcel_native_send(JNIEnv *env, jobject thiz) {
417 JHwParcel::GetNativeContext(env, thiz)->send();
418 }
419
JHwParcel_native_writeString(JNIEnv * env,jobject thiz,jstring valObj)420 static void JHwParcel_native_writeString(
421 JNIEnv *env, jobject thiz, jstring valObj) {
422 if (valObj == NULL) {
423 jniThrowException(env, "java/lang/NullPointerException", NULL);
424 return;
425 }
426
427 sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz);
428
429 const hidl_string *s =
430 impl->getStorage()->allocTemporaryString(env, valObj);
431
432 hardware::Parcel *parcel = impl->getParcel();
433
434 size_t parentHandle;
435 status_t err = parcel->writeBuffer(s, sizeof(*s), &parentHandle);
436
437 if (err == OK) {
438 err = ::android::hardware::writeEmbeddedToParcel(
439 *s, parcel, parentHandle, 0 /* parentOffset */);
440 }
441
442 signalExceptionForError(env, err);
443 }
444
JHwParcel_native_writeNativeHandle(JNIEnv * env,jobject thiz,jobject valObj)445 static void JHwParcel_native_writeNativeHandle(JNIEnv *env, jobject thiz, jobject valObj) {
446 sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz);
447
448 EphemeralStorage *storage = impl->getStorage();
449 native_handle_t *handle = JNativeHandle::MakeCppNativeHandle(env, valObj, storage);
450
451 hardware::Parcel *parcel = impl->getParcel();
452 status_t err = parcel->writeNativeHandleNoDup(handle);
453
454 signalExceptionForError(env, err);
455 }
456
457 #define DEFINE_PARCEL_VECTOR_WRITER(Suffix,Type) \
458 static void JHwParcel_native_write ## Suffix ## Vector( \
459 JNIEnv *env, jobject thiz, Type ## Array valObj) { \
460 if (valObj == NULL) { \
461 jniThrowException(env, "java/lang/NullPointerException", NULL); \
462 return; \
463 } \
464 \
465 sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz); \
466 \
467 const hidl_vec<Type> *vec = \
468 impl->getStorage()->allocTemporary ## Suffix ## Vector(env, valObj); \
469 \
470 hardware::Parcel *parcel = impl->getParcel(); \
471 \
472 size_t parentHandle; \
473 status_t err = parcel->writeBuffer(vec, sizeof(*vec), &parentHandle); \
474 \
475 if (err == OK) { \
476 size_t childHandle; \
477 \
478 err = ::android::hardware::writeEmbeddedToParcel( \
479 *vec, \
480 parcel, \
481 parentHandle, \
482 0 /* parentOffset */, \
483 &childHandle); \
484 } \
485 \
486 signalExceptionForError(env, err); \
487 }
488
DEFINE_PARCEL_VECTOR_WRITER(Int8,jbyte)489 DEFINE_PARCEL_VECTOR_WRITER(Int8,jbyte)
490 DEFINE_PARCEL_VECTOR_WRITER(Int16,jshort)
491 DEFINE_PARCEL_VECTOR_WRITER(Int32,jint)
492 DEFINE_PARCEL_VECTOR_WRITER(Int64,jlong)
493 DEFINE_PARCEL_VECTOR_WRITER(Float,jfloat)
494 DEFINE_PARCEL_VECTOR_WRITER(Double,jdouble)
495
496 static void JHwParcel_native_writeBoolVector(
497 JNIEnv *env, jobject thiz, jbooleanArray valObj) {
498 if (valObj == NULL) {
499 jniThrowException(env, "java/lang/NullPointerException", NULL);
500 return;
501 }
502
503 sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz);
504
505 void *vecPtr =
506 impl->getStorage()->allocTemporaryStorage(sizeof(hidl_vec<bool>));
507
508 hidl_vec<bool> *vec = new (vecPtr) hidl_vec<bool>;
509
510 jsize len = env->GetArrayLength(valObj);
511
512 jboolean *src = env->GetBooleanArrayElements(valObj, nullptr);
513
514 bool *dst =
515 (bool *)impl->getStorage()->allocTemporaryStorage(len * sizeof(bool));
516
517 for (jsize i = 0; i < len; ++i) {
518 dst[i] = src[i];
519 }
520
521 env->ReleaseBooleanArrayElements(valObj, src, 0 /* mode */);
522 src = nullptr;
523
524 vec->setToExternal(dst, len);
525
526 hardware::Parcel *parcel = impl->getParcel();
527
528 size_t parentHandle;
529 status_t err = parcel->writeBuffer(vec, sizeof(*vec), &parentHandle);
530
531 if (err == OK) {
532 size_t childHandle;
533
534 err = ::android::hardware::writeEmbeddedToParcel(
535 *vec,
536 parcel,
537 parentHandle,
538 0 /* parentOffset */,
539 &childHandle);
540 }
541
542 signalExceptionForError(env, err);
543 }
544
545 template<typename T>
WriteHidlVector(JNIEnv * env,jobject thiz,const hidl_vec<T> & vec)546 static void WriteHidlVector(JNIEnv *env, jobject thiz, const hidl_vec<T> &vec) {
547 hardware::Parcel *parcel = JHwParcel::GetNativeContext(env, thiz)->getParcel();
548
549 size_t parentHandle;
550 status_t err = parcel->writeBuffer(&vec, sizeof(vec), &parentHandle);
551
552 if (err == OK) {
553 size_t childHandle;
554 err = ::android::hardware::writeEmbeddedToParcel(
555 vec,
556 parcel,
557 parentHandle,
558 0 /* parentOffset */,
559 &childHandle);
560
561 for (size_t i = 0; (err == OK) && (i < vec.size()); ++i) {
562 err = ::android::hardware::writeEmbeddedToParcel(
563 vec[i],
564 parcel,
565 childHandle,
566 i * sizeof(T));
567 }
568 }
569
570 signalExceptionForError(env, err);
571 }
572
JHwParcel_native_writeStringVector(JNIEnv * env,jobject thiz,jobjectArray arrayObj)573 static void JHwParcel_native_writeStringVector(
574 JNIEnv *env, jobject thiz, jobjectArray arrayObj) {
575 if (arrayObj == nullptr) {
576 jniThrowException(env, "java/lang/NullPointerException", nullptr);
577 return;
578 }
579
580 sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz);
581 EphemeralStorage *storage = impl->getStorage();
582
583 void *vecPtr = storage->allocTemporaryStorage(sizeof(hidl_vec<hidl_string>));
584 hidl_vec<hidl_string> *vec = new (vecPtr) hidl_vec<hidl_string>();
585
586 jsize len = env->GetArrayLength(arrayObj);
587 hidl_string *strings = storage->allocStringArray(len);
588 vec->setToExternal(strings, len, false /* shouldOwn */);
589
590 for (jsize i = 0; i < len; ++i) {
591 ScopedLocalRef<jstring> stringObj(env, (jstring) env->GetObjectArrayElement(arrayObj, i));
592
593 const hidl_string *s = storage->allocTemporaryString(env, stringObj.get());
594 strings[i].setToExternal(s->c_str(), s->size());
595 }
596
597 WriteHidlVector(env, thiz, *vec);
598 }
599
JHwParcel_native_writeNativeHandleVector(JNIEnv * env,jobject thiz,jobjectArray jHandleArray)600 static void JHwParcel_native_writeNativeHandleVector(
601 JNIEnv *env, jobject thiz, jobjectArray jHandleArray) {
602 if (jHandleArray == nullptr) {
603 jniThrowException(env, "java/lang/NullPointerException", nullptr);
604 return;
605 }
606
607 sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz);
608 EphemeralStorage *storage = impl->getStorage();
609
610 void *vecPtr = storage->allocTemporaryStorage(sizeof(hidl_vec<hidl_handle>));
611 hidl_vec<hidl_handle> *vec = new (vecPtr) hidl_vec<hidl_handle>();
612
613 jsize len = env->GetArrayLength(jHandleArray);
614 hidl_handle *handles = static_cast<hidl_handle *>(
615 storage->allocTemporaryStorage(len * sizeof(hidl_handle)));
616
617 vec->setToExternal(handles, len, false /* shouldOwn */);
618 for (jsize i = 0; i < len; i++) {
619 ScopedLocalRef<jobject> jHandle(env, env->GetObjectArrayElement(jHandleArray, i));
620
621 native_handle_t* handle = JNativeHandle::MakeCppNativeHandle(env, jHandle.get(), storage);
622
623 new (&(handles[i])) hidl_handle();
624 handles[i].setTo(handle, false /* shouldOwn */);
625 }
626
627 WriteHidlVector(env, thiz, *vec);
628 }
629
JHwParcel_native_writeStrongBinder(JNIEnv * env,jobject thiz,jobject binderObj)630 static void JHwParcel_native_writeStrongBinder(
631 JNIEnv *env, jobject thiz, jobject binderObj) {
632 sp<hardware::IBinder> binder;
633 if (binderObj != NULL) {
634 ScopedLocalRef<jclass> hwBinderKlass(env, FindClassOrDie(env, PACKAGE_PATH "/HwBinder"));
635
636 ScopedLocalRef<jclass> hwRemoteBinderKlass(
637 env, FindClassOrDie(env, PACKAGE_PATH "/HwRemoteBinder"));
638
639 if (env->IsInstanceOf(binderObj, hwBinderKlass.get())) {
640 binder = JHwBinder::GetNativeBinder(env, binderObj);
641 } else if (env->IsInstanceOf(binderObj, hwRemoteBinderKlass.get())) {
642 binder = JHwRemoteBinder::GetNativeContext(
643 env, binderObj)->getBinder();
644 } else {
645 signalExceptionForError(env, INVALID_OPERATION);
646 return;
647 }
648 }
649
650 hardware::Parcel *parcel =
651 JHwParcel::GetNativeContext(env, thiz)->getParcel();
652
653 status_t err = parcel->writeStrongBinder(binder);
654 signalExceptionForError(env, err);
655 }
656
JHwParcel_native_writeHidlMemory(JNIEnv * env,jobject thiz,jobject jmem)657 static void JHwParcel_native_writeHidlMemory(
658 JNIEnv *env, jobject thiz, jobject jmem) {
659
660 if (jmem == nullptr) {
661 jniThrowException(env, "java/lang/NullPointerException", nullptr);
662 return;
663 }
664
665 status_t err = OK;
666
667 // Convert the Java object to its C++ counterpart.
668 const hardware::hidl_memory* cmem = JHidlMemory::fromJava(env, jmem);
669 if (cmem == nullptr) {
670 err = BAD_VALUE;
671 }
672
673 if (err == OK) {
674 // Write it to the parcel.
675 hardware::Parcel* parcel =
676 JHwParcel::GetNativeContext(env, thiz)->getParcel();
677
678 size_t parentHandle;
679 err = parcel->writeBuffer(cmem, sizeof(*cmem), &parentHandle);
680 if (err == OK) {
681 err = hardware::writeEmbeddedToParcel(*cmem, parcel, parentHandle, 0);
682 }
683 }
684 signalExceptionForError(env, err);
685 }
686
MakeStringObjFromHidlString(JNIEnv * env,const hidl_string & s)687 static jstring MakeStringObjFromHidlString(JNIEnv *env, const hidl_string &s) {
688 String16 utf16String(s.c_str(), s.size());
689
690 return env->NewString(
691 reinterpret_cast<const jchar *>(utf16String.string()),
692 utf16String.size());
693 }
694
JHwParcel_native_readString(JNIEnv * env,jobject thiz)695 static jstring JHwParcel_native_readString(JNIEnv *env, jobject thiz) {
696 hardware::Parcel *parcel =
697 JHwParcel::GetNativeContext(env, thiz)->getParcel();
698
699 size_t parentHandle;
700
701 const hidl_string *s;
702 status_t err = parcel->readBuffer(sizeof(*s), &parentHandle,
703 reinterpret_cast<const void**>(&s));
704
705 if (err != OK) {
706 signalExceptionForError(env, err);
707 return NULL;
708 }
709
710 err = ::android::hardware::readEmbeddedFromParcel(
711 const_cast<hidl_string &>(*s),
712 *parcel, parentHandle, 0 /* parentOffset */);
713
714 if (err != OK) {
715 signalExceptionForError(env, err);
716 return NULL;
717 }
718
719 return MakeStringObjFromHidlString(env, *s);
720 }
721
ReadNativeHandle(JNIEnv * env,jobject thiz,jboolean embedded,jlong parentHandle,jlong offset)722 static jobject ReadNativeHandle(JNIEnv *env, jobject thiz, jboolean embedded,
723 jlong parentHandle, jlong offset) {
724 hardware::Parcel *parcel =
725 JHwParcel::GetNativeContext(env, thiz)->getParcel();
726
727 const native_handle_t *handle = nullptr;
728 status_t err = OK;
729
730 if (embedded) {
731 err = parcel->readNullableEmbeddedNativeHandle(parentHandle, offset, &handle);
732 } else {
733 err = parcel->readNullableNativeHandleNoDup(&handle);
734 }
735
736 if (err != OK) {
737 signalExceptionForError(env, err);
738 return nullptr;
739 }
740
741 return JNativeHandle::MakeJavaNativeHandleObj(env, handle);
742 }
743
JHwParcel_native_readNativeHandle(JNIEnv * env,jobject thiz)744 static jobject JHwParcel_native_readNativeHandle(JNIEnv *env, jobject thiz) {
745 return ReadNativeHandle(env, thiz, false /*embedded*/, 0L /*parentHandle*/, 0L /*offset*/);
746 }
747
JHwParcel_native_readEmbeddedNativeHandle(JNIEnv * env,jobject thiz,jlong parentHandle,jlong offset)748 static jobject JHwParcel_native_readEmbeddedNativeHandle(
749 JNIEnv *env, jobject thiz, jlong parentHandle, jlong offset) {
750 return ReadNativeHandle(env, thiz, true /*embedded*/, parentHandle, offset);
751 }
752
753 #define DEFINE_PARCEL_VECTOR_READER(Suffix,Type,NewType) \
754 static Type ## Array JHwParcel_native_read ## Suffix ## Vector( \
755 JNIEnv *env, jobject thiz) { \
756 hardware::Parcel *parcel = \
757 JHwParcel::GetNativeContext(env, thiz)->getParcel(); \
758 size_t parentHandle; \
759 \
760 const hidl_vec<Type> *vec; \
761 status_t err = parcel->readBuffer(sizeof(*vec), &parentHandle, \
762 reinterpret_cast<const void**>(&vec)); \
763 \
764 if (err != OK) { \
765 signalExceptionForError(env, err); \
766 return NULL; \
767 } \
768 \
769 size_t childHandle; \
770 \
771 err = ::android::hardware::readEmbeddedFromParcel( \
772 const_cast<hidl_vec<Type> &>(*vec), \
773 *parcel, \
774 parentHandle, \
775 0 /* parentOffset */, \
776 &childHandle); \
777 \
778 if (err != OK) { \
779 signalExceptionForError(env, err); \
780 return NULL; \
781 } \
782 \
783 Type ## Array valObj = env->New ## NewType ## Array(vec->size()); \
784 env->Set ## NewType ## ArrayRegion(valObj, 0, vec->size(), &(*vec)[0]); \
785 \
786 return valObj; \
787 }
788
DEFINE_PARCEL_VECTOR_READER(Int8,jbyte,Byte)789 DEFINE_PARCEL_VECTOR_READER(Int8,jbyte,Byte)
790 DEFINE_PARCEL_VECTOR_READER(Int16,jshort,Short)
791 DEFINE_PARCEL_VECTOR_READER(Int32,jint,Int)
792 DEFINE_PARCEL_VECTOR_READER(Int64,jlong,Long)
793 DEFINE_PARCEL_VECTOR_READER(Float,jfloat,Float)
794 DEFINE_PARCEL_VECTOR_READER(Double,jdouble,Double)
795
796 static jbooleanArray JHwParcel_native_readBoolVector(JNIEnv *env, jobject thiz) {
797 hardware::Parcel *parcel = JHwParcel::GetNativeContext(env, thiz)->getParcel();
798
799 size_t parentHandle;
800
801 const hidl_vec<bool> *vec;
802 status_t err = parcel->readBuffer(sizeof(*vec), &parentHandle,
803 reinterpret_cast<const void**>(&vec));
804
805 if (err != OK) {
806 signalExceptionForError(env, err);
807 return NULL;
808 }
809
810 size_t childHandle;
811
812 err = ::android::hardware::readEmbeddedFromParcel(
813 const_cast<hidl_vec<bool> &>(*vec),
814 *parcel,
815 parentHandle,
816 0 /* parentOffset */,
817 &childHandle);
818
819 if (err != OK) {
820 signalExceptionForError(env, err);
821 return NULL;
822 }
823
824 jbooleanArray valObj = env->NewBooleanArray(vec->size());
825
826 for (size_t i = 0; i < vec->size(); ++i) {
827 jboolean x = (*vec)[i];
828 env->SetBooleanArrayRegion(valObj, i, 1, &x);
829 }
830
831 return valObj;
832 }
833
MakeStringArray(JNIEnv * env,const hidl_string * array,size_t size)834 static jobjectArray MakeStringArray(
835 JNIEnv *env, const hidl_string *array, size_t size) {
836 ScopedLocalRef<jclass> stringKlass(
837 env,
838 env->FindClass("java/lang/String"));
839
840 // XXX Why can't I use ScopedLocalRef<> for the arrayObj and the stringObjs?
841
842 jobjectArray arrayObj = env->NewObjectArray(size, stringKlass.get(), NULL);
843
844 for (size_t i = 0; i < size; ++i) {
845 jstring stringObj = MakeStringObjFromHidlString(env, array[i]);
846
847 env->SetObjectArrayElement(
848 arrayObj,
849 i,
850 stringObj);
851 }
852
853 return arrayObj;
854 }
855
856 template<typename T>
ReadHidlVector(JNIEnv * env,jobject thiz)857 static const hidl_vec<T> *ReadHidlVector(JNIEnv *env, jobject thiz) {
858 const hidl_vec<T> *vec;
859
860 hardware::Parcel *parcel = JHwParcel::GetNativeContext(env, thiz)->getParcel();
861
862 size_t parentHandle;
863 status_t err = parcel->readBuffer(sizeof(hidl_vec<T>),
864 &parentHandle, reinterpret_cast<const void **>(&vec));
865
866 if (err == OK) {
867 size_t childHandle;
868 err = ::android::hardware::readEmbeddedFromParcel(
869 const_cast<hidl_vec<T> &>(*vec),
870 *parcel, parentHandle,
871 0 /* parentOffset */,
872 &childHandle);
873
874 for (size_t i = 0; (err == OK) && (i < vec->size()); i++) {
875 err = android::hardware::readEmbeddedFromParcel(
876 const_cast<T &>((*vec)[i]),
877 *parcel,
878 childHandle,
879 i * sizeof(T) /* parentOffset */);
880 }
881 }
882
883 if (err != OK) {
884 signalExceptionForError(env, err);
885 return nullptr;
886 }
887
888 return vec;
889 }
890
JHwParcel_native_readStringVector(JNIEnv * env,jobject thiz)891 static jobjectArray JHwParcel_native_readStringVector(
892 JNIEnv *env, jobject thiz) {
893 const hidl_vec<hidl_string> *vec = ReadHidlVector<hidl_string>(env, thiz);
894 return MakeStringArray(env, &(*vec)[0], vec->size());
895 }
896
JHwParcel_native_readNativeHandleVector(JNIEnv * env,jobject thiz)897 static jobjectArray JHwParcel_native_readNativeHandleVector(
898 JNIEnv *env, jobject thiz) {
899 const hidl_vec<hidl_handle> *vec = ReadHidlVector<hidl_handle>(env, thiz);
900
901 jsize length = vec->size();
902 jobjectArray objArray = JNativeHandle::AllocJavaNativeHandleObjArray(
903 env, length);
904
905 for (jsize i = 0; i < length; i++) {
906 jobject jHandle = JNativeHandle::MakeJavaNativeHandleObj(env, (*vec)[i].getNativeHandle());
907
908 env->SetObjectArrayElement(objArray, i, jHandle);
909 }
910
911 return objArray;
912 }
913
readEmbeddedHidlMemory(JNIEnv * env,hardware::Parcel * parcel,const hardware::hidl_memory & mem,size_t parentHandle,size_t parentOffset,jobject * result)914 static status_t readEmbeddedHidlMemory(JNIEnv* env,
915 hardware::Parcel* parcel,
916 const hardware::hidl_memory& mem,
917 size_t parentHandle,
918 size_t parentOffset,
919 jobject* result) {
920 status_t err = hardware::readEmbeddedFromParcel(mem,
921 *parcel,
922 parentHandle,
923 parentOffset);
924 if (err == OK) {
925 // Convert to Java.
926 *result = JHidlMemory::toJava(env, mem);
927 if (*result == nullptr) {
928 err = BAD_VALUE;
929 }
930 }
931 return err;
932 }
933
JHwParcel_native_readHidlMemory(JNIEnv * env,jobject thiz)934 static jobject JHwParcel_native_readHidlMemory(
935 JNIEnv* env, jobject thiz) {
936 hardware::Parcel* parcel =
937 JHwParcel::GetNativeContext(env, thiz)->getParcel();
938
939 jobject result = nullptr;
940
941 const hardware::hidl_memory* mem;
942 size_t parentHandle;
943
944 status_t err = parcel->readBuffer(sizeof(*mem),
945 &parentHandle,
946 reinterpret_cast<const void**>(&mem));
947 if (err == OK) {
948 err = readEmbeddedHidlMemory(env,
949 parcel,
950 *mem,
951 parentHandle,
952 0,
953 &result);
954 }
955
956 signalExceptionForError(env, err);
957 return result;
958 }
959
JHwParcel_native_readEmbeddedHidlMemory(JNIEnv * env,jobject thiz,jlong fieldHandle,jlong parentHandle,jlong offset)960 static jobject JHwParcel_native_readEmbeddedHidlMemory(
961 JNIEnv* env,
962 jobject thiz,
963 jlong fieldHandle,
964 jlong parentHandle,
965 jlong offset) {
966 hardware::Parcel* parcel =
967 JHwParcel::GetNativeContext(env, thiz)->getParcel();
968
969 jobject result = nullptr;
970 const hardware::hidl_memory* mem =
971 reinterpret_cast<const hardware::hidl_memory*>(fieldHandle);
972 status_t err = readEmbeddedHidlMemory(env,
973 parcel,
974 *mem,
975 parentHandle,
976 offset,
977 &result);
978 signalExceptionForError(env, err);
979 return result;
980 }
981
JHwParcel_native_readStrongBinder(JNIEnv * env,jobject thiz)982 static jobject JHwParcel_native_readStrongBinder(JNIEnv *env, jobject thiz) {
983 hardware::Parcel *parcel =
984 JHwParcel::GetNativeContext(env, thiz)->getParcel();
985
986 sp<hardware::IBinder> binder = parcel->readStrongBinder();
987
988 if (binder == nullptr) {
989 return nullptr;
990 }
991
992 if (!validateCanUseHwBinder(binder)) {
993 jniThrowException(env, "java/lang/IllegalArgumentException",
994 "Local binder is not supported in Java");
995 return nullptr;
996 }
997
998 return JHwRemoteBinder::NewObject(env, binder);
999 }
1000
JHwParcel_native_readBuffer(JNIEnv * env,jobject thiz,jlong expectedSize)1001 static jobject JHwParcel_native_readBuffer(JNIEnv *env, jobject thiz,
1002 jlong expectedSize) {
1003 hardware::Parcel *parcel =
1004 JHwParcel::GetNativeContext(env, thiz)->getParcel();
1005
1006 size_t handle;
1007 const void *ptr;
1008
1009 if (expectedSize < 0) {
1010 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
1011 return nullptr;
1012 }
1013
1014 status_t status = parcel->readBuffer(expectedSize, &handle, &ptr);
1015
1016 if (status != OK) {
1017 jniThrowException(env, "java/util/NoSuchElementException", NULL);
1018 return nullptr;
1019 }
1020
1021 return JHwBlob::NewObject(env, ptr, handle);
1022 }
1023
JHwParcel_native_readEmbeddedBuffer(JNIEnv * env,jobject thiz,jlong expectedSize,jlong parentHandle,jlong offset,jboolean nullable)1024 static jobject JHwParcel_native_readEmbeddedBuffer(
1025 JNIEnv *env, jobject thiz, jlong expectedSize,
1026 jlong parentHandle, jlong offset, jboolean nullable) {
1027 hardware::Parcel *parcel =
1028 JHwParcel::GetNativeContext(env, thiz)->getParcel();
1029
1030 size_t childHandle;
1031
1032 const void *ptr;
1033 status_t status =
1034 parcel->readNullableEmbeddedBuffer(expectedSize,
1035 &childHandle, parentHandle, offset, &ptr);
1036
1037 if (expectedSize < 0) {
1038 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
1039 return nullptr;
1040 }
1041
1042 if (status != OK) {
1043 jniThrowException(env, "java/util/NoSuchElementException", NULL);
1044 return 0;
1045 } else if (status == OK && !nullable && ptr == nullptr) {
1046 jniThrowException(env, "java/lang/NullPointerException", NULL);
1047 return 0;
1048 }
1049
1050 return JHwBlob::NewObject(env, ptr, childHandle);
1051 }
1052
JHwParcel_native_writeBuffer(JNIEnv * env,jobject thiz,jobject blobObj)1053 static void JHwParcel_native_writeBuffer(
1054 JNIEnv *env, jobject thiz, jobject blobObj) {
1055 if (blobObj == nullptr) {
1056 jniThrowException(env, "java/lang/NullPointerException", NULL);
1057 return;
1058 }
1059
1060 hardware::Parcel *parcel =
1061 JHwParcel::GetNativeContext(env, thiz)->getParcel();
1062
1063 sp<JHwBlob> blob = JHwBlob::GetNativeContext(env, blobObj);
1064 status_t err = blob->writeToParcel(parcel);
1065
1066 if (err != OK) {
1067 signalExceptionForError(env, err);
1068 }
1069 }
1070
1071 static JNINativeMethod gMethods[] = {
1072 { "native_init", "()J", (void *)JHwParcel_native_init },
1073 { "native_setup", "(Z)V", (void *)JHwParcel_native_setup },
1074
1075 { "writeInterfaceToken", "(Ljava/lang/String;)V",
1076 (void *)JHwParcel_native_writeInterfaceToken },
1077
1078 { "writeBool", "(Z)V", (void *)JHwParcel_native_writeBool },
1079 { "writeInt8", "(B)V", (void *)JHwParcel_native_writeInt8 },
1080 { "writeInt16", "(S)V", (void *)JHwParcel_native_writeInt16 },
1081 { "writeInt32", "(I)V", (void *)JHwParcel_native_writeInt32 },
1082 { "writeInt64", "(J)V", (void *)JHwParcel_native_writeInt64 },
1083 { "writeFloat", "(F)V", (void *)JHwParcel_native_writeFloat },
1084 { "writeDouble", "(D)V", (void *)JHwParcel_native_writeDouble },
1085
1086 { "writeString", "(Ljava/lang/String;)V",
1087 (void *)JHwParcel_native_writeString },
1088
1089 { "writeNativeHandle", "(L" PACKAGE_PATH "/NativeHandle;)V",
1090 (void *)JHwParcel_native_writeNativeHandle },
1091
1092 { "writeBoolVector", "([Z)V", (void *)JHwParcel_native_writeBoolVector },
1093 { "writeInt8Vector", "([B)V", (void *)JHwParcel_native_writeInt8Vector },
1094 { "writeInt16Vector", "([S)V", (void *)JHwParcel_native_writeInt16Vector },
1095 { "writeInt32Vector", "([I)V", (void *)JHwParcel_native_writeInt32Vector },
1096 { "writeInt64Vector", "([J)V", (void *)JHwParcel_native_writeInt64Vector },
1097 { "writeFloatVector", "([F)V", (void *)JHwParcel_native_writeFloatVector },
1098
1099 { "writeDoubleVector", "([D)V",
1100 (void *)JHwParcel_native_writeDoubleVector },
1101
1102 { "writeStringVector", "([Ljava/lang/String;)V",
1103 (void *)JHwParcel_native_writeStringVector },
1104
1105 { "writeNativeHandleVector", "([L" PACKAGE_PATH "/NativeHandle;)V",
1106 (void *)JHwParcel_native_writeNativeHandleVector },
1107
1108 { "writeStrongBinder", "(L" PACKAGE_PATH "/IHwBinder;)V",
1109 (void *)JHwParcel_native_writeStrongBinder },
1110
1111 { "enforceInterface", "(Ljava/lang/String;)V",
1112 (void *)JHwParcel_native_enforceInterface },
1113
1114 { "readBool", "()Z", (void *)JHwParcel_native_readBool },
1115 { "readInt8", "()B", (void *)JHwParcel_native_readInt8 },
1116 { "readInt16", "()S", (void *)JHwParcel_native_readInt16 },
1117 { "readInt32", "()I", (void *)JHwParcel_native_readInt32 },
1118 { "readInt64", "()J", (void *)JHwParcel_native_readInt64 },
1119 { "readFloat", "()F", (void *)JHwParcel_native_readFloat },
1120 { "readDouble", "()D", (void *)JHwParcel_native_readDouble },
1121
1122 { "readString", "()Ljava/lang/String;",
1123 (void *)JHwParcel_native_readString },
1124
1125 { "readNativeHandle", "()L" PACKAGE_PATH "/NativeHandle;",
1126 (void *)JHwParcel_native_readNativeHandle },
1127
1128 { "readEmbeddedNativeHandle", "(JJ)L" PACKAGE_PATH "/NativeHandle;",
1129 (void *)JHwParcel_native_readEmbeddedNativeHandle },
1130
1131 { "readBoolVectorAsArray", "()[Z",
1132 (void *)JHwParcel_native_readBoolVector },
1133
1134 { "readInt8VectorAsArray", "()[B",
1135 (void *)JHwParcel_native_readInt8Vector },
1136
1137 { "readInt16VectorAsArray", "()[S",
1138 (void *)JHwParcel_native_readInt16Vector },
1139
1140 { "readInt32VectorAsArray", "()[I",
1141 (void *)JHwParcel_native_readInt32Vector },
1142
1143 { "readInt64VectorAsArray", "()[J",
1144 (void *)JHwParcel_native_readInt64Vector },
1145
1146 { "readFloatVectorAsArray", "()[F",
1147 (void *)JHwParcel_native_readFloatVector },
1148
1149 { "readDoubleVectorAsArray", "()[D",
1150 (void *)JHwParcel_native_readDoubleVector },
1151
1152 { "readStringVectorAsArray", "()[Ljava/lang/String;",
1153 (void *)JHwParcel_native_readStringVector },
1154
1155 { "readNativeHandleAsArray", "()[L" PACKAGE_PATH "/NativeHandle;",
1156 (void *)JHwParcel_native_readNativeHandleVector },
1157
1158 { "readStrongBinder", "()L" PACKAGE_PATH "/IHwBinder;",
1159 (void *)JHwParcel_native_readStrongBinder },
1160
1161 { "writeStatus", "(I)V", (void *)JHwParcel_native_writeStatus },
1162
1163 { "verifySuccess", "()V", (void *)JHwParcel_native_verifySuccess },
1164
1165 { "releaseTemporaryStorage", "()V",
1166 (void *)JHwParcel_native_releaseTemporaryStorage },
1167
1168 { "send", "()V", (void *)JHwParcel_native_send },
1169
1170 { "readBuffer", "(J)L" PACKAGE_PATH "/HwBlob;",
1171 (void *)JHwParcel_native_readBuffer },
1172
1173 { "readEmbeddedBuffer", "(JJJZ)L" PACKAGE_PATH "/HwBlob;",
1174 (void *)JHwParcel_native_readEmbeddedBuffer },
1175
1176 { "writeBuffer", "(L" PACKAGE_PATH "/HwBlob;)V",
1177 (void *)JHwParcel_native_writeBuffer },
1178
1179 { "release", "()V",
1180 (void *)JHwParcel_native_release },
1181
1182 {"writeHidlMemory", "(L" PACKAGE_PATH "/HidlMemory;)V",
1183 (void*) JHwParcel_native_writeHidlMemory},
1184
1185 {"readHidlMemory", "()L" PACKAGE_PATH "/HidlMemory;",
1186 (void*) JHwParcel_native_readHidlMemory},
1187
1188 {"readEmbeddedHidlMemory", "(JJJ)L" PACKAGE_PATH "/HidlMemory;",
1189 (void*) JHwParcel_native_readEmbeddedHidlMemory},
1190 };
1191
1192 namespace android {
1193
register_android_os_HwParcel(JNIEnv * env)1194 int register_android_os_HwParcel(JNIEnv *env) {
1195 return RegisterMethodsOrDie(env, CLASS_PATH, gMethods, NELEM(gMethods));
1196 }
1197
1198 } // namespace android
1199