blob: 6ea809aa95adb30a169e59a215f38fe38447b5d8 [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
Andreas Huberdab5fc62016-08-15 09:25:02 -0700172 mObject = env->NewWeakGlobalRef(thiz);
173}
174
175JHwParcel::~JHwParcel() {
176 JNIEnv *env = AndroidRuntime::getJNIEnv();
177
178 mStorage.release(env);
179
180 setParcel(NULL, false /* assumeOwnership */);
181
182 env->DeleteWeakGlobalRef(mObject);
183 mObject = NULL;
Andreas Huberdab5fc62016-08-15 09:25:02 -0700184}
185
186hardware::Parcel *JHwParcel::getParcel() {
187 return mParcel;
188}
189
190EphemeralStorage *JHwParcel::getStorage() {
191 return &mStorage;
192}
193
194void JHwParcel::setParcel(hardware::Parcel *parcel, bool assumeOwnership) {
195 if (mParcel && mOwnsParcel) {
196 delete mParcel;
197 }
198
199 mParcel = parcel;
200 mOwnsParcel = assumeOwnership;
201}
202
203// static
204jobject JHwParcel::NewObject(JNIEnv *env) {
205 ScopedLocalRef<jclass> clazz(env, FindClassOrDie(env, CLASS_PATH));
206
Andreas Huber9266f992016-08-25 11:21:21 -0700207 jmethodID constructID =
208 GetMethodIDOrDie(env, clazz.get(), "<init>", "(Z)V");
209
210 return env->NewObject(clazz.get(), constructID, false /* allocate */);
Andreas Huberdab5fc62016-08-15 09:25:02 -0700211}
212
213void JHwParcel::setTransactCallback(
214 ::android::hardware::IBinder::TransactCallback cb) {
215 mTransactCallback = cb;
216}
217
218void JHwParcel::send() {
219 CHECK(mTransactCallback != nullptr);
220 CHECK(mParcel != nullptr);
221
222 mTransactCallback(*mParcel);
223 mTransactCallback = nullptr;
224
225 mWasSent = true;
226}
227
228bool JHwParcel::wasSent() const {
229 return mWasSent;
230}
231
232} // namespace android
233
234////////////////////////////////////////////////////////////////////////////////
235
236using namespace android;
237
238static void releaseNativeContext(void *nativeContext) {
239 sp<JHwParcel> parcel = (JHwParcel *)nativeContext;
240
241 if (parcel != NULL) {
242 parcel->decStrong(NULL /* id */);
243 }
244}
245
246static jlong JHwParcel_native_init(JNIEnv *env) {
247 JHwParcel::InitClass(env);
248
249 return reinterpret_cast<jlong>(&releaseNativeContext);
250}
251
252static void JHwParcel_native_setup(
253 JNIEnv *env, jobject thiz, jboolean allocate) {
254 sp<JHwParcel> context = new JHwParcel(env, thiz);
255
256 if (allocate) {
257 context->setParcel(new hardware::Parcel, true /* assumeOwnership */);
258 }
259
260 JHwParcel::SetNativeContext(env, thiz, context);
261}
262
263static void JHwParcel_native_writeInterfaceToken(
264 JNIEnv *env, jobject thiz, jstring interfaceNameObj) {
265 if (interfaceNameObj == NULL) {
266 jniThrowException(env, "java/lang/NullPointerException", NULL);
267 return;
268 }
269
270 const jchar *interfaceName = env->GetStringCritical(interfaceNameObj, NULL);
271 if (interfaceName) {
Steven Morelandab2fca22016-11-11 12:33:41 -0800272 String8 nameCopy = String8(String16(
Andreas Huber9f026862016-11-03 15:46:04 -0700273 reinterpret_cast<const char16_t *>(interfaceName),
Steven Morelandab2fca22016-11-11 12:33:41 -0800274 env->GetStringLength(interfaceNameObj)));
Andreas Huberdab5fc62016-08-15 09:25:02 -0700275
276 env->ReleaseStringCritical(interfaceNameObj, interfaceName);
277 interfaceName = NULL;
278
Andreas Huber9f026862016-11-03 15:46:04 -0700279 hardware::Parcel *parcel =
280 JHwParcel::GetNativeContext(env, thiz)->getParcel();
281
Steven Morelandab2fca22016-11-11 12:33:41 -0800282 status_t err = parcel->writeInterfaceToken(nameCopy.string());
Andreas Huberdab5fc62016-08-15 09:25:02 -0700283 signalExceptionForError(env, err);
284 }
285}
286
287static void JHwParcel_native_enforceInterface(
288 JNIEnv *env, jobject thiz, jstring interfaceNameObj) {
289 // XXX original binder Parcel enforceInterface implementation does some
290 // mysterious things regarding strictModePolicy(), figure out if we need
291 // that here as well.
292 if (interfaceNameObj == NULL) {
293 jniThrowException(env, "java/lang/NullPointerException", NULL);
294 return;
295 }
296
297 const jchar *interfaceName = env->GetStringCritical(interfaceNameObj, NULL);
298 if (interfaceName) {
Steven Morelandab2fca22016-11-11 12:33:41 -0800299 String8 interfaceNameCopy = String8(String16(
Andreas Huber9f026862016-11-03 15:46:04 -0700300 reinterpret_cast<const char16_t *>(interfaceName),
Steven Morelandab2fca22016-11-11 12:33:41 -0800301 env->GetStringLength(interfaceNameObj)));
Andreas Huberdab5fc62016-08-15 09:25:02 -0700302
303 env->ReleaseStringCritical(interfaceNameObj, interfaceName);
304 interfaceName = NULL;
305
Andreas Huber9f026862016-11-03 15:46:04 -0700306 hardware::Parcel *parcel =
307 JHwParcel::GetNativeContext(env, thiz)->getParcel();
308
Steven Morelandab2fca22016-11-11 12:33:41 -0800309 bool valid = parcel->enforceInterface(interfaceNameCopy.string());
Andreas Huber9f026862016-11-03 15:46:04 -0700310
Andreas Huberdab5fc62016-08-15 09:25:02 -0700311 if (!valid) {
312 jniThrowException(
313 env,
314 "java/lang/SecurityException",
315 "HWBinder invocation to an incorrect interface");
316 }
317 }
318}
319
320#define DEFINE_PARCEL_WRITER(Suffix,Type) \
321static void JHwParcel_native_write ## Suffix( \
322 JNIEnv *env, jobject thiz, Type val) { \
323 hardware::Parcel *parcel = \
324 JHwParcel::GetNativeContext(env, thiz)->getParcel(); \
325 \
326 status_t err = parcel->write ## Suffix(val); \
327 signalExceptionForError(env, err); \
328}
329
330#define DEFINE_PARCEL_READER(Suffix,Type) \
331static Type JHwParcel_native_read ## Suffix( \
332 JNIEnv *env, jobject thiz) { \
333 hardware::Parcel *parcel = \
334 JHwParcel::GetNativeContext(env, thiz)->getParcel(); \
335 \
336 Type val; \
337 status_t err = parcel->read ## Suffix(&val); \
338 signalExceptionForError(env, err); \
339 \
340 return val; \
341}
342
Andreas Huber86635bb2016-08-24 16:19:03 -0700343DEFINE_PARCEL_WRITER(Bool,jboolean)
Andreas Huberdab5fc62016-08-15 09:25:02 -0700344DEFINE_PARCEL_WRITER(Int8,jbyte)
345DEFINE_PARCEL_WRITER(Int16,jshort)
346DEFINE_PARCEL_WRITER(Int32,jint)
347DEFINE_PARCEL_WRITER(Int64,jlong)
348DEFINE_PARCEL_WRITER(Float,jfloat)
349DEFINE_PARCEL_WRITER(Double,jdouble)
350
351DEFINE_PARCEL_READER(Int8,jbyte)
352DEFINE_PARCEL_READER(Int16,jshort)
353DEFINE_PARCEL_READER(Int32,jint)
354DEFINE_PARCEL_READER(Int64,jlong)
355DEFINE_PARCEL_READER(Float,jfloat)
356DEFINE_PARCEL_READER(Double,jdouble)
357
Andreas Huber86635bb2016-08-24 16:19:03 -0700358static jboolean JHwParcel_native_readBool(JNIEnv *env, jobject thiz) {
359 hardware::Parcel *parcel =
360 JHwParcel::GetNativeContext(env, thiz)->getParcel();
361
362 bool val;
363 status_t err = parcel->readBool(&val);
364 signalExceptionForError(env, err);
365
366 return (jboolean)val;
367}
368
Andreas Huberdab5fc62016-08-15 09:25:02 -0700369static void JHwParcel_native_writeStatus(
370 JNIEnv *env, jobject thiz, jint statusCode) {
371 using hardware::Status;
372
373 Status status;
374 switch (statusCode) {
375 case 0: // kStatusSuccess
376 status = Status::ok();
377 break;
378 case -1: // kStatusError
379 status = Status::fromStatusT(UNKNOWN_ERROR);
380 break;
381 default:
382 CHECK(!"Should not be here");
383 }
384
385 hardware::Parcel *parcel =
386 JHwParcel::GetNativeContext(env, thiz)->getParcel();
387
Yifan Hongddf31f62016-11-15 16:02:40 -0800388 status_t err = ::android::hardware::writeToParcel(status, parcel);
Andreas Huberdab5fc62016-08-15 09:25:02 -0700389 signalExceptionForError(env, err);
390}
391
392static void JHwParcel_native_verifySuccess(JNIEnv *env, jobject thiz) {
393 using hardware::Status;
394
395 hardware::Parcel *parcel =
396 JHwParcel::GetNativeContext(env, thiz)->getParcel();
397
398 Status status;
Yifan Hongddf31f62016-11-15 16:02:40 -0800399 status_t err = ::android::hardware::readFromParcel(&status, *parcel);
Andreas Huberdab5fc62016-08-15 09:25:02 -0700400 signalExceptionForError(env, err);
401}
402
Martijn Coenen3d726d12017-03-16 18:46:42 +0100403static void JHwParcel_native_release(
404 JNIEnv *env, jobject thiz) {
405 JHwParcel::GetNativeContext(env, thiz)->setParcel(NULL, false /* assumeOwnership */);
406}
407
Andreas Huberdab5fc62016-08-15 09:25:02 -0700408static void JHwParcel_native_releaseTemporaryStorage(
409 JNIEnv *env, jobject thiz) {
410 JHwParcel::GetNativeContext(env, thiz)->getStorage()->release(env);
411}
412
413static void JHwParcel_native_send(JNIEnv *env, jobject thiz) {
414 JHwParcel::GetNativeContext(env, thiz)->send();
415}
416
417static void JHwParcel_native_writeString(
418 JNIEnv *env, jobject thiz, jstring valObj) {
419 if (valObj == NULL) {
420 jniThrowException(env, "java/lang/NullPointerException", NULL);
421 return;
422 }
423
424 sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz);
425
426 const hidl_string *s =
427 impl->getStorage()->allocTemporaryString(env, valObj);
428
429 hardware::Parcel *parcel = impl->getParcel();
430
431 size_t parentHandle;
432 status_t err = parcel->writeBuffer(s, sizeof(*s), &parentHandle);
433
434 if (err == OK) {
Yifan Hong3bb65782016-11-11 17:20:54 -0800435 err = ::android::hardware::writeEmbeddedToParcel(
436 *s, parcel, parentHandle, 0 /* parentOffset */);
Andreas Huberdab5fc62016-08-15 09:25:02 -0700437 }
438
439 signalExceptionForError(env, err);
440}
441
Andreas Huberdab5fc62016-08-15 09:25:02 -0700442#define DEFINE_PARCEL_VECTOR_WRITER(Suffix,Type) \
443static void JHwParcel_native_write ## Suffix ## Vector( \
444 JNIEnv *env, jobject thiz, Type ## Array valObj) { \
445 if (valObj == NULL) { \
446 jniThrowException(env, "java/lang/NullPointerException", NULL); \
447 return; \
448 } \
449 \
450 sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz); \
451 \
452 const hidl_vec<Type> *vec = \
453 impl->getStorage()->allocTemporary ## Suffix ## Vector(env, valObj); \
454 \
455 hardware::Parcel *parcel = impl->getParcel(); \
456 \
457 size_t parentHandle; \
458 status_t err = parcel->writeBuffer(vec, sizeof(*vec), &parentHandle); \
459 \
460 if (err == OK) { \
461 size_t childHandle; \
462 \
Yifan Hong3bb65782016-11-11 17:20:54 -0800463 err = ::android::hardware::writeEmbeddedToParcel( \
464 *vec, \
Andreas Huberdab5fc62016-08-15 09:25:02 -0700465 parcel, \
466 parentHandle, \
467 0 /* parentOffset */, \
468 &childHandle); \
469 } \
470 \
471 signalExceptionForError(env, err); \
472}
473
Andreas Huberdab5fc62016-08-15 09:25:02 -0700474DEFINE_PARCEL_VECTOR_WRITER(Int8,jbyte)
475DEFINE_PARCEL_VECTOR_WRITER(Int16,jshort)
476DEFINE_PARCEL_VECTOR_WRITER(Int32,jint)
477DEFINE_PARCEL_VECTOR_WRITER(Int64,jlong)
478DEFINE_PARCEL_VECTOR_WRITER(Float,jfloat)
479DEFINE_PARCEL_VECTOR_WRITER(Double,jdouble)
480
Andreas Huber86635bb2016-08-24 16:19:03 -0700481static void JHwParcel_native_writeBoolVector(
482 JNIEnv *env, jobject thiz, jbooleanArray valObj) {
483 if (valObj == NULL) {
484 jniThrowException(env, "java/lang/NullPointerException", NULL);
485 return;
486 }
487
488 sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz);
489
Andreas Huber9266f992016-08-25 11:21:21 -0700490 void *vecPtr =
491 impl->getStorage()->allocTemporaryStorage(sizeof(hidl_vec<bool>));
492
493 hidl_vec<bool> *vec = new (vecPtr) hidl_vec<bool>;
Andreas Huber86635bb2016-08-24 16:19:03 -0700494
495 jsize len = env->GetArrayLength(valObj);
496
497 jboolean *src = env->GetBooleanArrayElements(valObj, nullptr);
498
499 bool *dst =
500 (bool *)impl->getStorage()->allocTemporaryStorage(len * sizeof(bool));
501
502 for (jsize i = 0; i < len; ++i) {
503 dst[i] = src[i];
504 }
505
506 env->ReleaseBooleanArrayElements(valObj, src, 0 /* mode */);
507 src = nullptr;
508
509 vec->setToExternal(dst, len);
510
511 hardware::Parcel *parcel = impl->getParcel();
512
513 size_t parentHandle;
514 status_t err = parcel->writeBuffer(vec, sizeof(*vec), &parentHandle);
515
516 if (err == OK) {
517 size_t childHandle;
518
Yifan Hong3bb65782016-11-11 17:20:54 -0800519 err = ::android::hardware::writeEmbeddedToParcel(
520 *vec,
Andreas Huber86635bb2016-08-24 16:19:03 -0700521 parcel,
522 parentHandle,
523 0 /* parentOffset */,
524 &childHandle);
525 }
526
527 signalExceptionForError(env, err);
528}
529
Andreas Huberdab5fc62016-08-15 09:25:02 -0700530static void JHwParcel_native_writeStrongBinder(
531 JNIEnv *env, jobject thiz, jobject binderObj) {
532 sp<hardware::IBinder> binder;
533 if (binderObj != NULL) {
534 ScopedLocalRef<jclass> hwBinderKlass(
535 env, FindClassOrDie(env, PACKAGE_PATH "/HwBinder"));
536
537 ScopedLocalRef<jclass> hwRemoteBinderKlass(
538 env, FindClassOrDie(env, PACKAGE_PATH "/HwRemoteBinder"));
539
540 if (env->IsInstanceOf(binderObj, hwBinderKlass.get())) {
Andreas Huber56bdb8a2017-06-16 14:56:12 -0700541 binder = JHwBinder::GetNativeBinder(env, binderObj);
Andreas Huberdab5fc62016-08-15 09:25:02 -0700542 } else if (env->IsInstanceOf(binderObj, hwRemoteBinderKlass.get())) {
543 binder = JHwRemoteBinder::GetNativeContext(
544 env, binderObj)->getBinder();
545 } else {
546 signalExceptionForError(env, INVALID_OPERATION);
547 return;
548 }
549 }
550
551 hardware::Parcel *parcel =
552 JHwParcel::GetNativeContext(env, thiz)->getParcel();
553
554 status_t err = parcel->writeStrongBinder(binder);
555 signalExceptionForError(env, err);
556}
557
558static jstring MakeStringObjFromHidlString(JNIEnv *env, const hidl_string &s) {
559 String16 utf16String(s.c_str(), s.size());
560
561 return env->NewString(
562 reinterpret_cast<const jchar *>(utf16String.string()),
563 utf16String.size());
564}
565
566static jstring JHwParcel_native_readString(JNIEnv *env, jobject thiz) {
567 hardware::Parcel *parcel =
568 JHwParcel::GetNativeContext(env, thiz)->getParcel();
569
570 size_t parentHandle;
571
Martijn Coenen24c82272017-01-11 12:35:56 +0100572 const hidl_string *s;
Martijn Coenen7c006392017-04-18 15:54:43 -0700573 status_t err = parcel->readBuffer(sizeof(*s), &parentHandle,
Martijn Coenen24c82272017-01-11 12:35:56 +0100574 reinterpret_cast<const void**>(&s));
Andreas Huberdab5fc62016-08-15 09:25:02 -0700575
Martijn Coenen24c82272017-01-11 12:35:56 +0100576 if (err != OK) {
577 signalExceptionForError(env, err);
Andreas Huberdab5fc62016-08-15 09:25:02 -0700578 return NULL;
579 }
580
Martijn Coenen24c82272017-01-11 12:35:56 +0100581 err = ::android::hardware::readEmbeddedFromParcel(
Martijn Coenen7c006392017-04-18 15:54:43 -0700582 const_cast<hidl_string &>(*s),
Andreas Huberdab5fc62016-08-15 09:25:02 -0700583 *parcel, parentHandle, 0 /* parentOffset */);
584
585 if (err != OK) {
586 signalExceptionForError(env, err);
587 return NULL;
588 }
589
590 return MakeStringObjFromHidlString(env, *s);
591}
592
Andreas Huberdab5fc62016-08-15 09:25:02 -0700593#define DEFINE_PARCEL_VECTOR_READER(Suffix,Type,NewType) \
594static Type ## Array JHwParcel_native_read ## Suffix ## Vector( \
595 JNIEnv *env, jobject thiz) { \
596 hardware::Parcel *parcel = \
597 JHwParcel::GetNativeContext(env, thiz)->getParcel(); \
Andreas Huberdab5fc62016-08-15 09:25:02 -0700598 size_t parentHandle; \
599 \
Martijn Coenen24c82272017-01-11 12:35:56 +0100600 const hidl_vec<Type> *vec; \
Martijn Coenen7c006392017-04-18 15:54:43 -0700601 status_t err = parcel->readBuffer(sizeof(*vec), &parentHandle, \
Martijn Coenen24c82272017-01-11 12:35:56 +0100602 reinterpret_cast<const void**>(&vec)); \
Andreas Huberdab5fc62016-08-15 09:25:02 -0700603 \
Martijn Coenen24c82272017-01-11 12:35:56 +0100604 if (err != OK) { \
605 signalExceptionForError(env, err); \
Andreas Huberdab5fc62016-08-15 09:25:02 -0700606 return NULL; \
607 } \
608 \
609 size_t childHandle; \
610 \
Martijn Coenen24c82272017-01-11 12:35:56 +0100611 err = ::android::hardware::readEmbeddedFromParcel( \
Martijn Coenen7c006392017-04-18 15:54:43 -0700612 const_cast<hidl_vec<Type> &>(*vec), \
Andreas Huberdab5fc62016-08-15 09:25:02 -0700613 *parcel, \
614 parentHandle, \
615 0 /* parentOffset */, \
616 &childHandle); \
617 \
618 if (err != OK) { \
619 signalExceptionForError(env, err); \
620 return NULL; \
621 } \
622 \
623 Type ## Array valObj = env->New ## NewType ## Array(vec->size()); \
624 env->Set ## NewType ## ArrayRegion(valObj, 0, vec->size(), &(*vec)[0]); \
625 \
626 return valObj; \
627}
628
Andreas Huberdab5fc62016-08-15 09:25:02 -0700629DEFINE_PARCEL_VECTOR_READER(Int8,jbyte,Byte)
630DEFINE_PARCEL_VECTOR_READER(Int16,jshort,Short)
631DEFINE_PARCEL_VECTOR_READER(Int32,jint,Int)
632DEFINE_PARCEL_VECTOR_READER(Int64,jlong,Long)
633DEFINE_PARCEL_VECTOR_READER(Float,jfloat,Float)
634DEFINE_PARCEL_VECTOR_READER(Double,jdouble,Double)
635
Andreas Huber86635bb2016-08-24 16:19:03 -0700636static jbooleanArray JHwParcel_native_readBoolVector(
637 JNIEnv *env, jobject thiz) {
638 hardware::Parcel *parcel =
639 JHwParcel::GetNativeContext(env, thiz)->getParcel();
640
641 size_t parentHandle;
642
Martijn Coenen24c82272017-01-11 12:35:56 +0100643 const hidl_vec<bool> *vec;
Martijn Coenen7c006392017-04-18 15:54:43 -0700644 status_t err = parcel->readBuffer(sizeof(*vec), &parentHandle,
Martijn Coenen24c82272017-01-11 12:35:56 +0100645 reinterpret_cast<const void**>(&vec));
Andreas Huber86635bb2016-08-24 16:19:03 -0700646
Martijn Coenen24c82272017-01-11 12:35:56 +0100647 if (err != OK) {
648 signalExceptionForError(env, err);
Andreas Huber86635bb2016-08-24 16:19:03 -0700649 return NULL;
650 }
651
652 size_t childHandle;
653
Martijn Coenen24c82272017-01-11 12:35:56 +0100654 err = ::android::hardware::readEmbeddedFromParcel(
Martijn Coenen7c006392017-04-18 15:54:43 -0700655 const_cast<hidl_vec<bool> &>(*vec),
Andreas Huber86635bb2016-08-24 16:19:03 -0700656 *parcel,
657 parentHandle,
658 0 /* parentOffset */,
659 &childHandle);
660
661 if (err != OK) {
662 signalExceptionForError(env, err);
663 return NULL;
664 }
665
666 jbooleanArray valObj = env->NewBooleanArray(vec->size());
667
668 for (size_t i = 0; i < vec->size(); ++i) {
669 jboolean x = (*vec)[i];
670 env->SetBooleanArrayRegion(valObj, i, 1, &x);
671 }
672
673 return valObj;
674}
675
Andreas Huberdab5fc62016-08-15 09:25:02 -0700676static jobjectArray MakeStringArray(
677 JNIEnv *env, const hidl_string *array, size_t size) {
678 ScopedLocalRef<jclass> stringKlass(
679 env,
680 env->FindClass("java/lang/String"));
681
682 // XXX Why can't I use ScopedLocalRef<> for the arrayObj and the stringObjs?
683
684 jobjectArray arrayObj = env->NewObjectArray(size, stringKlass.get(), NULL);
685
686 for (size_t i = 0; i < size; ++i) {
687 jstring stringObj = MakeStringObjFromHidlString(env, array[i]);
688
689 env->SetObjectArrayElement(
690 arrayObj,
691 i,
692 stringObj);
693 }
694
695 return arrayObj;
696}
697
Andreas Huberdab5fc62016-08-15 09:25:02 -0700698static jobjectArray JHwParcel_native_readStringVector(
699 JNIEnv *env, jobject thiz) {
700 typedef hidl_vec<hidl_string> string_vec;
701
702 hardware::Parcel *parcel =
703 JHwParcel::GetNativeContext(env, thiz)->getParcel();
704
705 size_t parentHandle;
706
Martijn Coenen24c82272017-01-11 12:35:56 +0100707 const string_vec *vec;
Martijn Coenen7c006392017-04-18 15:54:43 -0700708 status_t err = parcel->readBuffer(sizeof(*vec), &parentHandle,
Martijn Coenen24c82272017-01-11 12:35:56 +0100709 reinterpret_cast<const void **>(&vec));
Andreas Huberdab5fc62016-08-15 09:25:02 -0700710
Martijn Coenen24c82272017-01-11 12:35:56 +0100711 if (err != OK) {
712 signalExceptionForError(env, err);
Andreas Huberdab5fc62016-08-15 09:25:02 -0700713 return NULL;
714 }
715
716 size_t childHandle;
Martijn Coenen24c82272017-01-11 12:35:56 +0100717 err = ::android::hardware::readEmbeddedFromParcel(
Martijn Coenen7c006392017-04-18 15:54:43 -0700718 const_cast<string_vec &>(*vec),
Andreas Huberdab5fc62016-08-15 09:25:02 -0700719 *parcel, parentHandle, 0 /* parentOffset */, &childHandle);
720
721 for (size_t i = 0; (err == OK) && (i < vec->size()); ++i) {
Yifan Hong3bb65782016-11-11 17:20:54 -0800722 err = android::hardware::readEmbeddedFromParcel(
Martijn Coenen7c006392017-04-18 15:54:43 -0700723 const_cast<hidl_string &>((*vec)[i]),
Andreas Huberdab5fc62016-08-15 09:25:02 -0700724 *parcel,
725 childHandle,
Martijn Coenen7c006392017-04-18 15:54:43 -0700726 i * sizeof(hidl_string) /* parentOffset */);
Andreas Huberdab5fc62016-08-15 09:25:02 -0700727 }
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
Martijn Coenen7c006392017-04-18 15:54:43 -0700808static jobject JHwParcel_native_readBuffer(JNIEnv *env, jobject thiz,
809 jlong expectedSize) {
Andreas Huber9266f992016-08-25 11:21:21 -0700810 hardware::Parcel *parcel =
811 JHwParcel::GetNativeContext(env, thiz)->getParcel();
812
813 size_t handle;
Martijn Coenen24c82272017-01-11 12:35:56 +0100814 const void *ptr;
Martijn Coenen7c006392017-04-18 15:54:43 -0700815
816 if (expectedSize < 0) {
817 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
818 return nullptr;
819 }
820
821 status_t status = parcel->readBuffer(expectedSize, &handle, &ptr);
Andreas Huber9266f992016-08-25 11:21:21 -0700822
Martijn Coenen24c82272017-01-11 12:35:56 +0100823 if (status != OK) {
Andreas Huber9266f992016-08-25 11:21:21 -0700824 jniThrowException(env, "java/util/NoSuchElementException", NULL);
825 return nullptr;
826 }
827
828 return JHwBlob::NewObject(env, ptr, handle);
829}
830
831static jobject JHwParcel_native_readEmbeddedBuffer(
Martijn Coenen7c006392017-04-18 15:54:43 -0700832 JNIEnv *env, jobject thiz, jlong expectedSize,
833 jlong parentHandle, jlong offset, jboolean nullable) {
Andreas Huber9266f992016-08-25 11:21:21 -0700834 hardware::Parcel *parcel =
835 JHwParcel::GetNativeContext(env, thiz)->getParcel();
836
837 size_t childHandle;
838
Martijn Coenen24c82272017-01-11 12:35:56 +0100839 const void *ptr;
840 status_t status =
Martijn Coenen7c006392017-04-18 15:54:43 -0700841 parcel->readNullableEmbeddedBuffer(expectedSize,
842 &childHandle, parentHandle, offset, &ptr);
843
844 if (expectedSize < 0) {
845 jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
846 return nullptr;
847 }
Andreas Huber9266f992016-08-25 11:21:21 -0700848
Martijn Coenen24c82272017-01-11 12:35:56 +0100849 if (status != OK) {
Andreas Huber9266f992016-08-25 11:21:21 -0700850 jniThrowException(env, "java/util/NoSuchElementException", NULL);
851 return 0;
Martijn Coenen14fae062017-01-13 11:08:51 +0100852 } else if (status == OK && !nullable && ptr == nullptr) {
853 jniThrowException(env, "java/lang/NullPointerException", NULL);
854 return 0;
Andreas Huber9266f992016-08-25 11:21:21 -0700855 }
856
857 return JHwBlob::NewObject(env, ptr, childHandle);
858}
859
860static void JHwParcel_native_writeBuffer(
861 JNIEnv *env, jobject thiz, jobject blobObj) {
862 if (blobObj == nullptr) {
863 jniThrowException(env, "java/lang/NullPointerException", NULL);
864 return;
865 }
866
867 hardware::Parcel *parcel =
868 JHwParcel::GetNativeContext(env, thiz)->getParcel();
869
870 sp<JHwBlob> blob = JHwBlob::GetNativeContext(env, blobObj);
871 status_t err = blob->writeToParcel(parcel);
872
873 if (err != OK) {
874 signalExceptionForError(env, err);
875 }
876}
877
Andreas Huberdab5fc62016-08-15 09:25:02 -0700878static JNINativeMethod gMethods[] = {
879 { "native_init", "()J", (void *)JHwParcel_native_init },
880 { "native_setup", "(Z)V", (void *)JHwParcel_native_setup },
881
882 { "writeInterfaceToken", "(Ljava/lang/String;)V",
883 (void *)JHwParcel_native_writeInterfaceToken },
884
Andreas Huber86635bb2016-08-24 16:19:03 -0700885 { "writeBool", "(Z)V", (void *)JHwParcel_native_writeBool },
Andreas Huberdab5fc62016-08-15 09:25:02 -0700886 { "writeInt8", "(B)V", (void *)JHwParcel_native_writeInt8 },
887 { "writeInt16", "(S)V", (void *)JHwParcel_native_writeInt16 },
888 { "writeInt32", "(I)V", (void *)JHwParcel_native_writeInt32 },
889 { "writeInt64", "(J)V", (void *)JHwParcel_native_writeInt64 },
890 { "writeFloat", "(F)V", (void *)JHwParcel_native_writeFloat },
891 { "writeDouble", "(D)V", (void *)JHwParcel_native_writeDouble },
892
893 { "writeString", "(Ljava/lang/String;)V",
894 (void *)JHwParcel_native_writeString },
895
Andreas Huber86635bb2016-08-24 16:19:03 -0700896 { "writeBoolVector", "([Z)V", (void *)JHwParcel_native_writeBoolVector },
Andreas Huberdab5fc62016-08-15 09:25:02 -0700897 { "writeInt8Vector", "([B)V", (void *)JHwParcel_native_writeInt8Vector },
Andreas Huberdab5fc62016-08-15 09:25:02 -0700898 { "writeInt16Vector", "([S)V", (void *)JHwParcel_native_writeInt16Vector },
Andreas Huberdab5fc62016-08-15 09:25:02 -0700899 { "writeInt32Vector", "([I)V", (void *)JHwParcel_native_writeInt32Vector },
Andreas Huberdab5fc62016-08-15 09:25:02 -0700900 { "writeInt64Vector", "([J)V", (void *)JHwParcel_native_writeInt64Vector },
Andreas Huberdab5fc62016-08-15 09:25:02 -0700901 { "writeFloatVector", "([F)V", (void *)JHwParcel_native_writeFloatVector },
Andreas Huberdab5fc62016-08-15 09:25:02 -0700902
903 { "writeDoubleVector", "([D)V",
904 (void *)JHwParcel_native_writeDoubleVector },
905
Andreas Huberdab5fc62016-08-15 09:25:02 -0700906 { "writeStringVector", "([Ljava/lang/String;)V",
907 (void *)JHwParcel_native_writeStringVector },
908
909 { "writeStrongBinder", "(L" PACKAGE_PATH "/IHwBinder;)V",
910 (void *)JHwParcel_native_writeStrongBinder },
911
912 { "enforceInterface", "(Ljava/lang/String;)V",
913 (void *)JHwParcel_native_enforceInterface },
914
Andreas Huber86635bb2016-08-24 16:19:03 -0700915 { "readBool", "()Z", (void *)JHwParcel_native_readBool },
Andreas Huberdab5fc62016-08-15 09:25:02 -0700916 { "readInt8", "()B", (void *)JHwParcel_native_readInt8 },
917 { "readInt16", "()S", (void *)JHwParcel_native_readInt16 },
918 { "readInt32", "()I", (void *)JHwParcel_native_readInt32 },
919 { "readInt64", "()J", (void *)JHwParcel_native_readInt64 },
920 { "readFloat", "()F", (void *)JHwParcel_native_readFloat },
921 { "readDouble", "()D", (void *)JHwParcel_native_readDouble },
922
923 { "readString", "()Ljava/lang/String;",
924 (void *)JHwParcel_native_readString },
925
Andreas Huberef1a5652016-10-18 09:24:04 -0700926 { "readBoolVectorAsArray", "()[Z",
927 (void *)JHwParcel_native_readBoolVector },
Andreas Huberdab5fc62016-08-15 09:25:02 -0700928
Andreas Huberef1a5652016-10-18 09:24:04 -0700929 { "readInt8VectorAsArray", "()[B",
930 (void *)JHwParcel_native_readInt8Vector },
931
932 { "readInt16VectorAsArray", "()[S",
933 (void *)JHwParcel_native_readInt16Vector },
934
935 { "readInt32VectorAsArray", "()[I",
936 (void *)JHwParcel_native_readInt32Vector },
937
938 { "readInt64VectorAsArray", "()[J",
939 (void *)JHwParcel_native_readInt64Vector },
940
941 { "readFloatVectorAsArray", "()[F",
942 (void *)JHwParcel_native_readFloatVector },
943
944 { "readDoubleVectorAsArray", "()[D",
945 (void *)JHwParcel_native_readDoubleVector },
946
947 { "readStringVectorAsArray", "()[Ljava/lang/String;",
Andreas Huberdab5fc62016-08-15 09:25:02 -0700948 (void *)JHwParcel_native_readStringVector },
949
950 { "readStrongBinder", "()L" PACKAGE_PATH "/IHwBinder;",
951 (void *)JHwParcel_native_readStrongBinder },
952
953 { "writeStatus", "(I)V", (void *)JHwParcel_native_writeStatus },
954
955 { "verifySuccess", "()V", (void *)JHwParcel_native_verifySuccess },
956
957 { "releaseTemporaryStorage", "()V",
958 (void *)JHwParcel_native_releaseTemporaryStorage },
959
960 { "send", "()V", (void *)JHwParcel_native_send },
Andreas Huber9266f992016-08-25 11:21:21 -0700961
Martijn Coenen7c006392017-04-18 15:54:43 -0700962 { "readBuffer", "(J)L" PACKAGE_PATH "/HwBlob;",
Andreas Huber9266f992016-08-25 11:21:21 -0700963 (void *)JHwParcel_native_readBuffer },
964
Martijn Coenen7c006392017-04-18 15:54:43 -0700965 { "readEmbeddedBuffer", "(JJJZ)L" PACKAGE_PATH "/HwBlob;",
Andreas Huber9266f992016-08-25 11:21:21 -0700966 (void *)JHwParcel_native_readEmbeddedBuffer },
967
968 { "writeBuffer", "(L" PACKAGE_PATH "/HwBlob;)V",
969 (void *)JHwParcel_native_writeBuffer },
Martijn Coenen3d726d12017-03-16 18:46:42 +0100970
971 { "release", "()V",
972 (void *)JHwParcel_native_release },
973
Andreas Huberdab5fc62016-08-15 09:25:02 -0700974};
975
976namespace android {
977
978int register_android_os_HwParcel(JNIEnv *env) {
979 return RegisterMethodsOrDie(env, CLASS_PATH, gMethods, NELEM(gMethods));
980}
981
982} // namespace android