blob: a10d80746e46adc43b74f34a2a5fdf2601e4f0e4 [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
52void signalExceptionForError(JNIEnv *env, status_t err) {
53 switch (err) {
54 case OK:
55 break;
56
57 case NO_MEMORY:
58 {
59 jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
60 break;
61 }
62
63 case INVALID_OPERATION:
64 {
65 jniThrowException(
66 env, "java/lang/UnsupportedOperationException", NULL);
67 break;
68 }
69
70 case BAD_VALUE:
71 {
72 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
73 break;
74 }
75
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 {
117 jniThrowException(
118 env, "java/lang/RuntimeException", "Unknown error");
119
120 break;
121 }
122 }
123}
124
125// static
126void JHwParcel::InitClass(JNIEnv *env) {
127 ScopedLocalRef<jclass> clazz(
128 env, FindClassOrDie(env, CLASS_PATH));
129
130 gFields.contextID =
131 GetFieldIDOrDie(env, clazz.get(), "mNativeContext", "J");
132
133 gFields.constructID = GetMethodIDOrDie(env, clazz.get(), "<init>", "(Z)V");
134}
135
136// static
137sp<JHwParcel> JHwParcel::SetNativeContext(
138 JNIEnv *env, jobject thiz, const sp<JHwParcel> &context) {
139 sp<JHwParcel> old = (JHwParcel *)env->GetLongField(thiz, gFields.contextID);
140
141 if (context != NULL) {
142 context->incStrong(NULL /* id */);
143 }
144
145 if (old != NULL) {
146 old->decStrong(NULL /* id */);
147 }
148
149 env->SetLongField(thiz, gFields.contextID, (long)context.get());
150
151 return old;
152}
153
154// static
155sp<JHwParcel> JHwParcel::GetNativeContext(JNIEnv *env, jobject thiz) {
156 return (JHwParcel *)env->GetLongField(thiz, gFields.contextID);
157}
158
159JHwParcel::JHwParcel(JNIEnv *env, jobject thiz)
160 : mParcel(NULL),
161 mOwnsParcel(false),
162 mTransactCallback(nullptr),
163 mWasSent(false) {
164 jclass clazz = env->GetObjectClass(thiz);
165 CHECK(clazz != NULL);
166
167 mClass = (jclass)env->NewGlobalRef(clazz);
168 mObject = env->NewWeakGlobalRef(thiz);
169}
170
171JHwParcel::~JHwParcel() {
172 JNIEnv *env = AndroidRuntime::getJNIEnv();
173
174 mStorage.release(env);
175
176 setParcel(NULL, false /* assumeOwnership */);
177
178 env->DeleteWeakGlobalRef(mObject);
179 mObject = NULL;
180
181 env->DeleteGlobalRef(mClass);
182 mClass = NULL;
183}
184
185hardware::Parcel *JHwParcel::getParcel() {
186 return mParcel;
187}
188
189EphemeralStorage *JHwParcel::getStorage() {
190 return &mStorage;
191}
192
193void JHwParcel::setParcel(hardware::Parcel *parcel, bool assumeOwnership) {
194 if (mParcel && mOwnsParcel) {
195 delete mParcel;
196 }
197
198 mParcel = parcel;
199 mOwnsParcel = assumeOwnership;
200}
201
202// static
203jobject JHwParcel::NewObject(JNIEnv *env) {
204 ScopedLocalRef<jclass> clazz(env, FindClassOrDie(env, CLASS_PATH));
205
Andreas Huber9266f992016-08-25 11:21:21 -0700206 jmethodID constructID =
207 GetMethodIDOrDie(env, clazz.get(), "<init>", "(Z)V");
208
209 return env->NewObject(clazz.get(), constructID, false /* allocate */);
Andreas Huberdab5fc62016-08-15 09:25:02 -0700210}
211
212void JHwParcel::setTransactCallback(
213 ::android::hardware::IBinder::TransactCallback cb) {
214 mTransactCallback = cb;
215}
216
217void JHwParcel::send() {
218 CHECK(mTransactCallback != nullptr);
219 CHECK(mParcel != nullptr);
220
221 mTransactCallback(*mParcel);
222 mTransactCallback = nullptr;
223
224 mWasSent = true;
225}
226
227bool JHwParcel::wasSent() const {
228 return mWasSent;
229}
230
231} // namespace android
232
233////////////////////////////////////////////////////////////////////////////////
234
235using namespace android;
236
237static void releaseNativeContext(void *nativeContext) {
238 sp<JHwParcel> parcel = (JHwParcel *)nativeContext;
239
240 if (parcel != NULL) {
241 parcel->decStrong(NULL /* id */);
242 }
243}
244
245static jlong JHwParcel_native_init(JNIEnv *env) {
246 JHwParcel::InitClass(env);
247
248 return reinterpret_cast<jlong>(&releaseNativeContext);
249}
250
251static void JHwParcel_native_setup(
252 JNIEnv *env, jobject thiz, jboolean allocate) {
253 sp<JHwParcel> context = new JHwParcel(env, thiz);
254
255 if (allocate) {
256 context->setParcel(new hardware::Parcel, true /* assumeOwnership */);
257 }
258
259 JHwParcel::SetNativeContext(env, thiz, context);
260}
261
262static void JHwParcel_native_writeInterfaceToken(
263 JNIEnv *env, jobject thiz, jstring interfaceNameObj) {
264 if (interfaceNameObj == NULL) {
265 jniThrowException(env, "java/lang/NullPointerException", NULL);
266 return;
267 }
268
269 const jchar *interfaceName = env->GetStringCritical(interfaceNameObj, NULL);
270 if (interfaceName) {
Steven Morelandab2fca22016-11-11 12:33:41 -0800271 String8 nameCopy = String8(String16(
Andreas Huber9f026862016-11-03 15:46:04 -0700272 reinterpret_cast<const char16_t *>(interfaceName),
Steven Morelandab2fca22016-11-11 12:33:41 -0800273 env->GetStringLength(interfaceNameObj)));
Andreas Huberdab5fc62016-08-15 09:25:02 -0700274
275 env->ReleaseStringCritical(interfaceNameObj, interfaceName);
276 interfaceName = NULL;
277
Andreas Huber9f026862016-11-03 15:46:04 -0700278 hardware::Parcel *parcel =
279 JHwParcel::GetNativeContext(env, thiz)->getParcel();
280
Steven Morelandab2fca22016-11-11 12:33:41 -0800281 status_t err = parcel->writeInterfaceToken(nameCopy.string());
Andreas Huberdab5fc62016-08-15 09:25:02 -0700282 signalExceptionForError(env, err);
283 }
284}
285
286static void JHwParcel_native_enforceInterface(
287 JNIEnv *env, jobject thiz, jstring interfaceNameObj) {
288 // XXX original binder Parcel enforceInterface implementation does some
289 // mysterious things regarding strictModePolicy(), figure out if we need
290 // that here as well.
291 if (interfaceNameObj == NULL) {
292 jniThrowException(env, "java/lang/NullPointerException", NULL);
293 return;
294 }
295
296 const jchar *interfaceName = env->GetStringCritical(interfaceNameObj, NULL);
297 if (interfaceName) {
Steven Morelandab2fca22016-11-11 12:33:41 -0800298 String8 interfaceNameCopy = String8(String16(
Andreas Huber9f026862016-11-03 15:46:04 -0700299 reinterpret_cast<const char16_t *>(interfaceName),
Steven Morelandab2fca22016-11-11 12:33:41 -0800300 env->GetStringLength(interfaceNameObj)));
Andreas Huberdab5fc62016-08-15 09:25:02 -0700301
302 env->ReleaseStringCritical(interfaceNameObj, interfaceName);
303 interfaceName = NULL;
304
Andreas Huber9f026862016-11-03 15:46:04 -0700305 hardware::Parcel *parcel =
306 JHwParcel::GetNativeContext(env, thiz)->getParcel();
307
Steven Morelandab2fca22016-11-11 12:33:41 -0800308 bool valid = parcel->enforceInterface(interfaceNameCopy.string());
Andreas Huber9f026862016-11-03 15:46:04 -0700309
Andreas Huberdab5fc62016-08-15 09:25:02 -0700310 if (!valid) {
311 jniThrowException(
312 env,
313 "java/lang/SecurityException",
314 "HWBinder invocation to an incorrect interface");
315 }
316 }
317}
318
319#define DEFINE_PARCEL_WRITER(Suffix,Type) \
320static 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) \
330static 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
Andreas Huber86635bb2016-08-24 16:19:03 -0700342DEFINE_PARCEL_WRITER(Bool,jboolean)
Andreas Huberdab5fc62016-08-15 09:25:02 -0700343DEFINE_PARCEL_WRITER(Int8,jbyte)
344DEFINE_PARCEL_WRITER(Int16,jshort)
345DEFINE_PARCEL_WRITER(Int32,jint)
346DEFINE_PARCEL_WRITER(Int64,jlong)
347DEFINE_PARCEL_WRITER(Float,jfloat)
348DEFINE_PARCEL_WRITER(Double,jdouble)
349
350DEFINE_PARCEL_READER(Int8,jbyte)
351DEFINE_PARCEL_READER(Int16,jshort)
352DEFINE_PARCEL_READER(Int32,jint)
353DEFINE_PARCEL_READER(Int64,jlong)
354DEFINE_PARCEL_READER(Float,jfloat)
355DEFINE_PARCEL_READER(Double,jdouble)
356
Andreas Huber86635bb2016-08-24 16:19:03 -0700357static 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
Andreas Huberdab5fc62016-08-15 09:25:02 -0700368static 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
Yifan Hongddf31f62016-11-15 16:02:40 -0800387 status_t err = ::android::hardware::writeToParcel(status, parcel);
Andreas Huberdab5fc62016-08-15 09:25:02 -0700388 signalExceptionForError(env, err);
389}
390
391static 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;
Yifan Hongddf31f62016-11-15 16:02:40 -0800398 status_t err = ::android::hardware::readFromParcel(&status, *parcel);
Andreas Huberdab5fc62016-08-15 09:25:02 -0700399 signalExceptionForError(env, err);
400}
401
402static void JHwParcel_native_releaseTemporaryStorage(
403 JNIEnv *env, jobject thiz) {
404 JHwParcel::GetNativeContext(env, thiz)->getStorage()->release(env);
405}
406
407static void JHwParcel_native_send(JNIEnv *env, jobject thiz) {
408 JHwParcel::GetNativeContext(env, thiz)->send();
409}
410
411static void JHwParcel_native_writeString(
412 JNIEnv *env, jobject thiz, jstring valObj) {
413 if (valObj == NULL) {
414 jniThrowException(env, "java/lang/NullPointerException", NULL);
415 return;
416 }
417
418 sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz);
419
420 const hidl_string *s =
421 impl->getStorage()->allocTemporaryString(env, valObj);
422
423 hardware::Parcel *parcel = impl->getParcel();
424
425 size_t parentHandle;
426 status_t err = parcel->writeBuffer(s, sizeof(*s), &parentHandle);
427
428 if (err == OK) {
Yifan Hong3bb65782016-11-11 17:20:54 -0800429 err = ::android::hardware::writeEmbeddedToParcel(
430 *s, parcel, parentHandle, 0 /* parentOffset */);
Andreas Huberdab5fc62016-08-15 09:25:02 -0700431 }
432
433 signalExceptionForError(env, err);
434}
435
Andreas Huberdab5fc62016-08-15 09:25:02 -0700436#define DEFINE_PARCEL_VECTOR_WRITER(Suffix,Type) \
437static void JHwParcel_native_write ## Suffix ## Vector( \
438 JNIEnv *env, jobject thiz, Type ## Array valObj) { \
439 if (valObj == NULL) { \
440 jniThrowException(env, "java/lang/NullPointerException", NULL); \
441 return; \
442 } \
443 \
444 sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz); \
445 \
446 const hidl_vec<Type> *vec = \
447 impl->getStorage()->allocTemporary ## Suffix ## Vector(env, valObj); \
448 \
449 hardware::Parcel *parcel = impl->getParcel(); \
450 \
451 size_t parentHandle; \
452 status_t err = parcel->writeBuffer(vec, sizeof(*vec), &parentHandle); \
453 \
454 if (err == OK) { \
455 size_t childHandle; \
456 \
Yifan Hong3bb65782016-11-11 17:20:54 -0800457 err = ::android::hardware::writeEmbeddedToParcel( \
458 *vec, \
Andreas Huberdab5fc62016-08-15 09:25:02 -0700459 parcel, \
460 parentHandle, \
461 0 /* parentOffset */, \
462 &childHandle); \
463 } \
464 \
465 signalExceptionForError(env, err); \
466}
467
Andreas Huberdab5fc62016-08-15 09:25:02 -0700468DEFINE_PARCEL_VECTOR_WRITER(Int8,jbyte)
469DEFINE_PARCEL_VECTOR_WRITER(Int16,jshort)
470DEFINE_PARCEL_VECTOR_WRITER(Int32,jint)
471DEFINE_PARCEL_VECTOR_WRITER(Int64,jlong)
472DEFINE_PARCEL_VECTOR_WRITER(Float,jfloat)
473DEFINE_PARCEL_VECTOR_WRITER(Double,jdouble)
474
Andreas Huber86635bb2016-08-24 16:19:03 -0700475static void JHwParcel_native_writeBoolVector(
476 JNIEnv *env, jobject thiz, jbooleanArray valObj) {
477 if (valObj == NULL) {
478 jniThrowException(env, "java/lang/NullPointerException", NULL);
479 return;
480 }
481
482 sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz);
483
Andreas Huber9266f992016-08-25 11:21:21 -0700484 void *vecPtr =
485 impl->getStorage()->allocTemporaryStorage(sizeof(hidl_vec<bool>));
486
487 hidl_vec<bool> *vec = new (vecPtr) hidl_vec<bool>;
Andreas Huber86635bb2016-08-24 16:19:03 -0700488
489 jsize len = env->GetArrayLength(valObj);
490
491 jboolean *src = env->GetBooleanArrayElements(valObj, nullptr);
492
493 bool *dst =
494 (bool *)impl->getStorage()->allocTemporaryStorage(len * sizeof(bool));
495
496 for (jsize i = 0; i < len; ++i) {
497 dst[i] = src[i];
498 }
499
500 env->ReleaseBooleanArrayElements(valObj, src, 0 /* mode */);
501 src = nullptr;
502
503 vec->setToExternal(dst, len);
504
505 hardware::Parcel *parcel = impl->getParcel();
506
507 size_t parentHandle;
508 status_t err = parcel->writeBuffer(vec, sizeof(*vec), &parentHandle);
509
510 if (err == OK) {
511 size_t childHandle;
512
Yifan Hong3bb65782016-11-11 17:20:54 -0800513 err = ::android::hardware::writeEmbeddedToParcel(
514 *vec,
Andreas Huber86635bb2016-08-24 16:19:03 -0700515 parcel,
516 parentHandle,
517 0 /* parentOffset */,
518 &childHandle);
519 }
520
521 signalExceptionForError(env, err);
522}
523
Andreas Huberdab5fc62016-08-15 09:25:02 -0700524static void JHwParcel_native_writeStrongBinder(
525 JNIEnv *env, jobject thiz, jobject binderObj) {
526 sp<hardware::IBinder> binder;
527 if (binderObj != NULL) {
528 ScopedLocalRef<jclass> hwBinderKlass(
529 env, FindClassOrDie(env, PACKAGE_PATH "/HwBinder"));
530
531 ScopedLocalRef<jclass> hwRemoteBinderKlass(
532 env, FindClassOrDie(env, PACKAGE_PATH "/HwRemoteBinder"));
533
534 if (env->IsInstanceOf(binderObj, hwBinderKlass.get())) {
535 binder = JHwBinder::GetNativeContext(env, binderObj);
536 } else if (env->IsInstanceOf(binderObj, hwRemoteBinderKlass.get())) {
537 binder = JHwRemoteBinder::GetNativeContext(
538 env, binderObj)->getBinder();
539 } else {
540 signalExceptionForError(env, INVALID_OPERATION);
541 return;
542 }
543 }
544
545 hardware::Parcel *parcel =
546 JHwParcel::GetNativeContext(env, thiz)->getParcel();
547
548 status_t err = parcel->writeStrongBinder(binder);
549 signalExceptionForError(env, err);
550}
551
552static jstring MakeStringObjFromHidlString(JNIEnv *env, const hidl_string &s) {
553 String16 utf16String(s.c_str(), s.size());
554
555 return env->NewString(
556 reinterpret_cast<const jchar *>(utf16String.string()),
557 utf16String.size());
558}
559
560static jstring JHwParcel_native_readString(JNIEnv *env, jobject thiz) {
561 hardware::Parcel *parcel =
562 JHwParcel::GetNativeContext(env, thiz)->getParcel();
563
564 size_t parentHandle;
565
566 const hidl_string *s = static_cast<const hidl_string *>(
567 parcel->readBuffer(&parentHandle));
568
569 if (s == NULL) {
570 signalExceptionForError(env, UNKNOWN_ERROR);
571 return NULL;
572 }
573
Yifan Hong3bb65782016-11-11 17:20:54 -0800574 status_t err = ::android::hardware::readEmbeddedFromParcel(
575 const_cast<hidl_string *>(s),
Andreas Huberdab5fc62016-08-15 09:25:02 -0700576 *parcel, parentHandle, 0 /* parentOffset */);
577
578 if (err != OK) {
579 signalExceptionForError(env, err);
580 return NULL;
581 }
582
583 return MakeStringObjFromHidlString(env, *s);
584}
585
Andreas Huberdab5fc62016-08-15 09:25:02 -0700586#define DEFINE_PARCEL_VECTOR_READER(Suffix,Type,NewType) \
587static Type ## Array JHwParcel_native_read ## Suffix ## Vector( \
588 JNIEnv *env, jobject thiz) { \
589 hardware::Parcel *parcel = \
590 JHwParcel::GetNativeContext(env, thiz)->getParcel(); \
591 \
592 size_t parentHandle; \
593 \
594 const hidl_vec<Type> *vec = \
595 (const hidl_vec<Type> *)parcel->readBuffer(&parentHandle); \
596 \
597 if (vec == NULL) { \
598 signalExceptionForError(env, UNKNOWN_ERROR); \
599 return NULL; \
600 } \
601 \
602 size_t childHandle; \
603 \
Yifan Hong3bb65782016-11-11 17:20:54 -0800604 status_t err = ::android::hardware::readEmbeddedFromParcel( \
605 const_cast<hidl_vec<Type> *>(vec), \
Andreas Huberdab5fc62016-08-15 09:25:02 -0700606 *parcel, \
607 parentHandle, \
608 0 /* parentOffset */, \
609 &childHandle); \
610 \
611 if (err != OK) { \
612 signalExceptionForError(env, err); \
613 return NULL; \
614 } \
615 \
616 Type ## Array valObj = env->New ## NewType ## Array(vec->size()); \
617 env->Set ## NewType ## ArrayRegion(valObj, 0, vec->size(), &(*vec)[0]); \
618 \
619 return valObj; \
620}
621
Andreas Huberdab5fc62016-08-15 09:25:02 -0700622DEFINE_PARCEL_VECTOR_READER(Int8,jbyte,Byte)
623DEFINE_PARCEL_VECTOR_READER(Int16,jshort,Short)
624DEFINE_PARCEL_VECTOR_READER(Int32,jint,Int)
625DEFINE_PARCEL_VECTOR_READER(Int64,jlong,Long)
626DEFINE_PARCEL_VECTOR_READER(Float,jfloat,Float)
627DEFINE_PARCEL_VECTOR_READER(Double,jdouble,Double)
628
Andreas Huber86635bb2016-08-24 16:19:03 -0700629static jbooleanArray JHwParcel_native_readBoolVector(
630 JNIEnv *env, jobject thiz) {
631 hardware::Parcel *parcel =
632 JHwParcel::GetNativeContext(env, thiz)->getParcel();
633
634 size_t parentHandle;
635
636 const hidl_vec<bool> *vec =
637 (const hidl_vec<bool> *)parcel->readBuffer(&parentHandle);
638
639 if (vec == NULL) {
640 signalExceptionForError(env, UNKNOWN_ERROR);
641 return NULL;
642 }
643
644 size_t childHandle;
645
Yifan Hong3bb65782016-11-11 17:20:54 -0800646 status_t err = ::android::hardware::readEmbeddedFromParcel(
647 const_cast<hidl_vec<bool> *>(vec),
Andreas Huber86635bb2016-08-24 16:19:03 -0700648 *parcel,
649 parentHandle,
650 0 /* parentOffset */,
651 &childHandle);
652
653 if (err != OK) {
654 signalExceptionForError(env, err);
655 return NULL;
656 }
657
658 jbooleanArray valObj = env->NewBooleanArray(vec->size());
659
660 for (size_t i = 0; i < vec->size(); ++i) {
661 jboolean x = (*vec)[i];
662 env->SetBooleanArrayRegion(valObj, i, 1, &x);
663 }
664
665 return valObj;
666}
667
Andreas Huberdab5fc62016-08-15 09:25:02 -0700668static jobjectArray MakeStringArray(
669 JNIEnv *env, const hidl_string *array, size_t size) {
670 ScopedLocalRef<jclass> stringKlass(
671 env,
672 env->FindClass("java/lang/String"));
673
674 // XXX Why can't I use ScopedLocalRef<> for the arrayObj and the stringObjs?
675
676 jobjectArray arrayObj = env->NewObjectArray(size, stringKlass.get(), NULL);
677
678 for (size_t i = 0; i < size; ++i) {
679 jstring stringObj = MakeStringObjFromHidlString(env, array[i]);
680
681 env->SetObjectArrayElement(
682 arrayObj,
683 i,
684 stringObj);
685 }
686
687 return arrayObj;
688}
689
Andreas Huberdab5fc62016-08-15 09:25:02 -0700690static jobjectArray JHwParcel_native_readStringVector(
691 JNIEnv *env, jobject thiz) {
692 typedef hidl_vec<hidl_string> string_vec;
693
694 hardware::Parcel *parcel =
695 JHwParcel::GetNativeContext(env, thiz)->getParcel();
696
697 size_t parentHandle;
698
699 const string_vec *vec=
700 (const string_vec *)parcel->readBuffer(&parentHandle);
701
702 if (vec == NULL) {
703 signalExceptionForError(env, UNKNOWN_ERROR);
704 return NULL;
705 }
706
707 size_t childHandle;
Yifan Hong3bb65782016-11-11 17:20:54 -0800708 status_t err = ::android::hardware::readEmbeddedFromParcel(
709 const_cast<string_vec *>(vec),
Andreas Huberdab5fc62016-08-15 09:25:02 -0700710 *parcel, parentHandle, 0 /* parentOffset */, &childHandle);
711
712 for (size_t i = 0; (err == OK) && (i < vec->size()); ++i) {
Yifan Hong3bb65782016-11-11 17:20:54 -0800713 err = android::hardware::readEmbeddedFromParcel(
714 const_cast<hidl_vec<hidl_string> *>(vec),
Andreas Huberdab5fc62016-08-15 09:25:02 -0700715 *parcel,
716 childHandle,
717 i * sizeof(hidl_string),
718 nullptr /* childHandle */);
719 }
720
721 if (err != OK) {
722 signalExceptionForError(env, err);
723 return NULL;
724 }
725
726 return MakeStringArray(env, &(*vec)[0], vec->size());
727}
728
729static void JHwParcel_native_writeStringVector(
730 JNIEnv *env, jobject thiz, jobjectArray arrayObj) {
731 typedef hidl_vec<hidl_string> string_vec;
732
733 if (arrayObj == NULL) {
734 jniThrowException(env, "java/lang/NullPointerException", NULL);
735 return;
736 }
737
738 jsize len = env->GetArrayLength(arrayObj);
739
740 sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz);
741
Andreas Huber9266f992016-08-25 11:21:21 -0700742 void *vecPtr =
743 impl->getStorage()->allocTemporaryStorage(sizeof(string_vec));
744
745 string_vec *vec = new (vecPtr) string_vec;
Andreas Huberdab5fc62016-08-15 09:25:02 -0700746
747 hidl_string *strings = impl->getStorage()->allocStringArray(len);
748 vec->setToExternal(strings, len);
749
750 for (jsize i = 0; i < len; ++i) {
751 ScopedLocalRef<jstring> stringObj(
752 env,
753 (jstring)env->GetObjectArrayElement(arrayObj, i));
754
755 const hidl_string *s =
756 impl->getStorage()->allocTemporaryString(env, stringObj.get());
757
758 strings[i].setToExternal(s->c_str(), s->size());
759 }
760
761 hardware::Parcel *parcel = impl->getParcel();
762
763 size_t parentHandle;
764 status_t err = parcel->writeBuffer(vec, sizeof(*vec), &parentHandle);
765
766 if (err == OK) {
767 size_t childHandle;
Yifan Hong3bb65782016-11-11 17:20:54 -0800768 err = ::android::hardware::writeEmbeddedToParcel(
769 *vec,
Andreas Huberdab5fc62016-08-15 09:25:02 -0700770 parcel,
771 parentHandle,
772 0 /* parentOffset */,
773 &childHandle);
774
775 for (size_t i = 0; (err == OK) && (i < vec->size()); ++i) {
Yifan Hong3bb65782016-11-11 17:20:54 -0800776 err = ::android::hardware::writeEmbeddedToParcel(
777 (*vec)[i],
Andreas Huberdab5fc62016-08-15 09:25:02 -0700778 parcel,
779 childHandle,
780 i * sizeof(hidl_string));
781 }
782 }
783
784 signalExceptionForError(env, err);
785}
786
787static jobject JHwParcel_native_readStrongBinder(JNIEnv *env, jobject thiz) {
788 hardware::Parcel *parcel =
789 JHwParcel::GetNativeContext(env, thiz)->getParcel();
790
791 sp<hardware::IBinder> binder = parcel->readStrongBinder();
792
793 if (binder == NULL) {
794 return NULL;
795 }
796
797 return JHwRemoteBinder::NewObject(env, binder);
798}
799
Andreas Huber9266f992016-08-25 11:21:21 -0700800static jobject JHwParcel_native_readBuffer(JNIEnv *env, jobject thiz) {
801 hardware::Parcel *parcel =
802 JHwParcel::GetNativeContext(env, thiz)->getParcel();
803
804 size_t handle;
805 const void *ptr = parcel->readBuffer(&handle);
806
807 if (ptr == nullptr) {
808 jniThrowException(env, "java/util/NoSuchElementException", NULL);
809 return nullptr;
810 }
811
812 return JHwBlob::NewObject(env, ptr, handle);
813}
814
815static jobject JHwParcel_native_readEmbeddedBuffer(
816 JNIEnv *env, jobject thiz, jlong parentHandle, jlong offset) {
817 hardware::Parcel *parcel =
818 JHwParcel::GetNativeContext(env, thiz)->getParcel();
819
820 size_t childHandle;
821
822 const void *ptr =
823 parcel->readEmbeddedBuffer(&childHandle, parentHandle, offset);
824
825 if (ptr == nullptr) {
826 jniThrowException(env, "java/util/NoSuchElementException", NULL);
827 return 0;
828 }
829
830 return JHwBlob::NewObject(env, ptr, childHandle);
831}
832
833static void JHwParcel_native_writeBuffer(
834 JNIEnv *env, jobject thiz, jobject blobObj) {
835 if (blobObj == nullptr) {
836 jniThrowException(env, "java/lang/NullPointerException", NULL);
837 return;
838 }
839
840 hardware::Parcel *parcel =
841 JHwParcel::GetNativeContext(env, thiz)->getParcel();
842
843 sp<JHwBlob> blob = JHwBlob::GetNativeContext(env, blobObj);
844 status_t err = blob->writeToParcel(parcel);
845
846 if (err != OK) {
847 signalExceptionForError(env, err);
848 }
849}
850
Andreas Huberdab5fc62016-08-15 09:25:02 -0700851static JNINativeMethod gMethods[] = {
852 { "native_init", "()J", (void *)JHwParcel_native_init },
853 { "native_setup", "(Z)V", (void *)JHwParcel_native_setup },
854
855 { "writeInterfaceToken", "(Ljava/lang/String;)V",
856 (void *)JHwParcel_native_writeInterfaceToken },
857
Andreas Huber86635bb2016-08-24 16:19:03 -0700858 { "writeBool", "(Z)V", (void *)JHwParcel_native_writeBool },
Andreas Huberdab5fc62016-08-15 09:25:02 -0700859 { "writeInt8", "(B)V", (void *)JHwParcel_native_writeInt8 },
860 { "writeInt16", "(S)V", (void *)JHwParcel_native_writeInt16 },
861 { "writeInt32", "(I)V", (void *)JHwParcel_native_writeInt32 },
862 { "writeInt64", "(J)V", (void *)JHwParcel_native_writeInt64 },
863 { "writeFloat", "(F)V", (void *)JHwParcel_native_writeFloat },
864 { "writeDouble", "(D)V", (void *)JHwParcel_native_writeDouble },
865
866 { "writeString", "(Ljava/lang/String;)V",
867 (void *)JHwParcel_native_writeString },
868
Andreas Huber86635bb2016-08-24 16:19:03 -0700869 { "writeBoolVector", "([Z)V", (void *)JHwParcel_native_writeBoolVector },
Andreas Huberdab5fc62016-08-15 09:25:02 -0700870 { "writeInt8Vector", "([B)V", (void *)JHwParcel_native_writeInt8Vector },
Andreas Huberdab5fc62016-08-15 09:25:02 -0700871 { "writeInt16Vector", "([S)V", (void *)JHwParcel_native_writeInt16Vector },
Andreas Huberdab5fc62016-08-15 09:25:02 -0700872 { "writeInt32Vector", "([I)V", (void *)JHwParcel_native_writeInt32Vector },
Andreas Huberdab5fc62016-08-15 09:25:02 -0700873 { "writeInt64Vector", "([J)V", (void *)JHwParcel_native_writeInt64Vector },
Andreas Huberdab5fc62016-08-15 09:25:02 -0700874 { "writeFloatVector", "([F)V", (void *)JHwParcel_native_writeFloatVector },
Andreas Huberdab5fc62016-08-15 09:25:02 -0700875
876 { "writeDoubleVector", "([D)V",
877 (void *)JHwParcel_native_writeDoubleVector },
878
Andreas Huberdab5fc62016-08-15 09:25:02 -0700879 { "writeStringVector", "([Ljava/lang/String;)V",
880 (void *)JHwParcel_native_writeStringVector },
881
882 { "writeStrongBinder", "(L" PACKAGE_PATH "/IHwBinder;)V",
883 (void *)JHwParcel_native_writeStrongBinder },
884
885 { "enforceInterface", "(Ljava/lang/String;)V",
886 (void *)JHwParcel_native_enforceInterface },
887
Andreas Huber86635bb2016-08-24 16:19:03 -0700888 { "readBool", "()Z", (void *)JHwParcel_native_readBool },
Andreas Huberdab5fc62016-08-15 09:25:02 -0700889 { "readInt8", "()B", (void *)JHwParcel_native_readInt8 },
890 { "readInt16", "()S", (void *)JHwParcel_native_readInt16 },
891 { "readInt32", "()I", (void *)JHwParcel_native_readInt32 },
892 { "readInt64", "()J", (void *)JHwParcel_native_readInt64 },
893 { "readFloat", "()F", (void *)JHwParcel_native_readFloat },
894 { "readDouble", "()D", (void *)JHwParcel_native_readDouble },
895
896 { "readString", "()Ljava/lang/String;",
897 (void *)JHwParcel_native_readString },
898
Andreas Huberef1a5652016-10-18 09:24:04 -0700899 { "readBoolVectorAsArray", "()[Z",
900 (void *)JHwParcel_native_readBoolVector },
Andreas Huberdab5fc62016-08-15 09:25:02 -0700901
Andreas Huberef1a5652016-10-18 09:24:04 -0700902 { "readInt8VectorAsArray", "()[B",
903 (void *)JHwParcel_native_readInt8Vector },
904
905 { "readInt16VectorAsArray", "()[S",
906 (void *)JHwParcel_native_readInt16Vector },
907
908 { "readInt32VectorAsArray", "()[I",
909 (void *)JHwParcel_native_readInt32Vector },
910
911 { "readInt64VectorAsArray", "()[J",
912 (void *)JHwParcel_native_readInt64Vector },
913
914 { "readFloatVectorAsArray", "()[F",
915 (void *)JHwParcel_native_readFloatVector },
916
917 { "readDoubleVectorAsArray", "()[D",
918 (void *)JHwParcel_native_readDoubleVector },
919
920 { "readStringVectorAsArray", "()[Ljava/lang/String;",
Andreas Huberdab5fc62016-08-15 09:25:02 -0700921 (void *)JHwParcel_native_readStringVector },
922
923 { "readStrongBinder", "()L" PACKAGE_PATH "/IHwBinder;",
924 (void *)JHwParcel_native_readStrongBinder },
925
926 { "writeStatus", "(I)V", (void *)JHwParcel_native_writeStatus },
927
928 { "verifySuccess", "()V", (void *)JHwParcel_native_verifySuccess },
929
930 { "releaseTemporaryStorage", "()V",
931 (void *)JHwParcel_native_releaseTemporaryStorage },
932
933 { "send", "()V", (void *)JHwParcel_native_send },
Andreas Huber9266f992016-08-25 11:21:21 -0700934
935 { "readBuffer", "()L" PACKAGE_PATH "/HwBlob;",
936 (void *)JHwParcel_native_readBuffer },
937
938 { "readEmbeddedBuffer", "(JJ)L" PACKAGE_PATH "/HwBlob;",
939 (void *)JHwParcel_native_readEmbeddedBuffer },
940
941 { "writeBuffer", "(L" PACKAGE_PATH "/HwBlob;)V",
942 (void *)JHwParcel_native_writeBuffer },
Andreas Huberdab5fc62016-08-15 09:25:02 -0700943};
944
945namespace android {
946
947int register_android_os_HwParcel(JNIEnv *env) {
948 return RegisterMethodsOrDie(env, CLASS_PATH, gMethods, NELEM(gMethods));
949}
950
951} // namespace android