• 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_NativeHandle.h"
26 #include "android_os_HwRemoteBinder.h"
27 
28 #include <nativehelper/JNIHelp.h>
29 #include <android_runtime/AndroidRuntime.h>
30 #include <hidl/HidlTransportSupport.h>
31 #include <hidl/Status.h>
32 #include <nativehelper/ScopedLocalRef.h>
33 
34 #include "core_jni_helpers.h"
35 
36 using android::AndroidRuntime;
37 
38 using ::android::hardware::hidl_handle;
39 using ::android::hardware::hidl_string;
40 using ::android::hardware::hidl_vec;
41 
42 #define PACKAGE_PATH    "android/os"
43 #define CLASS_NAME      "HwParcel"
44 #define CLASS_PATH      PACKAGE_PATH "/" CLASS_NAME
45 
46 namespace android {
47 
48 static struct fields_t {
49     jfieldID contextID;
50     jmethodID constructID;
51 
52 } gFields;
53 
signalExceptionForError(JNIEnv * env,status_t err,bool canThrowRemoteException)54 void signalExceptionForError(JNIEnv *env, status_t err, bool canThrowRemoteException) {
55     switch (err) {
56         case OK:
57             break;
58 
59         case NO_MEMORY:
60         {
61             jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
62             break;
63         }
64 
65         case INVALID_OPERATION:
66         {
67             jniThrowException(
68                     env, "java/lang/UnsupportedOperationException", NULL);
69             break;
70         }
71 
72         case BAD_VALUE:
73         {
74             jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
75             break;
76         }
77 
78         case -ERANGE:
79         case BAD_INDEX:
80         {
81             jniThrowException(env, "java/lang/IndexOutOfBoundsException", NULL);
82             break;
83         }
84 
85         case BAD_TYPE:
86         {
87             jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
88             break;
89         }
90 
91         case NAME_NOT_FOUND:
92         {
93             jniThrowException(env, "java/util/NoSuchElementException", NULL);
94             break;
95         }
96 
97         case PERMISSION_DENIED:
98         {
99             jniThrowException(env, "java/lang/SecurityException", NULL);
100             break;
101         }
102 
103         case NO_INIT:
104         {
105             jniThrowException(
106                     env, "java/lang/RuntimeException", "Not initialized");
107             break;
108         }
109 
110         case ALREADY_EXISTS:
111         {
112             jniThrowException(
113                     env, "java/lang/RuntimeException", "Item already exists");
114             break;
115         }
116 
117         default:
118         {
119             std::stringstream ss;
120             ss << "HwBinder Error: (" << err << ")";
121 
122             jniThrowException(
123                     env,
124                     canThrowRemoteException ? "android/os/RemoteException" : "java/lang/RuntimeException",
125                     ss.str().c_str());
126 
127             break;
128         }
129     }
130 }
131 
132 // static
InitClass(JNIEnv * env)133 void JHwParcel::InitClass(JNIEnv *env) {
134     ScopedLocalRef<jclass> clazz(
135             env, FindClassOrDie(env, CLASS_PATH));
136 
137     gFields.contextID =
138         GetFieldIDOrDie(env, clazz.get(), "mNativeContext", "J");
139 
140     gFields.constructID = GetMethodIDOrDie(env, clazz.get(), "<init>", "(Z)V");
141 }
142 
143 // static
SetNativeContext(JNIEnv * env,jobject thiz,const sp<JHwParcel> & context)144 sp<JHwParcel> JHwParcel::SetNativeContext(
145         JNIEnv *env, jobject thiz, const sp<JHwParcel> &context) {
146     sp<JHwParcel> old = (JHwParcel *)env->GetLongField(thiz, gFields.contextID);
147 
148     if (context != NULL) {
149         context->incStrong(NULL /* id */);
150     }
151 
152     if (old != NULL) {
153         old->decStrong(NULL /* id */);
154     }
155 
156     env->SetLongField(thiz, gFields.contextID, (long)context.get());
157 
158     return old;
159 }
160 
161 // static
GetNativeContext(JNIEnv * env,jobject thiz)162 sp<JHwParcel> JHwParcel::GetNativeContext(JNIEnv *env, jobject thiz) {
163     return (JHwParcel *)env->GetLongField(thiz, gFields.contextID);
164 }
165 
JHwParcel(JNIEnv * env,jobject thiz)166 JHwParcel::JHwParcel(JNIEnv *env, jobject thiz)
167     : mParcel(NULL),
168       mOwnsParcel(false),
169       mTransactCallback(nullptr),
170       mWasSent(false) {
171 }
172 
~JHwParcel()173 JHwParcel::~JHwParcel() {
174     JNIEnv *env = AndroidRuntime::getJNIEnv();
175 
176     mStorage.release(env);
177 
178     setParcel(NULL, false /* assumeOwnership */);
179 }
180 
getParcel()181 hardware::Parcel *JHwParcel::getParcel() {
182     return mParcel;
183 }
184 
getStorage()185 EphemeralStorage *JHwParcel::getStorage() {
186     return &mStorage;
187 }
188 
setParcel(hardware::Parcel * parcel,bool assumeOwnership)189 void JHwParcel::setParcel(hardware::Parcel *parcel, bool assumeOwnership) {
190     if (mParcel && mOwnsParcel) {
191         delete mParcel;
192     }
193 
194     mParcel = parcel;
195     mOwnsParcel = assumeOwnership;
196 }
197 
198 // static
NewObject(JNIEnv * env)199 jobject JHwParcel::NewObject(JNIEnv *env) {
200     ScopedLocalRef<jclass> clazz(env, FindClassOrDie(env, CLASS_PATH));
201 
202     jmethodID constructID =
203         GetMethodIDOrDie(env, clazz.get(), "<init>", "(Z)V");
204 
205     return env->NewObject(clazz.get(), constructID, false /* allocate */);
206 }
207 
setTransactCallback(::android::hardware::IBinder::TransactCallback cb)208 void JHwParcel::setTransactCallback(
209         ::android::hardware::IBinder::TransactCallback cb) {
210     mTransactCallback = cb;
211 }
212 
send()213 void JHwParcel::send() {
214     CHECK(mTransactCallback != nullptr);
215     CHECK(mParcel != nullptr);
216 
217     mTransactCallback(*mParcel);
218     mTransactCallback = nullptr;
219 
220     mWasSent = true;
221 }
222 
wasSent() const223 bool JHwParcel::wasSent() const {
224     return mWasSent;
225 }
226 
227 }  // namespace android
228 
229 ////////////////////////////////////////////////////////////////////////////////
230 
231 using namespace android;
232 
releaseNativeContext(void * nativeContext)233 static void releaseNativeContext(void *nativeContext) {
234     sp<JHwParcel> parcel = (JHwParcel *)nativeContext;
235 
236     if (parcel != NULL) {
237         parcel->decStrong(NULL /* id */);
238     }
239 }
240 
JHwParcel_native_init(JNIEnv * env)241 static jlong JHwParcel_native_init(JNIEnv *env) {
242     JHwParcel::InitClass(env);
243 
244     return reinterpret_cast<jlong>(&releaseNativeContext);
245 }
246 
JHwParcel_native_setup(JNIEnv * env,jobject thiz,jboolean allocate)247 static void JHwParcel_native_setup(
248         JNIEnv *env, jobject thiz, jboolean allocate) {
249     sp<JHwParcel> context = new JHwParcel(env, thiz);
250 
251     if (allocate) {
252         context->setParcel(new hardware::Parcel, true /* assumeOwnership */);
253     }
254 
255     JHwParcel::SetNativeContext(env, thiz, context);
256 }
257 
JHwParcel_native_writeInterfaceToken(JNIEnv * env,jobject thiz,jstring interfaceNameObj)258 static void JHwParcel_native_writeInterfaceToken(
259         JNIEnv *env, jobject thiz, jstring interfaceNameObj) {
260     if (interfaceNameObj == NULL) {
261         jniThrowException(env, "java/lang/NullPointerException", NULL);
262         return;
263     }
264 
265     const jchar *interfaceName = env->GetStringCritical(interfaceNameObj, NULL);
266     if (interfaceName) {
267         String8 nameCopy = String8(String16(
268                 reinterpret_cast<const char16_t *>(interfaceName),
269                 env->GetStringLength(interfaceNameObj)));
270 
271         env->ReleaseStringCritical(interfaceNameObj, interfaceName);
272         interfaceName = NULL;
273 
274         hardware::Parcel *parcel =
275             JHwParcel::GetNativeContext(env, thiz)->getParcel();
276 
277         status_t err = parcel->writeInterfaceToken(nameCopy.string());
278         signalExceptionForError(env, err);
279     }
280 }
281 
JHwParcel_native_enforceInterface(JNIEnv * env,jobject thiz,jstring interfaceNameObj)282 static void JHwParcel_native_enforceInterface(
283         JNIEnv *env, jobject thiz, jstring interfaceNameObj) {
284     // XXX original binder Parcel enforceInterface implementation does some
285     // mysterious things regarding strictModePolicy(), figure out if we need
286     // that here as well.
287     if (interfaceNameObj == NULL) {
288         jniThrowException(env, "java/lang/NullPointerException", NULL);
289         return;
290     }
291 
292     const jchar *interfaceName = env->GetStringCritical(interfaceNameObj, NULL);
293     if (interfaceName) {
294         String8 interfaceNameCopy = String8(String16(
295                 reinterpret_cast<const char16_t *>(interfaceName),
296                 env->GetStringLength(interfaceNameObj)));
297 
298         env->ReleaseStringCritical(interfaceNameObj, interfaceName);
299         interfaceName = NULL;
300 
301         hardware::Parcel *parcel =
302             JHwParcel::GetNativeContext(env, thiz)->getParcel();
303 
304         bool valid = parcel->enforceInterface(interfaceNameCopy.string());
305 
306         if (!valid) {
307             jniThrowException(
308                     env,
309                     "java/lang/SecurityException",
310                     "HWBinder invocation to an incorrect interface");
311         }
312     }
313 }
314 
315 #define DEFINE_PARCEL_WRITER(Suffix,Type)                               \
316 static void JHwParcel_native_write ## Suffix(                           \
317         JNIEnv *env, jobject thiz, Type val) {                          \
318     hardware::Parcel *parcel =                                          \
319         JHwParcel::GetNativeContext(env, thiz)->getParcel();            \
320                                                                         \
321     status_t err = parcel->write ## Suffix(val);                        \
322     signalExceptionForError(env, err);                                  \
323 }
324 
325 #define DEFINE_PARCEL_READER(Suffix,Type)                               \
326 static Type JHwParcel_native_read ## Suffix(                            \
327         JNIEnv *env, jobject thiz) {                                    \
328     hardware::Parcel *parcel =                                          \
329         JHwParcel::GetNativeContext(env, thiz)->getParcel();            \
330                                                                         \
331     Type val;                                                           \
332     status_t err = parcel->read ## Suffix(&val);                        \
333     signalExceptionForError(env, err);                                  \
334                                                                         \
335     return val;                                                         \
336 }
337 
DEFINE_PARCEL_WRITER(Bool,jboolean)338 DEFINE_PARCEL_WRITER(Bool,jboolean)
339 DEFINE_PARCEL_WRITER(Int8,jbyte)
340 DEFINE_PARCEL_WRITER(Int16,jshort)
341 DEFINE_PARCEL_WRITER(Int32,jint)
342 DEFINE_PARCEL_WRITER(Int64,jlong)
343 DEFINE_PARCEL_WRITER(Float,jfloat)
344 DEFINE_PARCEL_WRITER(Double,jdouble)
345 
346 DEFINE_PARCEL_READER(Int8,jbyte)
347 DEFINE_PARCEL_READER(Int16,jshort)
348 DEFINE_PARCEL_READER(Int32,jint)
349 DEFINE_PARCEL_READER(Int64,jlong)
350 DEFINE_PARCEL_READER(Float,jfloat)
351 DEFINE_PARCEL_READER(Double,jdouble)
352 
353 static jboolean JHwParcel_native_readBool(JNIEnv *env, jobject thiz) {
354     hardware::Parcel *parcel =
355         JHwParcel::GetNativeContext(env, thiz)->getParcel();
356 
357     bool val;
358     status_t err = parcel->readBool(&val);
359     signalExceptionForError(env, err);
360 
361     return (jboolean)val;
362 }
363 
JHwParcel_native_writeStatus(JNIEnv * env,jobject thiz,jint statusCode)364 static void JHwParcel_native_writeStatus(
365         JNIEnv *env, jobject thiz, jint statusCode) {
366     using hardware::Status;
367 
368     Status status;
369     switch (statusCode) {
370         case 0:  // kStatusSuccess
371             status = Status::ok();
372             break;
373         case -1:  // kStatusError
374             status = Status::fromStatusT(UNKNOWN_ERROR);
375             break;
376         default:
377             CHECK(!"Should not be here");
378     }
379 
380     hardware::Parcel *parcel =
381         JHwParcel::GetNativeContext(env, thiz)->getParcel();
382 
383     status_t err = ::android::hardware::writeToParcel(status, parcel);
384     signalExceptionForError(env, err);
385 }
386 
JHwParcel_native_verifySuccess(JNIEnv * env,jobject thiz)387 static void JHwParcel_native_verifySuccess(JNIEnv *env, jobject thiz) {
388     using hardware::Status;
389 
390     hardware::Parcel *parcel =
391         JHwParcel::GetNativeContext(env, thiz)->getParcel();
392 
393     Status status;
394     status_t err = ::android::hardware::readFromParcel(&status, *parcel);
395     signalExceptionForError(env, err);
396 
397     if (!status.isOk()) {
398         signalExceptionForError(env, UNKNOWN_ERROR, true /* canThrowRemoteException */);
399     }
400 }
401 
JHwParcel_native_release(JNIEnv * env,jobject thiz)402 static void JHwParcel_native_release(
403         JNIEnv *env, jobject thiz) {
404     JHwParcel::GetNativeContext(env, thiz)->setParcel(NULL, false /* assumeOwnership */);
405 }
406 
JHwParcel_native_releaseTemporaryStorage(JNIEnv * env,jobject thiz)407 static void JHwParcel_native_releaseTemporaryStorage(
408         JNIEnv *env, jobject thiz) {
409     JHwParcel::GetNativeContext(env, thiz)->getStorage()->release(env);
410 }
411 
JHwParcel_native_send(JNIEnv * env,jobject thiz)412 static void JHwParcel_native_send(JNIEnv *env, jobject thiz) {
413     JHwParcel::GetNativeContext(env, thiz)->send();
414 }
415 
JHwParcel_native_writeString(JNIEnv * env,jobject thiz,jstring valObj)416 static void JHwParcel_native_writeString(
417         JNIEnv *env, jobject thiz, jstring valObj) {
418     if (valObj == NULL) {
419         jniThrowException(env, "java/lang/NullPointerException", NULL);
420         return;
421     }
422 
423     sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz);
424 
425     const hidl_string *s =
426         impl->getStorage()->allocTemporaryString(env, valObj);
427 
428     hardware::Parcel *parcel = impl->getParcel();
429 
430     size_t parentHandle;
431     status_t err = parcel->writeBuffer(s, sizeof(*s), &parentHandle);
432 
433     if (err == OK) {
434         err = ::android::hardware::writeEmbeddedToParcel(
435                 *s, parcel, parentHandle, 0 /* parentOffset */);
436     }
437 
438     signalExceptionForError(env, err);
439 }
440 
JHwParcel_native_writeNativeHandle(JNIEnv * env,jobject thiz,jobject valObj)441 static void JHwParcel_native_writeNativeHandle(JNIEnv *env, jobject thiz, jobject valObj) {
442     sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz);
443 
444     EphemeralStorage *storage = impl->getStorage();
445     native_handle_t *handle = JNativeHandle::MakeCppNativeHandle(env, valObj, storage);
446 
447     hardware::Parcel *parcel = impl->getParcel();
448     status_t err = parcel->writeNativeHandleNoDup(handle);
449 
450     signalExceptionForError(env, err);
451 }
452 
453 #define DEFINE_PARCEL_VECTOR_WRITER(Suffix,Type)                               \
454 static void JHwParcel_native_write ## Suffix ## Vector(                        \
455         JNIEnv *env, jobject thiz, Type ## Array valObj) {                     \
456     if (valObj == NULL) {                                                      \
457         jniThrowException(env, "java/lang/NullPointerException", NULL);        \
458         return;                                                                \
459     }                                                                          \
460                                                                                \
461     sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz);               \
462                                                                                \
463     const hidl_vec<Type> *vec =                                                \
464         impl->getStorage()->allocTemporary ## Suffix ## Vector(env, valObj);   \
465                                                                                \
466     hardware::Parcel *parcel = impl->getParcel();                              \
467                                                                                \
468     size_t parentHandle;                                                       \
469     status_t err = parcel->writeBuffer(vec, sizeof(*vec), &parentHandle);      \
470                                                                                \
471     if (err == OK) {                                                           \
472         size_t childHandle;                                                    \
473                                                                                \
474         err = ::android::hardware::writeEmbeddedToParcel(                      \
475                 *vec,                                                          \
476                 parcel,                                                        \
477                 parentHandle,                                                  \
478                 0 /* parentOffset */,                                          \
479                 &childHandle);                                                 \
480     }                                                                          \
481                                                                                \
482     signalExceptionForError(env, err);                                         \
483 }
484 
DEFINE_PARCEL_VECTOR_WRITER(Int8,jbyte)485 DEFINE_PARCEL_VECTOR_WRITER(Int8,jbyte)
486 DEFINE_PARCEL_VECTOR_WRITER(Int16,jshort)
487 DEFINE_PARCEL_VECTOR_WRITER(Int32,jint)
488 DEFINE_PARCEL_VECTOR_WRITER(Int64,jlong)
489 DEFINE_PARCEL_VECTOR_WRITER(Float,jfloat)
490 DEFINE_PARCEL_VECTOR_WRITER(Double,jdouble)
491 
492 static void JHwParcel_native_writeBoolVector(
493         JNIEnv *env, jobject thiz, jbooleanArray valObj) {
494     if (valObj == NULL) {
495         jniThrowException(env, "java/lang/NullPointerException", NULL);
496         return;
497     }
498 
499     sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz);
500 
501     void *vecPtr =
502         impl->getStorage()->allocTemporaryStorage(sizeof(hidl_vec<bool>));
503 
504     hidl_vec<bool> *vec = new (vecPtr) hidl_vec<bool>;
505 
506     jsize len = env->GetArrayLength(valObj);
507 
508     jboolean *src = env->GetBooleanArrayElements(valObj, nullptr);
509 
510     bool *dst =
511         (bool *)impl->getStorage()->allocTemporaryStorage(len * sizeof(bool));
512 
513     for (jsize i = 0; i < len; ++i) {
514         dst[i] = src[i];
515     }
516 
517     env->ReleaseBooleanArrayElements(valObj, src, 0 /* mode */);
518     src = nullptr;
519 
520     vec->setToExternal(dst, len);
521 
522     hardware::Parcel *parcel = impl->getParcel();
523 
524     size_t parentHandle;
525     status_t err = parcel->writeBuffer(vec, sizeof(*vec), &parentHandle);
526 
527     if (err == OK) {
528         size_t childHandle;
529 
530         err = ::android::hardware::writeEmbeddedToParcel(
531                 *vec,
532                 parcel,
533                 parentHandle,
534                 0 /* parentOffset */,
535                 &childHandle);
536     }
537 
538     signalExceptionForError(env, err);
539 }
540 
541 template<typename T>
WriteHidlVector(JNIEnv * env,jobject thiz,const hidl_vec<T> & vec)542 static void WriteHidlVector(JNIEnv *env, jobject thiz, const hidl_vec<T> &vec) {
543     hardware::Parcel *parcel = JHwParcel::GetNativeContext(env, thiz)->getParcel();
544 
545     size_t parentHandle;
546     status_t err = parcel->writeBuffer(&vec, sizeof(vec), &parentHandle);
547 
548     if (err == OK) {
549         size_t childHandle;
550         err = ::android::hardware::writeEmbeddedToParcel(
551                 vec,
552                 parcel,
553                 parentHandle,
554                 0 /* parentOffset */,
555                 &childHandle);
556 
557         for (size_t i = 0; (err == OK) && (i < vec.size()); ++i) {
558             err = ::android::hardware::writeEmbeddedToParcel(
559                     vec[i],
560                     parcel,
561                     childHandle,
562                     i * sizeof(T));
563         }
564     }
565 
566     signalExceptionForError(env, err);
567 }
568 
JHwParcel_native_writeStringVector(JNIEnv * env,jobject thiz,jobjectArray arrayObj)569 static void JHwParcel_native_writeStringVector(
570         JNIEnv *env, jobject thiz, jobjectArray arrayObj) {
571     if (arrayObj == nullptr) {
572         jniThrowException(env, "java/lang/NullPointerException", nullptr);
573         return;
574     }
575 
576     sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz);
577     EphemeralStorage *storage = impl->getStorage();
578 
579     void *vecPtr = storage->allocTemporaryStorage(sizeof(hidl_vec<hidl_string>));
580     hidl_vec<hidl_string> *vec = new (vecPtr) hidl_vec<hidl_string>();
581 
582     jsize len = env->GetArrayLength(arrayObj);
583     hidl_string *strings = storage->allocStringArray(len);
584     vec->setToExternal(strings, len, false /* shouldOwn */);
585 
586     for (jsize i = 0; i < len; ++i) {
587         ScopedLocalRef<jstring> stringObj(env, (jstring) env->GetObjectArrayElement(arrayObj, i));
588 
589         const hidl_string *s = storage->allocTemporaryString(env, stringObj.get());
590         strings[i].setToExternal(s->c_str(), s->size());
591     }
592 
593     WriteHidlVector(env, thiz, *vec);
594 }
595 
JHwParcel_native_writeNativeHandleVector(JNIEnv * env,jobject thiz,jobjectArray jHandleArray)596 static void JHwParcel_native_writeNativeHandleVector(
597         JNIEnv *env, jobject thiz, jobjectArray jHandleArray) {
598     if (jHandleArray == nullptr) {
599         jniThrowException(env, "java/lang/NullPointerException", nullptr);
600         return;
601     }
602 
603     sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz);
604     EphemeralStorage *storage = impl->getStorage();
605 
606     void *vecPtr = storage->allocTemporaryStorage(sizeof(hidl_vec<hidl_handle>));
607     hidl_vec<hidl_handle> *vec = new (vecPtr) hidl_vec<hidl_handle>();
608 
609     jsize len = env->GetArrayLength(jHandleArray);
610     hidl_handle *handles = static_cast<hidl_handle *>(
611             storage->allocTemporaryStorage(len * sizeof(hidl_handle)));
612 
613     vec->setToExternal(handles, len, false /* shouldOwn */);
614     for (jsize i = 0; i < len; i++) {
615         ScopedLocalRef<jobject> jHandle(env, env->GetObjectArrayElement(jHandleArray, i));
616 
617         native_handle_t* handle = JNativeHandle::MakeCppNativeHandle(env, jHandle.get(), storage);
618 
619         new (&(handles[i])) hidl_handle();
620         handles[i].setTo(handle, false /* shouldOwn */);
621     }
622 
623     WriteHidlVector(env, thiz, *vec);
624 }
625 
JHwParcel_native_writeStrongBinder(JNIEnv * env,jobject thiz,jobject binderObj)626 static void JHwParcel_native_writeStrongBinder(
627         JNIEnv *env, jobject thiz, jobject binderObj) {
628     sp<hardware::IBinder> binder;
629     if (binderObj != NULL) {
630         ScopedLocalRef<jclass> hwBinderKlass(env, FindClassOrDie(env, PACKAGE_PATH "/HwBinder"));
631 
632         ScopedLocalRef<jclass> hwRemoteBinderKlass(
633                 env, FindClassOrDie(env, PACKAGE_PATH "/HwRemoteBinder"));
634 
635         if (env->IsInstanceOf(binderObj, hwBinderKlass.get())) {
636             binder = JHwBinder::GetNativeBinder(env, binderObj);
637         } else if (env->IsInstanceOf(binderObj, hwRemoteBinderKlass.get())) {
638             binder = JHwRemoteBinder::GetNativeContext(
639                     env, binderObj)->getBinder();
640         } else {
641             signalExceptionForError(env, INVALID_OPERATION);
642             return;
643         }
644     }
645 
646     hardware::Parcel *parcel =
647         JHwParcel::GetNativeContext(env, thiz)->getParcel();
648 
649     status_t err = parcel->writeStrongBinder(binder);
650     signalExceptionForError(env, err);
651 }
652 
MakeStringObjFromHidlString(JNIEnv * env,const hidl_string & s)653 static jstring MakeStringObjFromHidlString(JNIEnv *env, const hidl_string &s) {
654     String16 utf16String(s.c_str(), s.size());
655 
656     return env->NewString(
657             reinterpret_cast<const jchar *>(utf16String.string()),
658             utf16String.size());
659 }
660 
JHwParcel_native_readString(JNIEnv * env,jobject thiz)661 static jstring JHwParcel_native_readString(JNIEnv *env, jobject thiz) {
662     hardware::Parcel *parcel =
663         JHwParcel::GetNativeContext(env, thiz)->getParcel();
664 
665     size_t parentHandle;
666 
667     const hidl_string *s;
668     status_t err = parcel->readBuffer(sizeof(*s), &parentHandle,
669             reinterpret_cast<const void**>(&s));
670 
671     if (err != OK) {
672         signalExceptionForError(env, err);
673         return NULL;
674     }
675 
676     err = ::android::hardware::readEmbeddedFromParcel(
677             const_cast<hidl_string &>(*s),
678             *parcel, parentHandle, 0 /* parentOffset */);
679 
680     if (err != OK) {
681         signalExceptionForError(env, err);
682         return NULL;
683     }
684 
685     return MakeStringObjFromHidlString(env, *s);
686 }
687 
ReadNativeHandle(JNIEnv * env,jobject thiz,jboolean embedded,jlong parentHandle,jlong offset)688 static jobject ReadNativeHandle(JNIEnv *env, jobject thiz, jboolean embedded,
689         jlong parentHandle, jlong offset) {
690     hardware::Parcel *parcel =
691             JHwParcel::GetNativeContext(env, thiz)->getParcel();
692 
693     const native_handle_t *handle = nullptr;
694     status_t err = OK;
695 
696     if (embedded) {
697         err = parcel->readNullableEmbeddedNativeHandle(parentHandle, offset, &handle);
698     } else {
699         err = parcel->readNullableNativeHandleNoDup(&handle);
700     }
701 
702     if (err != OK) {
703         signalExceptionForError(env, err);
704         return nullptr;
705     }
706 
707     return JNativeHandle::MakeJavaNativeHandleObj(env, handle);
708 }
709 
JHwParcel_native_readNativeHandle(JNIEnv * env,jobject thiz)710 static jobject JHwParcel_native_readNativeHandle(JNIEnv *env, jobject thiz) {
711     return ReadNativeHandle(env, thiz, false /*embedded*/, 0L /*parentHandle*/, 0L /*offset*/);
712 }
713 
JHwParcel_native_readEmbeddedNativeHandle(JNIEnv * env,jobject thiz,jlong parentHandle,jlong offset)714 static jobject JHwParcel_native_readEmbeddedNativeHandle(
715         JNIEnv *env, jobject thiz, jlong parentHandle, jlong offset) {
716     return ReadNativeHandle(env, thiz, true /*embedded*/, parentHandle, offset);
717 }
718 
719 #define DEFINE_PARCEL_VECTOR_READER(Suffix,Type,NewType)                       \
720 static Type ## Array JHwParcel_native_read ## Suffix ## Vector(                \
721         JNIEnv *env, jobject thiz) {                                           \
722     hardware::Parcel *parcel =                                                 \
723         JHwParcel::GetNativeContext(env, thiz)->getParcel();                   \
724     size_t parentHandle;                                                       \
725                                                                                \
726     const hidl_vec<Type> *vec;                                                 \
727     status_t err = parcel->readBuffer(sizeof(*vec), &parentHandle,             \
728             reinterpret_cast<const void**>(&vec));                             \
729                                                                                \
730     if (err != OK) {                                                           \
731         signalExceptionForError(env, err);                                     \
732         return NULL;                                                           \
733     }                                                                          \
734                                                                                \
735     size_t childHandle;                                                        \
736                                                                                \
737     err = ::android::hardware::readEmbeddedFromParcel(                         \
738                 const_cast<hidl_vec<Type> &>(*vec),                            \
739                 *parcel,                                                       \
740                 parentHandle,                                                  \
741                 0 /* parentOffset */,                                          \
742                 &childHandle);                                                 \
743                                                                                \
744     if (err != OK) {                                                           \
745         signalExceptionForError(env, err);                                     \
746         return NULL;                                                           \
747     }                                                                          \
748                                                                                \
749     Type ## Array valObj = env->New ## NewType ## Array(vec->size());          \
750     env->Set ## NewType ## ArrayRegion(valObj, 0, vec->size(), &(*vec)[0]);    \
751                                                                                \
752     return valObj;                                                             \
753 }
754 
DEFINE_PARCEL_VECTOR_READER(Int8,jbyte,Byte)755 DEFINE_PARCEL_VECTOR_READER(Int8,jbyte,Byte)
756 DEFINE_PARCEL_VECTOR_READER(Int16,jshort,Short)
757 DEFINE_PARCEL_VECTOR_READER(Int32,jint,Int)
758 DEFINE_PARCEL_VECTOR_READER(Int64,jlong,Long)
759 DEFINE_PARCEL_VECTOR_READER(Float,jfloat,Float)
760 DEFINE_PARCEL_VECTOR_READER(Double,jdouble,Double)
761 
762 static jbooleanArray JHwParcel_native_readBoolVector(JNIEnv *env, jobject thiz) {
763     hardware::Parcel *parcel = JHwParcel::GetNativeContext(env, thiz)->getParcel();
764 
765     size_t parentHandle;
766 
767     const hidl_vec<bool> *vec;
768     status_t err = parcel->readBuffer(sizeof(*vec), &parentHandle,
769             reinterpret_cast<const void**>(&vec));
770 
771     if (err != OK) {
772         signalExceptionForError(env, err);
773         return NULL;
774     }
775 
776     size_t childHandle;
777 
778     err = ::android::hardware::readEmbeddedFromParcel(
779                 const_cast<hidl_vec<bool> &>(*vec),
780                 *parcel,
781                 parentHandle,
782                 0 /* parentOffset */,
783                 &childHandle);
784 
785     if (err != OK) {
786         signalExceptionForError(env, err);
787         return NULL;
788     }
789 
790     jbooleanArray valObj = env->NewBooleanArray(vec->size());
791 
792     for (size_t i = 0; i < vec->size(); ++i) {
793         jboolean x = (*vec)[i];
794         env->SetBooleanArrayRegion(valObj, i, 1, &x);
795     }
796 
797     return valObj;
798 }
799 
MakeStringArray(JNIEnv * env,const hidl_string * array,size_t size)800 static jobjectArray MakeStringArray(
801         JNIEnv *env, const hidl_string *array, size_t size) {
802     ScopedLocalRef<jclass> stringKlass(
803             env,
804             env->FindClass("java/lang/String"));
805 
806     // XXX Why can't I use ScopedLocalRef<> for the arrayObj and the stringObjs?
807 
808     jobjectArray arrayObj = env->NewObjectArray(size, stringKlass.get(), NULL);
809 
810     for (size_t i = 0; i < size; ++i) {
811         jstring stringObj = MakeStringObjFromHidlString(env, array[i]);
812 
813         env->SetObjectArrayElement(
814                 arrayObj,
815                 i,
816                 stringObj);
817     }
818 
819     return arrayObj;
820 }
821 
822 template<typename T>
ReadHidlVector(JNIEnv * env,jobject thiz)823 static const hidl_vec<T> *ReadHidlVector(JNIEnv *env, jobject thiz) {
824     const hidl_vec<T> *vec;
825 
826     hardware::Parcel *parcel = JHwParcel::GetNativeContext(env, thiz)->getParcel();
827 
828     size_t parentHandle;
829     status_t err = parcel->readBuffer(sizeof(hidl_vec<T>),
830             &parentHandle, reinterpret_cast<const void **>(&vec));
831 
832     if (err == OK) {
833         size_t childHandle;
834         err = ::android::hardware::readEmbeddedFromParcel(
835                 const_cast<hidl_vec<T> &>(*vec),
836                 *parcel, parentHandle,
837                 0 /* parentOffset */,
838                 &childHandle);
839 
840         for (size_t i = 0; (err == OK) && (i < vec->size()); i++) {
841             err = android::hardware::readEmbeddedFromParcel(
842                     const_cast<T &>((*vec)[i]),
843                     *parcel,
844                     childHandle,
845                     i * sizeof(T) /* parentOffset */);
846         }
847     }
848 
849     if (err != OK) {
850         signalExceptionForError(env, err);
851         return nullptr;
852     }
853 
854     return vec;
855 }
856 
JHwParcel_native_readStringVector(JNIEnv * env,jobject thiz)857 static jobjectArray JHwParcel_native_readStringVector(
858         JNIEnv *env, jobject thiz) {
859     const hidl_vec<hidl_string> *vec = ReadHidlVector<hidl_string>(env, thiz);
860     return MakeStringArray(env, &(*vec)[0], vec->size());
861 }
862 
JHwParcel_native_readNativeHandleVector(JNIEnv * env,jobject thiz)863 static jobjectArray JHwParcel_native_readNativeHandleVector(
864         JNIEnv *env, jobject thiz) {
865     const hidl_vec<hidl_handle> *vec = ReadHidlVector<hidl_handle>(env, thiz);
866 
867     jsize length = vec->size();
868     jobjectArray objArray = JNativeHandle::AllocJavaNativeHandleObjArray(
869             env, length);
870 
871     for (jsize i = 0; i < length; i++) {
872         jobject jHandle = JNativeHandle::MakeJavaNativeHandleObj(env, (*vec)[i].getNativeHandle());
873 
874         env->SetObjectArrayElement(objArray, i, jHandle);
875     }
876 
877     return objArray;
878 }
879 
JHwParcel_native_readStrongBinder(JNIEnv * env,jobject thiz)880 static jobject JHwParcel_native_readStrongBinder(JNIEnv *env, jobject thiz) {
881     hardware::Parcel *parcel =
882         JHwParcel::GetNativeContext(env, thiz)->getParcel();
883 
884     sp<hardware::IBinder> binder = parcel->readStrongBinder();
885 
886     if (binder == NULL) {
887         return NULL;
888     }
889 
890     return JHwRemoteBinder::NewObject(env, binder);
891 }
892 
JHwParcel_native_readBuffer(JNIEnv * env,jobject thiz,jlong expectedSize)893 static jobject JHwParcel_native_readBuffer(JNIEnv *env, jobject thiz,
894                                            jlong expectedSize) {
895     hardware::Parcel *parcel =
896         JHwParcel::GetNativeContext(env, thiz)->getParcel();
897 
898     size_t handle;
899     const void *ptr;
900 
901     if (expectedSize < 0) {
902         jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
903         return nullptr;
904     }
905 
906     status_t status = parcel->readBuffer(expectedSize, &handle, &ptr);
907 
908     if (status != OK) {
909         jniThrowException(env, "java/util/NoSuchElementException", NULL);
910         return nullptr;
911     }
912 
913     return JHwBlob::NewObject(env, ptr, handle);
914 }
915 
JHwParcel_native_readEmbeddedBuffer(JNIEnv * env,jobject thiz,jlong expectedSize,jlong parentHandle,jlong offset,jboolean nullable)916 static jobject JHwParcel_native_readEmbeddedBuffer(
917         JNIEnv *env, jobject thiz, jlong expectedSize,
918         jlong parentHandle, jlong offset, jboolean nullable) {
919     hardware::Parcel *parcel =
920         JHwParcel::GetNativeContext(env, thiz)->getParcel();
921 
922     size_t childHandle;
923 
924     const void *ptr;
925     status_t status =
926         parcel->readNullableEmbeddedBuffer(expectedSize,
927                 &childHandle, parentHandle, offset, &ptr);
928 
929     if (expectedSize < 0) {
930         jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
931         return nullptr;
932     }
933 
934     if (status != OK) {
935         jniThrowException(env, "java/util/NoSuchElementException", NULL);
936         return 0;
937     } else if (status == OK && !nullable && ptr == nullptr) {
938         jniThrowException(env, "java/lang/NullPointerException", NULL);
939         return 0;
940     }
941 
942     return JHwBlob::NewObject(env, ptr, childHandle);
943 }
944 
JHwParcel_native_writeBuffer(JNIEnv * env,jobject thiz,jobject blobObj)945 static void JHwParcel_native_writeBuffer(
946         JNIEnv *env, jobject thiz, jobject blobObj) {
947     if (blobObj == nullptr) {
948         jniThrowException(env, "java/lang/NullPointerException", NULL);
949         return;
950     }
951 
952     hardware::Parcel *parcel =
953         JHwParcel::GetNativeContext(env, thiz)->getParcel();
954 
955     sp<JHwBlob> blob = JHwBlob::GetNativeContext(env, blobObj);
956     status_t err = blob->writeToParcel(parcel);
957 
958     if (err != OK) {
959         signalExceptionForError(env, err);
960     }
961 }
962 
963 static JNINativeMethod gMethods[] = {
964     { "native_init", "()J", (void *)JHwParcel_native_init },
965     { "native_setup", "(Z)V", (void *)JHwParcel_native_setup },
966 
967     { "writeInterfaceToken", "(Ljava/lang/String;)V",
968         (void *)JHwParcel_native_writeInterfaceToken },
969 
970     { "writeBool", "(Z)V", (void *)JHwParcel_native_writeBool },
971     { "writeInt8", "(B)V", (void *)JHwParcel_native_writeInt8 },
972     { "writeInt16", "(S)V", (void *)JHwParcel_native_writeInt16 },
973     { "writeInt32", "(I)V", (void *)JHwParcel_native_writeInt32 },
974     { "writeInt64", "(J)V", (void *)JHwParcel_native_writeInt64 },
975     { "writeFloat", "(F)V", (void *)JHwParcel_native_writeFloat },
976     { "writeDouble", "(D)V", (void *)JHwParcel_native_writeDouble },
977 
978     { "writeString", "(Ljava/lang/String;)V",
979         (void *)JHwParcel_native_writeString },
980 
981     { "writeNativeHandle", "(L" PACKAGE_PATH "/NativeHandle;)V",
982         (void *)JHwParcel_native_writeNativeHandle },
983 
984     { "writeBoolVector", "([Z)V", (void *)JHwParcel_native_writeBoolVector },
985     { "writeInt8Vector", "([B)V", (void *)JHwParcel_native_writeInt8Vector },
986     { "writeInt16Vector", "([S)V", (void *)JHwParcel_native_writeInt16Vector },
987     { "writeInt32Vector", "([I)V", (void *)JHwParcel_native_writeInt32Vector },
988     { "writeInt64Vector", "([J)V", (void *)JHwParcel_native_writeInt64Vector },
989     { "writeFloatVector", "([F)V", (void *)JHwParcel_native_writeFloatVector },
990 
991     { "writeDoubleVector", "([D)V",
992         (void *)JHwParcel_native_writeDoubleVector },
993 
994     { "writeStringVector", "([Ljava/lang/String;)V",
995         (void *)JHwParcel_native_writeStringVector },
996 
997     { "writeNativeHandleVector", "([L" PACKAGE_PATH "/NativeHandle;)V",
998         (void *)JHwParcel_native_writeNativeHandleVector },
999 
1000     { "writeStrongBinder", "(L" PACKAGE_PATH "/IHwBinder;)V",
1001         (void *)JHwParcel_native_writeStrongBinder },
1002 
1003     { "enforceInterface", "(Ljava/lang/String;)V",
1004         (void *)JHwParcel_native_enforceInterface },
1005 
1006     { "readBool", "()Z", (void *)JHwParcel_native_readBool },
1007     { "readInt8", "()B", (void *)JHwParcel_native_readInt8 },
1008     { "readInt16", "()S", (void *)JHwParcel_native_readInt16 },
1009     { "readInt32", "()I", (void *)JHwParcel_native_readInt32 },
1010     { "readInt64", "()J", (void *)JHwParcel_native_readInt64 },
1011     { "readFloat", "()F", (void *)JHwParcel_native_readFloat },
1012     { "readDouble", "()D", (void *)JHwParcel_native_readDouble },
1013 
1014     { "readString", "()Ljava/lang/String;",
1015         (void *)JHwParcel_native_readString },
1016 
1017     { "readNativeHandle", "()L" PACKAGE_PATH "/NativeHandle;",
1018         (void *)JHwParcel_native_readNativeHandle },
1019 
1020     { "readEmbeddedNativeHandle", "(JJ)L" PACKAGE_PATH "/NativeHandle;",
1021         (void *)JHwParcel_native_readEmbeddedNativeHandle },
1022 
1023     { "readBoolVectorAsArray", "()[Z",
1024         (void *)JHwParcel_native_readBoolVector },
1025 
1026     { "readInt8VectorAsArray", "()[B",
1027         (void *)JHwParcel_native_readInt8Vector },
1028 
1029     { "readInt16VectorAsArray", "()[S",
1030         (void *)JHwParcel_native_readInt16Vector },
1031 
1032     { "readInt32VectorAsArray", "()[I",
1033         (void *)JHwParcel_native_readInt32Vector },
1034 
1035     { "readInt64VectorAsArray", "()[J",
1036         (void *)JHwParcel_native_readInt64Vector },
1037 
1038     { "readFloatVectorAsArray", "()[F",
1039         (void *)JHwParcel_native_readFloatVector },
1040 
1041     { "readDoubleVectorAsArray", "()[D",
1042         (void *)JHwParcel_native_readDoubleVector },
1043 
1044     { "readStringVectorAsArray", "()[Ljava/lang/String;",
1045         (void *)JHwParcel_native_readStringVector },
1046 
1047     { "readNativeHandleAsArray", "()[L" PACKAGE_PATH "/NativeHandle;",
1048         (void *)JHwParcel_native_readNativeHandleVector },
1049 
1050     { "readStrongBinder", "()L" PACKAGE_PATH "/IHwBinder;",
1051         (void *)JHwParcel_native_readStrongBinder },
1052 
1053     { "writeStatus", "(I)V", (void *)JHwParcel_native_writeStatus },
1054 
1055     { "verifySuccess", "()V", (void *)JHwParcel_native_verifySuccess },
1056 
1057     { "releaseTemporaryStorage", "()V",
1058         (void *)JHwParcel_native_releaseTemporaryStorage },
1059 
1060     { "send", "()V", (void *)JHwParcel_native_send },
1061 
1062     { "readBuffer", "(J)L" PACKAGE_PATH "/HwBlob;",
1063         (void *)JHwParcel_native_readBuffer },
1064 
1065     { "readEmbeddedBuffer", "(JJJZ)L" PACKAGE_PATH "/HwBlob;",
1066         (void *)JHwParcel_native_readEmbeddedBuffer },
1067 
1068     { "writeBuffer", "(L" PACKAGE_PATH "/HwBlob;)V",
1069         (void *)JHwParcel_native_writeBuffer },
1070 
1071     { "release", "()V",
1072         (void *)JHwParcel_native_release },
1073 
1074 };
1075 
1076 namespace android {
1077 
register_android_os_HwParcel(JNIEnv * env)1078 int register_android_os_HwParcel(JNIEnv *env) {
1079     return RegisterMethodsOrDie(env, CLASS_PATH, gMethods, NELEM(gMethods));
1080 }
1081 
1082 }  // namespace android
1083