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