Adds framework support for hidl-gen Java backend. (to support structs) (DO NOT MERGE)
Bug: 30575790
Change-Id: Ida30d8fe7a1b210e98f1a0ea5d429a0112f9ef3f
Signed-off-by: Iliyan Malchev <malchev@google.com>
diff --git a/core/java/android/os/HwBlob.java b/core/java/android/os/HwBlob.java
new file mode 100644
index 0000000..153c6e6
--- /dev/null
+++ b/core/java/android/os/HwBlob.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+import libcore.util.NativeAllocationRegistry;
+
+/** @hide */
+public class HwBlob {
+ private static final String TAG = "HwBlob";
+
+ private static final NativeAllocationRegistry sNativeRegistry;
+
+ public HwBlob(int size) {
+ native_setup(size);
+
+ sNativeRegistry.registerNativeAllocation(
+ this,
+ mNativeContext);
+ }
+
+ public native final boolean getBool(long offset);
+ public native final byte getInt8(long offset);
+ public native final short getInt16(long offset);
+ public native final int getInt32(long offset);
+ public native final long getInt64(long offset);
+ public native final float getFloat(long offset);
+ public native final double getDouble(long offset);
+ public native final String getString(long offset);
+
+ public native final void putBool(long offset, boolean x);
+ public native final void putInt8(long offset, byte x);
+ public native final void putInt16(long offset, short x);
+ public native final void putInt32(long offset, int x);
+ public native final void putInt64(long offset, long x);
+ public native final void putFloat(long offset, float x);
+ public native final void putDouble(long offset, double x);
+ public native final void putString(long offset, String x);
+
+ public native final void putBlob(long offset, HwBlob blob);
+
+ public native final long handle();
+
+ // Returns address of the "freeFunction".
+ private static native final long native_init();
+
+ private native final void native_setup(int size);
+
+ static {
+ long freeFunction = native_init();
+
+ sNativeRegistry = new NativeAllocationRegistry(
+ HwBlob.class.getClassLoader(),
+ freeFunction,
+ 128 /* size */);
+ }
+
+ private long mNativeContext;
+}
+
+
diff --git a/core/java/android/os/HwParcel.java b/core/java/android/os/HwParcel.java
index 52579e5..e4d5718 100644
--- a/core/java/android/os/HwParcel.java
+++ b/core/java/android/os/HwParcel.java
@@ -101,6 +101,14 @@
public native final IHwBinder readStrongBinder();
+ // Handle is stored as part of the blob.
+ public native final HwBlob readBuffer();
+
+ public native final HwBlob readEmbeddedBuffer(
+ long parentHandle, long offset);
+
+ public native final void writeBuffer(HwBlob blob);
+
public native final void writeStatus(int status);
public native final void verifySuccess();
public native final void releaseTemporaryStorage();
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 08be2eb..7e1a0ab 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -81,6 +81,7 @@
android_text_StaticLayout.cpp \
android_os_Debug.cpp \
android_os_HwBinder.cpp \
+ android_os_HwBlob.cpp \
android_os_HwParcel.cpp \
android_os_HwRemoteBinder.cpp \
android_os_MemoryFile.cpp \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 109d3fb..07392c4 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -157,6 +157,7 @@
extern int register_android_nio_utils(JNIEnv* env);
extern int register_android_os_Debug(JNIEnv* env);
extern int register_android_os_HwBinder(JNIEnv *env);
+extern int register_android_os_HwBlob(JNIEnv *env);
extern int register_android_os_HwParcel(JNIEnv *env);
extern int register_android_os_HwRemoteBinder(JNIEnv *env);
extern int register_android_os_MessageQueue(JNIEnv* env);
@@ -1291,6 +1292,7 @@
REG_JNI(register_android_os_Binder),
REG_JNI(register_android_os_Parcel),
REG_JNI(register_android_os_HwBinder),
+ REG_JNI(register_android_os_HwBlob),
REG_JNI(register_android_os_HwParcel),
REG_JNI(register_android_os_HwRemoteBinder),
REG_JNI(register_android_nio_utils),
diff --git a/core/jni/android_os_HwBlob.cpp b/core/jni/android_os_HwBlob.cpp
new file mode 100644
index 0000000..6972cf1
--- /dev/null
+++ b/core/jni/android_os_HwBlob.cpp
@@ -0,0 +1,452 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "android_os_HwBlob"
+#include <android-base/logging.h>
+
+#include "android_os_HwBlob.h"
+
+#include "android_os_HwParcel.h"
+
+#include <JNIHelp.h>
+#include <android_runtime/AndroidRuntime.h>
+#include <hwbinder/Status.h>
+#include <nativehelper/ScopedLocalRef.h>
+
+#include "core_jni_helpers.h"
+
+using android::AndroidRuntime;
+using android::hardware::hidl_string;
+
+#define PACKAGE_PATH "android/os"
+#define CLASS_NAME "HwBlob"
+#define CLASS_PATH PACKAGE_PATH "/" CLASS_NAME
+
+namespace android {
+
+static struct fields_t {
+ jfieldID contextID;
+ jmethodID constructID;
+
+} gFields;
+
+// static
+void JHwBlob::InitClass(JNIEnv *env) {
+ ScopedLocalRef<jclass> clazz(
+ env, FindClassOrDie(env, CLASS_PATH));
+
+ gFields.contextID =
+ GetFieldIDOrDie(env, clazz.get(), "mNativeContext", "J");
+
+ gFields.constructID = GetMethodIDOrDie(env, clazz.get(), "<init>", "(I)V");
+}
+
+// static
+sp<JHwBlob> JHwBlob::SetNativeContext(
+ JNIEnv *env, jobject thiz, const sp<JHwBlob> &context) {
+ sp<JHwBlob> old = (JHwBlob *)env->GetLongField(thiz, gFields.contextID);
+
+ if (context != NULL) {
+ context->incStrong(NULL /* id */);
+ }
+
+ if (old != NULL) {
+ old->decStrong(NULL /* id */);
+ }
+
+ env->SetLongField(thiz, gFields.contextID, (long)context.get());
+
+ return old;
+}
+
+// static
+sp<JHwBlob> JHwBlob::GetNativeContext(JNIEnv *env, jobject thiz) {
+ return (JHwBlob *)env->GetLongField(thiz, gFields.contextID);
+}
+
+JHwBlob::JHwBlob(JNIEnv *env, jobject thiz, size_t size)
+ : mBuffer(nullptr),
+ mSize(size),
+ mOwnsBuffer(true),
+ mHandle(0) {
+ jclass clazz = env->GetObjectClass(thiz);
+ CHECK(clazz != NULL);
+
+ mClass = (jclass)env->NewGlobalRef(clazz);
+ mObject = env->NewWeakGlobalRef(thiz);
+
+ if (size > 0) {
+ mBuffer = malloc(size);
+ }
+}
+
+JHwBlob::~JHwBlob() {
+ if (mOwnsBuffer) {
+ free(mBuffer);
+ mBuffer = nullptr;
+ }
+
+ JNIEnv *env = AndroidRuntime::getJNIEnv();
+
+ env->DeleteWeakGlobalRef(mObject);
+ mObject = NULL;
+
+ env->DeleteGlobalRef(mClass);
+ mClass = NULL;
+}
+
+void JHwBlob::setTo(const void *ptr, size_t handle) {
+ CHECK_EQ(mSize, 0u);
+ CHECK(mBuffer == nullptr);
+
+ mBuffer = const_cast<void *>(ptr);
+ mSize = SIZE_MAX; // XXX
+ mOwnsBuffer = false;
+ mHandle = handle;
+}
+
+status_t JHwBlob::getHandle(size_t *handle) const {
+ if (mOwnsBuffer) {
+ return INVALID_OPERATION;
+ }
+
+ *handle = mHandle;
+
+ return OK;
+}
+
+status_t JHwBlob::read(size_t offset, void *data, size_t size) const {
+ if (offset + size > mSize) {
+ return -ERANGE;
+ }
+
+ memcpy(data, (const uint8_t *)mBuffer + offset, size);
+
+ return OK;
+}
+
+status_t JHwBlob::write(size_t offset, const void *data, size_t size) {
+ if (offset + size > mSize) {
+ return -ERANGE;
+ }
+
+ memcpy((uint8_t *)mBuffer + offset, data, size);
+
+ return OK;
+}
+
+status_t JHwBlob::getString(size_t offset, const hidl_string **s) const {
+ if ((offset + sizeof(hidl_string)) > mSize) {
+ return -ERANGE;
+ }
+
+ *s = reinterpret_cast<const hidl_string *>(
+ (const uint8_t *)mBuffer + offset);
+
+ return OK;
+}
+
+const void *JHwBlob::data() const {
+ return mBuffer;
+}
+
+size_t JHwBlob::size() const {
+ return mSize;
+}
+
+status_t JHwBlob::putBlob(size_t offset, const sp<JHwBlob> &blob) {
+ size_t index = mSubBlobs.add();
+ BlobInfo *info = &mSubBlobs.editItemAt(index);
+
+ info->mOffset = offset;
+ info->mBlob = blob;
+
+ const void *data = blob->data();
+
+ return write(offset, &data, sizeof(data));
+}
+
+status_t JHwBlob::writeToParcel(hardware::Parcel *parcel) const {
+ size_t handle;
+ status_t err = parcel->writeBuffer(data(), size(), &handle);
+
+ if (err != OK) {
+ return err;
+ }
+
+ for (size_t i = 0; i < mSubBlobs.size(); ++i) {
+ const BlobInfo &info = mSubBlobs[i];
+
+ err = info.mBlob->writeEmbeddedToParcel(parcel, handle, info.mOffset);
+
+ if (err != OK) {
+ return err;
+ }
+ }
+
+ return OK;
+}
+
+status_t JHwBlob::writeEmbeddedToParcel(
+ hardware::Parcel *parcel,
+ size_t parentHandle,
+ size_t parentOffset) const {
+ size_t handle;
+ status_t err = parcel->writeEmbeddedBuffer(
+ data(), size(), &handle, parentHandle, parentOffset);
+
+ if (err != OK) {
+ return err;
+ }
+
+ for (size_t i = 0; i < mSubBlobs.size(); ++i) {
+ const BlobInfo &info = mSubBlobs[i];
+
+ err = info.mBlob->writeEmbeddedToParcel(parcel, handle, info.mOffset);
+
+ if (err != OK) {
+ return err;
+ }
+ }
+
+ return OK;
+}
+
+// static
+jobject JHwBlob::NewObject(JNIEnv *env, const void *ptr, size_t handle) {
+ jobject obj = JHwBlob::NewObject(env, 0 /* size */);
+ JHwBlob::GetNativeContext(env, obj)->setTo(ptr, handle);
+
+ return obj;
+}
+
+// static
+jobject JHwBlob::NewObject(JNIEnv *env, size_t size) {
+ ScopedLocalRef<jclass> clazz(env, FindClassOrDie(env, CLASS_PATH));
+
+ jmethodID constructID =
+ GetMethodIDOrDie(env, clazz.get(), "<init>", "(I)V");
+
+ // XXX Again cannot refer to gFields.constructID because InitClass may
+ // not have been called yet.
+
+ return env->NewObject(clazz.get(), constructID, size);
+}
+
+} // namespace android
+
+////////////////////////////////////////////////////////////////////////////////
+
+using namespace android;
+
+static void releaseNativeContext(void *nativeContext) {
+ sp<JHwBlob> parcel = (JHwBlob *)nativeContext;
+
+ if (parcel != NULL) {
+ parcel->decStrong(NULL /* id */);
+ }
+}
+
+static jlong JHwBlob_native_init(JNIEnv *env) {
+ JHwBlob::InitClass(env);
+
+ return reinterpret_cast<jlong>(&releaseNativeContext);
+}
+
+static void JHwBlob_native_setup(
+ JNIEnv *env, jobject thiz, jint size) {
+ sp<JHwBlob> context = new JHwBlob(env, thiz, size);
+
+ JHwBlob::SetNativeContext(env, thiz, context);
+}
+
+#define DEFINE_BLOB_GETTER(Suffix,Type) \
+static Type JHwBlob_native_get ## Suffix( \
+ JNIEnv *env, jobject thiz, jlong offset) { \
+ sp<JHwBlob> blob = JHwBlob::GetNativeContext(env, thiz); \
+ \
+ Type x; \
+ status_t err = blob->read(offset, &x, sizeof(x)); \
+ \
+ if (err != OK) { \
+ signalExceptionForError(env, err); \
+ return 0; \
+ } \
+ \
+ return x; \
+}
+
+DEFINE_BLOB_GETTER(Int8,jbyte)
+DEFINE_BLOB_GETTER(Int16,jshort)
+DEFINE_BLOB_GETTER(Int32,jint)
+DEFINE_BLOB_GETTER(Int64,jlong)
+DEFINE_BLOB_GETTER(Float,jfloat)
+DEFINE_BLOB_GETTER(Double,jdouble)
+
+static jboolean JHwBlob_native_getBool(
+ JNIEnv *env, jobject thiz, jlong offset) {
+ sp<JHwBlob> blob = JHwBlob::GetNativeContext(env, thiz);
+
+ bool x;
+ status_t err = blob->read(offset, &x, sizeof(x));
+
+ if (err != OK) {
+ signalExceptionForError(env, err);
+ return 0;
+ }
+
+ return (jboolean)x;
+}
+
+static jstring JHwBlob_native_getString(
+ JNIEnv *env, jobject thiz, jlong offset) {
+ sp<JHwBlob> blob = JHwBlob::GetNativeContext(env, thiz);
+
+ const hidl_string *s;
+ status_t err = blob->getString(offset, &s);
+
+ if (err != OK) {
+ signalExceptionForError(env, err);
+ return nullptr;
+ }
+
+ return env->NewStringUTF(s->c_str());
+}
+
+#define DEFINE_BLOB_PUTTER(Suffix,Type) \
+static void JHwBlob_native_put ## Suffix( \
+ JNIEnv *env, jobject thiz, jlong offset, Type x) { \
+ \
+ sp<JHwBlob> blob = JHwBlob::GetNativeContext(env, thiz); \
+ \
+ status_t err = blob->write(offset, &x, sizeof(x)); \
+ \
+ if (err != OK) { \
+ signalExceptionForError(env, err); \
+ } \
+}
+
+DEFINE_BLOB_PUTTER(Int8,jbyte)
+DEFINE_BLOB_PUTTER(Int16,jshort)
+DEFINE_BLOB_PUTTER(Int32,jint)
+DEFINE_BLOB_PUTTER(Int64,jlong)
+DEFINE_BLOB_PUTTER(Float,jfloat)
+DEFINE_BLOB_PUTTER(Double,jdouble)
+
+static void JHwBlob_native_putBool(
+ JNIEnv *env, jobject thiz, jlong offset, jboolean x) {
+
+ sp<JHwBlob> blob = JHwBlob::GetNativeContext(env, thiz);
+
+ bool b = (bool)x;
+ status_t err = blob->write(offset, &b, sizeof(b));
+
+ if (err != OK) {
+ signalExceptionForError(env, err);
+ }
+}
+
+static void JHwBlob_native_putString(
+ JNIEnv *env, jobject thiz, jlong offset, jstring stringObj) {
+ if (stringObj == nullptr) {
+ jniThrowException(env, "java/lang/NullPointerException", nullptr);
+ return;
+ }
+
+ const char *s = env->GetStringUTFChars(stringObj, nullptr);
+
+ if (s == nullptr) {
+ return;
+ }
+
+ size_t size = strlen(s) + 1;
+ ScopedLocalRef<jobject> subBlobObj(env, JHwBlob::NewObject(env, size));
+ sp<JHwBlob> subBlob = JHwBlob::GetNativeContext(env, subBlobObj.get());
+ subBlob->write(0 /* offset */, s, size);
+
+ env->ReleaseStringUTFChars(stringObj, s);
+ s = nullptr;
+
+ hidl_string tmp;
+ tmp.setToExternal(static_cast<const char *>(subBlob->data()), size);
+
+ sp<JHwBlob> blob = JHwBlob::GetNativeContext(env, thiz);
+ blob->write(offset, &tmp, sizeof(tmp));
+ blob->putBlob(offset + hidl_string::kOffsetOfBuffer, subBlob);
+}
+
+static void JHwBlob_native_putBlob(
+ JNIEnv *env, jobject thiz, jlong offset, jobject blobObj) {
+ if (blobObj == nullptr) {
+ jniThrowException(env, "java/lang/NullPointerException", nullptr);
+ return;
+ }
+
+ sp<JHwBlob> blob = JHwBlob::GetNativeContext(env, thiz);
+ sp<JHwBlob> subBlob = JHwBlob::GetNativeContext(env, blobObj);
+
+ blob->putBlob(offset, subBlob);
+}
+
+static jlong JHwBlob_native_handle(JNIEnv *env, jobject thiz) {
+ size_t handle;
+ status_t err = JHwBlob::GetNativeContext(env, thiz)->getHandle(&handle);
+
+ if (err != OK) {
+ signalExceptionForError(env, err);
+ return 0;
+ }
+
+ return handle;
+}
+
+static JNINativeMethod gMethods[] = {
+ { "native_init", "()J", (void *)JHwBlob_native_init },
+ { "native_setup", "(I)V", (void *)JHwBlob_native_setup },
+
+ { "getBool", "(J)Z", (void *)JHwBlob_native_getBool },
+ { "getInt8", "(J)B", (void *)JHwBlob_native_getInt8 },
+ { "getInt16", "(J)S", (void *)JHwBlob_native_getInt16 },
+ { "getInt32", "(J)I", (void *)JHwBlob_native_getInt32 },
+ { "getInt64", "(J)J", (void *)JHwBlob_native_getInt64 },
+ { "getFloat", "(J)F", (void *)JHwBlob_native_getFloat },
+ { "getDouble", "(J)D", (void *)JHwBlob_native_getDouble },
+ { "getString", "(J)Ljava/lang/String;", (void *)JHwBlob_native_getString },
+
+ { "putBool", "(JZ)V", (void *)JHwBlob_native_putBool },
+ { "putInt8", "(JB)V", (void *)JHwBlob_native_putInt8 },
+ { "putInt16", "(JS)V", (void *)JHwBlob_native_putInt16 },
+ { "putInt32", "(JI)V", (void *)JHwBlob_native_putInt32 },
+ { "putInt64", "(JJ)V", (void *)JHwBlob_native_putInt64 },
+ { "putFloat", "(JF)V", (void *)JHwBlob_native_putFloat },
+ { "putDouble", "(JD)V", (void *)JHwBlob_native_putDouble },
+ { "putString", "(JLjava/lang/String;)V", (void *)JHwBlob_native_putString },
+
+ { "putBlob", "(JL" PACKAGE_PATH "/HwBlob;)V",
+ (void *)JHwBlob_native_putBlob },
+
+ { "handle", "()J", (void *)JHwBlob_native_handle },
+};
+
+namespace android {
+
+int register_android_os_HwBlob(JNIEnv *env) {
+ return RegisterMethodsOrDie(env, CLASS_PATH, gMethods, NELEM(gMethods));
+}
+
+} // namespace android
+
diff --git a/core/jni/android_os_HwBlob.h b/core/jni/android_os_HwBlob.h
new file mode 100644
index 0000000..6bd82e9
--- /dev/null
+++ b/core/jni/android_os_HwBlob.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_OS_HW_BLOB_H
+#define ANDROID_OS_HW_BLOB_H
+
+#include <android-base/macros.h>
+#include <jni.h>
+#include <hidl/HidlSupport.h>
+#include <utils/RefBase.h>
+#include <utils/Vector.h>
+
+namespace android {
+
+struct JHwBlob : public RefBase {
+ static void InitClass(JNIEnv *env);
+
+ static sp<JHwBlob> SetNativeContext(
+ JNIEnv *env, jobject thiz, const sp<JHwBlob> &context);
+
+ static sp<JHwBlob> GetNativeContext(JNIEnv *env, jobject thiz);
+
+ static jobject NewObject(JNIEnv *env, const void *ptr, size_t handle);
+ static jobject NewObject(JNIEnv *env, size_t size);
+
+ JHwBlob(JNIEnv *env, jobject thiz, size_t size);
+
+ void setTo(const void *ptr, size_t handle);
+
+ status_t getHandle(size_t *handle) const;
+
+ status_t read(size_t offset, void *data, size_t size) const;
+ status_t write(size_t offset, const void *data, size_t size);
+
+ status_t getString(
+ size_t offset, const android::hardware::hidl_string **s) const;
+
+ const void *data() const;
+ size_t size() const;
+
+ status_t putBlob(size_t offset, const sp<JHwBlob> &blob);
+
+ status_t writeToParcel(hardware::Parcel *parcel) const;
+
+ status_t writeEmbeddedToParcel(
+ hardware::Parcel *parcel,
+ size_t parentHandle,
+ size_t parentOffset) const;
+
+protected:
+ virtual ~JHwBlob();
+
+private:
+ struct BlobInfo {
+ size_t mOffset;
+ sp<JHwBlob> mBlob;
+ };
+
+ jclass mClass;
+ jobject mObject;
+
+ void *mBuffer;
+ size_t mSize;
+ bool mOwnsBuffer;
+
+ size_t mHandle;
+
+ Vector<BlobInfo> mSubBlobs;
+
+ DISALLOW_COPY_AND_ASSIGN(JHwBlob);
+};
+
+int register_android_os_HwBlob(JNIEnv *env);
+
+} // namespace android
+
+#endif // ANDROID_OS_HW_BLOB_H
+
diff --git a/core/jni/android_os_HwParcel.cpp b/core/jni/android_os_HwParcel.cpp
index 94918f6..226d61b 100644
--- a/core/jni/android_os_HwParcel.cpp
+++ b/core/jni/android_os_HwParcel.cpp
@@ -21,6 +21,7 @@
#include "android_os_HwParcel.h"
#include "android_os_HwBinder.h"
+#include "android_os_HwBlob.h"
#include "android_os_HwRemoteBinder.h"
#include <JNIHelp.h>
@@ -71,6 +72,7 @@
break;
}
+ case -ERANGE:
case BAD_INDEX:
{
jniThrowException(env, "java/lang/IndexOutOfBoundsException", NULL);
@@ -200,8 +202,10 @@
jobject JHwParcel::NewObject(JNIEnv *env) {
ScopedLocalRef<jclass> clazz(env, FindClassOrDie(env, CLASS_PATH));
- return env->NewObject(
- clazz.get(), gFields.constructID, false /* allocate */);
+ jmethodID constructID =
+ GetMethodIDOrDie(env, clazz.get(), "<init>", "(Z)V");
+
+ return env->NewObject(clazz.get(), constructID, false /* allocate */);
}
void JHwParcel::setTransactCallback(
@@ -547,9 +551,10 @@
sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz);
- hidl_vec<bool> *vec =
- (hidl_vec<bool> *)impl->getStorage()->allocTemporaryStorage(
- sizeof(hidl_vec<bool>));
+ void *vecPtr =
+ impl->getStorage()->allocTemporaryStorage(sizeof(hidl_vec<bool>));
+
+ hidl_vec<bool> *vec = new (vecPtr) hidl_vec<bool>;
jsize len = env->GetArrayLength(valObj);
@@ -917,9 +922,10 @@
sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz);
- string_vec *vec =
- (string_vec *)impl->getStorage()->allocTemporaryStorage(
- sizeof(string_vec));
+ void *vecPtr =
+ impl->getStorage()->allocTemporaryStorage(sizeof(string_vec));
+
+ string_vec *vec = new (vecPtr) string_vec;
hidl_string *strings = impl->getStorage()->allocStringArray(len);
vec->setToExternal(strings, len);
@@ -972,6 +978,57 @@
return JHwRemoteBinder::NewObject(env, binder);
}
+static jobject JHwParcel_native_readBuffer(JNIEnv *env, jobject thiz) {
+ hardware::Parcel *parcel =
+ JHwParcel::GetNativeContext(env, thiz)->getParcel();
+
+ size_t handle;
+ const void *ptr = parcel->readBuffer(&handle);
+
+ if (ptr == nullptr) {
+ jniThrowException(env, "java/util/NoSuchElementException", NULL);
+ return nullptr;
+ }
+
+ return JHwBlob::NewObject(env, ptr, handle);
+}
+
+static jobject JHwParcel_native_readEmbeddedBuffer(
+ JNIEnv *env, jobject thiz, jlong parentHandle, jlong offset) {
+ hardware::Parcel *parcel =
+ JHwParcel::GetNativeContext(env, thiz)->getParcel();
+
+ size_t childHandle;
+
+ const void *ptr =
+ parcel->readEmbeddedBuffer(&childHandle, parentHandle, offset);
+
+ if (ptr == nullptr) {
+ jniThrowException(env, "java/util/NoSuchElementException", NULL);
+ return 0;
+ }
+
+ return JHwBlob::NewObject(env, ptr, childHandle);
+}
+
+static void JHwParcel_native_writeBuffer(
+ JNIEnv *env, jobject thiz, jobject blobObj) {
+ if (blobObj == nullptr) {
+ jniThrowException(env, "java/lang/NullPointerException", NULL);
+ return;
+ }
+
+ hardware::Parcel *parcel =
+ JHwParcel::GetNativeContext(env, thiz)->getParcel();
+
+ sp<JHwBlob> blob = JHwBlob::GetNativeContext(env, blobObj);
+ status_t err = blob->writeToParcel(parcel);
+
+ if (err != OK) {
+ signalExceptionForError(env, err);
+ }
+}
+
static JNINativeMethod gMethods[] = {
{ "native_init", "()J", (void *)JHwParcel_native_init },
{ "native_setup", "(Z)V", (void *)JHwParcel_native_setup },
@@ -1062,6 +1119,15 @@
(void *)JHwParcel_native_releaseTemporaryStorage },
{ "send", "()V", (void *)JHwParcel_native_send },
+
+ { "readBuffer", "()L" PACKAGE_PATH "/HwBlob;",
+ (void *)JHwParcel_native_readBuffer },
+
+ { "readEmbeddedBuffer", "(JJ)L" PACKAGE_PATH "/HwBlob;",
+ (void *)JHwParcel_native_readEmbeddedBuffer },
+
+ { "writeBuffer", "(L" PACKAGE_PATH "/HwBlob;)V",
+ (void *)JHwParcel_native_writeBuffer },
};
namespace android {
diff --git a/core/jni/hwbinder/EphemeralStorage.cpp b/core/jni/hwbinder/EphemeralStorage.cpp
index e508708..187beee 100644
--- a/core/jni/hwbinder/EphemeralStorage.cpp
+++ b/core/jni/hwbinder/EphemeralStorage.cpp
@@ -99,9 +99,9 @@
item.mPtr = (void *)val; \
mItems.push_back(item); \
\
- hidl_vec<Type> *vec = \
- (hidl_vec<Type> *)allocTemporaryStorage(sizeof(hidl_vec<Type>)); \
+ void *vecPtr = allocTemporaryStorage(sizeof(hidl_vec<Type>)); \
\
+ hidl_vec<Type> *vec = new (vecPtr) hidl_vec<Type>; \
vec->setToExternal(const_cast<Type *>(val), len); \
\
return vec; \