• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 //#define LOG_NDEBUG 0
18 #define LOG_TAG "android_os_HwParcel"
19 #include <android-base/logging.h>
20 
21 #include "android_os_HwParcel.h"
22 
23 #include "android_os_HwBinder.h"
24 #include "android_os_HwBlob.h"
25 #include "android_os_HwRemoteBinder.h"
26 
27 #include <JNIHelp.h>
28 #include <android_runtime/AndroidRuntime.h>
29 #include <hidl/HidlTransportSupport.h>
30 #include <hidl/Status.h>
31 #include <nativehelper/ScopedLocalRef.h>
32 
33 #include "core_jni_helpers.h"
34 
35 using android::AndroidRuntime;
36 
37 using ::android::hardware::hidl_string;
38 using ::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 
44 namespace android {
45 
46 static struct fields_t {
47     jfieldID contextID;
48     jmethodID constructID;
49 
50 } gFields;
51 
signalExceptionForError(JNIEnv * env,status_t err,bool canThrowRemoteException)52 void signalExceptionForError(JNIEnv *env, status_t err, bool canThrowRemoteException) {
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 
76         case -ERANGE:
77         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             std::stringstream ss;
118             ss << "HwBinder Error: (" << err << ")";
119 
120             jniThrowException(
121                     env,
122                     canThrowRemoteException ? "android/os/RemoteException" : "java/lang/RuntimeException",
123                     ss.str().c_str());
124 
125             break;
126         }
127     }
128 }
129 
130 // static
InitClass(JNIEnv * env)131 void 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
SetNativeContext(JNIEnv * env,jobject thiz,const sp<JHwParcel> & context)142 sp<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
GetNativeContext(JNIEnv * env,jobject thiz)160 sp<JHwParcel> JHwParcel::GetNativeContext(JNIEnv *env, jobject thiz) {
161     return (JHwParcel *)env->GetLongField(thiz, gFields.contextID);
162 }
163 
JHwParcel(JNIEnv * env,jobject thiz)164 JHwParcel::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 
~JHwParcel()176 JHwParcel::~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 
getParcel()190 hardware::Parcel *JHwParcel::getParcel() {
191     return mParcel;
192 }
193 
getStorage()194 EphemeralStorage *JHwParcel::getStorage() {
195     return &mStorage;
196 }
197 
setParcel(hardware::Parcel * parcel,bool assumeOwnership)198 void 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
NewObject(JNIEnv * env)208 jobject JHwParcel::NewObject(JNIEnv *env) {
209     ScopedLocalRef<jclass> clazz(env, FindClassOrDie(env, CLASS_PATH));
210 
211     jmethodID constructID =
212         GetMethodIDOrDie(env, clazz.get(), "<init>", "(Z)V");
213 
214     return env->NewObject(clazz.get(), constructID, false /* allocate */);
215 }
216 
setTransactCallback(::android::hardware::IBinder::TransactCallback cb)217 void JHwParcel::setTransactCallback(
218         ::android::hardware::IBinder::TransactCallback cb) {
219     mTransactCallback = cb;
220 }
221 
send()222 void JHwParcel::send() {
223     CHECK(mTransactCallback != nullptr);
224     CHECK(mParcel != nullptr);
225 
226     mTransactCallback(*mParcel);
227     mTransactCallback = nullptr;
228 
229     mWasSent = true;
230 }
231 
wasSent() const232 bool JHwParcel::wasSent() const {
233     return mWasSent;
234 }
235 
236 }  // namespace android
237 
238 ////////////////////////////////////////////////////////////////////////////////
239 
240 using namespace android;
241 
releaseNativeContext(void * nativeContext)242 static void releaseNativeContext(void *nativeContext) {
243     sp<JHwParcel> parcel = (JHwParcel *)nativeContext;
244 
245     if (parcel != NULL) {
246         parcel->decStrong(NULL /* id */);
247     }
248 }
249 
JHwParcel_native_init(JNIEnv * env)250 static jlong JHwParcel_native_init(JNIEnv *env) {
251     JHwParcel::InitClass(env);
252 
253     return reinterpret_cast<jlong>(&releaseNativeContext);
254 }
255 
JHwParcel_native_setup(JNIEnv * env,jobject thiz,jboolean allocate)256 static 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 
JHwParcel_native_writeInterfaceToken(JNIEnv * env,jobject thiz,jstring interfaceNameObj)267 static 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) {
276         String8 nameCopy = String8(String16(
277                 reinterpret_cast<const char16_t *>(interfaceName),
278                 env->GetStringLength(interfaceNameObj)));
279 
280         env->ReleaseStringCritical(interfaceNameObj, interfaceName);
281         interfaceName = NULL;
282 
283         hardware::Parcel *parcel =
284             JHwParcel::GetNativeContext(env, thiz)->getParcel();
285 
286         status_t err = parcel->writeInterfaceToken(nameCopy.string());
287         signalExceptionForError(env, err);
288     }
289 }
290 
JHwParcel_native_enforceInterface(JNIEnv * env,jobject thiz,jstring interfaceNameObj)291 static 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) {
303         String8 interfaceNameCopy = String8(String16(
304                 reinterpret_cast<const char16_t *>(interfaceName),
305                 env->GetStringLength(interfaceNameObj)));
306 
307         env->ReleaseStringCritical(interfaceNameObj, interfaceName);
308         interfaceName = NULL;
309 
310         hardware::Parcel *parcel =
311             JHwParcel::GetNativeContext(env, thiz)->getParcel();
312 
313         bool valid = parcel->enforceInterface(interfaceNameCopy.string());
314 
315         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)                               \
325 static 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)                               \
335 static 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 
DEFINE_PARCEL_WRITER(Bool,jboolean)347 DEFINE_PARCEL_WRITER(Bool,jboolean)
348 DEFINE_PARCEL_WRITER(Int8,jbyte)
349 DEFINE_PARCEL_WRITER(Int16,jshort)
350 DEFINE_PARCEL_WRITER(Int32,jint)
351 DEFINE_PARCEL_WRITER(Int64,jlong)
352 DEFINE_PARCEL_WRITER(Float,jfloat)
353 DEFINE_PARCEL_WRITER(Double,jdouble)
354 
355 DEFINE_PARCEL_READER(Int8,jbyte)
356 DEFINE_PARCEL_READER(Int16,jshort)
357 DEFINE_PARCEL_READER(Int32,jint)
358 DEFINE_PARCEL_READER(Int64,jlong)
359 DEFINE_PARCEL_READER(Float,jfloat)
360 DEFINE_PARCEL_READER(Double,jdouble)
361 
362 static 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 
JHwParcel_native_writeStatus(JNIEnv * env,jobject thiz,jint statusCode)373 static 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 
392     status_t err = ::android::hardware::writeToParcel(status, parcel);
393     signalExceptionForError(env, err);
394 }
395 
JHwParcel_native_verifySuccess(JNIEnv * env,jobject thiz)396 static 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;
403     status_t err = ::android::hardware::readFromParcel(&status, *parcel);
404     signalExceptionForError(env, err);
405 }
406 
JHwParcel_native_release(JNIEnv * env,jobject thiz)407 static void JHwParcel_native_release(
408         JNIEnv *env, jobject thiz) {
409     JHwParcel::GetNativeContext(env, thiz)->setParcel(NULL, false /* assumeOwnership */);
410 }
411 
JHwParcel_native_releaseTemporaryStorage(JNIEnv * env,jobject thiz)412 static void JHwParcel_native_releaseTemporaryStorage(
413         JNIEnv *env, jobject thiz) {
414     JHwParcel::GetNativeContext(env, thiz)->getStorage()->release(env);
415 }
416 
JHwParcel_native_send(JNIEnv * env,jobject thiz)417 static void JHwParcel_native_send(JNIEnv *env, jobject thiz) {
418     JHwParcel::GetNativeContext(env, thiz)->send();
419 }
420 
JHwParcel_native_writeString(JNIEnv * env,jobject thiz,jstring valObj)421 static void JHwParcel_native_writeString(
422         JNIEnv *env, jobject thiz, jstring valObj) {
423     if (valObj == NULL) {
424         jniThrowException(env, "java/lang/NullPointerException", NULL);
425         return;
426     }
427 
428     sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz);
429 
430     const hidl_string *s =
431         impl->getStorage()->allocTemporaryString(env, valObj);
432 
433     hardware::Parcel *parcel = impl->getParcel();
434 
435     size_t parentHandle;
436     status_t err = parcel->writeBuffer(s, sizeof(*s), &parentHandle);
437 
438     if (err == OK) {
439         err = ::android::hardware::writeEmbeddedToParcel(
440                 *s, parcel, parentHandle, 0 /* parentOffset */);
441     }
442 
443     signalExceptionForError(env, err);
444 }
445 
446 #define DEFINE_PARCEL_VECTOR_WRITER(Suffix,Type)                               \
447 static void JHwParcel_native_write ## Suffix ## Vector(                        \
448         JNIEnv *env, jobject thiz, Type ## Array valObj) {                     \
449     if (valObj == NULL) {                                                      \
450         jniThrowException(env, "java/lang/NullPointerException", NULL);        \
451         return;                                                                \
452     }                                                                          \
453                                                                                \
454     sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz);               \
455                                                                                \
456     const hidl_vec<Type> *vec =                                                \
457         impl->getStorage()->allocTemporary ## Suffix ## Vector(env, valObj);   \
458                                                                                \
459     hardware::Parcel *parcel = impl->getParcel();                              \
460                                                                                \
461     size_t parentHandle;                                                       \
462     status_t err = parcel->writeBuffer(vec, sizeof(*vec), &parentHandle);      \
463                                                                                \
464     if (err == OK) {                                                           \
465         size_t childHandle;                                                    \
466                                                                                \
467         err = ::android::hardware::writeEmbeddedToParcel(                      \
468                 *vec,                                                          \
469                 parcel,                                                        \
470                 parentHandle,                                                  \
471                 0 /* parentOffset */,                                          \
472                 &childHandle);                                                 \
473     }                                                                          \
474                                                                                \
475     signalExceptionForError(env, err);                                         \
476 }
477 
DEFINE_PARCEL_VECTOR_WRITER(Int8,jbyte)478 DEFINE_PARCEL_VECTOR_WRITER(Int8,jbyte)
479 DEFINE_PARCEL_VECTOR_WRITER(Int16,jshort)
480 DEFINE_PARCEL_VECTOR_WRITER(Int32,jint)
481 DEFINE_PARCEL_VECTOR_WRITER(Int64,jlong)
482 DEFINE_PARCEL_VECTOR_WRITER(Float,jfloat)
483 DEFINE_PARCEL_VECTOR_WRITER(Double,jdouble)
484 
485 static void JHwParcel_native_writeBoolVector(
486         JNIEnv *env, jobject thiz, jbooleanArray valObj) {
487     if (valObj == NULL) {
488         jniThrowException(env, "java/lang/NullPointerException", NULL);
489         return;
490     }
491 
492     sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz);
493 
494     void *vecPtr =
495         impl->getStorage()->allocTemporaryStorage(sizeof(hidl_vec<bool>));
496 
497     hidl_vec<bool> *vec = new (vecPtr) hidl_vec<bool>;
498 
499     jsize len = env->GetArrayLength(valObj);
500 
501     jboolean *src = env->GetBooleanArrayElements(valObj, nullptr);
502 
503     bool *dst =
504         (bool *)impl->getStorage()->allocTemporaryStorage(len * sizeof(bool));
505 
506     for (jsize i = 0; i < len; ++i) {
507         dst[i] = src[i];
508     }
509 
510     env->ReleaseBooleanArrayElements(valObj, src, 0 /* mode */);
511     src = nullptr;
512 
513     vec->setToExternal(dst, len);
514 
515     hardware::Parcel *parcel = impl->getParcel();
516 
517     size_t parentHandle;
518     status_t err = parcel->writeBuffer(vec, sizeof(*vec), &parentHandle);
519 
520     if (err == OK) {
521         size_t childHandle;
522 
523         err = ::android::hardware::writeEmbeddedToParcel(
524                 *vec,
525                 parcel,
526                 parentHandle,
527                 0 /* parentOffset */,
528                 &childHandle);
529     }
530 
531     signalExceptionForError(env, err);
532 }
533 
JHwParcel_native_writeStrongBinder(JNIEnv * env,jobject thiz,jobject binderObj)534 static void JHwParcel_native_writeStrongBinder(
535         JNIEnv *env, jobject thiz, jobject binderObj) {
536     sp<hardware::IBinder> binder;
537     if (binderObj != NULL) {
538         ScopedLocalRef<jclass> hwBinderKlass(
539                 env, FindClassOrDie(env, PACKAGE_PATH "/HwBinder"));
540 
541         ScopedLocalRef<jclass> hwRemoteBinderKlass(
542                 env, FindClassOrDie(env, PACKAGE_PATH "/HwRemoteBinder"));
543 
544         if (env->IsInstanceOf(binderObj, hwBinderKlass.get())) {
545             binder = JHwBinder::GetNativeContext(env, binderObj);
546         } else if (env->IsInstanceOf(binderObj, hwRemoteBinderKlass.get())) {
547             binder = JHwRemoteBinder::GetNativeContext(
548                     env, binderObj)->getBinder();
549         } else {
550             signalExceptionForError(env, INVALID_OPERATION);
551             return;
552         }
553     }
554 
555     hardware::Parcel *parcel =
556         JHwParcel::GetNativeContext(env, thiz)->getParcel();
557 
558     status_t err = parcel->writeStrongBinder(binder);
559     signalExceptionForError(env, err);
560 }
561 
MakeStringObjFromHidlString(JNIEnv * env,const hidl_string & s)562 static jstring MakeStringObjFromHidlString(JNIEnv *env, const hidl_string &s) {
563     String16 utf16String(s.c_str(), s.size());
564 
565     return env->NewString(
566             reinterpret_cast<const jchar *>(utf16String.string()),
567             utf16String.size());
568 }
569 
JHwParcel_native_readString(JNIEnv * env,jobject thiz)570 static jstring JHwParcel_native_readString(JNIEnv *env, jobject thiz) {
571     hardware::Parcel *parcel =
572         JHwParcel::GetNativeContext(env, thiz)->getParcel();
573 
574     size_t parentHandle;
575 
576     const hidl_string *s;
577     status_t err = parcel->readBuffer(sizeof(*s), &parentHandle,
578             reinterpret_cast<const void**>(&s));
579 
580     if (err != OK) {
581         signalExceptionForError(env, err);
582         return NULL;
583     }
584 
585     err = ::android::hardware::readEmbeddedFromParcel(
586             const_cast<hidl_string &>(*s),
587             *parcel, parentHandle, 0 /* parentOffset */);
588 
589     if (err != OK) {
590         signalExceptionForError(env, err);
591         return NULL;
592     }
593 
594     return MakeStringObjFromHidlString(env, *s);
595 }
596 
597 #define DEFINE_PARCEL_VECTOR_READER(Suffix,Type,NewType)                       \
598 static Type ## Array JHwParcel_native_read ## Suffix ## Vector(                \
599         JNIEnv *env, jobject thiz) {                                           \
600     hardware::Parcel *parcel =                                                 \
601         JHwParcel::GetNativeContext(env, thiz)->getParcel();                   \
602     size_t parentHandle;                                                       \
603                                                                                \
604     const hidl_vec<Type> *vec;                                                 \
605     status_t err = parcel->readBuffer(sizeof(*vec), &parentHandle,             \
606             reinterpret_cast<const void**>(&vec));                             \
607                                                                                \
608     if (err != OK) {                                                           \
609         signalExceptionForError(env, err);                                     \
610         return NULL;                                                           \
611     }                                                                          \
612                                                                                \
613     size_t childHandle;                                                        \
614                                                                                \
615     err = ::android::hardware::readEmbeddedFromParcel(                         \
616                 const_cast<hidl_vec<Type> &>(*vec),                            \
617                 *parcel,                                                       \
618                 parentHandle,                                                  \
619                 0 /* parentOffset */,                                          \
620                 &childHandle);                                                 \
621                                                                                \
622     if (err != OK) {                                                           \
623         signalExceptionForError(env, err);                                     \
624         return NULL;                                                           \
625     }                                                                          \
626                                                                                \
627     Type ## Array valObj = env->New ## NewType ## Array(vec->size());          \
628     env->Set ## NewType ## ArrayRegion(valObj, 0, vec->size(), &(*vec)[0]);    \
629                                                                                \
630     return valObj;                                                             \
631 }
632 
DEFINE_PARCEL_VECTOR_READER(Int8,jbyte,Byte)633 DEFINE_PARCEL_VECTOR_READER(Int8,jbyte,Byte)
634 DEFINE_PARCEL_VECTOR_READER(Int16,jshort,Short)
635 DEFINE_PARCEL_VECTOR_READER(Int32,jint,Int)
636 DEFINE_PARCEL_VECTOR_READER(Int64,jlong,Long)
637 DEFINE_PARCEL_VECTOR_READER(Float,jfloat,Float)
638 DEFINE_PARCEL_VECTOR_READER(Double,jdouble,Double)
639 
640 static jbooleanArray JHwParcel_native_readBoolVector(
641         JNIEnv *env, jobject thiz) {
642     hardware::Parcel *parcel =
643         JHwParcel::GetNativeContext(env, thiz)->getParcel();
644 
645     size_t parentHandle;
646 
647     const hidl_vec<bool> *vec;
648     status_t err = parcel->readBuffer(sizeof(*vec), &parentHandle,
649             reinterpret_cast<const void**>(&vec));
650 
651     if (err != OK) {
652         signalExceptionForError(env, err);
653         return NULL;
654     }
655 
656     size_t childHandle;
657 
658     err = ::android::hardware::readEmbeddedFromParcel(
659                 const_cast<hidl_vec<bool> &>(*vec),
660                 *parcel,
661                 parentHandle,
662                 0 /* parentOffset */,
663                 &childHandle);
664 
665     if (err != OK) {
666         signalExceptionForError(env, err);
667         return NULL;
668     }
669 
670     jbooleanArray valObj = env->NewBooleanArray(vec->size());
671 
672     for (size_t i = 0; i < vec->size(); ++i) {
673         jboolean x = (*vec)[i];
674         env->SetBooleanArrayRegion(valObj, i, 1, &x);
675     }
676 
677     return valObj;
678 }
679 
MakeStringArray(JNIEnv * env,const hidl_string * array,size_t size)680 static jobjectArray MakeStringArray(
681         JNIEnv *env, const hidl_string *array, size_t size) {
682     ScopedLocalRef<jclass> stringKlass(
683             env,
684             env->FindClass("java/lang/String"));
685 
686     // XXX Why can't I use ScopedLocalRef<> for the arrayObj and the stringObjs?
687 
688     jobjectArray arrayObj = env->NewObjectArray(size, stringKlass.get(), NULL);
689 
690     for (size_t i = 0; i < size; ++i) {
691         jstring stringObj = MakeStringObjFromHidlString(env, array[i]);
692 
693         env->SetObjectArrayElement(
694                 arrayObj,
695                 i,
696                 stringObj);
697     }
698 
699     return arrayObj;
700 }
701 
JHwParcel_native_readStringVector(JNIEnv * env,jobject thiz)702 static jobjectArray JHwParcel_native_readStringVector(
703         JNIEnv *env, jobject thiz) {
704     typedef hidl_vec<hidl_string> string_vec;
705 
706     hardware::Parcel *parcel =
707         JHwParcel::GetNativeContext(env, thiz)->getParcel();
708 
709     size_t parentHandle;
710 
711     const string_vec *vec;
712     status_t err = parcel->readBuffer(sizeof(*vec), &parentHandle,
713             reinterpret_cast<const void **>(&vec));
714 
715     if (err != OK) {
716         signalExceptionForError(env, err);
717         return NULL;
718     }
719 
720     size_t childHandle;
721     err = ::android::hardware::readEmbeddedFromParcel(
722             const_cast<string_vec &>(*vec),
723             *parcel, parentHandle, 0 /* parentOffset */, &childHandle);
724 
725     for (size_t i = 0; (err == OK) && (i < vec->size()); ++i) {
726         err = android::hardware::readEmbeddedFromParcel(
727                     const_cast<hidl_string &>((*vec)[i]),
728                     *parcel,
729                     childHandle,
730                     i * sizeof(hidl_string) /* parentOffset */);
731     }
732 
733     if (err != OK) {
734         signalExceptionForError(env, err);
735         return NULL;
736     }
737 
738     return MakeStringArray(env, &(*vec)[0], vec->size());
739 }
740 
JHwParcel_native_writeStringVector(JNIEnv * env,jobject thiz,jobjectArray arrayObj)741 static void JHwParcel_native_writeStringVector(
742         JNIEnv *env, jobject thiz, jobjectArray arrayObj) {
743     typedef hidl_vec<hidl_string> string_vec;
744 
745     if (arrayObj == NULL) {
746         jniThrowException(env, "java/lang/NullPointerException", NULL);
747         return;
748     }
749 
750     jsize len = env->GetArrayLength(arrayObj);
751 
752     sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz);
753 
754     void *vecPtr =
755         impl->getStorage()->allocTemporaryStorage(sizeof(string_vec));
756 
757     string_vec *vec = new (vecPtr) string_vec;
758 
759     hidl_string *strings = impl->getStorage()->allocStringArray(len);
760     vec->setToExternal(strings, len);
761 
762     for (jsize i = 0; i < len; ++i) {
763         ScopedLocalRef<jstring> stringObj(
764                 env,
765                 (jstring)env->GetObjectArrayElement(arrayObj, i));
766 
767         const hidl_string *s =
768             impl->getStorage()->allocTemporaryString(env, stringObj.get());
769 
770         strings[i].setToExternal(s->c_str(), s->size());
771     }
772 
773     hardware::Parcel *parcel = impl->getParcel();
774 
775     size_t parentHandle;
776     status_t err = parcel->writeBuffer(vec, sizeof(*vec), &parentHandle);
777 
778     if (err == OK) {
779         size_t childHandle;
780         err = ::android::hardware::writeEmbeddedToParcel(
781                 *vec,
782                 parcel,
783                 parentHandle,
784                 0 /* parentOffset */,
785                 &childHandle);
786 
787         for (size_t i = 0; (err == OK) && (i < vec->size()); ++i) {
788             err = ::android::hardware::writeEmbeddedToParcel(
789                     (*vec)[i],
790                     parcel,
791                     childHandle,
792                     i * sizeof(hidl_string));
793         }
794     }
795 
796     signalExceptionForError(env, err);
797 }
798 
JHwParcel_native_readStrongBinder(JNIEnv * env,jobject thiz)799 static jobject JHwParcel_native_readStrongBinder(JNIEnv *env, jobject thiz) {
800     hardware::Parcel *parcel =
801         JHwParcel::GetNativeContext(env, thiz)->getParcel();
802 
803     sp<hardware::IBinder> binder = parcel->readStrongBinder();
804 
805     if (binder == NULL) {
806         return NULL;
807     }
808 
809     return JHwRemoteBinder::NewObject(env, binder);
810 }
811 
JHwParcel_native_readBuffer(JNIEnv * env,jobject thiz,jlong expectedSize)812 static jobject JHwParcel_native_readBuffer(JNIEnv *env, jobject thiz,
813                                            jlong expectedSize) {
814     hardware::Parcel *parcel =
815         JHwParcel::GetNativeContext(env, thiz)->getParcel();
816 
817     size_t handle;
818     const void *ptr;
819 
820     if (expectedSize < 0) {
821         jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
822         return nullptr;
823     }
824 
825     status_t status = parcel->readBuffer(expectedSize, &handle, &ptr);
826 
827     if (status != OK) {
828         jniThrowException(env, "java/util/NoSuchElementException", NULL);
829         return nullptr;
830     }
831 
832     return JHwBlob::NewObject(env, ptr, handle);
833 }
834 
JHwParcel_native_readEmbeddedBuffer(JNIEnv * env,jobject thiz,jlong expectedSize,jlong parentHandle,jlong offset,jboolean nullable)835 static jobject JHwParcel_native_readEmbeddedBuffer(
836         JNIEnv *env, jobject thiz, jlong expectedSize,
837         jlong parentHandle, jlong offset, jboolean nullable) {
838     hardware::Parcel *parcel =
839         JHwParcel::GetNativeContext(env, thiz)->getParcel();
840 
841     size_t childHandle;
842 
843     const void *ptr;
844     status_t status =
845         parcel->readNullableEmbeddedBuffer(expectedSize,
846                 &childHandle, parentHandle, offset, &ptr);
847 
848     if (expectedSize < 0) {
849         jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
850         return nullptr;
851     }
852 
853     if (status != OK) {
854         jniThrowException(env, "java/util/NoSuchElementException", NULL);
855         return 0;
856     } else if (status == OK && !nullable && ptr == nullptr) {
857         jniThrowException(env, "java/lang/NullPointerException", NULL);
858         return 0;
859     }
860 
861     return JHwBlob::NewObject(env, ptr, childHandle);
862 }
863 
JHwParcel_native_writeBuffer(JNIEnv * env,jobject thiz,jobject blobObj)864 static void JHwParcel_native_writeBuffer(
865         JNIEnv *env, jobject thiz, jobject blobObj) {
866     if (blobObj == nullptr) {
867         jniThrowException(env, "java/lang/NullPointerException", NULL);
868         return;
869     }
870 
871     hardware::Parcel *parcel =
872         JHwParcel::GetNativeContext(env, thiz)->getParcel();
873 
874     sp<JHwBlob> blob = JHwBlob::GetNativeContext(env, blobObj);
875     status_t err = blob->writeToParcel(parcel);
876 
877     if (err != OK) {
878         signalExceptionForError(env, err);
879     }
880 }
881 
882 static JNINativeMethod gMethods[] = {
883     { "native_init", "()J", (void *)JHwParcel_native_init },
884     { "native_setup", "(Z)V", (void *)JHwParcel_native_setup },
885 
886     { "writeInterfaceToken", "(Ljava/lang/String;)V",
887         (void *)JHwParcel_native_writeInterfaceToken },
888 
889     { "writeBool", "(Z)V", (void *)JHwParcel_native_writeBool },
890     { "writeInt8", "(B)V", (void *)JHwParcel_native_writeInt8 },
891     { "writeInt16", "(S)V", (void *)JHwParcel_native_writeInt16 },
892     { "writeInt32", "(I)V", (void *)JHwParcel_native_writeInt32 },
893     { "writeInt64", "(J)V", (void *)JHwParcel_native_writeInt64 },
894     { "writeFloat", "(F)V", (void *)JHwParcel_native_writeFloat },
895     { "writeDouble", "(D)V", (void *)JHwParcel_native_writeDouble },
896 
897     { "writeString", "(Ljava/lang/String;)V",
898         (void *)JHwParcel_native_writeString },
899 
900     { "writeBoolVector", "([Z)V", (void *)JHwParcel_native_writeBoolVector },
901     { "writeInt8Vector", "([B)V", (void *)JHwParcel_native_writeInt8Vector },
902     { "writeInt16Vector", "([S)V", (void *)JHwParcel_native_writeInt16Vector },
903     { "writeInt32Vector", "([I)V", (void *)JHwParcel_native_writeInt32Vector },
904     { "writeInt64Vector", "([J)V", (void *)JHwParcel_native_writeInt64Vector },
905     { "writeFloatVector", "([F)V", (void *)JHwParcel_native_writeFloatVector },
906 
907     { "writeDoubleVector", "([D)V",
908         (void *)JHwParcel_native_writeDoubleVector },
909 
910     { "writeStringVector", "([Ljava/lang/String;)V",
911         (void *)JHwParcel_native_writeStringVector },
912 
913     { "writeStrongBinder", "(L" PACKAGE_PATH "/IHwBinder;)V",
914         (void *)JHwParcel_native_writeStrongBinder },
915 
916     { "enforceInterface", "(Ljava/lang/String;)V",
917         (void *)JHwParcel_native_enforceInterface },
918 
919     { "readBool", "()Z", (void *)JHwParcel_native_readBool },
920     { "readInt8", "()B", (void *)JHwParcel_native_readInt8 },
921     { "readInt16", "()S", (void *)JHwParcel_native_readInt16 },
922     { "readInt32", "()I", (void *)JHwParcel_native_readInt32 },
923     { "readInt64", "()J", (void *)JHwParcel_native_readInt64 },
924     { "readFloat", "()F", (void *)JHwParcel_native_readFloat },
925     { "readDouble", "()D", (void *)JHwParcel_native_readDouble },
926 
927     { "readString", "()Ljava/lang/String;",
928         (void *)JHwParcel_native_readString },
929 
930     { "readBoolVectorAsArray", "()[Z",
931         (void *)JHwParcel_native_readBoolVector },
932 
933     { "readInt8VectorAsArray", "()[B",
934         (void *)JHwParcel_native_readInt8Vector },
935 
936     { "readInt16VectorAsArray", "()[S",
937         (void *)JHwParcel_native_readInt16Vector },
938 
939     { "readInt32VectorAsArray", "()[I",
940         (void *)JHwParcel_native_readInt32Vector },
941 
942     { "readInt64VectorAsArray", "()[J",
943         (void *)JHwParcel_native_readInt64Vector },
944 
945     { "readFloatVectorAsArray", "()[F",
946         (void *)JHwParcel_native_readFloatVector },
947 
948     { "readDoubleVectorAsArray", "()[D",
949         (void *)JHwParcel_native_readDoubleVector },
950 
951     { "readStringVectorAsArray", "()[Ljava/lang/String;",
952         (void *)JHwParcel_native_readStringVector },
953 
954     { "readStrongBinder", "()L" PACKAGE_PATH "/IHwBinder;",
955         (void *)JHwParcel_native_readStrongBinder },
956 
957     { "writeStatus", "(I)V", (void *)JHwParcel_native_writeStatus },
958 
959     { "verifySuccess", "()V", (void *)JHwParcel_native_verifySuccess },
960 
961     { "releaseTemporaryStorage", "()V",
962         (void *)JHwParcel_native_releaseTemporaryStorage },
963 
964     { "send", "()V", (void *)JHwParcel_native_send },
965 
966     { "readBuffer", "(J)L" PACKAGE_PATH "/HwBlob;",
967         (void *)JHwParcel_native_readBuffer },
968 
969     { "readEmbeddedBuffer", "(JJJZ)L" PACKAGE_PATH "/HwBlob;",
970         (void *)JHwParcel_native_readEmbeddedBuffer },
971 
972     { "writeBuffer", "(L" PACKAGE_PATH "/HwBlob;)V",
973         (void *)JHwParcel_native_writeBuffer },
974 
975     { "release", "()V",
976         (void *)JHwParcel_native_release },
977 
978 };
979 
980 namespace android {
981 
register_android_os_HwParcel(JNIEnv * env)982 int register_android_os_HwParcel(JNIEnv *env) {
983     return RegisterMethodsOrDie(env, CLASS_PATH, gMethods, NELEM(gMethods));
984 }
985 
986 }  // namespace android
987