blob: 061349aee96fc2d80bd8d22bd15aa96934158561 [file] [log] [blame]
Andreas Huberdab5fc62016-08-15 09:25:02 -07001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//#define LOG_NDEBUG 0
18#define LOG_TAG "android_os_HwParcel"
19#include <android-base/logging.h>
20
21#include "android_os_HwParcel.h"
22
23#include "android_os_HwBinder.h"
Andreas Huber9266f992016-08-25 11:21:21 -070024#include "android_os_HwBlob.h"
Andreas Huberdab5fc62016-08-15 09:25:02 -070025#include "android_os_HwRemoteBinder.h"
26
Steven Moreland2279b252017-07-19 09:50:45 -070027#include <nativehelper/JNIHelp.h>
Andreas Huberdab5fc62016-08-15 09:25:02 -070028#include <android_runtime/AndroidRuntime.h>
Yifan Hongddf31f62016-11-15 16:02:40 -080029#include <hidl/HidlTransportSupport.h>
Martijn Coenenaa2c32f2016-09-01 01:37:05 +020030#include <hidl/Status.h>
Andreas Huberdab5fc62016-08-15 09:25:02 -070031#include <nativehelper/ScopedLocalRef.h>
32
33#include "core_jni_helpers.h"
34
35using android::AndroidRuntime;
36
37using ::android::hardware::hidl_string;
38using ::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
44namespace android {
45
46static struct fields_t {
47 jfieldID contextID;
48 jmethodID constructID;
49
50} gFields;
51
Steven Morelande62b1f32016-12-20 15:55:48 -080052void signalExceptionForError(JNIEnv *env, status_t err, bool canThrowRemoteException) {
Andreas Huberdab5fc62016-08-15 09:25:02 -070053 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
Andreas Huber9266f992016-08-25 11:21:21 -070076 case -ERANGE:
Andreas Huberdab5fc62016-08-15 09:25:02 -070077 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 {
Steven Morelande62b1f32016-12-20 15:55:48 -0800117 std::stringstream ss;
118 ss << "HwBinder Error: (" << err << ")";
119
Andreas Huberdab5fc62016-08-15 09:25:02 -0700120 jniThrowException(
Steven Morelande62b1f32016-12-20 15:55:48 -0800121 env,
122 canThrowRemoteException ? "android/os/RemoteException" : "java/lang/RuntimeException",
123 ss.str().c_str());
Andreas Huberdab5fc62016-08-15 09:25:02 -0700124
125 break;
126 }
127 }
128}
129
130// static
131void 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
142sp<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
160sp<JHwParcel> JHwParcel::GetNativeContext(JNIEnv *env, jobject thiz) {
161 return (JHwParcel *)env->GetLongField(thiz, gFields.contextID);
162}
163
164JHwParcel::JHwParcel(JNIEnv *env, jobject thiz)
165 : mParcel(NULL),
166 mOwnsParcel(false),
167 mTransactCallback(nullptr),
168 mWasSent(false) {
Andreas Huberdab5fc62016-08-15 09:25:02 -0700169}
170
171JHwParcel::~JHwParcel() {
172 JNIEnv *env = AndroidRuntime::getJNIEnv();
173
174 mStorage.release(env);
175
176 setParcel(NULL, false /* assumeOwnership */);
Andreas Huberdab5fc62016-08-15 09:25:02 -0700177}
178
179hardware::Parcel *JHwParcel::getParcel() {
180 return mParcel;
181}
182
183EphemeralStorage *JHwParcel::getStorage() {
184 return &mStorage;
185}
186
187void JHwParcel::setParcel(hardware::Parcel *parcel, bool assumeOwnership) {
188 if (mParcel && mOwnsParcel) {
189 delete mParcel;
190 }
191
192 mParcel = parcel;
193 mOwnsParcel = assumeOwnership;
194}
195
196// static
197jobject JHwParcel::NewObject(JNIEnv *env) {
198 ScopedLocalRef<jclass> clazz(env, FindClassOrDie(env, CLASS_PATH));
199
Andreas Huber9266f992016-08-25 11:21:21 -0700200 jmethodID constructID =
201 GetMethodIDOrDie(env, clazz.get(), "<init>", "(Z)V");
202
203 return env->NewObject(clazz.get(), constructID, false /* allocate */);
Andreas Huberdab5fc62016-08-15 09:25:02 -0700204}
205
206void JHwParcel::setTransactCallback(
207 ::android::hardware::IBinder::TransactCallback cb) {
208 mTransactCallback = cb;
209}
210
211void JHwParcel::send() {
212 CHECK(mTransactCallback != nullptr);
213 CHECK(mParcel != nullptr);
214
215 mTransactCallback(*mParcel);
216 mTransactCallback = nullptr;
217
218 mWasSent = true;
219}
220
221bool JHwParcel::wasSent() const {
222 return mWasSent;
223}
224
225} // namespace android
226
227////////////////////////////////////////////////////////////////////////////////
228
229using namespace android;
230
231static void releaseNativeContext(void *nativeContext) {
232 sp<JHwParcel> parcel = (JHwParcel *)nativeContext;
233
234 if (parcel != NULL) {
235 parcel->decStrong(NULL /* id */);
236 }
237}
238
239static jlong JHwParcel_native_init(JNIEnv *env) {
240 JHwParcel::InitClass(env);
241
242 return reinterpret_cast<jlong>(&releaseNativeContext);
243}
244
245static void JHwParcel_native_setup(
246 JNIEnv *env, jobject thiz, jboolean allocate) {
247 sp<JHwParcel> context = new JHwParcel(env, thiz);
248
249 if (allocate) {
250 context->setParcel(new hardware::Parcel, true /* assumeOwnership */);
251 }
252
253 JHwParcel::SetNativeContext(env, thiz, context);
254}
255
256static void JHwParcel_native_writeInterfaceToken(
257 JNIEnv *env, jobject thiz, jstring interfaceNameObj) {
258 if (interfaceNameObj == NULL) {
259 jniThrowException(env, "java/lang/NullPointerException", NULL);
260 return;
261 }
262
263 const jchar *interfaceName = env->GetStringCritical(interfaceNameObj, NULL);
264 if (interfaceName) {
Steven Morelandab2fca22016-11-11 12:33:41 -0800265 String8 nameCopy = String8(String16(
Andreas Huber9f026862016-11-03 15:46:04 -0700266 reinterpret_cast<const char16_t *>(interfaceName),
Steven Morelandab2fca22016-11-11 12:33:41 -0800267 env->GetStringLength(interfaceNameObj)));
Andreas Huberdab5fc62016-08-15 09:25:02 -0700268
269 env->ReleaseStringCritical(interfaceNameObj, interfaceName);
270 interfaceName = NULL;
271
Andreas Huber9f026862016-11-03 15:46:04 -0700272 hardware::Parcel *parcel =
273 JHwParcel::GetNativeContext(env, thiz)->getParcel();
274
Steven Morelandab2fca22016-11-11 12:33:41 -0800275 status_t err = parcel->writeInterfaceToken(nameCopy.string());
Andreas Huberdab5fc62016-08-15 09:25:02 -0700276 signalExceptionForError(env, err);
277 }
278}
279
280static void JHwParcel_native_enforceInterface(
281 JNIEnv *env, jobject thiz, jstring interfaceNameObj) {
282 // XXX original binder Parcel enforceInterface implementation does some
283 // mysterious things regarding strictModePolicy(), figure out if we need
284 // that here as well.
285 if (interfaceNameObj == NULL) {
286 jniThrowException(env, "java/lang/NullPointerException", NULL);
287 return;
288 }
289
290 const jchar *interfaceName = env->GetStringCritical(interfaceNameObj, NULL);
291 if (interfaceName) {
Steven Morelandab2fca22016-11-11 12:33:41 -0800292 String8 interfaceNameCopy = String8(String16(
Andreas Huber9f026862016-11-03 15:46:04 -0700293 reinterpret_cast<const char16_t *>(interfaceName),
Steven Morelandab2fca22016-11-11 12:33:41 -0800294 env->GetStringLength(interfaceNameObj)));
Andreas Huberdab5fc62016-08-15 09:25:02 -0700295
296 env->ReleaseStringCritical(interfaceNameObj, interfaceName);
297 interfaceName = NULL;
298
Andreas Huber9f026862016-11-03 15:46:04 -0700299 hardware::Parcel *parcel =
300 JHwParcel::GetNativeContext(env, thiz)->getParcel();
301
Steven Morelandab2fca22016-11-11 12:33:41 -0800302 bool valid = parcel->enforceInterface(interfaceNameCopy.string());
Andreas Huber9f026862016-11-03 15:46:04 -0700303
Andreas Huberdab5fc62016-08-15 09:25:02 -0700304 if (!valid) {
305 jniThrowException(
306 env,
307 "java/lang/SecurityException",
308 "HWBinder invocation to an incorrect interface");
309 }
310 }
311}
312
313#define DEFINE_PARCEL_WRITER(Suffix,Type) \
314static void JHwParcel_native_write ## Suffix( \
315 JNIEnv *env, jobject thiz, Type val) { \
316 hardware::Parcel *parcel = \
317 JHwParcel::GetNativeContext(env, thiz)->getParcel(); \
318 \
319 status_t err = parcel->write ## Suffix(val); \
320 signalExceptionForError(env, err); \
321}
322
323#define DEFINE_PARCEL_READER(Suffix,Type) \
324static Type JHwParcel_native_read ## Suffix( \
325 JNIEnv *env, jobject thiz) { \
326 hardware::Parcel *parcel = \
327 JHwParcel::GetNativeContext(env, thiz)->getParcel(); \
328 \
329 Type val; \
330 status_t err = parcel->read ## Suffix(&val); \
331 signalExceptionForError(env, err); \
332 \
333 return val; \
334}
335
Andreas Huber86635bb2016-08-24 16:19:03 -0700336DEFINE_PARCEL_WRITER(Bool,jboolean)
Andreas Huberdab5fc62016-08-15 09:25:02 -0700337DEFINE_PARCEL_WRITER(Int8,jbyte)
338DEFINE_PARCEL_WRITER(Int16,jshort)
339DEFINE_PARCEL_WRITER(Int32,jint)
340DEFINE_PARCEL_WRITER(Int64,jlong)
341DEFINE_PARCEL_WRITER(Float,jfloat)
342DEFINE_PARCEL_WRITER(Double,jdouble)
343
344DEFINE_PARCEL_READER(Int8,jbyte)
345DEFINE_PARCEL_READER(Int16,jshort)
346DEFINE_PARCEL_READER(Int32,jint)
347DEFINE_PARCEL_READER(Int64,jlong)
348DEFINE_PARCEL_READER(Float,jfloat)
349DEFINE_PARCEL_READER(Double,jdouble)
350
Andreas Huber86635bb2016-08-24 16:19:03 -0700351static jboolean JHwParcel_native_readBool(JNIEnv *env, jobject thiz) {
352 hardware::Parcel *parcel =
353 JHwParcel::GetNativeContext(env, thiz)->getParcel();
354
355 bool val;
356 status_t err = parcel->readBool(&val);
357 signalExceptionForError(env, err);
358
359 return (jboolean)val;
360}
361
Andreas Huberdab5fc62016-08-15 09:25:02 -0700362static void JHwParcel_native_writeStatus(
363 JNIEnv *env, jobject thiz, jint statusCode) {
364 using hardware::Status;
365
366 Status status;
367 switch (statusCode) {
368 case 0: // kStatusSuccess
369 status = Status::ok();
370 break;
371 case -1: // kStatusError
372 status = Status::fromStatusT(UNKNOWN_ERROR);
373 break;
374 default:
375 CHECK(!"Should not be here");
376 }
377
378 hardware::Parcel *parcel =
379 JHwParcel::GetNativeContext(env, thiz)->getParcel();
380
Yifan Hongddf31f62016-11-15 16:02:40 -0800381 status_t err = ::android::hardware::writeToParcel(status, parcel);
Andreas Huberdab5fc62016-08-15 09:25:02 -0700382 signalExceptionForError(env, err);
383}
384
385static void JHwParcel_native_verifySuccess(JNIEnv *env, jobject thiz) {
386 using hardware::Status;
387
388 hardware::Parcel *parcel =
389 JHwParcel::GetNativeContext(env, thiz)->getParcel();
390
391 Status status;
Yifan Hongddf31f62016-11-15 16:02:40 -0800392 status_t err = ::android::hardware::readFromParcel(&status, *parcel);
Andreas Huberdab5fc62016-08-15 09:25:02 -0700393 signalExceptionForError(env, err);
Steven Moreland2ef0cbd2018-01-17 13:26:35 -0800394
395 if (!status.isOk()) {
396 signalExceptionForError(env, UNKNOWN_ERROR, true /* canThrowRemoteException */);
397 }
Andreas Huberdab5fc62016-08-15 09:25:02 -0700398}
399
Martijn Coenen3d726d12017-03-16 18:46:42 +0100400static void JHwParcel_native_release(
401 JNIEnv *env, jobject thiz) {
402 JHwParcel::GetNativeContext(env, thiz)->setParcel(NULL, false /* assumeOwnership */);
403}
404
Andreas Huberdab5fc62016-08-15 09:25:02 -0700405static void JHwParcel_native_releaseTemporaryStorage(
406 JNIEnv *env, jobject thiz) {
407 JHwParcel::GetNativeContext(env, thiz)->getStorage()->release(env);
408}
409
410static void JHwParcel_native_send(JNIEnv *env, jobject thiz) {
411 JHwParcel::GetNativeContext(env, thiz)->send();
412}
413
414static void JHwParcel_native_writeString(
415 JNIEnv *env, jobject thiz, jstring valObj) {
416 if (valObj == NULL) {
417 jniThrowException(env, "java/lang/NullPointerException", NULL);
418 return;
419 }
420
421 sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz);
422
423 const hidl_string *s =
424 impl->getStorage()->allocTemporaryString(env, valObj);
425
426 hardware::Parcel *parcel = impl->getParcel();
427
428 size_t parentHandle;
429 status_t err = parcel->writeBuffer(s, sizeof(*s), &parentHandle);
430
431 if (err == OK) {
Yifan Hong3bb65782016-11-11 17:20:54 -0800432 err = ::android::hardware::writeEmbeddedToParcel(
433 *s, parcel, parentHandle, 0 /* parentOffset */);
Andreas Huberdab5fc62016-08-15 09:25:02 -0700434 }
435
436 signalExceptionForError(env, err);
437}
438
Andreas Huberdab5fc62016-08-15 09:25:02 -0700439#define DEFINE_PARCEL_VECTOR_WRITER(Suffix,Type) \
440static void JHwParcel_native_write ## Suffix ## Vector( \
441 JNIEnv *env, jobject thiz, Type ## Array valObj) { \
442 if (valObj == NULL) { \
443 jniThrowException(env, "java/lang/NullPointerException", NULL); \
444 return; \
445 } \
446 \
447 sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz); \
448 \
449 const hidl_vec<Type> *vec = \
450 impl->getStorage()->allocTemporary ## Suffix ## Vector(env, valObj); \
451 \
452 hardware::Parcel *parcel = impl->getParcel(); \
453 \
454 size_t parentHandle; \
455 status_t err = parcel->writeBuffer(vec, sizeof(*vec), &parentHandle); \
456 \
457 if (err == OK) { \
458 size_t childHandle; \
459 \
Yifan Hong3bb65782016-11-11 17:20:54 -0800460 err = ::android::hardware::writeEmbeddedToParcel( \
461 *vec, \
Andreas Huberdab5fc62016-08-15 09:25:02 -0700462 parcel, \
463 parentHandle, \
464 0 /* parentOffset */, \
465 &childHandle); \
466 } \
467 \
468 signalExceptionForError(env, err); \
469}
470
Andreas Huberdab5fc62016-08-15 09:25:02 -0700471DEFINE_PARCEL_VECTOR_WRITER(Int8,jbyte)
472DEFINE_PARCEL_VECTOR_WRITER(Int16,jshort)
473DEFINE_PARCEL_VECTOR_WRITER(Int32,jint)
474DEFINE_PARCEL_VECTOR_WRITER(Int64,jlong)
475DEFINE_PARCEL_VECTOR_WRITER(Float,jfloat)
476DEFINE_PARCEL_VECTOR_WRITER(Double,jdouble)
477
Andreas Huber86635bb2016-08-24 16:19:03 -0700478static void JHwParcel_native_writeBoolVector(
479 JNIEnv *env, jobject thiz, jbooleanArray valObj) {
480 if (valObj == NULL) {
481 jniThrowException(env, "java/lang/NullPointerException", NULL);
482 return;
483 }
484
485 sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz);
486
Andreas Huber9266f992016-08-25 11:21:21 -0700487 void *vecPtr =
488 impl->getStorage()->allocTemporaryStorage(sizeof(hidl_vec<bool>));
489
490 hidl_vec<bool> *vec = new (vecPtr) hidl_vec<bool>;
Andreas Huber86635bb2016-08-24 16:19:03 -0700491
492 jsize len = env->GetArrayLength(valObj);
493
494 jboolean *src = env->GetBooleanArrayElements(valObj, nullptr);
495
496 bool *dst =
497 (bool *)impl->getStorage()->allocTemporaryStorage(len * sizeof(bool));
498
499 for (jsize i = 0; i < len; ++i) {
500 dst[i] = src[i];
501 }
502
503 env->ReleaseBooleanArrayElements(valObj, src, 0 /* mode */);
504 src = nullptr;
505
506 vec->setToExternal(dst, len);
507
508 hardware::Parcel *parcel = impl->getParcel();
509
510 size_t parentHandle;
511 status_t err = parcel->writeBuffer(vec, sizeof(*vec), &parentHandle);
512
513 if (err == OK) {
514 size_t childHandle;
515
Yifan Hong3bb65782016-11-11 17:20:54 -0800516 err = ::android::hardware::writeEmbeddedToParcel(
517 *vec,
Andreas Huber86635bb2016-08-24 16:19:03 -0700518 parcel,
519 parentHandle,
520 0 /* parentOffset */,
521 &childHandle);
522 }
523
524 signalExceptionForError(env, err);
525}
526
Andreas Huberdab5fc62016-08-15 09:25:02 -0700527static void JHwParcel_native_writeStrongBinder(
528 JNIEnv *env, jobject thiz, jobject binderObj) {
529 sp<hardware::IBinder> binder;
530 if (binderObj != NULL) {
531 ScopedLocalRef<jclass> hwBinderKlass(
532 env, FindClassOrDie(env, PACKAGE_PATH "/HwBinder"));
533
534 ScopedLocalRef<jclass> hwRemoteBinderKlass(
535 env, FindClassOrDie(env, PACKAGE_PATH "/HwRemoteBinder"));
536
537 if (env->IsInstanceOf(binderObj, hwBinderKlass.get())) {
Andreas Huber56bdb8a2017-06-16 14:56:12 -0700538 binder = JHwBinder::GetNativeBinder(env, binderObj);
Andreas Huberdab5fc62016-08-15 09:25:02 -0700539 } else if (env->IsInstanceOf(binderObj, hwRemoteBinderKlass.get())) {
540 binder = JHwRemoteBinder::GetNativeContext(
541 env, binderObj)->getBinder();
542 } else {
543 signalExceptionForError(env, INVALID_OPERATION);
544 return;
545 }
546 }
547
548 hardware::Parcel *parcel =
549 JHwParcel::GetNativeContext(env, thiz)->getParcel();
550
551 status_t err = parcel->writeStrongBinder(binder);
552 signalExceptionForError(env, err);
553}
554
555static jstring MakeStringObjFromHidlString(JNIEnv *env, const hidl_string &s) {
556 String16 utf16String(s.c_str(), s.size());
557
558 return env->NewString(
559 reinterpret_cast<const jchar *>(utf16String.string()),
560 utf16String.size());
561}
562
563static jstring JHwParcel_native_readString(JNIEnv *env, jobject thiz) {
564 hardware::Parcel *parcel =
565 JHwParcel::GetNativeContext(env, thiz)->getParcel();
566
567 size_t parentHandle;
568
Martijn Coenen24c82272017-01-11 12:35:56 +0100569 const hidl_string *s;
Martijn Coenen7c006392017-04-18 15:54:43 -0700570 status_t err = parcel->readBuffer(sizeof(*s), &parentHandle,
Martijn Coenen24c82272017-01-11 12:35:56 +0100571 reinterpret_cast<const void**>(&s));
Andreas Huberdab5fc62016-08-15 09:25:02 -0700572
Martijn Coenen24c82272017-01-11 12:35:56 +0100573 if (err != OK) {
574 signalExceptionForError(env, err);
Andreas Huberdab5fc62016-08-15 09:25:02 -0700575 return NULL;
576 }
577
Martijn Coenen24c82272017-01-11 12:35:56 +0100578 err = ::android::hardware::readEmbeddedFromParcel(
Martijn Coenen7c006392017-04-18 15:54:43 -0700579 const_cast<hidl_string &>(*s),
Andreas Huberdab5fc62016-08-15 09:25:02 -0700580 *parcel, parentHandle, 0 /* parentOffset */);
581
582 if (err != OK) {
583 signalExceptionForError(env, err);
584 return NULL;
585 }
586
587 return MakeStringObjFromHidlString(env, *s);
588}
589
Andreas Huberdab5fc62016-08-15 09:25:02 -0700590#define DEFINE_PARCEL_VECTOR_READER(Suffix,Type,NewType) \
591static Type ## Array JHwParcel_native_read ## Suffix ## Vector( \
592 JNIEnv *env, jobject thiz) { \
593 hardware::Parcel *parcel = \
594 JHwParcel::GetNativeContext(env, thiz)->getParcel(); \
Andreas Huberdab5fc62016-08-15 09:25:02 -0700595 size_t parentHandle; \
596 \
Martijn Coenen24c82272017-01-11 12:35:56 +0100597 const hidl_vec<Type> *vec; \
Martijn Coenen7c006392017-04-18 15:54:43 -0700598 status_t err = parcel->readBuffer(sizeof(*vec), &parentHandle, \
Martijn Coenen24c82272017-01-11 12:35:56 +0100599 reinterpret_cast<const void**>(&vec)); \
Andreas Huberdab5fc62016-08-15 09:25:02 -0700600 \
Martijn Coenen24c82272017-01-11 12:35:56 +0100601 if (err != OK) { \
602 signalExceptionForError(env, err); \
Andreas Huberdab5fc62016-08-15 09:25:02 -0700603 return NULL; \
604 } \
605 \
606 size_t childHandle; \
607 \
Martijn Coenen24c82272017-01-11 12:35:56 +0100608 err = ::android::hardware::readEmbeddedFromParcel( \
Martijn Coenen7c006392017-04-18 15:54:43 -0700609 const_cast<hidl_vec<Type> &>(*vec), \
Andreas Huberdab5fc62016-08-15 09:25:02 -0700610 *parcel, \
611 parentHandle, \
612 0 /* parentOffset */, \
613 &childHandle); \
614 \
615 if (err != OK) { \
616 signalExceptionForError(env, err); \
617 return NULL; \
618 } \
619 \
620 Type ## Array valObj = env->New ## NewType ## Array(vec->size()); \
621 env->Set ## NewType ## ArrayRegion(valObj, 0, vec->size(), &(*vec)[0]); \
622 \
623 return valObj; \
624}
625
Andreas Huberdab5fc62016-08-15 09:25:02 -0700626DEFINE_PARCEL_VECTOR_READER(Int8,jbyte,Byte)
627DEFINE_PARCEL_VECTOR_READER(Int16,jshort,Short)
628DEFINE_PARCEL_VECTOR_READER(Int32,jint,Int)
629DEFINE_PARCEL_VECTOR_READER(Int64,jlong,Long)
630DEFINE_PARCEL_VECTOR_READER(Float,jfloat,Float)
631DEFINE_PARCEL_VECTOR_READER(Double,jdouble,Double)
632
Andreas Huber86635bb2016-08-24 16:19:03 -0700633static jbooleanArray JHwParcel_native_readBoolVector(
634 JNIEnv *env, jobject thiz) {
635 hardware::Parcel *parcel =
636 JHwParcel::GetNativeContext(env, thiz)->getParcel();
637
638 size_t parentHandle;
639
Martijn Coenen24c82272017-01-11 12:35:56 +0100640 const hidl_vec<bool> *vec;
Martijn Coenen7c006392017-04-18 15:54:43 -0700641 status_t err = parcel->readBuffer(sizeof(*vec), &parentHandle,
Martijn Coenen24c82272017-01-11 12:35:56 +0100642 reinterpret_cast<const void**>(&vec));
Andreas Huber86635bb2016-08-24 16:19:03 -0700643
Martijn Coenen24c82272017-01-11 12:35:56 +0100644 if (err != OK) {
645 signalExceptionForError(env, err);
Andreas Huber86635bb2016-08-24 16:19:03 -0700646 return NULL;
647 }
648
649 size_t childHandle;
650
Martijn Coenen24c82272017-01-11 12:35:56 +0100651 err = ::android::hardware::readEmbeddedFromParcel(
Martijn Coenen7c006392017-04-18 15:54:43 -0700652 const_cast<hidl_vec<bool> &>(*vec),
Andreas Huber86635bb2016-08-24 16:19:03 -0700653 *parcel,
654 parentHandle,
655 0 /* parentOffset */,
656 &childHandle);
657
658 if (err != OK) {
659 signalExceptionForError(env, err);
660 return NULL;
661 }
662
663 jbooleanArray valObj = env->NewBooleanArray(vec->size());
664
665 for (size_t i = 0; i < vec->size(); ++i) {
666 jboolean x = (*vec)[i];
667 env->SetBooleanArrayRegion(valObj, i, 1, &x);
668 }
669
670 return valObj;
671}
672
Andreas Huberdab5fc62016-08-15 09:25:02 -0700673static jobjectArray MakeStringArray(
674 JNIEnv *env, const hidl_string *array, size_t size) {
675 ScopedLocalRef<jclass> stringKlass(
676 env,
677 env->FindClass("java/lang/String"));
678
679 // XXX Why can't I use ScopedLocalRef<> for the arrayObj and the stringObjs?
680
681 jobjectArray arrayObj = env->NewObjectArray(size, stringKlass.get(), NULL);
682
683 for (size_t i = 0; i < size; ++i) {
684 jstring stringObj = MakeStringObjFromHidlString(env, array[i]);
685
686 env->SetObjectArrayElement(
687 arrayObj,
688 i,
689 stringObj);
690 }
691
692 return arrayObj;
693}
694
Andreas Huberdab5fc62016-08-15 09:25:02 -0700695static jobjectArray JHwParcel_native_readStringVector(
696 JNIEnv *env, jobject thiz) {
697 typedef hidl_vec<hidl_string> string_vec;
698
699 hardware::Parcel *parcel =
700 JHwParcel::GetNativeContext(env, thiz)->getParcel();
701
702 size_t parentHandle;
703
Martijn Coenen24c82272017-01-11 12:35:56 +0100704 const string_vec *vec;
Martijn Coenen7c006392017-04-18 15:54:43 -0700705 status_t err = parcel->readBuffer(sizeof(*vec), &parentHandle,
Martijn Coenen24c82272017-01-11 12:35:56 +0100706 reinterpret_cast<const void **>(&vec));
Andreas Huberdab5fc62016-08-15 09:25:02 -0700707
Martijn Coenen24c82272017-01-11 12:35:56 +0100708 if (err != OK) {
709 signalExceptionForError(env, err);
Andreas Huberdab5fc62016-08-15 09:25:02 -0700710 return NULL;
711 }
712
713 size_t childHandle;
Martijn Coenen24c82272017-01-11 12:35:56 +0100714 err = ::android::hardware::readEmbeddedFromParcel(
Martijn Coenen7c006392017-04-18 15:54:43 -0700715 const_cast<string_vec &>(*vec),
Andreas Huberdab5fc62016-08-15 09:25:02 -0700716 *parcel, parentHandle, 0 /* parentOffset */, &childHandle);
717
718 for (size_t i = 0; (err == OK) && (i < vec->size()); ++i) {
Yifan Hong3bb65782016-11-11 17:20:54 -0800719 err = android::hardware::readEmbeddedFromParcel(
Martijn Coenen7c006392017-04-18 15:54:43 -0700720 const_cast<hidl_string &>((*vec)[i]),
Andreas Huberdab5fc62016-08-15 09:25:02 -0700721 *parcel,
722 childHandle,
Martijn Coenen7c006392017-04-18 15:54:43 -0700723 i * sizeof(hidl_string) /* parentOffset */);
Andreas Huberdab5fc62016-08-15 09:25:02 -0700724 }
725
726 if (err != OK) {
727 signalExceptionForError(env, err);
728 return NULL;
729 }
730
731 return MakeStringArray(env, &(*vec)[0], vec->size());
732}
733
734static void JHwParcel_native_writeStringVector(
735 JNIEnv *env, jobject thiz, jobjectArray arrayObj) {
736 typedef hidl_vec<hidl_string> string_vec;
737
738 if (arrayObj == NULL) {
739 jniThrowException(env, "java/lang/NullPointerException", NULL);
740 return;
741 }
742
743 jsize len = env->GetArrayLength(arrayObj);
744
745 sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz);
746
Andreas Huber9266f992016-08-25 11:21:21 -0700747 void *vecPtr =
748 impl->getStorage()->allocTemporaryStorage(sizeof(string_vec));
749
750 string_vec *vec = new (vecPtr) string_vec;
Andreas Huberdab5fc62016-08-15 09:25:02 -0700751
752 hidl_string *strings = impl->getStorage()->allocStringArray(len);
753 vec->setToExternal(strings, len);
754
755 for (jsize i = 0; i < len; ++i) {
756 ScopedLocalRef<jstring> stringObj(
757 env,
758 (jstring)env->GetObjectArrayElement(arrayObj, i));
759
760 const hidl_string *s =
761 impl->getStorage()->allocTemporaryString(env, stringObj.get());
762
763 strings[i].setToExternal(s->c_str(), s->size());
764 }
765
766 hardware::Parcel *parcel = impl->getParcel();
767
768 size_t parentHandle;
769 status_t err = parcel->writeBuffer(vec, sizeof(*vec), &parentHandle);
770
771 if (err == OK) {
772 size_t childHandle;
Yifan Hong3bb65782016-11-11 17:20:54 -0800773 err = ::android::hardware::writeEmbeddedToParcel(
774 *vec,
Andreas Huberdab5fc62016-08-15 09:25:02 -0700775 parcel,
776 parentHandle,
777 0 /* parentOffset */,
778 &childHandle);
779
780 for (size_t i = 0; (err == OK) && (i < vec->size()); ++i) {
Yifan Hong3bb65782016-11-11 17:20:54 -0800781 err = ::android::hardware::writeEmbeddedToParcel(
782 (*vec)[i],
Andreas Huberdab5fc62016-08-15 09:25:02 -0700783 parcel,
784 childHandle,
785 i * sizeof(hidl_string));
786 }
787 }
788
789 signalExceptionForError(env, err);
790}
791
792static jobject JHwParcel_native_readStrongBinder(JNIEnv *env, jobject thiz) {
793 hardware::Parcel *parcel =
794 JHwParcel::GetNativeContext(env, thiz)->getParcel();
795
796 sp<hardware::IBinder> binder = parcel->readStrongBinder();
797
798 if (binder == NULL) {
799 return NULL;
800 }
801
802 return JHwRemoteBinder::NewObject(env, binder);
803}
804
Martijn Coenen7c006392017-04-18 15:54:43 -0700805static jobject JHwParcel_native_readBuffer(JNIEnv *env, jobject thiz,
806 jlong expectedSize) {
Andreas Huber9266f992016-08-25 11:21:21 -0700807 hardware::Parcel *parcel =
808 JHwParcel::GetNativeContext(env, thiz)->getParcel();
809
810 size_t handle;
Martijn Coenen24c82272017-01-11 12:35:56 +0100811 const void *ptr;
Martijn Coenen7c006392017-04-18 15:54:43 -0700812
813 if (expectedSize < 0) {
814 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
815 return nullptr;
816 }
817
818 status_t status = parcel->readBuffer(expectedSize, &handle, &ptr);
Andreas Huber9266f992016-08-25 11:21:21 -0700819
Martijn Coenen24c82272017-01-11 12:35:56 +0100820 if (status != OK) {
Andreas Huber9266f992016-08-25 11:21:21 -0700821 jniThrowException(env, "java/util/NoSuchElementException", NULL);
822 return nullptr;
823 }
824
825 return JHwBlob::NewObject(env, ptr, handle);
826}
827
828static jobject JHwParcel_native_readEmbeddedBuffer(
Martijn Coenen7c006392017-04-18 15:54:43 -0700829 JNIEnv *env, jobject thiz, jlong expectedSize,
830 jlong parentHandle, jlong offset, jboolean nullable) {
Andreas Huber9266f992016-08-25 11:21:21 -0700831 hardware::Parcel *parcel =
832 JHwParcel::GetNativeContext(env, thiz)->getParcel();
833
834 size_t childHandle;
835
Martijn Coenen24c82272017-01-11 12:35:56 +0100836 const void *ptr;
837 status_t status =
Martijn Coenen7c006392017-04-18 15:54:43 -0700838 parcel->readNullableEmbeddedBuffer(expectedSize,
839 &childHandle, parentHandle, offset, &ptr);
840
841 if (expectedSize < 0) {
842 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
843 return nullptr;
844 }
Andreas Huber9266f992016-08-25 11:21:21 -0700845
Martijn Coenen24c82272017-01-11 12:35:56 +0100846 if (status != OK) {
Andreas Huber9266f992016-08-25 11:21:21 -0700847 jniThrowException(env, "java/util/NoSuchElementException", NULL);
848 return 0;
Martijn Coenen14fae062017-01-13 11:08:51 +0100849 } else if (status == OK && !nullable && ptr == nullptr) {
850 jniThrowException(env, "java/lang/NullPointerException", NULL);
851 return 0;
Andreas Huber9266f992016-08-25 11:21:21 -0700852 }
853
854 return JHwBlob::NewObject(env, ptr, childHandle);
855}
856
857static void JHwParcel_native_writeBuffer(
858 JNIEnv *env, jobject thiz, jobject blobObj) {
859 if (blobObj == nullptr) {
860 jniThrowException(env, "java/lang/NullPointerException", NULL);
861 return;
862 }
863
864 hardware::Parcel *parcel =
865 JHwParcel::GetNativeContext(env, thiz)->getParcel();
866
867 sp<JHwBlob> blob = JHwBlob::GetNativeContext(env, blobObj);
868 status_t err = blob->writeToParcel(parcel);
869
870 if (err != OK) {
871 signalExceptionForError(env, err);
872 }
873}
874
Andreas Huberdab5fc62016-08-15 09:25:02 -0700875static JNINativeMethod gMethods[] = {
876 { "native_init", "()J", (void *)JHwParcel_native_init },
877 { "native_setup", "(Z)V", (void *)JHwParcel_native_setup },
878
879 { "writeInterfaceToken", "(Ljava/lang/String;)V",
880 (void *)JHwParcel_native_writeInterfaceToken },
881
Andreas Huber86635bb2016-08-24 16:19:03 -0700882 { "writeBool", "(Z)V", (void *)JHwParcel_native_writeBool },
Andreas Huberdab5fc62016-08-15 09:25:02 -0700883 { "writeInt8", "(B)V", (void *)JHwParcel_native_writeInt8 },
884 { "writeInt16", "(S)V", (void *)JHwParcel_native_writeInt16 },
885 { "writeInt32", "(I)V", (void *)JHwParcel_native_writeInt32 },
886 { "writeInt64", "(J)V", (void *)JHwParcel_native_writeInt64 },
887 { "writeFloat", "(F)V", (void *)JHwParcel_native_writeFloat },
888 { "writeDouble", "(D)V", (void *)JHwParcel_native_writeDouble },
889
890 { "writeString", "(Ljava/lang/String;)V",
891 (void *)JHwParcel_native_writeString },
892
Andreas Huber86635bb2016-08-24 16:19:03 -0700893 { "writeBoolVector", "([Z)V", (void *)JHwParcel_native_writeBoolVector },
Andreas Huberdab5fc62016-08-15 09:25:02 -0700894 { "writeInt8Vector", "([B)V", (void *)JHwParcel_native_writeInt8Vector },
Andreas Huberdab5fc62016-08-15 09:25:02 -0700895 { "writeInt16Vector", "([S)V", (void *)JHwParcel_native_writeInt16Vector },
Andreas Huberdab5fc62016-08-15 09:25:02 -0700896 { "writeInt32Vector", "([I)V", (void *)JHwParcel_native_writeInt32Vector },
Andreas Huberdab5fc62016-08-15 09:25:02 -0700897 { "writeInt64Vector", "([J)V", (void *)JHwParcel_native_writeInt64Vector },
Andreas Huberdab5fc62016-08-15 09:25:02 -0700898 { "writeFloatVector", "([F)V", (void *)JHwParcel_native_writeFloatVector },
Andreas Huberdab5fc62016-08-15 09:25:02 -0700899
900 { "writeDoubleVector", "([D)V",
901 (void *)JHwParcel_native_writeDoubleVector },
902
Andreas Huberdab5fc62016-08-15 09:25:02 -0700903 { "writeStringVector", "([Ljava/lang/String;)V",
904 (void *)JHwParcel_native_writeStringVector },
905
906 { "writeStrongBinder", "(L" PACKAGE_PATH "/IHwBinder;)V",
907 (void *)JHwParcel_native_writeStrongBinder },
908
909 { "enforceInterface", "(Ljava/lang/String;)V",
910 (void *)JHwParcel_native_enforceInterface },
911
Andreas Huber86635bb2016-08-24 16:19:03 -0700912 { "readBool", "()Z", (void *)JHwParcel_native_readBool },
Andreas Huberdab5fc62016-08-15 09:25:02 -0700913 { "readInt8", "()B", (void *)JHwParcel_native_readInt8 },
914 { "readInt16", "()S", (void *)JHwParcel_native_readInt16 },
915 { "readInt32", "()I", (void *)JHwParcel_native_readInt32 },
916 { "readInt64", "()J", (void *)JHwParcel_native_readInt64 },
917 { "readFloat", "()F", (void *)JHwParcel_native_readFloat },
918 { "readDouble", "()D", (void *)JHwParcel_native_readDouble },
919
920 { "readString", "()Ljava/lang/String;",
921 (void *)JHwParcel_native_readString },
922
Andreas Huberef1a5652016-10-18 09:24:04 -0700923 { "readBoolVectorAsArray", "()[Z",
924 (void *)JHwParcel_native_readBoolVector },
Andreas Huberdab5fc62016-08-15 09:25:02 -0700925
Andreas Huberef1a5652016-10-18 09:24:04 -0700926 { "readInt8VectorAsArray", "()[B",
927 (void *)JHwParcel_native_readInt8Vector },
928
929 { "readInt16VectorAsArray", "()[S",
930 (void *)JHwParcel_native_readInt16Vector },
931
932 { "readInt32VectorAsArray", "()[I",
933 (void *)JHwParcel_native_readInt32Vector },
934
935 { "readInt64VectorAsArray", "()[J",
936 (void *)JHwParcel_native_readInt64Vector },
937
938 { "readFloatVectorAsArray", "()[F",
939 (void *)JHwParcel_native_readFloatVector },
940
941 { "readDoubleVectorAsArray", "()[D",
942 (void *)JHwParcel_native_readDoubleVector },
943
944 { "readStringVectorAsArray", "()[Ljava/lang/String;",
Andreas Huberdab5fc62016-08-15 09:25:02 -0700945 (void *)JHwParcel_native_readStringVector },
946
947 { "readStrongBinder", "()L" PACKAGE_PATH "/IHwBinder;",
948 (void *)JHwParcel_native_readStrongBinder },
949
950 { "writeStatus", "(I)V", (void *)JHwParcel_native_writeStatus },
951
952 { "verifySuccess", "()V", (void *)JHwParcel_native_verifySuccess },
953
954 { "releaseTemporaryStorage", "()V",
955 (void *)JHwParcel_native_releaseTemporaryStorage },
956
957 { "send", "()V", (void *)JHwParcel_native_send },
Andreas Huber9266f992016-08-25 11:21:21 -0700958
Martijn Coenen7c006392017-04-18 15:54:43 -0700959 { "readBuffer", "(J)L" PACKAGE_PATH "/HwBlob;",
Andreas Huber9266f992016-08-25 11:21:21 -0700960 (void *)JHwParcel_native_readBuffer },
961
Martijn Coenen7c006392017-04-18 15:54:43 -0700962 { "readEmbeddedBuffer", "(JJJZ)L" PACKAGE_PATH "/HwBlob;",
Andreas Huber9266f992016-08-25 11:21:21 -0700963 (void *)JHwParcel_native_readEmbeddedBuffer },
964
965 { "writeBuffer", "(L" PACKAGE_PATH "/HwBlob;)V",
966 (void *)JHwParcel_native_writeBuffer },
Martijn Coenen3d726d12017-03-16 18:46:42 +0100967
968 { "release", "()V",
969 (void *)JHwParcel_native_release },
970
Andreas Huberdab5fc62016-08-15 09:25:02 -0700971};
972
973namespace android {
974
975int register_android_os_HwParcel(JNIEnv *env) {
976 return RegisterMethodsOrDie(env, CLASS_PATH, gMethods, NELEM(gMethods));
977}
978
979} // namespace android