diff options
| -rw-r--r-- | core/java/android/os/HwBlob.java | 74 | ||||
| -rw-r--r-- | core/java/android/os/HwParcel.java | 8 | ||||
| -rw-r--r-- | core/jni/Android.mk | 1 | ||||
| -rw-r--r-- | core/jni/AndroidRuntime.cpp | 2 | ||||
| -rw-r--r-- | core/jni/android_os_HwBlob.cpp | 452 | ||||
| -rw-r--r-- | core/jni/android_os_HwBlob.h | 91 | ||||
| -rw-r--r-- | core/jni/android_os_HwParcel.cpp | 82 | ||||
| -rw-r--r-- | core/jni/hwbinder/EphemeralStorage.cpp | 4 |
8 files changed, 704 insertions, 10 deletions
diff --git a/core/java/android/os/HwBlob.java b/core/java/android/os/HwBlob.java new file mode 100644 index 000000000000..153c6e634ecb --- /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 52579e53fbb1..e4d57184ede9 100644 --- a/core/java/android/os/HwParcel.java +++ b/core/java/android/os/HwParcel.java @@ -101,6 +101,14 @@ public class HwParcel { 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 08be2eb126e0..7e1a0ab06457 100644 --- a/core/jni/Android.mk +++ b/core/jni/Android.mk @@ -81,6 +81,7 @@ LOCAL_SRC_FILES:= \ 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 109d3fbcd847..07392c4055d3 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -157,6 +157,7 @@ extern int register_android_database_SQLiteDebug(JNIEnv* env); 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 @@ static const RegJNIRec gRegJNI[] = { 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 000000000000..6972cf120969 --- /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 000000000000..6bd82e98e911 --- /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 94918f69a2ff..226d61ba57f3 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 @@ void signalExceptionForError(JNIEnv *env, status_t err) { break; } + case -ERANGE: case BAD_INDEX: { jniThrowException(env, "java/lang/IndexOutOfBoundsException", NULL); @@ -200,8 +202,10 @@ void JHwParcel::setParcel(hardware::Parcel *parcel, bool assumeOwnership) { 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 @@ static void JHwParcel_native_writeBoolVector( 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 @@ static void JHwParcel_native_writeStringVector( 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 @@ static jobject JHwParcel_native_readStrongBinder(JNIEnv *env, jobject thiz) { 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 @@ static JNINativeMethod gMethods[] = { (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 e5087081ba55..187beeea4de1 100644 --- a/core/jni/hwbinder/EphemeralStorage.cpp +++ b/core/jni/hwbinder/EphemeralStorage.cpp @@ -99,9 +99,9 @@ const hidl_vec<Type> *EphemeralStorage::allocTemporary ## Suffix ## Vector( \ 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; \ |