Adds framework support for hidl-gen Java backend. (to support structs)
Bug: 30575790 Change-Id: Ida30d8fe7a1b210e98f1a0ea5d429a0112f9ef3f Signed-off-by: Iliyan Malchev <malchev@google.com>
This commit is contained in:
committed by
Martijn Coenen
parent
e1eb45d8d6
commit
50546a98ed
74
core/java/android/os/HwBlob.java
Normal file
74
core/java/android/os/HwBlob.java
Normal file
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -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),
|
||||
|
||||
452
core/jni/android_os_HwBlob.cpp
Normal file
452
core/jni/android_os_HwBlob.cpp
Normal file
@@ -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
|
||||
|
||||
91
core/jni/android_os_HwBlob.h
Normal file
91
core/jni/android_os_HwBlob.h
Normal file
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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; \
|
||||
|
||||
Reference in New Issue
Block a user