• 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 <nativehelper/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 }
170 
~JHwParcel()171 JHwParcel::~JHwParcel() {
172     JNIEnv *env = AndroidRuntime::getJNIEnv();
173 
174     mStorage.release(env);
175 
176     setParcel(NULL, false /* assumeOwnership */);
177 }
178 
getParcel()179 hardware::Parcel *JHwParcel::getParcel() {
180     return mParcel;
181 }
182 
getStorage()183 EphemeralStorage *JHwParcel::getStorage() {
184     return &mStorage;
185 }
186 
setParcel(hardware::Parcel * parcel,bool assumeOwnership)187 void JHwParcel::setParcel(hardware::Parcel *parcel, bool assumeOwnership) {
188     if (mParcel && mOwnsParcel) {
189         delete mParcel;
190     }
191 
192     mParcel = parcel;
193     mOwnsParcel = assumeOwnership;
194 }
195 
196 // static
NewObject(JNIEnv * env)197 jobject JHwParcel::NewObject(JNIEnv *env) {
198     ScopedLocalRef<jclass> clazz(env, FindClassOrDie(env, CLASS_PATH));
199 
200     jmethodID constructID =
201         GetMethodIDOrDie(env, clazz.get(), "<init>", "(Z)V");
202 
203     return env->NewObject(clazz.get(), constructID, false /* allocate */);
204 }
205 
setTransactCallback(::android::hardware::IBinder::TransactCallback cb)206 void JHwParcel::setTransactCallback(
207         ::android::hardware::IBinder::TransactCallback cb) {
208     mTransactCallback = cb;
209 }
210 
send()211 void JHwParcel::send() {
212     CHECK(mTransactCallback != nullptr);
213     CHECK(mParcel != nullptr);
214 
215     mTransactCallback(*mParcel);
216     mTransactCallback = nullptr;
217 
218     mWasSent = true;
219 }
220 
wasSent() const221 bool JHwParcel::wasSent() const {
222     return mWasSent;
223 }
224 
225 }  // namespace android
226 
227 ////////////////////////////////////////////////////////////////////////////////
228 
229 using namespace android;
230 
releaseNativeContext(void * nativeContext)231 static void releaseNativeContext(void *nativeContext) {
232     sp<JHwParcel> parcel = (JHwParcel *)nativeContext;
233 
234     if (parcel != NULL) {
235         parcel->decStrong(NULL /* id */);
236     }
237 }
238 
JHwParcel_native_init(JNIEnv * env)239 static jlong JHwParcel_native_init(JNIEnv *env) {
240     JHwParcel::InitClass(env);
241 
242     return reinterpret_cast<jlong>(&releaseNativeContext);
243 }
244 
JHwParcel_native_setup(JNIEnv * env,jobject thiz,jboolean allocate)245 static void JHwParcel_native_setup(
246         JNIEnv *env, jobject thiz, jboolean allocate) {
247     sp<JHwParcel> context = new JHwParcel(env, thiz);
248 
249     if (allocate) {
250         context->setParcel(new hardware::Parcel, true /* assumeOwnership */);
251     }
252 
253     JHwParcel::SetNativeContext(env, thiz, context);
254 }
255 
JHwParcel_native_writeInterfaceToken(JNIEnv * env,jobject thiz,jstring interfaceNameObj)256 static void JHwParcel_native_writeInterfaceToken(
257         JNIEnv *env, jobject thiz, jstring interfaceNameObj) {
258     if (interfaceNameObj == NULL) {
259         jniThrowException(env, "java/lang/NullPointerException", NULL);
260         return;
261     }
262 
263     const jchar *interfaceName = env->GetStringCritical(interfaceNameObj, NULL);
264     if (interfaceName) {
265         String8 nameCopy = String8(String16(
266                 reinterpret_cast<const char16_t *>(interfaceName),
267                 env->GetStringLength(interfaceNameObj)));
268 
269         env->ReleaseStringCritical(interfaceNameObj, interfaceName);
270         interfaceName = NULL;
271 
272         hardware::Parcel *parcel =
273             JHwParcel::GetNativeContext(env, thiz)->getParcel();
274 
275         status_t err = parcel->writeInterfaceToken(nameCopy.string());
276         signalExceptionForError(env, err);
277     }
278 }
279 
JHwParcel_native_enforceInterface(JNIEnv * env,jobject thiz,jstring interfaceNameObj)280 static void JHwParcel_native_enforceInterface(
281         JNIEnv *env, jobject thiz, jstring interfaceNameObj) {
282     // XXX original binder Parcel enforceInterface implementation does some
283     // mysterious things regarding strictModePolicy(), figure out if we need
284     // that here as well.
285     if (interfaceNameObj == NULL) {
286         jniThrowException(env, "java/lang/NullPointerException", NULL);
287         return;
288     }
289 
290     const jchar *interfaceName = env->GetStringCritical(interfaceNameObj, NULL);
291     if (interfaceName) {
292         String8 interfaceNameCopy = String8(String16(
293                 reinterpret_cast<const char16_t *>(interfaceName),
294                 env->GetStringLength(interfaceNameObj)));
295 
296         env->ReleaseStringCritical(interfaceNameObj, interfaceName);
297         interfaceName = NULL;
298 
299         hardware::Parcel *parcel =
300             JHwParcel::GetNativeContext(env, thiz)->getParcel();
301 
302         bool valid = parcel->enforceInterface(interfaceNameCopy.string());
303 
304         if (!valid) {
305             jniThrowException(
306                     env,
307                     "java/lang/SecurityException",
308                     "HWBinder invocation to an incorrect interface");
309         }
310     }
311 }
312 
313 #define DEFINE_PARCEL_WRITER(Suffix,Type)                               \
314 static void JHwParcel_native_write ## Suffix(                           \
315         JNIEnv *env, jobject thiz, Type val) {                          \
316     hardware::Parcel *parcel =                                          \
317         JHwParcel::GetNativeContext(env, thiz)->getParcel();            \
318                                                                         \
319     status_t err = parcel->write ## Suffix(val);                        \
320     signalExceptionForError(env, err);                                  \
321 }
322 
323 #define DEFINE_PARCEL_READER(Suffix,Type)                               \
324 static Type JHwParcel_native_read ## Suffix(                            \
325         JNIEnv *env, jobject thiz) {                                    \
326     hardware::Parcel *parcel =                                          \
327         JHwParcel::GetNativeContext(env, thiz)->getParcel();            \
328                                                                         \
329     Type val;                                                           \
330     status_t err = parcel->read ## Suffix(&val);                        \
331     signalExceptionForError(env, err);                                  \
332                                                                         \
333     return val;                                                         \
334 }
335 
DEFINE_PARCEL_WRITER(Bool,jboolean)336 DEFINE_PARCEL_WRITER(Bool,jboolean)
337 DEFINE_PARCEL_WRITER(Int8,jbyte)
338 DEFINE_PARCEL_WRITER(Int16,jshort)
339 DEFINE_PARCEL_WRITER(Int32,jint)
340 DEFINE_PARCEL_WRITER(Int64,jlong)
341 DEFINE_PARCEL_WRITER(Float,jfloat)
342 DEFINE_PARCEL_WRITER(Double,jdouble)
343 
344 DEFINE_PARCEL_READER(Int8,jbyte)
345 DEFINE_PARCEL_READER(Int16,jshort)
346 DEFINE_PARCEL_READER(Int32,jint)
347 DEFINE_PARCEL_READER(Int64,jlong)
348 DEFINE_PARCEL_READER(Float,jfloat)
349 DEFINE_PARCEL_READER(Double,jdouble)
350 
351 static jboolean JHwParcel_native_readBool(JNIEnv *env, jobject thiz) {
352     hardware::Parcel *parcel =
353         JHwParcel::GetNativeContext(env, thiz)->getParcel();
354 
355     bool val;
356     status_t err = parcel->readBool(&val);
357     signalExceptionForError(env, err);
358 
359     return (jboolean)val;
360 }
361 
JHwParcel_native_writeStatus(JNIEnv * env,jobject thiz,jint statusCode)362 static void JHwParcel_native_writeStatus(
363         JNIEnv *env, jobject thiz, jint statusCode) {
364     using hardware::Status;
365 
366     Status status;
367     switch (statusCode) {
368         case 0:  // kStatusSuccess
369             status = Status::ok();
370             break;
371         case -1:  // kStatusError
372             status = Status::fromStatusT(UNKNOWN_ERROR);
373             break;
374         default:
375             CHECK(!"Should not be here");
376     }
377 
378     hardware::Parcel *parcel =
379         JHwParcel::GetNativeContext(env, thiz)->getParcel();
380 
381     status_t err = ::android::hardware::writeToParcel(status, parcel);
382     signalExceptionForError(env, err);
383 }
384 
JHwParcel_native_verifySuccess(JNIEnv * env,jobject thiz)385 static void JHwParcel_native_verifySuccess(JNIEnv *env, jobject thiz) {
386     using hardware::Status;
387 
388     hardware::Parcel *parcel =
389         JHwParcel::GetNativeContext(env, thiz)->getParcel();
390 
391     Status status;
392     status_t err = ::android::hardware::readFromParcel(&status, *parcel);
393     signalExceptionForError(env, err);
394 }
395 
JHwParcel_native_release(JNIEnv * env,jobject thiz)396 static void JHwParcel_native_release(
397         JNIEnv *env, jobject thiz) {
398     JHwParcel::GetNativeContext(env, thiz)->setParcel(NULL, false /* assumeOwnership */);
399 }
400 
JHwParcel_native_releaseTemporaryStorage(JNIEnv * env,jobject thiz)401 static void JHwParcel_native_releaseTemporaryStorage(
402         JNIEnv *env, jobject thiz) {
403     JHwParcel::GetNativeContext(env, thiz)->getStorage()->release(env);
404 }
405 
JHwParcel_native_send(JNIEnv * env,jobject thiz)406 static void JHwParcel_native_send(JNIEnv *env, jobject thiz) {
407     JHwParcel::GetNativeContext(env, thiz)->send();
408 }
409 
JHwParcel_native_writeString(JNIEnv * env,jobject thiz,jstring valObj)410 static void JHwParcel_native_writeString(
411         JNIEnv *env, jobject thiz, jstring valObj) {
412     if (valObj == NULL) {
413         jniThrowException(env, "java/lang/NullPointerException", NULL);
414         return;
415     }
416 
417     sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz);
418 
419     const hidl_string *s =
420         impl->getStorage()->allocTemporaryString(env, valObj);
421 
422     hardware::Parcel *parcel = impl->getParcel();
423 
424     size_t parentHandle;
425     status_t err = parcel->writeBuffer(s, sizeof(*s), &parentHandle);
426 
427     if (err == OK) {
428         err = ::android::hardware::writeEmbeddedToParcel(
429                 *s, parcel, parentHandle, 0 /* parentOffset */);
430     }
431 
432     signalExceptionForError(env, err);
433 }
434 
435 #define DEFINE_PARCEL_VECTOR_WRITER(Suffix,Type)                               \
436 static void JHwParcel_native_write ## Suffix ## Vector(                        \
437         JNIEnv *env, jobject thiz, Type ## Array valObj) {                     \
438     if (valObj == NULL) {                                                      \
439         jniThrowException(env, "java/lang/NullPointerException", NULL);        \
440         return;                                                                \
441     }                                                                          \
442                                                                                \
443     sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz);               \
444                                                                                \
445     const hidl_vec<Type> *vec =                                                \
446         impl->getStorage()->allocTemporary ## Suffix ## Vector(env, valObj);   \
447                                                                                \
448     hardware::Parcel *parcel = impl->getParcel();                              \
449                                                                                \
450     size_t parentHandle;                                                       \
451     status_t err = parcel->writeBuffer(vec, sizeof(*vec), &parentHandle);      \
452                                                                                \
453     if (err == OK) {                                                           \
454         size_t childHandle;                                                    \
455                                                                                \
456         err = ::android::hardware::writeEmbeddedToParcel(                      \
457                 *vec,                                                          \
458                 parcel,                                                        \
459                 parentHandle,                                                  \
460                 0 /* parentOffset */,                                          \
461                 &childHandle);                                                 \
462     }                                                                          \
463                                                                                \
464     signalExceptionForError(env, err);                                         \
465 }
466 
DEFINE_PARCEL_VECTOR_WRITER(Int8,jbyte)467 DEFINE_PARCEL_VECTOR_WRITER(Int8,jbyte)
468 DEFINE_PARCEL_VECTOR_WRITER(Int16,jshort)
469 DEFINE_PARCEL_VECTOR_WRITER(Int32,jint)
470 DEFINE_PARCEL_VECTOR_WRITER(Int64,jlong)
471 DEFINE_PARCEL_VECTOR_WRITER(Float,jfloat)
472 DEFINE_PARCEL_VECTOR_WRITER(Double,jdouble)
473 
474 static void JHwParcel_native_writeBoolVector(
475         JNIEnv *env, jobject thiz, jbooleanArray valObj) {
476     if (valObj == NULL) {
477         jniThrowException(env, "java/lang/NullPointerException", NULL);
478         return;
479     }
480 
481     sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz);
482 
483     void *vecPtr =
484         impl->getStorage()->allocTemporaryStorage(sizeof(hidl_vec<bool>));
485 
486     hidl_vec<bool> *vec = new (vecPtr) hidl_vec<bool>;
487 
488     jsize len = env->GetArrayLength(valObj);
489 
490     jboolean *src = env->GetBooleanArrayElements(valObj, nullptr);
491 
492     bool *dst =
493         (bool *)impl->getStorage()->allocTemporaryStorage(len * sizeof(bool));
494 
495     for (jsize i = 0; i < len; ++i) {
496         dst[i] = src[i];
497     }
498 
499     env->ReleaseBooleanArrayElements(valObj, src, 0 /* mode */);
500     src = nullptr;
501 
502     vec->setToExternal(dst, len);
503 
504     hardware::Parcel *parcel = impl->getParcel();
505 
506     size_t parentHandle;
507     status_t err = parcel->writeBuffer(vec, sizeof(*vec), &parentHandle);
508 
509     if (err == OK) {
510         size_t childHandle;
511 
512         err = ::android::hardware::writeEmbeddedToParcel(
513                 *vec,
514                 parcel,
515                 parentHandle,
516                 0 /* parentOffset */,
517                 &childHandle);
518     }
519 
520     signalExceptionForError(env, err);
521 }
522 
JHwParcel_native_writeStrongBinder(JNIEnv * env,jobject thiz,jobject binderObj)523 static void JHwParcel_native_writeStrongBinder(
524         JNIEnv *env, jobject thiz, jobject binderObj) {
525     sp<hardware::IBinder> binder;
526     if (binderObj != NULL) {
527         ScopedLocalRef<jclass> hwBinderKlass(
528                 env, FindClassOrDie(env, PACKAGE_PATH "/HwBinder"));
529 
530         ScopedLocalRef<jclass> hwRemoteBinderKlass(
531                 env, FindClassOrDie(env, PACKAGE_PATH "/HwRemoteBinder"));
532 
533         if (env->IsInstanceOf(binderObj, hwBinderKlass.get())) {
534             binder = JHwBinder::GetNativeBinder(env, binderObj);
535         } else if (env->IsInstanceOf(binderObj, hwRemoteBinderKlass.get())) {
536             binder = JHwRemoteBinder::GetNativeContext(
537                     env, binderObj)->getBinder();
538         } else {
539             signalExceptionForError(env, INVALID_OPERATION);
540             return;
541         }
542     }
543 
544     hardware::Parcel *parcel =
545         JHwParcel::GetNativeContext(env, thiz)->getParcel();
546 
547     status_t err = parcel->writeStrongBinder(binder);
548     signalExceptionForError(env, err);
549 }
550 
MakeStringObjFromHidlString(JNIEnv * env,const hidl_string & s)551 static jstring MakeStringObjFromHidlString(JNIEnv *env, const hidl_string &s) {
552     String16 utf16String(s.c_str(), s.size());
553 
554     return env->NewString(
555             reinterpret_cast<const jchar *>(utf16String.string()),
556             utf16String.size());
557 }
558 
JHwParcel_native_readString(JNIEnv * env,jobject thiz)559 static jstring JHwParcel_native_readString(JNIEnv *env, jobject thiz) {
560     hardware::Parcel *parcel =
561         JHwParcel::GetNativeContext(env, thiz)->getParcel();
562 
563     size_t parentHandle;
564 
565     const hidl_string *s;
566     status_t err = parcel->readBuffer(sizeof(*s), &parentHandle,
567             reinterpret_cast<const void**>(&s));
568 
569     if (err != OK) {
570         signalExceptionForError(env, err);
571         return NULL;
572     }
573 
574     err = ::android::hardware::readEmbeddedFromParcel(
575             const_cast<hidl_string &>(*s),
576             *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 
586 #define DEFINE_PARCEL_VECTOR_READER(Suffix,Type,NewType)                       \
587 static Type ## Array JHwParcel_native_read ## Suffix ## Vector(                \
588         JNIEnv *env, jobject thiz) {                                           \
589     hardware::Parcel *parcel =                                                 \
590         JHwParcel::GetNativeContext(env, thiz)->getParcel();                   \
591     size_t parentHandle;                                                       \
592                                                                                \
593     const hidl_vec<Type> *vec;                                                 \
594     status_t err = parcel->readBuffer(sizeof(*vec), &parentHandle,             \
595             reinterpret_cast<const void**>(&vec));                             \
596                                                                                \
597     if (err != OK) {                                                           \
598         signalExceptionForError(env, err);                                     \
599         return NULL;                                                           \
600     }                                                                          \
601                                                                                \
602     size_t childHandle;                                                        \
603                                                                                \
604     err = ::android::hardware::readEmbeddedFromParcel(                         \
605                 const_cast<hidl_vec<Type> &>(*vec),                            \
606                 *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 
DEFINE_PARCEL_VECTOR_READER(Int8,jbyte,Byte)622 DEFINE_PARCEL_VECTOR_READER(Int8,jbyte,Byte)
623 DEFINE_PARCEL_VECTOR_READER(Int16,jshort,Short)
624 DEFINE_PARCEL_VECTOR_READER(Int32,jint,Int)
625 DEFINE_PARCEL_VECTOR_READER(Int64,jlong,Long)
626 DEFINE_PARCEL_VECTOR_READER(Float,jfloat,Float)
627 DEFINE_PARCEL_VECTOR_READER(Double,jdouble,Double)
628 
629 static 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     status_t err = parcel->readBuffer(sizeof(*vec), &parentHandle,
638             reinterpret_cast<const void**>(&vec));
639 
640     if (err != OK) {
641         signalExceptionForError(env, err);
642         return NULL;
643     }
644 
645     size_t childHandle;
646 
647     err = ::android::hardware::readEmbeddedFromParcel(
648                 const_cast<hidl_vec<bool> &>(*vec),
649                 *parcel,
650                 parentHandle,
651                 0 /* parentOffset */,
652                 &childHandle);
653 
654     if (err != OK) {
655         signalExceptionForError(env, err);
656         return NULL;
657     }
658 
659     jbooleanArray valObj = env->NewBooleanArray(vec->size());
660 
661     for (size_t i = 0; i < vec->size(); ++i) {
662         jboolean x = (*vec)[i];
663         env->SetBooleanArrayRegion(valObj, i, 1, &x);
664     }
665 
666     return valObj;
667 }
668 
MakeStringArray(JNIEnv * env,const hidl_string * array,size_t size)669 static jobjectArray MakeStringArray(
670         JNIEnv *env, const hidl_string *array, size_t size) {
671     ScopedLocalRef<jclass> stringKlass(
672             env,
673             env->FindClass("java/lang/String"));
674 
675     // XXX Why can't I use ScopedLocalRef<> for the arrayObj and the stringObjs?
676 
677     jobjectArray arrayObj = env->NewObjectArray(size, stringKlass.get(), NULL);
678 
679     for (size_t i = 0; i < size; ++i) {
680         jstring stringObj = MakeStringObjFromHidlString(env, array[i]);
681 
682         env->SetObjectArrayElement(
683                 arrayObj,
684                 i,
685                 stringObj);
686     }
687 
688     return arrayObj;
689 }
690 
JHwParcel_native_readStringVector(JNIEnv * env,jobject thiz)691 static jobjectArray JHwParcel_native_readStringVector(
692         JNIEnv *env, jobject thiz) {
693     typedef hidl_vec<hidl_string> string_vec;
694 
695     hardware::Parcel *parcel =
696         JHwParcel::GetNativeContext(env, thiz)->getParcel();
697 
698     size_t parentHandle;
699 
700     const string_vec *vec;
701     status_t err = parcel->readBuffer(sizeof(*vec), &parentHandle,
702             reinterpret_cast<const void **>(&vec));
703 
704     if (err != OK) {
705         signalExceptionForError(env, err);
706         return NULL;
707     }
708 
709     size_t childHandle;
710     err = ::android::hardware::readEmbeddedFromParcel(
711             const_cast<string_vec &>(*vec),
712             *parcel, parentHandle, 0 /* parentOffset */, &childHandle);
713 
714     for (size_t i = 0; (err == OK) && (i < vec->size()); ++i) {
715         err = android::hardware::readEmbeddedFromParcel(
716                     const_cast<hidl_string &>((*vec)[i]),
717                     *parcel,
718                     childHandle,
719                     i * sizeof(hidl_string) /* parentOffset */);
720     }
721 
722     if (err != OK) {
723         signalExceptionForError(env, err);
724         return NULL;
725     }
726 
727     return MakeStringArray(env, &(*vec)[0], vec->size());
728 }
729 
JHwParcel_native_writeStringVector(JNIEnv * env,jobject thiz,jobjectArray arrayObj)730 static void JHwParcel_native_writeStringVector(
731         JNIEnv *env, jobject thiz, jobjectArray arrayObj) {
732     typedef hidl_vec<hidl_string> string_vec;
733 
734     if (arrayObj == NULL) {
735         jniThrowException(env, "java/lang/NullPointerException", NULL);
736         return;
737     }
738 
739     jsize len = env->GetArrayLength(arrayObj);
740 
741     sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz);
742 
743     void *vecPtr =
744         impl->getStorage()->allocTemporaryStorage(sizeof(string_vec));
745 
746     string_vec *vec = new (vecPtr) string_vec;
747 
748     hidl_string *strings = impl->getStorage()->allocStringArray(len);
749     vec->setToExternal(strings, len);
750 
751     for (jsize i = 0; i < len; ++i) {
752         ScopedLocalRef<jstring> stringObj(
753                 env,
754                 (jstring)env->GetObjectArrayElement(arrayObj, i));
755 
756         const hidl_string *s =
757             impl->getStorage()->allocTemporaryString(env, stringObj.get());
758 
759         strings[i].setToExternal(s->c_str(), s->size());
760     }
761 
762     hardware::Parcel *parcel = impl->getParcel();
763 
764     size_t parentHandle;
765     status_t err = parcel->writeBuffer(vec, sizeof(*vec), &parentHandle);
766 
767     if (err == OK) {
768         size_t childHandle;
769         err = ::android::hardware::writeEmbeddedToParcel(
770                 *vec,
771                 parcel,
772                 parentHandle,
773                 0 /* parentOffset */,
774                 &childHandle);
775 
776         for (size_t i = 0; (err == OK) && (i < vec->size()); ++i) {
777             err = ::android::hardware::writeEmbeddedToParcel(
778                     (*vec)[i],
779                     parcel,
780                     childHandle,
781                     i * sizeof(hidl_string));
782         }
783     }
784 
785     signalExceptionForError(env, err);
786 }
787 
JHwParcel_native_readStrongBinder(JNIEnv * env,jobject thiz)788 static jobject JHwParcel_native_readStrongBinder(JNIEnv *env, jobject thiz) {
789     hardware::Parcel *parcel =
790         JHwParcel::GetNativeContext(env, thiz)->getParcel();
791 
792     sp<hardware::IBinder> binder = parcel->readStrongBinder();
793 
794     if (binder == NULL) {
795         return NULL;
796     }
797 
798     return JHwRemoteBinder::NewObject(env, binder);
799 }
800 
JHwParcel_native_readBuffer(JNIEnv * env,jobject thiz,jlong expectedSize)801 static jobject JHwParcel_native_readBuffer(JNIEnv *env, jobject thiz,
802                                            jlong expectedSize) {
803     hardware::Parcel *parcel =
804         JHwParcel::GetNativeContext(env, thiz)->getParcel();
805 
806     size_t handle;
807     const void *ptr;
808 
809     if (expectedSize < 0) {
810         jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
811         return nullptr;
812     }
813 
814     status_t status = parcel->readBuffer(expectedSize, &handle, &ptr);
815 
816     if (status != OK) {
817         jniThrowException(env, "java/util/NoSuchElementException", NULL);
818         return nullptr;
819     }
820 
821     return JHwBlob::NewObject(env, ptr, handle);
822 }
823 
JHwParcel_native_readEmbeddedBuffer(JNIEnv * env,jobject thiz,jlong expectedSize,jlong parentHandle,jlong offset,jboolean nullable)824 static jobject JHwParcel_native_readEmbeddedBuffer(
825         JNIEnv *env, jobject thiz, jlong expectedSize,
826         jlong parentHandle, jlong offset, jboolean nullable) {
827     hardware::Parcel *parcel =
828         JHwParcel::GetNativeContext(env, thiz)->getParcel();
829 
830     size_t childHandle;
831 
832     const void *ptr;
833     status_t status =
834         parcel->readNullableEmbeddedBuffer(expectedSize,
835                 &childHandle, parentHandle, offset, &ptr);
836 
837     if (expectedSize < 0) {
838         jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
839         return nullptr;
840     }
841 
842     if (status != OK) {
843         jniThrowException(env, "java/util/NoSuchElementException", NULL);
844         return 0;
845     } else if (status == OK && !nullable && ptr == nullptr) {
846         jniThrowException(env, "java/lang/NullPointerException", NULL);
847         return 0;
848     }
849 
850     return JHwBlob::NewObject(env, ptr, childHandle);
851 }
852 
JHwParcel_native_writeBuffer(JNIEnv * env,jobject thiz,jobject blobObj)853 static void JHwParcel_native_writeBuffer(
854         JNIEnv *env, jobject thiz, jobject blobObj) {
855     if (blobObj == nullptr) {
856         jniThrowException(env, "java/lang/NullPointerException", NULL);
857         return;
858     }
859 
860     hardware::Parcel *parcel =
861         JHwParcel::GetNativeContext(env, thiz)->getParcel();
862 
863     sp<JHwBlob> blob = JHwBlob::GetNativeContext(env, blobObj);
864     status_t err = blob->writeToParcel(parcel);
865 
866     if (err != OK) {
867         signalExceptionForError(env, err);
868     }
869 }
870 
871 static JNINativeMethod gMethods[] = {
872     { "native_init", "()J", (void *)JHwParcel_native_init },
873     { "native_setup", "(Z)V", (void *)JHwParcel_native_setup },
874 
875     { "writeInterfaceToken", "(Ljava/lang/String;)V",
876         (void *)JHwParcel_native_writeInterfaceToken },
877 
878     { "writeBool", "(Z)V", (void *)JHwParcel_native_writeBool },
879     { "writeInt8", "(B)V", (void *)JHwParcel_native_writeInt8 },
880     { "writeInt16", "(S)V", (void *)JHwParcel_native_writeInt16 },
881     { "writeInt32", "(I)V", (void *)JHwParcel_native_writeInt32 },
882     { "writeInt64", "(J)V", (void *)JHwParcel_native_writeInt64 },
883     { "writeFloat", "(F)V", (void *)JHwParcel_native_writeFloat },
884     { "writeDouble", "(D)V", (void *)JHwParcel_native_writeDouble },
885 
886     { "writeString", "(Ljava/lang/String;)V",
887         (void *)JHwParcel_native_writeString },
888 
889     { "writeBoolVector", "([Z)V", (void *)JHwParcel_native_writeBoolVector },
890     { "writeInt8Vector", "([B)V", (void *)JHwParcel_native_writeInt8Vector },
891     { "writeInt16Vector", "([S)V", (void *)JHwParcel_native_writeInt16Vector },
892     { "writeInt32Vector", "([I)V", (void *)JHwParcel_native_writeInt32Vector },
893     { "writeInt64Vector", "([J)V", (void *)JHwParcel_native_writeInt64Vector },
894     { "writeFloatVector", "([F)V", (void *)JHwParcel_native_writeFloatVector },
895 
896     { "writeDoubleVector", "([D)V",
897         (void *)JHwParcel_native_writeDoubleVector },
898 
899     { "writeStringVector", "([Ljava/lang/String;)V",
900         (void *)JHwParcel_native_writeStringVector },
901 
902     { "writeStrongBinder", "(L" PACKAGE_PATH "/IHwBinder;)V",
903         (void *)JHwParcel_native_writeStrongBinder },
904 
905     { "enforceInterface", "(Ljava/lang/String;)V",
906         (void *)JHwParcel_native_enforceInterface },
907 
908     { "readBool", "()Z", (void *)JHwParcel_native_readBool },
909     { "readInt8", "()B", (void *)JHwParcel_native_readInt8 },
910     { "readInt16", "()S", (void *)JHwParcel_native_readInt16 },
911     { "readInt32", "()I", (void *)JHwParcel_native_readInt32 },
912     { "readInt64", "()J", (void *)JHwParcel_native_readInt64 },
913     { "readFloat", "()F", (void *)JHwParcel_native_readFloat },
914     { "readDouble", "()D", (void *)JHwParcel_native_readDouble },
915 
916     { "readString", "()Ljava/lang/String;",
917         (void *)JHwParcel_native_readString },
918 
919     { "readBoolVectorAsArray", "()[Z",
920         (void *)JHwParcel_native_readBoolVector },
921 
922     { "readInt8VectorAsArray", "()[B",
923         (void *)JHwParcel_native_readInt8Vector },
924 
925     { "readInt16VectorAsArray", "()[S",
926         (void *)JHwParcel_native_readInt16Vector },
927 
928     { "readInt32VectorAsArray", "()[I",
929         (void *)JHwParcel_native_readInt32Vector },
930 
931     { "readInt64VectorAsArray", "()[J",
932         (void *)JHwParcel_native_readInt64Vector },
933 
934     { "readFloatVectorAsArray", "()[F",
935         (void *)JHwParcel_native_readFloatVector },
936 
937     { "readDoubleVectorAsArray", "()[D",
938         (void *)JHwParcel_native_readDoubleVector },
939 
940     { "readStringVectorAsArray", "()[Ljava/lang/String;",
941         (void *)JHwParcel_native_readStringVector },
942 
943     { "readStrongBinder", "()L" PACKAGE_PATH "/IHwBinder;",
944         (void *)JHwParcel_native_readStrongBinder },
945 
946     { "writeStatus", "(I)V", (void *)JHwParcel_native_writeStatus },
947 
948     { "verifySuccess", "()V", (void *)JHwParcel_native_verifySuccess },
949 
950     { "releaseTemporaryStorage", "()V",
951         (void *)JHwParcel_native_releaseTemporaryStorage },
952 
953     { "send", "()V", (void *)JHwParcel_native_send },
954 
955     { "readBuffer", "(J)L" PACKAGE_PATH "/HwBlob;",
956         (void *)JHwParcel_native_readBuffer },
957 
958     { "readEmbeddedBuffer", "(JJJZ)L" PACKAGE_PATH "/HwBlob;",
959         (void *)JHwParcel_native_readEmbeddedBuffer },
960 
961     { "writeBuffer", "(L" PACKAGE_PATH "/HwBlob;)V",
962         (void *)JHwParcel_native_writeBuffer },
963 
964     { "release", "()V",
965         (void *)JHwParcel_native_release },
966 
967 };
968 
969 namespace android {
970 
register_android_os_HwParcel(JNIEnv * env)971 int register_android_os_HwParcel(JNIEnv *env) {
972     return RegisterMethodsOrDie(env, CLASS_PATH, gMethods, NELEM(gMethods));
973 }
974 
975 }  // namespace android
976