• 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 #undef ANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION // TODO:remove this and fix code
17 
18 //#define LOG_NDEBUG 0
19 #define LOG_TAG "android_os_HwBlob"
20 #include <android-base/logging.h>
21 
22 #include "android_os_HwBlob.h"
23 
24 #include "android_os_HwParcel.h"
25 #include "android_os_NativeHandle.h"
26 
27 #include <nativehelper/JNIHelp.h>
28 #include <android_runtime/AndroidRuntime.h>
29 #include <hidl/Status.h>
30 #include <nativehelper/ScopedLocalRef.h>
31 #include <nativehelper/ScopedPrimitiveArray.h>
32 
33 #include "core_jni_helpers.h"
34 
35 using android::AndroidRuntime;
36 using android::hardware::hidl_handle;
37 using android::hardware::hidl_string;
38 
39 #define PACKAGE_PATH    "android/os"
40 #define CLASS_NAME      "HwBlob"
41 #define CLASS_PATH      PACKAGE_PATH "/" CLASS_NAME
42 
43 namespace android {
44 
45 static struct fields_t {
46     jfieldID contextID;
47     jmethodID constructID;
48 
49 } gFields;
50 
51 // static
InitClass(JNIEnv * env)52 void JHwBlob::InitClass(JNIEnv *env) {
53     ScopedLocalRef<jclass> clazz(
54             env, FindClassOrDie(env, CLASS_PATH));
55 
56     gFields.contextID =
57         GetFieldIDOrDie(env, clazz.get(), "mNativeContext", "J");
58 
59     gFields.constructID = GetMethodIDOrDie(env, clazz.get(), "<init>", "(I)V");
60 }
61 
62 // static
SetNativeContext(JNIEnv * env,jobject thiz,const sp<JHwBlob> & context)63 sp<JHwBlob> JHwBlob::SetNativeContext(
64         JNIEnv *env, jobject thiz, const sp<JHwBlob> &context) {
65     sp<JHwBlob> old = (JHwBlob *)env->GetLongField(thiz, gFields.contextID);
66 
67     if (context != nullptr) {
68         context->incStrong(nullptr /* id */);
69     }
70 
71     if (old != nullptr) {
72         old->decStrong(nullptr /* id */);
73     }
74 
75     env->SetLongField(thiz, gFields.contextID, (long)context.get());
76 
77     return old;
78 }
79 
80 // static
GetNativeContext(JNIEnv * env,jobject thiz)81 sp<JHwBlob> JHwBlob::GetNativeContext(JNIEnv *env, jobject thiz) {
82     return (JHwBlob *)env->GetLongField(thiz, gFields.contextID);
83 }
84 
JHwBlob(JNIEnv * env,jobject thiz,size_t size)85 JHwBlob::JHwBlob(JNIEnv *env, jobject thiz, size_t size)
86     : mBuffer(nullptr),
87       mSize(size),
88       mType(BlobType::GENERIC),
89       mOwnsBuffer(true),
90       mHandle(0) {
91     if (size > 0) {
92         mBuffer = calloc(size, 1);
93     }
94 }
95 
~JHwBlob()96 JHwBlob::~JHwBlob() {
97     if (mOwnsBuffer) {
98         free(mBuffer);
99         mBuffer = nullptr;
100     }
101 }
102 
setTo(const void * ptr,size_t handle)103 void JHwBlob::setTo(const void *ptr, size_t handle) {
104     CHECK_EQ(mSize, 0u);
105     CHECK(mBuffer == nullptr);
106 
107     mBuffer = const_cast<void *>(ptr);
108     mSize = SIZE_MAX;  // XXX
109     mOwnsBuffer = false;
110     mHandle = handle;
111 }
112 
getHandle(size_t * handle) const113 status_t JHwBlob::getHandle(size_t *handle) const {
114     if (mOwnsBuffer) {
115         return INVALID_OPERATION;
116     }
117 
118     *handle = mHandle;
119 
120     return OK;
121 }
122 
read(size_t offset,void * data,size_t size) const123 status_t JHwBlob::read(size_t offset, void *data, size_t size) const {
124     if (offset + size > mSize) {
125         return -ERANGE;
126     }
127 
128     memcpy(data, (const uint8_t *)mBuffer + offset, size);
129 
130     return OK;
131 }
132 
write(size_t offset,const void * data,size_t size)133 status_t JHwBlob::write(size_t offset, const void *data, size_t size) {
134     if (offset + size > mSize) {
135         return -ERANGE;
136     }
137 
138     memcpy((uint8_t *)mBuffer + offset, data, size);
139 
140     return OK;
141 }
142 
getString(size_t offset,const hidl_string ** s) const143 status_t JHwBlob::getString(size_t offset, const hidl_string **s) const {
144     if ((offset + sizeof(hidl_string)) > mSize) {
145         return -ERANGE;
146     }
147 
148     *s = reinterpret_cast<const hidl_string *>(
149             (const uint8_t *)mBuffer + offset);
150 
151     return OK;
152 }
153 
data() const154 const void *JHwBlob::data() const {
155     return mBuffer;
156 }
157 
data()158 void *JHwBlob::data() {
159     return mBuffer;
160 }
161 
size() const162 size_t JHwBlob::size() const {
163     return mSize;
164 }
165 
specializeBlobTo(BlobType type)166 void JHwBlob::specializeBlobTo(BlobType type) {
167     CHECK_EQ(static_cast<int>(mType), static_cast<int>(BlobType::GENERIC));
168     mType = type;
169 }
170 
type() const171 JHwBlob::BlobType JHwBlob::type() const {
172     return mType;
173 }
174 
putBlob(size_t offset,const sp<JHwBlob> & blob)175 status_t JHwBlob::putBlob(size_t offset, const sp<JHwBlob> &blob) {
176     size_t index = mSubBlobs.add();
177     BlobInfo *info = &mSubBlobs.editItemAt(index);
178 
179     info->mOffset = offset;
180     info->mBlob = blob;
181 
182     const void *data = blob->data();
183 
184     return write(offset, &data, sizeof(data));
185 }
186 
writeToParcel(hardware::Parcel * parcel) const187 status_t JHwBlob::writeToParcel(hardware::Parcel *parcel) const {
188     CHECK_EQ(static_cast<int>(mType), static_cast<int>(BlobType::GENERIC));
189 
190     size_t handle = 0;
191     status_t err = parcel->writeBuffer(data(), size(), &handle);
192 
193     if (err != OK) {
194         return err;
195     }
196 
197     return writeSubBlobsToParcel(parcel, handle);
198 }
199 
writeEmbeddedToParcel(hardware::Parcel * parcel,size_t parentHandle,size_t parentOffset) const200 status_t JHwBlob::writeEmbeddedToParcel(
201         hardware::Parcel *parcel,
202         size_t parentHandle,
203         size_t parentOffset) const {
204     size_t handle = 0;
205     status_t err = OK;
206 
207     switch (mType) {
208         case BlobType::GENERIC: {
209             err = parcel->writeEmbeddedBuffer(data(), size(), &handle, parentHandle, parentOffset);
210             break;
211         }
212         case BlobType::NATIVE_HANDLE: {
213             err = parcel->writeEmbeddedNativeHandle(
214                     static_cast<const native_handle *>(data()), parentHandle, parentOffset);
215 
216             CHECK(mSubBlobs.empty());
217             break;
218         }
219         default: { err = INVALID_OPERATION; }
220     }
221 
222     if (err != OK) {
223         return err;
224     }
225 
226     return writeSubBlobsToParcel(parcel, handle);
227 }
228 
writeSubBlobsToParcel(hardware::Parcel * parcel,size_t parentHandle) const229 status_t JHwBlob::writeSubBlobsToParcel(hardware::Parcel *parcel,
230         size_t parentHandle) const {
231     for (size_t i = 0; i < mSubBlobs.size(); ++i) {
232         const BlobInfo &info = mSubBlobs[i];
233         status_t err = info.mBlob->writeEmbeddedToParcel(parcel, parentHandle, info.mOffset);
234 
235         if (err != OK) {
236             return err;
237         }
238     }
239 
240     return OK;
241 }
242 
243 // static
NewObject(JNIEnv * env,const void * ptr,size_t handle)244 jobject JHwBlob::NewObject(JNIEnv *env, const void *ptr, size_t handle) {
245     jobject obj = JHwBlob::NewObject(env, 0 /* size */);
246     JHwBlob::GetNativeContext(env, obj)->setTo(ptr, handle);
247 
248     return obj;
249 }
250 
251 // static
NewObject(JNIEnv * env,size_t size)252 jobject JHwBlob::NewObject(JNIEnv *env, size_t size) {
253     ScopedLocalRef<jclass> clazz(env, FindClassOrDie(env, CLASS_PATH));
254 
255     jmethodID constructID =
256         GetMethodIDOrDie(env, clazz.get(), "<init>", "(I)V");
257 
258     // XXX Again cannot refer to gFields.constructID because InitClass may
259     // not have been called yet.
260 
261     // Cases:
262     // - this originates from another process (something so large should not fit
263     //   in the binder buffer, and it should be rejected by the binder driver)
264     // - if this is used in process, this code makes too many heap copies (in
265     //   order to retrofit HIDL's scatter-gather format to java types) to
266     //   justify passing such a large amount of data over this path. So the
267     //   alternative (updating the constructor and other code to accept other
268     //   types, should also probably not be taken in this case).
269     CHECK_LE(size, static_cast<size_t>(std::numeric_limits<jint>::max()));
270 
271     return env->NewObject(clazz.get(), constructID, static_cast<jint>(size));
272 }
273 
274 }  // namespace android
275 
276 ////////////////////////////////////////////////////////////////////////////////
277 
278 using namespace android;
279 
releaseNativeContext(void * nativeContext)280 static void releaseNativeContext(void *nativeContext) {
281     sp<JHwBlob> parcel = (JHwBlob *)nativeContext;
282 
283     if (parcel != nullptr) {
284         parcel->decStrong(nullptr /* id */);
285     }
286 }
287 
JHwBlob_native_init(JNIEnv * env,jclass)288 static jlong JHwBlob_native_init(JNIEnv *env, jclass /*clazz*/) {
289     JHwBlob::InitClass(env);
290 
291     return reinterpret_cast<jlong>(&releaseNativeContext);
292 }
293 
JHwBlob_native_setup(JNIEnv * env,jobject thiz,jint size)294 static void JHwBlob_native_setup(
295         JNIEnv *env, jobject thiz, jint size) {
296     sp<JHwBlob> context = new JHwBlob(env, thiz, size);
297 
298     JHwBlob::SetNativeContext(env, thiz, context);
299 }
300 
301 #define DEFINE_BLOB_GETTER(Suffix,Type)                                        \
302 static Type JHwBlob_native_get ## Suffix(                                      \
303         JNIEnv *env, jobject thiz, jlong offset) {                             \
304     sp<JHwBlob> blob = JHwBlob::GetNativeContext(env, thiz);                   \
305                                                                                \
306     Type x;                                                                    \
307     status_t err = blob->read(offset, &x, sizeof(x));                          \
308                                                                                \
309     if (err != OK) {                                                           \
310         signalExceptionForError(env, err);                                     \
311         return 0;                                                              \
312     }                                                                          \
313                                                                                \
314     return x;                                                                  \
315 }
316 
DEFINE_BLOB_GETTER(Int8,jbyte)317 DEFINE_BLOB_GETTER(Int8,jbyte)
318 DEFINE_BLOB_GETTER(Int16,jshort)
319 DEFINE_BLOB_GETTER(Int32,jint)
320 DEFINE_BLOB_GETTER(Int64,jlong)
321 DEFINE_BLOB_GETTER(Float,jfloat)
322 DEFINE_BLOB_GETTER(Double,jdouble)
323 
324 static jboolean JHwBlob_native_getBool(
325         JNIEnv *env, jobject thiz, jlong offset) {
326     sp<JHwBlob> blob = JHwBlob::GetNativeContext(env, thiz);
327 
328     bool x;
329     status_t err = blob->read(offset, &x, sizeof(x));
330 
331     if (err != OK) {
332         signalExceptionForError(env, err);
333         return 0;
334     }
335 
336     return (jboolean)x;
337 }
338 
JHwBlob_native_getString(JNIEnv * env,jobject thiz,jlong offset)339 static jstring JHwBlob_native_getString(
340         JNIEnv *env, jobject thiz, jlong offset) {
341     sp<JHwBlob> blob = JHwBlob::GetNativeContext(env, thiz);
342 
343     const hidl_string *s;
344     status_t err = blob->getString(offset, &s);
345 
346     if (err != OK) {
347         signalExceptionForError(env, err);
348         return nullptr;
349     }
350 
351     return env->NewStringUTF(s->c_str());
352 }
353 
JHwBlob_native_getFieldHandle(JNIEnv * env,jobject thiz,jlong offset)354 static jlong JHwBlob_native_getFieldHandle(JNIEnv* env,
355                                            jobject thiz,
356                                            jlong offset) {
357     sp<JHwBlob> blob = JHwBlob::GetNativeContext(env, thiz);
358 
359     return reinterpret_cast<jlong>(blob->data()) + offset;
360 }
361 
362 #define DEFINE_BLOB_ARRAY_COPIER(Suffix,Type,NewType)                          \
363 static void JHwBlob_native_copyTo ## Suffix ## Array(                          \
364         JNIEnv *env,                                                           \
365         jobject thiz,                                                          \
366         jlong offset,                                                          \
367         Type ## Array array,                                                   \
368         jint size) {                                                           \
369     if (array == nullptr) {                                                    \
370         jniThrowException(env, "java/lang/NullPointerException", nullptr);     \
371         return;                                                                \
372     }                                                                          \
373                                                                                \
374     if (env->GetArrayLength(array) < size) {                                   \
375         signalExceptionForError(env, BAD_VALUE);                               \
376         return;                                                                \
377     }                                                                          \
378                                                                                \
379     sp<JHwBlob> blob = JHwBlob::GetNativeContext(env, thiz);                   \
380                                                                                \
381     if ((offset + size * sizeof(Type)) > blob->size()) {                       \
382         signalExceptionForError(env, -ERANGE);                                 \
383         return;                                                                \
384     }                                                                          \
385                                                                                \
386     env->Set ## NewType ## ArrayRegion(                                        \
387             array,                                                             \
388             0 /* start */,                                                     \
389             size,                                                              \
390             reinterpret_cast<const Type *>(                                    \
391                 static_cast<const uint8_t *>(blob->data()) + offset));         \
392 }
393 
DEFINE_BLOB_ARRAY_COPIER(Int8,jbyte,Byte)394 DEFINE_BLOB_ARRAY_COPIER(Int8,jbyte,Byte)
395 DEFINE_BLOB_ARRAY_COPIER(Int16,jshort,Short)
396 DEFINE_BLOB_ARRAY_COPIER(Int32,jint,Int)
397 DEFINE_BLOB_ARRAY_COPIER(Int64,jlong,Long)
398 DEFINE_BLOB_ARRAY_COPIER(Float,jfloat,Float)
399 DEFINE_BLOB_ARRAY_COPIER(Double,jdouble,Double)
400 
401 static void JHwBlob_native_copyToBoolArray(
402         JNIEnv *env,
403         jobject thiz,
404         jlong offset,
405         jbooleanArray array,
406         jint size) {
407     if (array == nullptr) {
408         jniThrowException(env, "java/lang/NullPointerException", nullptr);
409         return;
410     }
411 
412     if (env->GetArrayLength(array) < size) {
413         signalExceptionForError(env, BAD_VALUE);
414         return;
415     }
416 
417     sp<JHwBlob> blob = JHwBlob::GetNativeContext(env, thiz);
418 
419     if ((offset + size * sizeof(bool)) > blob->size()) {
420         signalExceptionForError(env, -ERANGE);
421         return;
422     }
423 
424     const bool *src =
425         reinterpret_cast<const bool *>(
426                 static_cast<const uint8_t *>(blob->data()) + offset);
427 
428     jboolean *dst = env->GetBooleanArrayElements(array, nullptr /* isCopy */);
429 
430     for (jint i = 0; i < size; ++i) {
431         dst[i] = src[i];
432     }
433 
434     env->ReleaseBooleanArrayElements(array, dst, 0 /* mode */);
435     dst = nullptr;
436 }
437 
438 #define DEFINE_BLOB_PUTTER(Suffix,Type)                                        \
439 static void JHwBlob_native_put ## Suffix(                                      \
440         JNIEnv *env, jobject thiz, jlong offset, Type x) {                     \
441                                                                                \
442     sp<JHwBlob> blob = JHwBlob::GetNativeContext(env, thiz);                   \
443                                                                                \
444     status_t err = blob->write(offset, &x, sizeof(x));                         \
445                                                                                \
446     if (err != OK) {                                                           \
447         signalExceptionForError(env, err);                                     \
448     }                                                                          \
449 }
450 
DEFINE_BLOB_PUTTER(Int8,jbyte)451 DEFINE_BLOB_PUTTER(Int8,jbyte)
452 DEFINE_BLOB_PUTTER(Int16,jshort)
453 DEFINE_BLOB_PUTTER(Int32,jint)
454 DEFINE_BLOB_PUTTER(Int64,jlong)
455 DEFINE_BLOB_PUTTER(Float,jfloat)
456 DEFINE_BLOB_PUTTER(Double,jdouble)
457 
458 static void JHwBlob_native_putBool(
459         JNIEnv *env, jobject thiz, jlong offset, jboolean x) {
460 
461     sp<JHwBlob> blob = JHwBlob::GetNativeContext(env, thiz);
462 
463     bool b = (bool)x;
464     status_t err = blob->write(offset, &b, sizeof(b));
465 
466     if (err != OK) {
467         signalExceptionForError(env, err);
468     }
469 }
470 
JHwBlob_native_putString(JNIEnv * env,jobject thiz,jlong offset,jstring stringObj)471 static void JHwBlob_native_putString(
472         JNIEnv *env, jobject thiz, jlong offset, jstring stringObj) {
473     if (stringObj == nullptr) {
474         jniThrowException(env, "java/lang/NullPointerException", nullptr);
475         return;
476     }
477 
478     const char *s = env->GetStringUTFChars(stringObj, nullptr);
479 
480     if (s == nullptr) {
481         return;
482     }
483 
484     size_t size = strlen(s) + 1;
485     ScopedLocalRef<jobject> subBlobObj(env, JHwBlob::NewObject(env, size));
486     sp<JHwBlob> subBlob = JHwBlob::GetNativeContext(env, subBlobObj.get());
487     subBlob->write(0 /* offset */, s, size);
488 
489     env->ReleaseStringUTFChars(stringObj, s);
490     s = nullptr;
491 
492     hidl_string tmp;
493     tmp.setToExternal(static_cast<const char *>(subBlob->data()), size - 1);
494 
495     sp<JHwBlob> blob = JHwBlob::GetNativeContext(env, thiz);
496     blob->write(offset, &tmp, sizeof(tmp));
497     blob->putBlob(offset + hidl_string::kOffsetOfBuffer, subBlob);
498 }
499 
JHwBlob_native_putNativeHandle(JNIEnv * env,jobject thiz,jlong offset,jobject jHandle)500 static void JHwBlob_native_putNativeHandle(JNIEnv *env, jobject thiz,
501         jlong offset, jobject jHandle) {
502     std::unique_ptr<native_handle_t, int(*)(native_handle_t*)> nativeHandle(
503             JNativeHandle::MakeCppNativeHandle(env, jHandle, nullptr /* storage */),
504             native_handle_delete);
505 
506     size_t size = 0;
507     if (nativeHandle != nullptr) {
508         size = sizeof(native_handle_t) + nativeHandle->numFds * sizeof(int)
509                + nativeHandle->numInts * sizeof(int);
510     }
511 
512     ScopedLocalRef<jobject> subBlobObj(env, JHwBlob::NewObject(env, size));
513     sp<JHwBlob> subBlob = JHwBlob::GetNativeContext(env, subBlobObj.get());
514     subBlob->specializeBlobTo(JHwBlob::BlobType::NATIVE_HANDLE);
515     subBlob->write(0 /* offset */, nativeHandle.get(), size);
516 
517     hidl_handle cppHandle;
518     cppHandle.setTo(static_cast<native_handle_t *>(subBlob->data()), false /* shouldOwn */);
519 
520     sp<JHwBlob> blob = JHwBlob::GetNativeContext(env, thiz);
521     blob->write(offset, &cppHandle, sizeof(cppHandle));
522     blob->putBlob(offset + hidl_handle::kOffsetOfNativeHandle, subBlob);
523 }
524 
525 #define DEFINE_BLOB_ARRAY_PUTTER(Suffix,Type,NewType)                          \
526 static void JHwBlob_native_put ## Suffix ## Array(                             \
527         JNIEnv *env, jobject thiz, jlong offset, Type ## Array array) {        \
528     Scoped ## NewType ## ArrayRO autoArray(env, array);                        \
529                                                                                \
530     if (array == nullptr) {                                                    \
531         /* NullpointerException already pending */                             \
532         return;                                                                \
533     }                                                                          \
534                                                                                \
535     sp<JHwBlob> blob = JHwBlob::GetNativeContext(env, thiz);                   \
536                                                                                \
537     status_t err = blob->write(                                                \
538             offset, autoArray.get(), autoArray.size() * sizeof(Type));         \
539                                                                                \
540     if (err != OK) {                                                           \
541         signalExceptionForError(env, err);                                     \
542     }                                                                          \
543 }
544 
DEFINE_BLOB_ARRAY_PUTTER(Int8,jbyte,Byte)545 DEFINE_BLOB_ARRAY_PUTTER(Int8,jbyte,Byte)
546 DEFINE_BLOB_ARRAY_PUTTER(Int16,jshort,Short)
547 DEFINE_BLOB_ARRAY_PUTTER(Int32,jint,Int)
548 DEFINE_BLOB_ARRAY_PUTTER(Int64,jlong,Long)
549 DEFINE_BLOB_ARRAY_PUTTER(Float,jfloat,Float)
550 DEFINE_BLOB_ARRAY_PUTTER(Double,jdouble,Double)
551 
552 static void JHwBlob_native_putBoolArray(
553         JNIEnv *env, jobject thiz, jlong offset, jbooleanArray array) {
554     ScopedBooleanArrayRO autoArray(env, array);
555 
556     if (array == nullptr) {
557         /* NullpointerException already pending */
558         return;
559     }
560 
561     sp<JHwBlob> blob = JHwBlob::GetNativeContext(env, thiz);
562 
563     if ((offset + autoArray.size() * sizeof(bool)) > blob->size()) {
564         signalExceptionForError(env, -ERANGE);
565         return;
566     }
567 
568     const jboolean *src = autoArray.get();
569 
570     bool *dst = reinterpret_cast<bool *>(
571             static_cast<uint8_t *>(blob->data()) + offset);
572 
573     for (size_t i = 0; i < autoArray.size(); ++i) {
574         dst[i] = src[i];
575     }
576 }
577 
JHwBlob_native_putBlob(JNIEnv * env,jobject thiz,jlong offset,jobject blobObj)578 static void JHwBlob_native_putBlob(
579         JNIEnv *env, jobject thiz, jlong offset, jobject blobObj) {
580     if (blobObj == nullptr) {
581         jniThrowException(env, "java/lang/NullPointerException", nullptr);
582         return;
583     }
584 
585     sp<JHwBlob> blob = JHwBlob::GetNativeContext(env, thiz);
586     sp<JHwBlob> subBlob = JHwBlob::GetNativeContext(env, blobObj);
587 
588     blob->putBlob(offset, subBlob);
589 }
590 
JHwBlob_native_handle(JNIEnv * env,jobject thiz)591 static jlong JHwBlob_native_handle(JNIEnv *env, jobject thiz) {
592     size_t handle;
593     status_t err = JHwBlob::GetNativeContext(env, thiz)->getHandle(&handle);
594 
595     if (err != OK) {
596         signalExceptionForError(env, err);
597         return 0;
598     }
599 
600     return handle;
601 }
602 
603 static JNINativeMethod gMethods[] = {
native_init()604     { "native_init", "()J", (void *)JHwBlob_native_init },
native_setup(I)605     { "native_setup", "(I)V", (void *)JHwBlob_native_setup },
606 
getBool(J)607     { "getBool", "(J)Z", (void *)JHwBlob_native_getBool },
getInt8(J)608     { "getInt8", "(J)B", (void *)JHwBlob_native_getInt8 },
getInt16(J)609     { "getInt16", "(J)S", (void *)JHwBlob_native_getInt16 },
getInt32(J)610     { "getInt32", "(J)I", (void *)JHwBlob_native_getInt32 },
getInt64(J)611     { "getInt64", "(J)J", (void *)JHwBlob_native_getInt64 },
getFloat(J)612     { "getFloat", "(J)F", (void *)JHwBlob_native_getFloat },
getDouble(J)613     { "getDouble", "(J)D", (void *)JHwBlob_native_getDouble },
getString(J)614     { "getString", "(J)Ljava/lang/String;", (void *)JHwBlob_native_getString },
getFieldHandle(J)615     { "getFieldHandle", "(J)J", (void*) JHwBlob_native_getFieldHandle},
616 
copyToBoolArray(J[ZI)617     { "copyToBoolArray", "(J[ZI)V", (void *)JHwBlob_native_copyToBoolArray },
copyToInt8Array(J[BI)618     { "copyToInt8Array", "(J[BI)V", (void *)JHwBlob_native_copyToInt8Array },
copyToInt16Array(J[SI)619     { "copyToInt16Array", "(J[SI)V", (void *)JHwBlob_native_copyToInt16Array },
copyToInt32Array(J[II)620     { "copyToInt32Array", "(J[II)V", (void *)JHwBlob_native_copyToInt32Array },
copyToInt64Array(J[JI)621     { "copyToInt64Array", "(J[JI)V", (void *)JHwBlob_native_copyToInt64Array },
copyToFloatArray(J[FI)622     { "copyToFloatArray", "(J[FI)V", (void *)JHwBlob_native_copyToFloatArray },
copyToDoubleArray(J[DI)623     { "copyToDoubleArray", "(J[DI)V", (void *)JHwBlob_native_copyToDoubleArray },
624 
putBool(JZ)625     { "putBool", "(JZ)V", (void *)JHwBlob_native_putBool },
putInt8(JB)626     { "putInt8", "(JB)V", (void *)JHwBlob_native_putInt8 },
putInt16(JS)627     { "putInt16", "(JS)V", (void *)JHwBlob_native_putInt16 },
putInt32(JI)628     { "putInt32", "(JI)V", (void *)JHwBlob_native_putInt32 },
putInt64(JJ)629     { "putInt64", "(JJ)V", (void *)JHwBlob_native_putInt64 },
putFloat(JF)630     { "putFloat", "(JF)V", (void *)JHwBlob_native_putFloat },
putDouble(JD)631     { "putDouble", "(JD)V", (void *)JHwBlob_native_putDouble },
putString(JLjava/lang/String;)632     { "putString", "(JLjava/lang/String;)V", (void *)JHwBlob_native_putString },
633     { "putNativeHandle", "(JL" PACKAGE_PATH "/NativeHandle;)V",
634         (void*)JHwBlob_native_putNativeHandle },
635 
putBoolArray(J[Z)636     { "putBoolArray", "(J[Z)V", (void *)JHwBlob_native_putBoolArray },
putInt8Array(J[B)637     { "putInt8Array", "(J[B)V", (void *)JHwBlob_native_putInt8Array },
putInt16Array(J[S)638     { "putInt16Array", "(J[S)V", (void *)JHwBlob_native_putInt16Array },
putInt32Array(J[I)639     { "putInt32Array", "(J[I)V", (void *)JHwBlob_native_putInt32Array },
putInt64Array(J[J)640     { "putInt64Array", "(J[J)V", (void *)JHwBlob_native_putInt64Array },
putFloatArray(J[F)641     { "putFloatArray", "(J[F)V", (void *)JHwBlob_native_putFloatArray },
putDoubleArray(J[D)642     { "putDoubleArray", "(J[D)V", (void *)JHwBlob_native_putDoubleArray },
643 
644     { "putBlob", "(JL" PACKAGE_PATH "/HwBlob;)V",
645         (void *)JHwBlob_native_putBlob },
646 
handle()647     { "handle", "()J", (void *)JHwBlob_native_handle },
648 };
649 
650 namespace android {
651 
register_android_os_HwBlob(JNIEnv * env)652 int register_android_os_HwBlob(JNIEnv *env) {
653     return RegisterMethodsOrDie(env, CLASS_PATH, gMethods, NELEM(gMethods));
654 }
655 
656 }  // namespace android
657 
658