Link against libhidl for HidlSupport/svcmgr (DO NOT MERGE)
am: 242030ddad -s ours
Change-Id: I46a3b0bb7739551f546c3b05f86ae222d70ff2c8
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 fe7cdcc..e4d5718 100644
--- a/core/java/android/os/HwParcel.java
+++ b/core/java/android/os/HwParcel.java
@@ -44,6 +44,7 @@
}
public native final void writeInterfaceToken(String interfaceName);
+ public native final void writeBool(boolean val);
public native final void writeInt8(byte val);
public native final void writeInt16(short val);
public native final void writeInt32(int val);
@@ -52,6 +53,8 @@
public native final void writeDouble(double val);
public native final void writeString(String val);
+ public native final void writeBoolArray(int size, boolean[] val);
+ public native final void writeBoolVector(boolean[] val);
public native final void writeInt8Array(int size, byte[] val);
public native final void writeInt8Vector(byte[] val);
public native final void writeInt16Array(int size, short[] val);
@@ -70,6 +73,7 @@
public native final void writeStrongBinder(IHwBinder binder);
public native final void enforceInterface(String interfaceName);
+ public native final boolean readBool();
public native final byte readInt8();
public native final short readInt16();
public native final int readInt32();
@@ -78,6 +82,8 @@
public native final double readDouble();
public native final String readString();
+ public native final boolean[] readBoolArray(int size);
+ public native final boolean[] readBoolVector();
public native final byte[] readInt8Array(int size);
public native final byte[] readInt8Vector();
public native final short[] readInt16Array(int size);
@@ -95,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_HwBinder.cpp b/core/jni/android_os_HwBinder.cpp
index 132ed95..97833a0 100644
--- a/core/jni/android_os_HwBinder.cpp
+++ b/core/jni/android_os_HwBinder.cpp
@@ -26,8 +26,8 @@
#include <JNIHelp.h>
#include <android_runtime/AndroidRuntime.h>
#include <hidl/IServiceManager.h>
+#include <hidl/Status.h>
#include <hwbinder/ProcessState.h>
-#include <hwbinder/Status.h>
#include <nativehelper/ScopedLocalRef.h>
#include "core_jni_helpers.h"
diff --git a/core/jni/android_os_HwBlob.cpp b/core/jni/android_os_HwBlob.cpp
new file mode 100644
index 0000000..b2dee06
--- /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 <hidl/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 0202303..d453b29 100644
--- a/core/jni/android_os_HwParcel.cpp
+++ b/core/jni/android_os_HwParcel.cpp
@@ -21,11 +21,12 @@
#include "android_os_HwParcel.h"
#include "android_os_HwBinder.h"
+#include "android_os_HwBlob.h"
#include "android_os_HwRemoteBinder.h"
#include <JNIHelp.h>
#include <android_runtime/AndroidRuntime.h>
-#include <hwbinder/Status.h>
+#include <hidl/Status.h>
#include <nativehelper/ScopedLocalRef.h>
#include "core_jni_helpers.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(
@@ -333,6 +337,7 @@
return val; \
}
+DEFINE_PARCEL_WRITER(Bool,jboolean)
DEFINE_PARCEL_WRITER(Int8,jbyte)
DEFINE_PARCEL_WRITER(Int16,jshort)
DEFINE_PARCEL_WRITER(Int32,jint)
@@ -347,6 +352,17 @@
DEFINE_PARCEL_READER(Float,jfloat)
DEFINE_PARCEL_READER(Double,jdouble)
+static jboolean JHwParcel_native_readBool(JNIEnv *env, jobject thiz) {
+ hardware::Parcel *parcel =
+ JHwParcel::GetNativeContext(env, thiz)->getParcel();
+
+ bool val;
+ status_t err = parcel->readBool(&val);
+ signalExceptionForError(env, err);
+
+ return (jboolean)val;
+}
+
static void JHwParcel_native_writeStatus(
JNIEnv *env, jobject thiz, jint statusCode) {
using hardware::Status;
@@ -489,6 +505,91 @@
DEFINE_PARCEL_VECTOR_WRITER(Float,jfloat)
DEFINE_PARCEL_VECTOR_WRITER(Double,jdouble)
+static void JHwParcel_native_writeBoolArray(
+ JNIEnv *env, jobject thiz, jint size, jbooleanArray valObj) {
+ if (valObj == NULL) {
+ jniThrowException(env, "java/lang/NullPointerException", NULL);
+ return;
+ }
+
+ jsize len = env->GetArrayLength(valObj);
+
+ if (len != size) {
+ jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
+ return;
+ }
+
+ sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz);
+
+ jboolean *src = env->GetBooleanArrayElements(valObj, nullptr);
+
+ bool *dst =
+ (bool *)impl->getStorage()->allocTemporaryStorage(size * sizeof(bool));
+
+ for (jint i = 0; i < size; ++i) {
+ dst[i] = src[i];
+ }
+
+ env->ReleaseBooleanArrayElements(valObj, src, 0 /* mode */);
+ src = nullptr;
+
+ hardware::Parcel *parcel = impl->getParcel();
+
+ size_t parentHandle;
+ status_t err = parcel->writeBuffer(
+ dst, size * sizeof(*dst), &parentHandle);
+
+ signalExceptionForError(env, err);
+}
+
+static void JHwParcel_native_writeBoolVector(
+ JNIEnv *env, jobject thiz, jbooleanArray valObj) {
+ if (valObj == NULL) {
+ jniThrowException(env, "java/lang/NullPointerException", NULL);
+ return;
+ }
+
+ sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz);
+
+ void *vecPtr =
+ impl->getStorage()->allocTemporaryStorage(sizeof(hidl_vec<bool>));
+
+ hidl_vec<bool> *vec = new (vecPtr) hidl_vec<bool>;
+
+ jsize len = env->GetArrayLength(valObj);
+
+ jboolean *src = env->GetBooleanArrayElements(valObj, nullptr);
+
+ bool *dst =
+ (bool *)impl->getStorage()->allocTemporaryStorage(len * sizeof(bool));
+
+ for (jsize i = 0; i < len; ++i) {
+ dst[i] = src[i];
+ }
+
+ env->ReleaseBooleanArrayElements(valObj, src, 0 /* mode */);
+ src = nullptr;
+
+ vec->setToExternal(dst, len);
+
+ hardware::Parcel *parcel = impl->getParcel();
+
+ size_t parentHandle;
+ status_t err = parcel->writeBuffer(vec, sizeof(*vec), &parentHandle);
+
+ if (err == OK) {
+ size_t childHandle;
+
+ err = vec->writeEmbeddedToParcel(
+ parcel,
+ parentHandle,
+ 0 /* parentOffset */,
+ &childHandle);
+ }
+
+ signalExceptionForError(env, err);
+}
+
static void JHwParcel_native_writeStrongBinder(
JNIEnv *env, jobject thiz, jobject binderObj) {
sp<hardware::IBinder> binder;
@@ -616,6 +717,64 @@
DEFINE_PARCEL_VECTOR_READER(Float,jfloat,Float)
DEFINE_PARCEL_VECTOR_READER(Double,jdouble,Double)
+static jbooleanArray JHwParcel_native_readBoolArray(
+ JNIEnv *env, jobject thiz, jint size) {
+ hardware::Parcel *parcel =
+ JHwParcel::GetNativeContext(env, thiz)->getParcel();
+
+ size_t parentHandle;
+ const bool *val = static_cast<const bool *>(
+ parcel->readBuffer(&parentHandle));
+
+ jbooleanArray valObj = env->NewBooleanArray(size);
+
+ for (jint i = 0; i < size; ++i) {
+ jboolean x = val[i];
+ env->SetBooleanArrayRegion(valObj, i, 1, &x);
+ }
+
+ return valObj;
+}
+
+static jbooleanArray JHwParcel_native_readBoolVector(
+ JNIEnv *env, jobject thiz) {
+ hardware::Parcel *parcel =
+ JHwParcel::GetNativeContext(env, thiz)->getParcel();
+
+ size_t parentHandle;
+
+ const hidl_vec<bool> *vec =
+ (const hidl_vec<bool> *)parcel->readBuffer(&parentHandle);
+
+ if (vec == NULL) {
+ signalExceptionForError(env, UNKNOWN_ERROR);
+ return NULL;
+ }
+
+ size_t childHandle;
+
+ status_t err = const_cast<hidl_vec<bool> *>(vec)
+ ->readEmbeddedFromParcel(
+ *parcel,
+ parentHandle,
+ 0 /* parentOffset */,
+ &childHandle);
+
+ if (err != OK) {
+ signalExceptionForError(env, err);
+ return NULL;
+ }
+
+ jbooleanArray valObj = env->NewBooleanArray(vec->size());
+
+ for (size_t i = 0; i < vec->size(); ++i) {
+ jboolean x = (*vec)[i];
+ env->SetBooleanArrayRegion(valObj, i, 1, &x);
+ }
+
+ return valObj;
+}
+
static jobjectArray MakeStringArray(
JNIEnv *env, const hidl_string *array, size_t size) {
ScopedLocalRef<jclass> stringKlass(
@@ -763,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);
@@ -818,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 },
@@ -825,6 +1036,7 @@
{ "writeInterfaceToken", "(Ljava/lang/String;)V",
(void *)JHwParcel_native_writeInterfaceToken },
+ { "writeBool", "(Z)V", (void *)JHwParcel_native_writeBool },
{ "writeInt8", "(B)V", (void *)JHwParcel_native_writeInt8 },
{ "writeInt16", "(S)V", (void *)JHwParcel_native_writeInt16 },
{ "writeInt32", "(I)V", (void *)JHwParcel_native_writeInt32 },
@@ -835,6 +1047,8 @@
{ "writeString", "(Ljava/lang/String;)V",
(void *)JHwParcel_native_writeString },
+ { "writeBoolArray", "(I[Z)V", (void *)JHwParcel_native_writeBoolArray },
+ { "writeBoolVector", "([Z)V", (void *)JHwParcel_native_writeBoolVector },
{ "writeInt8Array", "(I[B)V", (void *)JHwParcel_native_writeInt8Array },
{ "writeInt8Vector", "([B)V", (void *)JHwParcel_native_writeInt8Vector },
{ "writeInt16Array", "(I[S)V", (void *)JHwParcel_native_writeInt16Array },
@@ -862,6 +1076,7 @@
{ "enforceInterface", "(Ljava/lang/String;)V",
(void *)JHwParcel_native_enforceInterface },
+ { "readBool", "()Z", (void *)JHwParcel_native_readBool },
{ "readInt8", "()B", (void *)JHwParcel_native_readInt8 },
{ "readInt16", "()S", (void *)JHwParcel_native_readInt16 },
{ "readInt32", "()I", (void *)JHwParcel_native_readInt32 },
@@ -872,6 +1087,8 @@
{ "readString", "()Ljava/lang/String;",
(void *)JHwParcel_native_readString },
+ { "readBoolArray", "(I)[Z", (void *)JHwParcel_native_readBoolArray },
+ { "readBoolVector", "()[Z", (void *)JHwParcel_native_readBoolVector },
{ "readInt8Array", "(I)[B", (void *)JHwParcel_native_readInt8Array },
{ "readInt8Vector", "()[B", (void *)JHwParcel_native_readInt8Vector },
{ "readInt16Array", "(I)[S", (void *)JHwParcel_native_readInt16Array },
@@ -902,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/android_os_HwRemoteBinder.cpp b/core/jni/android_os_HwRemoteBinder.cpp
index 81ba368..3023ba8 100644
--- a/core/jni/android_os_HwRemoteBinder.cpp
+++ b/core/jni/android_os_HwRemoteBinder.cpp
@@ -25,7 +25,7 @@
#include <JNIHelp.h>
#include <android_runtime/AndroidRuntime.h>
#include <hidl/IServiceManager.h>
-#include <hwbinder/Status.h>
+#include <hidl/Status.h>
#include <nativehelper/ScopedLocalRef.h>
#include "core_jni_helpers.h"
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; \