blob: 1bd233313ca370b89aa870b578289d4bdb1318bf [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
27#include <JNIHelp.h>
28#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) {
169 jclass clazz = env->GetObjectClass(thiz);
170 CHECK(clazz != NULL);
171
172 mClass = (jclass)env->NewGlobalRef(clazz);
173 mObject = env->NewWeakGlobalRef(thiz);
174}
175
176JHwParcel::~JHwParcel() {
177 JNIEnv *env = AndroidRuntime::getJNIEnv();
178
179 mStorage.release(env);
180
181 setParcel(NULL, false /* assumeOwnership */);
182
183 env->DeleteWeakGlobalRef(mObject);
184 mObject = NULL;
185
186 env->DeleteGlobalRef(mClass);
187 mClass = NULL;
188}
189
190hardware::Parcel *JHwParcel::getParcel() {
191 return mParcel;
192}
193
194EphemeralStorage *JHwParcel::getStorage() {
195 return &mStorage;
196}
197
198void JHwParcel::setParcel(hardware::Parcel *parcel, bool assumeOwnership) {
199 if (mParcel && mOwnsParcel) {
200 delete mParcel;
201 }
202
203 mParcel = parcel;
204 mOwnsParcel = assumeOwnership;
205}
206
207// static
208jobject JHwParcel::NewObject(JNIEnv *env) {
209 ScopedLocalRef<jclass> clazz(env, FindClassOrDie(env, CLASS_PATH));
210
Andreas Huber9266f992016-08-25 11:21:21 -0700211 jmethodID constructID =
212 GetMethodIDOrDie(env, clazz.get(), "<init>", "(Z)V");
213
214 return env->NewObject(clazz.get(), constructID, false /* allocate */);
Andreas Huberdab5fc62016-08-15 09:25:02 -0700215}
216
217void JHwParcel::setTransactCallback(
218 ::android::hardware::IBinder::TransactCallback cb) {
219 mTransactCallback = cb;
220}
221
222void JHwParcel::send() {
223 CHECK(mTransactCallback != nullptr);
224 CHECK(mParcel != nullptr);
225
226 mTransactCallback(*mParcel);
227 mTransactCallback = nullptr;
228
229 mWasSent = true;
230}
231
232bool JHwParcel::wasSent() const {
233 return mWasSent;
234}
235
236} // namespace android
237
238////////////////////////////////////////////////////////////////////////////////
239
240using namespace android;
241
242static void releaseNativeContext(void *nativeContext) {
243 sp<JHwParcel> parcel = (JHwParcel *)nativeContext;
244
245 if (parcel != NULL) {
246 parcel->decStrong(NULL /* id */);
247 }
248}
249
250static jlong JHwParcel_native_init(JNIEnv *env) {
251 JHwParcel::InitClass(env);
252
253 return reinterpret_cast<jlong>(&releaseNativeContext);
254}
255
256static void JHwParcel_native_setup(
257 JNIEnv *env, jobject thiz, jboolean allocate) {
258 sp<JHwParcel> context = new JHwParcel(env, thiz);
259
260 if (allocate) {
261 context->setParcel(new hardware::Parcel, true /* assumeOwnership */);
262 }
263
264 JHwParcel::SetNativeContext(env, thiz, context);
265}
266
267static void JHwParcel_native_writeInterfaceToken(
268 JNIEnv *env, jobject thiz, jstring interfaceNameObj) {
269 if (interfaceNameObj == NULL) {
270 jniThrowException(env, "java/lang/NullPointerException", NULL);
271 return;
272 }
273
274 const jchar *interfaceName = env->GetStringCritical(interfaceNameObj, NULL);
275 if (interfaceName) {
Steven Morelandab2fca22016-11-11 12:33:41 -0800276 String8 nameCopy = String8(String16(
Andreas Huber9f026862016-11-03 15:46:04 -0700277 reinterpret_cast<const char16_t *>(interfaceName),
Steven Morelandab2fca22016-11-11 12:33:41 -0800278 env->GetStringLength(interfaceNameObj)));
Andreas Huberdab5fc62016-08-15 09:25:02 -0700279
280 env->ReleaseStringCritical(interfaceNameObj, interfaceName);
281 interfaceName = NULL;
282
Andreas Huber9f026862016-11-03 15:46:04 -0700283 hardware::Parcel *parcel =
284 JHwParcel::GetNativeContext(env, thiz)->getParcel();
285
Steven Morelandab2fca22016-11-11 12:33:41 -0800286 status_t err = parcel->writeInterfaceToken(nameCopy.string());
Andreas Huberdab5fc62016-08-15 09:25:02 -0700287 signalExceptionForError(env, err);
288 }
289}
290
291static void JHwParcel_native_enforceInterface(
292 JNIEnv *env, jobject thiz, jstring interfaceNameObj) {
293 // XXX original binder Parcel enforceInterface implementation does some
294 // mysterious things regarding strictModePolicy(), figure out if we need
295 // that here as well.
296 if (interfaceNameObj == NULL) {
297 jniThrowException(env, "java/lang/NullPointerException", NULL);
298 return;
299 }
300
301 const jchar *interfaceName = env->GetStringCritical(interfaceNameObj, NULL);
302 if (interfaceName) {
Steven Morelandab2fca22016-11-11 12:33:41 -0800303 String8 interfaceNameCopy = String8(String16(
Andreas Huber9f026862016-11-03 15:46:04 -0700304 reinterpret_cast<const char16_t *>(interfaceName),
Steven Morelandab2fca22016-11-11 12:33:41 -0800305 env->GetStringLength(interfaceNameObj)));
Andreas Huberdab5fc62016-08-15 09:25:02 -0700306
307 env->ReleaseStringCritical(interfaceNameObj, interfaceName);
308 interfaceName = NULL;
309
Andreas Huber9f026862016-11-03 15:46:04 -0700310 hardware::Parcel *parcel =
311 JHwParcel::GetNativeContext(env, thiz)->getParcel();
312
Steven Morelandab2fca22016-11-11 12:33:41 -0800313 bool valid = parcel->enforceInterface(interfaceNameCopy.string());
Andreas Huber9f026862016-11-03 15:46:04 -0700314
Andreas Huberdab5fc62016-08-15 09:25:02 -0700315 if (!valid) {
316 jniThrowException(
317 env,
318 "java/lang/SecurityException",
319 "HWBinder invocation to an incorrect interface");
320 }
321 }
322}
323
324#define DEFINE_PARCEL_WRITER(Suffix,Type) \
325static void JHwParcel_native_write ## Suffix( \
326 JNIEnv *env, jobject thiz, Type val) { \
327 hardware::Parcel *parcel = \
328 JHwParcel::GetNativeContext(env, thiz)->getParcel(); \
329 \
330 status_t err = parcel->write ## Suffix(val); \
331 signalExceptionForError(env, err); \
332}
333
334#define DEFINE_PARCEL_READER(Suffix,Type) \
335static Type JHwParcel_native_read ## Suffix( \
336 JNIEnv *env, jobject thiz) { \
337 hardware::Parcel *parcel = \
338 JHwParcel::GetNativeContext(env, thiz)->getParcel(); \
339 \
340 Type val; \
341 status_t err = parcel->read ## Suffix(&val); \
342 signalExceptionForError(env, err); \
343 \
344 return val; \
345}
346
Andreas Huber86635bb2016-08-24 16:19:03 -0700347DEFINE_PARCEL_WRITER(Bool,jboolean)
Andreas Huberdab5fc62016-08-15 09:25:02 -0700348DEFINE_PARCEL_WRITER(Int8,jbyte)
349DEFINE_PARCEL_WRITER(Int16,jshort)
350DEFINE_PARCEL_WRITER(Int32,jint)
351DEFINE_PARCEL_WRITER(Int64,jlong)
352DEFINE_PARCEL_WRITER(Float,jfloat)
353DEFINE_PARCEL_WRITER(Double,jdouble)
354
355DEFINE_PARCEL_READER(Int8,jbyte)
356DEFINE_PARCEL_READER(Int16,jshort)
357DEFINE_PARCEL_READER(Int32,jint)
358DEFINE_PARCEL_READER(Int64,jlong)
359DEFINE_PARCEL_READER(Float,jfloat)
360DEFINE_PARCEL_READER(Double,jdouble)
361
Andreas Huber86635bb2016-08-24 16:19:03 -0700362static jboolean JHwParcel_native_readBool(JNIEnv *env, jobject thiz) {
363 hardware::Parcel *parcel =
364 JHwParcel::GetNativeContext(env, thiz)->getParcel();
365
366 bool val;
367 status_t err = parcel->readBool(&val);
368 signalExceptionForError(env, err);
369
370 return (jboolean)val;
371}
372
Andreas Huberdab5fc62016-08-15 09:25:02 -0700373static void JHwParcel_native_writeStatus(
374 JNIEnv *env, jobject thiz, jint statusCode) {
375 using hardware::Status;
376
377 Status status;
378 switch (statusCode) {
379 case 0: // kStatusSuccess
380 status = Status::ok();
381 break;
382 case -1: // kStatusError
383 status = Status::fromStatusT(UNKNOWN_ERROR);
384 break;
385 default:
386 CHECK(!"Should not be here");
387 }
388
389 hardware::Parcel *parcel =
390 JHwParcel::GetNativeContext(env, thiz)->getParcel();
391
Yifan Hongddf31f62016-11-15 16:02:40 -0800392 status_t err = ::android::hardware::writeToParcel(status, parcel);
Andreas Huberdab5fc62016-08-15 09:25:02 -0700393 signalExceptionForError(env, err);
394}
395
396static void JHwParcel_native_verifySuccess(JNIEnv *env, jobject thiz) {
397 using hardware::Status;
398
399 hardware::Parcel *parcel =
400 JHwParcel::GetNativeContext(env, thiz)->getParcel();
401
402 Status status;
Yifan Hongddf31f62016-11-15 16:02:40 -0800403 status_t err = ::android::hardware::readFromParcel(&status, *parcel);
Andreas Huberdab5fc62016-08-15 09:25:02 -0700404 signalExceptionForError(env, err);
405}
406
407static void JHwParcel_native_releaseTemporaryStorage(
408 JNIEnv *env, jobject thiz) {
409 JHwParcel::GetNativeContext(env, thiz)->getStorage()->release(env);
410}
411
412static void JHwParcel_native_send(JNIEnv *env, jobject thiz) {
413 JHwParcel::GetNativeContext(env, thiz)->send();
414}
415
416static void JHwParcel_native_writeString(
417 JNIEnv *env, jobject thiz, jstring valObj) {
418 if (valObj == NULL) {
419 jniThrowException(env, "java/lang/NullPointerException", NULL);
420 return;
421 }
422
423 sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz);
424
425 const hidl_string *s =
426 impl->getStorage()->allocTemporaryString(env, valObj);
427
428 hardware::Parcel *parcel = impl->getParcel();
429
430 size_t parentHandle;
431 status_t err = parcel->writeBuffer(s, sizeof(*s), &parentHandle);
432
433 if (err == OK) {
Yifan Hong3bb65782016-11-11 17:20:54 -0800434 err = ::android::hardware::writeEmbeddedToParcel(
435 *s, parcel, parentHandle, 0 /* parentOffset */);
Andreas Huberdab5fc62016-08-15 09:25:02 -0700436 }
437
438 signalExceptionForError(env, err);
439}
440
Andreas Huberdab5fc62016-08-15 09:25:02 -0700441#define DEFINE_PARCEL_VECTOR_WRITER(Suffix,Type) \
442static void JHwParcel_native_write ## Suffix ## Vector( \
443 JNIEnv *env, jobject thiz, Type ## Array valObj) { \
444 if (valObj == NULL) { \
445 jniThrowException(env, "java/lang/NullPointerException", NULL); \
446 return; \
447 } \
448 \
449 sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz); \
450 \
451 const hidl_vec<Type> *vec = \
452 impl->getStorage()->allocTemporary ## Suffix ## Vector(env, valObj); \
453 \
454 hardware::Parcel *parcel = impl->getParcel(); \
455 \
456 size_t parentHandle; \
457 status_t err = parcel->writeBuffer(vec, sizeof(*vec), &parentHandle); \
458 \
459 if (err == OK) { \
460 size_t childHandle; \
461 \
Yifan Hong3bb65782016-11-11 17:20:54 -0800462 err = ::android::hardware::writeEmbeddedToParcel( \
463 *vec, \
Andreas Huberdab5fc62016-08-15 09:25:02 -0700464 parcel, \
465 parentHandle, \
466 0 /* parentOffset */, \
467 &childHandle); \
468 } \
469 \
470 signalExceptionForError(env, err); \
471}
472
Andreas Huberdab5fc62016-08-15 09:25:02 -0700473DEFINE_PARCEL_VECTOR_WRITER(Int8,jbyte)
474DEFINE_PARCEL_VECTOR_WRITER(Int16,jshort)
475DEFINE_PARCEL_VECTOR_WRITER(Int32,jint)
476DEFINE_PARCEL_VECTOR_WRITER(Int64,jlong)
477DEFINE_PARCEL_VECTOR_WRITER(Float,jfloat)
478DEFINE_PARCEL_VECTOR_WRITER(Double,jdouble)
479
Andreas Huber86635bb2016-08-24 16:19:03 -0700480static void JHwParcel_native_writeBoolVector(
481 JNIEnv *env, jobject thiz, jbooleanArray valObj) {
482 if (valObj == NULL) {
483 jniThrowException(env, "java/lang/NullPointerException", NULL);
484 return;
485 }
486
487 sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz);
488
Andreas Huber9266f992016-08-25 11:21:21 -0700489 void *vecPtr =
490 impl->getStorage()->allocTemporaryStorage(sizeof(hidl_vec<bool>));
491
492 hidl_vec<bool> *vec = new (vecPtr) hidl_vec<bool>;
Andreas Huber86635bb2016-08-24 16:19:03 -0700493
494 jsize len = env->GetArrayLength(valObj);
495
496 jboolean *src = env->GetBooleanArrayElements(valObj, nullptr);
497
498 bool *dst =
499 (bool *)impl->getStorage()->allocTemporaryStorage(len * sizeof(bool));
500
501 for (jsize i = 0; i < len; ++i) {
502 dst[i] = src[i];
503 }
504
505 env->ReleaseBooleanArrayElements(valObj, src, 0 /* mode */);
506 src = nullptr;
507
508 vec->setToExternal(dst, len);
509
510 hardware::Parcel *parcel = impl->getParcel();
511
512 size_t parentHandle;
513 status_t err = parcel->writeBuffer(vec, sizeof(*vec), &parentHandle);
514
515 if (err == OK) {
516 size_t childHandle;
517
Yifan Hong3bb65782016-11-11 17:20:54 -0800518 err = ::android::hardware::writeEmbeddedToParcel(
519 *vec,
Andreas Huber86635bb2016-08-24 16:19:03 -0700520 parcel,
521 parentHandle,
522 0 /* parentOffset */,
523 &childHandle);
524 }
525
526 signalExceptionForError(env, err);
527}
528
Andreas Huberdab5fc62016-08-15 09:25:02 -0700529static void JHwParcel_native_writeStrongBinder(
530 JNIEnv *env, jobject thiz, jobject binderObj) {
531 sp<hardware::IBinder> binder;
532 if (binderObj != NULL) {
533 ScopedLocalRef<jclass> hwBinderKlass(
534 env, FindClassOrDie(env, PACKAGE_PATH "/HwBinder"));
535
536 ScopedLocalRef<jclass> hwRemoteBinderKlass(
537 env, FindClassOrDie(env, PACKAGE_PATH "/HwRemoteBinder"));
538
539 if (env->IsInstanceOf(binderObj, hwBinderKlass.get())) {
540 binder = JHwBinder::GetNativeContext(env, binderObj);
541 } else if (env->IsInstanceOf(binderObj, hwRemoteBinderKlass.get())) {
542 binder = JHwRemoteBinder::GetNativeContext(
543 env, binderObj)->getBinder();
544 } else {
545 signalExceptionForError(env, INVALID_OPERATION);
546 return;
547 }
548 }
549
550 hardware::Parcel *parcel =
551 JHwParcel::GetNativeContext(env, thiz)->getParcel();
552
553 status_t err = parcel->writeStrongBinder(binder);
554 signalExceptionForError(env, err);
555}
556
557static jstring MakeStringObjFromHidlString(JNIEnv *env, const hidl_string &s) {
558 String16 utf16String(s.c_str(), s.size());
559
560 return env->NewString(
561 reinterpret_cast<const jchar *>(utf16String.string()),
562 utf16String.size());
563}
564
565static jstring JHwParcel_native_readString(JNIEnv *env, jobject thiz) {
566 hardware::Parcel *parcel =
567 JHwParcel::GetNativeContext(env, thiz)->getParcel();
568
569 size_t parentHandle;
570
Martijn Coenen24c82272017-01-11 12:35:56 +0100571 const hidl_string *s;
572 status_t err = parcel->readBuffer(&parentHandle,
573 reinterpret_cast<const void**>(&s));
Andreas Huberdab5fc62016-08-15 09:25:02 -0700574
Martijn Coenen24c82272017-01-11 12:35:56 +0100575 if (err != OK) {
576 signalExceptionForError(env, err);
Andreas Huberdab5fc62016-08-15 09:25:02 -0700577 return NULL;
578 }
579
Martijn Coenen24c82272017-01-11 12:35:56 +0100580 err = ::android::hardware::readEmbeddedFromParcel(
Yifan Hong3bb65782016-11-11 17:20:54 -0800581 const_cast<hidl_string *>(s),
Andreas Huberdab5fc62016-08-15 09:25:02 -0700582 *parcel, parentHandle, 0 /* parentOffset */);
583
584 if (err != OK) {
585 signalExceptionForError(env, err);
586 return NULL;
587 }
588
589 return MakeStringObjFromHidlString(env, *s);
590}
591
Andreas Huberdab5fc62016-08-15 09:25:02 -0700592#define DEFINE_PARCEL_VECTOR_READER(Suffix,Type,NewType) \
593static Type ## Array JHwParcel_native_read ## Suffix ## Vector( \
594 JNIEnv *env, jobject thiz) { \
595 hardware::Parcel *parcel = \
596 JHwParcel::GetNativeContext(env, thiz)->getParcel(); \
Andreas Huberdab5fc62016-08-15 09:25:02 -0700597 size_t parentHandle; \
598 \
Martijn Coenen24c82272017-01-11 12:35:56 +0100599 const hidl_vec<Type> *vec; \
600 status_t err = parcel->readBuffer(&parentHandle, \
601 reinterpret_cast<const void**>(&vec)); \
Andreas Huberdab5fc62016-08-15 09:25:02 -0700602 \
Martijn Coenen24c82272017-01-11 12:35:56 +0100603 if (err != OK) { \
604 signalExceptionForError(env, err); \
Andreas Huberdab5fc62016-08-15 09:25:02 -0700605 return NULL; \
606 } \
607 \
608 size_t childHandle; \
609 \
Martijn Coenen24c82272017-01-11 12:35:56 +0100610 err = ::android::hardware::readEmbeddedFromParcel( \
Yifan Hong3bb65782016-11-11 17:20:54 -0800611 const_cast<hidl_vec<Type> *>(vec), \
Andreas Huberdab5fc62016-08-15 09:25:02 -0700612 *parcel, \
613 parentHandle, \
614 0 /* parentOffset */, \
615 &childHandle); \
616 \
617 if (err != OK) { \
618 signalExceptionForError(env, err); \
619 return NULL; \
620 } \
621 \
622 Type ## Array valObj = env->New ## NewType ## Array(vec->size()); \
623 env->Set ## NewType ## ArrayRegion(valObj, 0, vec->size(), &(*vec)[0]); \
624 \
625 return valObj; \
626}
627
Andreas Huberdab5fc62016-08-15 09:25:02 -0700628DEFINE_PARCEL_VECTOR_READER(Int8,jbyte,Byte)
629DEFINE_PARCEL_VECTOR_READER(Int16,jshort,Short)
630DEFINE_PARCEL_VECTOR_READER(Int32,jint,Int)
631DEFINE_PARCEL_VECTOR_READER(Int64,jlong,Long)
632DEFINE_PARCEL_VECTOR_READER(Float,jfloat,Float)
633DEFINE_PARCEL_VECTOR_READER(Double,jdouble,Double)
634
Andreas Huber86635bb2016-08-24 16:19:03 -0700635static jbooleanArray JHwParcel_native_readBoolVector(
636 JNIEnv *env, jobject thiz) {
637 hardware::Parcel *parcel =
638 JHwParcel::GetNativeContext(env, thiz)->getParcel();
639
640 size_t parentHandle;
641
Martijn Coenen24c82272017-01-11 12:35:56 +0100642 const hidl_vec<bool> *vec;
643 status_t err = parcel->readBuffer(&parentHandle,
644 reinterpret_cast<const void**>(&vec));
Andreas Huber86635bb2016-08-24 16:19:03 -0700645
Martijn Coenen24c82272017-01-11 12:35:56 +0100646 if (err != OK) {
647 signalExceptionForError(env, err);
Andreas Huber86635bb2016-08-24 16:19:03 -0700648 return NULL;
649 }
650
651 size_t childHandle;
652
Martijn Coenen24c82272017-01-11 12:35:56 +0100653 err = ::android::hardware::readEmbeddedFromParcel(
Yifan Hong3bb65782016-11-11 17:20:54 -0800654 const_cast<hidl_vec<bool> *>(vec),
Andreas Huber86635bb2016-08-24 16:19:03 -0700655 *parcel,
656 parentHandle,
657 0 /* parentOffset */,
658 &childHandle);
659
660 if (err != OK) {
661 signalExceptionForError(env, err);
662 return NULL;
663 }
664
665 jbooleanArray valObj = env->NewBooleanArray(vec->size());
666
667 for (size_t i = 0; i < vec->size(); ++i) {
668 jboolean x = (*vec)[i];
669 env->SetBooleanArrayRegion(valObj, i, 1, &x);
670 }
671
672 return valObj;
673}
674
Andreas Huberdab5fc62016-08-15 09:25:02 -0700675static jobjectArray MakeStringArray(
676 JNIEnv *env, const hidl_string *array, size_t size) {
677 ScopedLocalRef<jclass> stringKlass(
678 env,
679 env->FindClass("java/lang/String"));
680
681 // XXX Why can't I use ScopedLocalRef<> for the arrayObj and the stringObjs?
682
683 jobjectArray arrayObj = env->NewObjectArray(size, stringKlass.get(), NULL);
684
685 for (size_t i = 0; i < size; ++i) {
686 jstring stringObj = MakeStringObjFromHidlString(env, array[i]);
687
688 env->SetObjectArrayElement(
689 arrayObj,
690 i,
691 stringObj);
692 }
693
694 return arrayObj;
695}
696
Andreas Huberdab5fc62016-08-15 09:25:02 -0700697static jobjectArray JHwParcel_native_readStringVector(
698 JNIEnv *env, jobject thiz) {
699 typedef hidl_vec<hidl_string> string_vec;
700
701 hardware::Parcel *parcel =
702 JHwParcel::GetNativeContext(env, thiz)->getParcel();
703
704 size_t parentHandle;
705
Martijn Coenen24c82272017-01-11 12:35:56 +0100706 const string_vec *vec;
707 status_t err = parcel->readBuffer(&parentHandle,
708 reinterpret_cast<const void **>(&vec));
Andreas Huberdab5fc62016-08-15 09:25:02 -0700709
Martijn Coenen24c82272017-01-11 12:35:56 +0100710 if (err != OK) {
711 signalExceptionForError(env, err);
Andreas Huberdab5fc62016-08-15 09:25:02 -0700712 return NULL;
713 }
714
715 size_t childHandle;
Martijn Coenen24c82272017-01-11 12:35:56 +0100716 err = ::android::hardware::readEmbeddedFromParcel(
Yifan Hong3bb65782016-11-11 17:20:54 -0800717 const_cast<string_vec *>(vec),
Andreas Huberdab5fc62016-08-15 09:25:02 -0700718 *parcel, parentHandle, 0 /* parentOffset */, &childHandle);
719
720 for (size_t i = 0; (err == OK) && (i < vec->size()); ++i) {
Yifan Hong3bb65782016-11-11 17:20:54 -0800721 err = android::hardware::readEmbeddedFromParcel(
722 const_cast<hidl_vec<hidl_string> *>(vec),
Andreas Huberdab5fc62016-08-15 09:25:02 -0700723 *parcel,
724 childHandle,
725 i * sizeof(hidl_string),
726 nullptr /* childHandle */);
727 }
728
729 if (err != OK) {
730 signalExceptionForError(env, err);
731 return NULL;
732 }
733
734 return MakeStringArray(env, &(*vec)[0], vec->size());
735}
736
737static void JHwParcel_native_writeStringVector(
738 JNIEnv *env, jobject thiz, jobjectArray arrayObj) {
739 typedef hidl_vec<hidl_string> string_vec;
740
741 if (arrayObj == NULL) {
742 jniThrowException(env, "java/lang/NullPointerException", NULL);
743 return;
744 }
745
746 jsize len = env->GetArrayLength(arrayObj);
747
748 sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz);
749
Andreas Huber9266f992016-08-25 11:21:21 -0700750 void *vecPtr =
751 impl->getStorage()->allocTemporaryStorage(sizeof(string_vec));
752
753 string_vec *vec = new (vecPtr) string_vec;
Andreas Huberdab5fc62016-08-15 09:25:02 -0700754
755 hidl_string *strings = impl->getStorage()->allocStringArray(len);
756 vec->setToExternal(strings, len);
757
758 for (jsize i = 0; i < len; ++i) {
759 ScopedLocalRef<jstring> stringObj(
760 env,
761 (jstring)env->GetObjectArrayElement(arrayObj, i));
762
763 const hidl_string *s =
764 impl->getStorage()->allocTemporaryString(env, stringObj.get());
765
766 strings[i].setToExternal(s->c_str(), s->size());
767 }
768
769 hardware::Parcel *parcel = impl->getParcel();
770
771 size_t parentHandle;
772 status_t err = parcel->writeBuffer(vec, sizeof(*vec), &parentHandle);
773
774 if (err == OK) {
775 size_t childHandle;
Yifan Hong3bb65782016-11-11 17:20:54 -0800776 err = ::android::hardware::writeEmbeddedToParcel(
777 *vec,
Andreas Huberdab5fc62016-08-15 09:25:02 -0700778 parcel,
779 parentHandle,
780 0 /* parentOffset */,
781 &childHandle);
782
783 for (size_t i = 0; (err == OK) && (i < vec->size()); ++i) {
Yifan Hong3bb65782016-11-11 17:20:54 -0800784 err = ::android::hardware::writeEmbeddedToParcel(
785 (*vec)[i],
Andreas Huberdab5fc62016-08-15 09:25:02 -0700786 parcel,
787 childHandle,
788 i * sizeof(hidl_string));
789 }
790 }
791
792 signalExceptionForError(env, err);
793}
794
795static jobject JHwParcel_native_readStrongBinder(JNIEnv *env, jobject thiz) {
796 hardware::Parcel *parcel =
797 JHwParcel::GetNativeContext(env, thiz)->getParcel();
798
799 sp<hardware::IBinder> binder = parcel->readStrongBinder();
800
801 if (binder == NULL) {
802 return NULL;
803 }
804
805 return JHwRemoteBinder::NewObject(env, binder);
806}
807
Andreas Huber9266f992016-08-25 11:21:21 -0700808static jobject JHwParcel_native_readBuffer(JNIEnv *env, jobject thiz) {
809 hardware::Parcel *parcel =
810 JHwParcel::GetNativeContext(env, thiz)->getParcel();
811
812 size_t handle;
Martijn Coenen24c82272017-01-11 12:35:56 +0100813 const void *ptr;
814 status_t status = parcel->readBuffer(&handle, &ptr);
Andreas Huber9266f992016-08-25 11:21:21 -0700815
Martijn Coenen24c82272017-01-11 12:35:56 +0100816 if (status != OK) {
Andreas Huber9266f992016-08-25 11:21:21 -0700817 jniThrowException(env, "java/util/NoSuchElementException", NULL);
818 return nullptr;
819 }
820
821 return JHwBlob::NewObject(env, ptr, handle);
822}
823
824static jobject JHwParcel_native_readEmbeddedBuffer(
Martijn Coenen14fae062017-01-13 11:08:51 +0100825 JNIEnv *env, jobject thiz, jlong parentHandle, jlong offset,
826 jboolean nullable) {
Andreas Huber9266f992016-08-25 11:21:21 -0700827 hardware::Parcel *parcel =
828 JHwParcel::GetNativeContext(env, thiz)->getParcel();
829
830 size_t childHandle;
831
Martijn Coenen24c82272017-01-11 12:35:56 +0100832 const void *ptr;
833 status_t status =
Martijn Coenen14fae062017-01-13 11:08:51 +0100834 parcel->readNullableEmbeddedBuffer(&childHandle, parentHandle, offset,
835 &ptr);
Andreas Huber9266f992016-08-25 11:21:21 -0700836
Martijn Coenen24c82272017-01-11 12:35:56 +0100837 if (status != OK) {
Andreas Huber9266f992016-08-25 11:21:21 -0700838 jniThrowException(env, "java/util/NoSuchElementException", NULL);
839 return 0;
Martijn Coenen14fae062017-01-13 11:08:51 +0100840 } else if (status == OK && !nullable && ptr == nullptr) {
841 jniThrowException(env, "java/lang/NullPointerException", NULL);
842 return 0;
Andreas Huber9266f992016-08-25 11:21:21 -0700843 }
844
845 return JHwBlob::NewObject(env, ptr, childHandle);
846}
847
848static void JHwParcel_native_writeBuffer(
849 JNIEnv *env, jobject thiz, jobject blobObj) {
850 if (blobObj == nullptr) {
851 jniThrowException(env, "java/lang/NullPointerException", NULL);
852 return;
853 }
854
855 hardware::Parcel *parcel =
856 JHwParcel::GetNativeContext(env, thiz)->getParcel();
857
858 sp<JHwBlob> blob = JHwBlob::GetNativeContext(env, blobObj);
859 status_t err = blob->writeToParcel(parcel);
860
861 if (err != OK) {
862 signalExceptionForError(env, err);
863 }
864}
865
Andreas Huberdab5fc62016-08-15 09:25:02 -0700866static JNINativeMethod gMethods[] = {
867 { "native_init", "()J", (void *)JHwParcel_native_init },
868 { "native_setup", "(Z)V", (void *)JHwParcel_native_setup },
869
870 { "writeInterfaceToken", "(Ljava/lang/String;)V",
871 (void *)JHwParcel_native_writeInterfaceToken },
872
Andreas Huber86635bb2016-08-24 16:19:03 -0700873 { "writeBool", "(Z)V", (void *)JHwParcel_native_writeBool },
Andreas Huberdab5fc62016-08-15 09:25:02 -0700874 { "writeInt8", "(B)V", (void *)JHwParcel_native_writeInt8 },
875 { "writeInt16", "(S)V", (void *)JHwParcel_native_writeInt16 },
876 { "writeInt32", "(I)V", (void *)JHwParcel_native_writeInt32 },
877 { "writeInt64", "(J)V", (void *)JHwParcel_native_writeInt64 },
878 { "writeFloat", "(F)V", (void *)JHwParcel_native_writeFloat },
879 { "writeDouble", "(D)V", (void *)JHwParcel_native_writeDouble },
880
881 { "writeString", "(Ljava/lang/String;)V",
882 (void *)JHwParcel_native_writeString },
883
Andreas Huber86635bb2016-08-24 16:19:03 -0700884 { "writeBoolVector", "([Z)V", (void *)JHwParcel_native_writeBoolVector },
Andreas Huberdab5fc62016-08-15 09:25:02 -0700885 { "writeInt8Vector", "([B)V", (void *)JHwParcel_native_writeInt8Vector },
Andreas Huberdab5fc62016-08-15 09:25:02 -0700886 { "writeInt16Vector", "([S)V", (void *)JHwParcel_native_writeInt16Vector },
Andreas Huberdab5fc62016-08-15 09:25:02 -0700887 { "writeInt32Vector", "([I)V", (void *)JHwParcel_native_writeInt32Vector },
Andreas Huberdab5fc62016-08-15 09:25:02 -0700888 { "writeInt64Vector", "([J)V", (void *)JHwParcel_native_writeInt64Vector },
Andreas Huberdab5fc62016-08-15 09:25:02 -0700889 { "writeFloatVector", "([F)V", (void *)JHwParcel_native_writeFloatVector },
Andreas Huberdab5fc62016-08-15 09:25:02 -0700890
891 { "writeDoubleVector", "([D)V",
892 (void *)JHwParcel_native_writeDoubleVector },
893
Andreas Huberdab5fc62016-08-15 09:25:02 -0700894 { "writeStringVector", "([Ljava/lang/String;)V",
895 (void *)JHwParcel_native_writeStringVector },
896
897 { "writeStrongBinder", "(L" PACKAGE_PATH "/IHwBinder;)V",
898 (void *)JHwParcel_native_writeStrongBinder },
899
900 { "enforceInterface", "(Ljava/lang/String;)V",
901 (void *)JHwParcel_native_enforceInterface },
902
Andreas Huber86635bb2016-08-24 16:19:03 -0700903 { "readBool", "()Z", (void *)JHwParcel_native_readBool },
Andreas Huberdab5fc62016-08-15 09:25:02 -0700904 { "readInt8", "()B", (void *)JHwParcel_native_readInt8 },
905 { "readInt16", "()S", (void *)JHwParcel_native_readInt16 },
906 { "readInt32", "()I", (void *)JHwParcel_native_readInt32 },
907 { "readInt64", "()J", (void *)JHwParcel_native_readInt64 },
908 { "readFloat", "()F", (void *)JHwParcel_native_readFloat },
909 { "readDouble", "()D", (void *)JHwParcel_native_readDouble },
910
911 { "readString", "()Ljava/lang/String;",
912 (void *)JHwParcel_native_readString },
913
Andreas Huberef1a5652016-10-18 09:24:04 -0700914 { "readBoolVectorAsArray", "()[Z",
915 (void *)JHwParcel_native_readBoolVector },
Andreas Huberdab5fc62016-08-15 09:25:02 -0700916
Andreas Huberef1a5652016-10-18 09:24:04 -0700917 { "readInt8VectorAsArray", "()[B",
918 (void *)JHwParcel_native_readInt8Vector },
919
920 { "readInt16VectorAsArray", "()[S",
921 (void *)JHwParcel_native_readInt16Vector },
922
923 { "readInt32VectorAsArray", "()[I",
924 (void *)JHwParcel_native_readInt32Vector },
925
926 { "readInt64VectorAsArray", "()[J",
927 (void *)JHwParcel_native_readInt64Vector },
928
929 { "readFloatVectorAsArray", "()[F",
930 (void *)JHwParcel_native_readFloatVector },
931
932 { "readDoubleVectorAsArray", "()[D",
933 (void *)JHwParcel_native_readDoubleVector },
934
935 { "readStringVectorAsArray", "()[Ljava/lang/String;",
Andreas Huberdab5fc62016-08-15 09:25:02 -0700936 (void *)JHwParcel_native_readStringVector },
937
938 { "readStrongBinder", "()L" PACKAGE_PATH "/IHwBinder;",
939 (void *)JHwParcel_native_readStrongBinder },
940
941 { "writeStatus", "(I)V", (void *)JHwParcel_native_writeStatus },
942
943 { "verifySuccess", "()V", (void *)JHwParcel_native_verifySuccess },
944
945 { "releaseTemporaryStorage", "()V",
946 (void *)JHwParcel_native_releaseTemporaryStorage },
947
948 { "send", "()V", (void *)JHwParcel_native_send },
Andreas Huber9266f992016-08-25 11:21:21 -0700949
950 { "readBuffer", "()L" PACKAGE_PATH "/HwBlob;",
951 (void *)JHwParcel_native_readBuffer },
952
Martijn Coenen14fae062017-01-13 11:08:51 +0100953 { "readEmbeddedBuffer", "(JJZ)L" PACKAGE_PATH "/HwBlob;",
Andreas Huber9266f992016-08-25 11:21:21 -0700954 (void *)JHwParcel_native_readEmbeddedBuffer },
955
956 { "writeBuffer", "(L" PACKAGE_PATH "/HwBlob;)V",
957 (void *)JHwParcel_native_writeBuffer },
Andreas Huberdab5fc62016-08-15 09:25:02 -0700958};
959
960namespace android {
961
962int register_android_os_HwParcel(JNIEnv *env) {
963 return RegisterMethodsOrDie(env, CLASS_PATH, gMethods, NELEM(gMethods));
964}
965
966} // namespace android