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