--- /dev/null
+/*
+ * 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 abstract class HwBinder implements IHwBinder {
+ private static final String TAG = "HwBinder";
+
+ private static final NativeAllocationRegistry sNativeRegistry;
+
+ public HwBinder() {
+ native_setup();
+
+ sNativeRegistry.registerNativeAllocation(
+ this,
+ mNativeContext);
+ }
+
+ public final native void transact(
+ int code, HwParcel request, HwParcel reply, int flags);
+
+ public abstract void onTransact(
+ int code, HwParcel request, HwParcel reply, int flags);
+
+ public native final void registerService(String serviceName);
+ public static native final IHwBinder getService(String serviceName);
+
+ // Returns address of the "freeFunction".
+ private static native final long native_init();
+
+ private native final void native_setup();
+
+ static {
+ long freeFunction = native_init();
+
+ sNativeRegistry = new NativeAllocationRegistry(
+ HwBinder.class.getClassLoader(),
+ freeFunction,
+ 128 /* size */);
+ }
+
+ private long mNativeContext;
+}
--- /dev/null
+/*
+ * 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 HwParcel {
+ private static final String TAG = "HwParcel";
+
+ public static final int STATUS_SUCCESS = 0;
+ public static final int STATUS_ERROR = -1;
+
+ private static final NativeAllocationRegistry sNativeRegistry;
+
+ private HwParcel(boolean allocate) {
+ native_setup(allocate);
+
+ sNativeRegistry.registerNativeAllocation(
+ this,
+ mNativeContext);
+ }
+
+ public HwParcel() {
+ native_setup(true /* allocate */);
+
+ sNativeRegistry.registerNativeAllocation(
+ this,
+ mNativeContext);
+ }
+
+ public native final void writeInterfaceToken(String interfaceName);
+ public native final void writeInt8(byte val);
+ public native final void writeInt16(short val);
+ public native final void writeInt32(int val);
+ public native final void writeInt64(long val);
+ public native final void writeFloat(float val);
+ public native final void writeDouble(double val);
+ public native final void writeString(String 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);
+ public native final void writeInt16Vector(short[] val);
+ public native final void writeInt32Array(int size, int[] val);
+ public native final void writeInt32Vector(int[] val);
+ public native final void writeInt64Array(int size, long[] val);
+ public native final void writeInt64Vector(long[] val);
+ public native final void writeFloatArray(int size, float[] val);
+ public native final void writeFloatVector(float[] val);
+ public native final void writeDoubleArray(int size, double[] val);
+ public native final void writeDoubleVector(double[] val);
+ public native final void writeStringArray(int size, String[] val);
+ public native final void writeStringVector(String[] val);
+
+ public native final void writeStrongBinder(IHwBinder binder);
+
+ public native final void enforceInterface(String interfaceName);
+ public native final byte readInt8();
+ public native final short readInt16();
+ public native final int readInt32();
+ public native final long readInt64();
+ public native final float readFloat();
+ public native final double readDouble();
+ public native final String readString();
+
+ public native final byte[] readInt8Array(int size);
+ public native final byte[] readInt8Vector();
+ public native final short[] readInt16Array(int size);
+ public native final short[] readInt16Vector();
+ public native final int[] readInt32Array(int size);
+ public native final int[] readInt32Vector();
+ public native final long[] readInt64Array(int size);
+ public native final long[] readInt64Vector();
+ public native final float[] readFloatArray(int size);
+ public native final float[] readFloatVector();
+ public native final double[] readDoubleArray(int size);
+ public native final double[] readDoubleVector();
+ public native final String[] readStringArray(int size);
+ public native final String[] readStringVector();
+
+ public native final IHwBinder readStrongBinder();
+
+ public native final void writeStatus(int status);
+ public native final void verifySuccess();
+ public native final void releaseTemporaryStorage();
+
+ public native final void send();
+
+ // Returns address of the "freeFunction".
+ private static native final long native_init();
+
+ private native final void native_setup(boolean allocate);
+
+ static {
+ long freeFunction = native_init();
+
+ sNativeRegistry = new NativeAllocationRegistry(
+ HwParcel.class.getClassLoader(),
+ freeFunction,
+ 128 /* size */);
+ }
+
+ private long mNativeContext;
+}
+
--- /dev/null
+/*
+ * 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 HwRemoteBinder implements IHwBinder {
+ private static final String TAG = "HwRemoteBinder";
+
+ private static final NativeAllocationRegistry sNativeRegistry;
+
+ public HwRemoteBinder() {
+ native_setup_empty();
+
+ sNativeRegistry.registerNativeAllocation(
+ this,
+ mNativeContext);
+ }
+
+ public IHwInterface queryLocalInterface(String descriptor) {
+ return null;
+ }
+
+ public native final void transact(
+ int code, HwParcel request, HwParcel reply, int flags);
+
+ private static native final long native_init();
+
+ private native final void native_setup_empty();
+
+ static {
+ long freeFunction = native_init();
+
+ sNativeRegistry = new NativeAllocationRegistry(
+ HwRemoteBinder.class.getClassLoader(),
+ freeFunction,
+ 128 /* size */);
+ }
+
+ private long mNativeContext;
+}
--- /dev/null
+/*
+ * 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;
+
+/** @hide */
+public interface IHwBinder {
+ // MUST match libhwbinder/IBinder.h definition !!!
+ public static final int FIRST_CALL_TRANSACTION = 1;
+
+ public void transact(
+ int code, HwParcel request, HwParcel reply, int flags);
+
+ public IHwInterface queryLocalInterface(String descriptor);
+}
--- /dev/null
+/*
+ * 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;
+
+/** @hide */
+public interface IHwInterface {
+ public IHwBinder asBinder();
+}
android_text_AndroidBidi.cpp \
android_text_StaticLayout.cpp \
android_os_Debug.cpp \
+ android_os_HwBinder.cpp \
+ android_os_HwParcel.cpp \
+ android_os_HwRemoteBinder.cpp \
android_os_MemoryFile.cpp \
android_os_MessageQueue.cpp \
android_os_Parcel.cpp \
com_android_internal_os_PathClassLoaderFactory.cpp \
com_android_internal_os_Zygote.cpp \
com_android_internal_util_VirtualRefBasePtr.cpp \
- com_android_internal_view_animation_NativeInterpolatorFactoryHelper.cpp
+ com_android_internal_view_animation_NativeInterpolatorFactoryHelper.cpp \
+ hwbinder/EphemeralStorage.cpp \
LOCAL_C_INCLUDES += \
$(JNI_H_INCLUDE) \
libradio_metadata \
libnativeloader \
libmemunreachable \
+ libhwbinder \
LOCAL_SHARED_LIBRARIES += \
libhwui \
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_HwParcel(JNIEnv *env);
+extern int register_android_os_HwRemoteBinder(JNIEnv *env);
extern int register_android_os_MessageQueue(JNIEnv* env);
extern int register_android_os_Parcel(JNIEnv* env);
extern int register_android_os_SELinux(JNIEnv* env);
REG_JNI(register_android_os_SystemProperties),
REG_JNI(register_android_os_Binder),
REG_JNI(register_android_os_Parcel),
+ REG_JNI(register_android_os_HwBinder),
+ REG_JNI(register_android_os_HwParcel),
+ REG_JNI(register_android_os_HwRemoteBinder),
REG_JNI(register_android_nio_utils),
REG_JNI(register_android_graphics_Canvas),
REG_JNI(register_android_graphics_Graphics),
--- /dev/null
+/*
+ * 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_HwBinder"
+#include <android-base/logging.h>
+
+#include "android_os_HwBinder.h"
+
+#include "android_os_HwParcel.h"
+#include "android_os_HwRemoteBinder.h"
+
+#include <JNIHelp.h>
+#include <android_runtime/AndroidRuntime.h>
+#include <hwbinder/IServiceManager.h>
+#include <hwbinder/ProcessState.h>
+#include <hwbinder/Status.h>
+#include <nativehelper/ScopedLocalRef.h>
+
+#include "core_jni_helpers.h"
+
+using android::AndroidRuntime;
+
+#define PACKAGE_PATH "android/os"
+#define CLASS_NAME "HwBinder"
+#define CLASS_PATH PACKAGE_PATH "/" CLASS_NAME
+
+namespace android {
+
+static struct fields_t {
+ jfieldID contextID;
+ jmethodID onTransactID;
+
+} gFields;
+
+// static
+void JHwBinder::InitClass(JNIEnv *env) {
+ ScopedLocalRef<jclass> clazz(
+ env, FindClassOrDie(env, CLASS_PATH));
+
+ gFields.contextID =
+ GetFieldIDOrDie(env, clazz.get(), "mNativeContext", "J");
+
+ gFields.onTransactID =
+ GetMethodIDOrDie(
+ env,
+ clazz.get(),
+ "onTransact",
+ "(IL" PACKAGE_PATH "/HwParcel;L" PACKAGE_PATH "/HwParcel;I)V");
+}
+
+// static
+sp<JHwBinder> JHwBinder::SetNativeContext(
+ JNIEnv *env, jobject thiz, const sp<JHwBinder> &context) {
+ sp<JHwBinder> old =
+ (JHwBinder *)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<JHwBinder> JHwBinder::GetNativeContext(
+ JNIEnv *env, jobject thiz) {
+ return (JHwBinder *)env->GetLongField(thiz, gFields.contextID);
+}
+
+JHwBinder::JHwBinder(JNIEnv *env, jobject thiz) {
+ jclass clazz = env->GetObjectClass(thiz);
+ CHECK(clazz != NULL);
+
+ mClass = (jclass)env->NewGlobalRef(clazz);
+ mObject = env->NewWeakGlobalRef(thiz);
+}
+
+JHwBinder::~JHwBinder() {
+ JNIEnv *env = AndroidRuntime::getJNIEnv();
+
+ env->DeleteWeakGlobalRef(mObject);
+ mObject = NULL;
+
+ env->DeleteGlobalRef(mClass);
+ mClass = NULL;
+}
+
+status_t JHwBinder::onTransact(
+ uint32_t code,
+ const hardware::Parcel &data,
+ hardware::Parcel *reply,
+ uint32_t flags,
+ TransactCallback callback) {
+ JNIEnv *env = AndroidRuntime::getJNIEnv();
+
+ ScopedLocalRef<jobject> requestObj(env, JHwParcel::NewObject(env));
+ JHwParcel::GetNativeContext(env, requestObj.get())->setParcel(
+ const_cast<hardware::Parcel *>(&data), false /* assumeOwnership */);
+
+ ScopedLocalRef<jobject> replyObj(env, JHwParcel::NewObject(env));
+
+ sp<JHwParcel> replyContext =
+ JHwParcel::GetNativeContext(env, replyObj.get());
+
+ replyContext->setParcel(reply, false /* assumeOwnership */);
+ replyContext->setTransactCallback(callback);
+
+ env->CallVoidMethod(
+ mObject,
+ gFields.onTransactID,
+ code,
+ requestObj.get(),
+ replyObj.get(),
+ flags);
+
+ status_t err = OK;
+
+ if (!replyContext->wasSent()) {
+ // The implementation never finished the transaction.
+ err = UNKNOWN_ERROR; // XXX special error code instead?
+
+ reply->setDataPosition(0 /* pos */);
+ }
+
+ // Release all temporary storage now that scatter-gather data
+ // has been consolidated, either by calling the TransactCallback,
+ // if wasSent() == true or clearing the reply parcel (setDataOffset above).
+ replyContext->getStorage()->release(env);
+
+ // We cannot permanently pass ownership of "data" and "reply" over to their
+ // Java object wrappers (we don't own them ourselves).
+
+ JHwParcel::GetNativeContext(env, requestObj.get())->setParcel(
+ NULL /* parcel */, false /* assumeOwnership */);
+
+ replyContext->setParcel(
+ NULL /* parcel */, false /* assumeOwnership */);
+
+ return err;
+}
+
+} // namespace android
+
+////////////////////////////////////////////////////////////////////////////////
+
+using namespace android;
+
+static void releaseNativeContext(void *nativeContext) {
+ sp<JHwBinder> binder = (JHwBinder *)nativeContext;
+
+ if (binder != NULL) {
+ binder->decStrong(NULL /* id */);
+ }
+}
+
+static jlong JHwBinder_native_init(JNIEnv *env) {
+ JHwBinder::InitClass(env);
+
+ return reinterpret_cast<jlong>(&releaseNativeContext);
+}
+
+static void JHwBinder_native_setup(JNIEnv *env, jobject thiz) {
+ sp<JHwBinder> context = new JHwBinder(env, thiz);
+
+ JHwBinder::SetNativeContext(env, thiz, context);
+}
+
+static void JHwBinder_native_transact(
+ JNIEnv * /* env */,
+ jobject /* thiz */,
+ jint /* code */,
+ jobject /* requestObj */,
+ jobject /* replyObj */,
+ jint /* flags */) {
+ CHECK(!"Should not be here");
+}
+
+static void JHwBinder_native_registerService(
+ JNIEnv *env, jobject thiz, jstring serviceNameObj) {
+ if (serviceNameObj == NULL) {
+ jniThrowException(env, "java/lang/NullPointerException", NULL);
+ return;
+ }
+
+ const jchar *serviceName = env->GetStringCritical(serviceNameObj, NULL);
+
+ if (serviceName == NULL) {
+ return; // XXX exception already pending?
+ }
+
+ const hardware::hidl_version kVersion = hardware::make_hidl_version(1, 0);
+
+ sp<hardware::IBinder> binder = JHwBinder::GetNativeContext(env, thiz);
+
+ status_t err = hardware::defaultServiceManager()->addService(
+ String16(reinterpret_cast<const char16_t *>(serviceName)),
+ binder,
+ kVersion);
+
+ env->ReleaseStringCritical(serviceNameObj, serviceName);
+ serviceName = NULL;
+
+ if (err == OK) {
+ LOG(INFO) << "Starting thread pool.";
+ ::android::hardware::ProcessState::self()->startThreadPool();
+ }
+
+ signalExceptionForError(env, err);
+}
+
+static jobject JHwBinder_native_getService(
+ JNIEnv *env, jclass /* clazzObj */, jstring serviceNameObj) {
+ if (serviceNameObj == NULL) {
+ jniThrowException(env, "java/lang/NullPointerException", NULL);
+ return NULL;
+ }
+
+ const jchar *serviceName = env->GetStringCritical(serviceNameObj, NULL);
+
+ if (serviceName == NULL) {
+ return NULL; // XXX exception already pending?
+ }
+
+ const hardware::hidl_version kVersion = hardware::make_hidl_version(1, 0);
+
+ LOG(INFO) << "looking for service '"
+ << String8(String16(
+ reinterpret_cast<const char16_t *>(serviceName))).string()
+ << "'";
+
+ sp<hardware::IBinder> service =
+ hardware::defaultServiceManager()->getService(
+ String16(reinterpret_cast<const char16_t *>(serviceName)),
+ kVersion);
+
+ env->ReleaseStringCritical(serviceNameObj, serviceName);
+ serviceName = NULL;
+
+ if (service == NULL) {
+ signalExceptionForError(env, NAME_NOT_FOUND);
+ return NULL;
+ }
+
+ return JHwRemoteBinder::NewObject(env, service);
+}
+
+static JNINativeMethod gMethods[] = {
+ { "native_init", "()J", (void *)JHwBinder_native_init },
+ { "native_setup", "()V", (void *)JHwBinder_native_setup },
+
+ { "transact",
+ "(IL" PACKAGE_PATH "/HwParcel;L" PACKAGE_PATH "/HwParcel;I)V",
+ (void *)JHwBinder_native_transact },
+
+ { "registerService", "(Ljava/lang/String;)V",
+ (void *)JHwBinder_native_registerService },
+
+ { "getService", "(Ljava/lang/String;)L" PACKAGE_PATH "/IHwBinder;",
+ (void *)JHwBinder_native_getService },
+};
+
+namespace android {
+
+int register_android_os_HwBinder(JNIEnv *env) {
+ return RegisterMethodsOrDie(env, CLASS_PATH, gMethods, NELEM(gMethods));
+}
+
+} // namespace android
--- /dev/null
+/*
+ * 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_BINDER_H
+#define _ANDROID_OS_HW_BINDER_H
+
+#include <android-base/macros.h>
+#include <hwbinder/Binder.h>
+#include <jni.h>
+#include <utils/RefBase.h>
+
+namespace android {
+
+struct JHwBinder : public hardware::BBinder {
+ static void InitClass(JNIEnv *env);
+
+ static sp<JHwBinder> SetNativeContext(
+ JNIEnv *env, jobject thiz, const sp<JHwBinder> &context);
+
+ static sp<JHwBinder> GetNativeContext(JNIEnv *env, jobject thiz);
+
+ JHwBinder(JNIEnv *env, jobject thiz);
+
+protected:
+ virtual ~JHwBinder();
+
+ virtual status_t onTransact(
+ uint32_t code,
+ const hardware::Parcel &data,
+ hardware::Parcel *reply,
+ uint32_t flags,
+ TransactCallback callback);
+
+private:
+ jclass mClass;
+ jobject mObject;
+
+ DISALLOW_COPY_AND_ASSIGN(JHwBinder);
+};
+
+int register_android_os_HwBinder(JNIEnv *env);
+
+} // namespace android
+
+#endif // _ANDROID_OS_HW_BINDER_H
+
+
--- /dev/null
+/*
+ * 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_HwParcel"
+#include <android-base/logging.h>
+
+#include "android_os_HwParcel.h"
+
+#include "android_os_HwBinder.h"
+#include "android_os_HwRemoteBinder.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;
+using ::android::hardware::hidl_vec;
+
+#define PACKAGE_PATH "android/os"
+#define CLASS_NAME "HwParcel"
+#define CLASS_PATH PACKAGE_PATH "/" CLASS_NAME
+
+namespace android {
+
+static struct fields_t {
+ jfieldID contextID;
+ jmethodID constructID;
+
+} gFields;
+
+void signalExceptionForError(JNIEnv *env, status_t err) {
+ switch (err) {
+ case OK:
+ break;
+
+ case NO_MEMORY:
+ {
+ jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
+ break;
+ }
+
+ case INVALID_OPERATION:
+ {
+ jniThrowException(
+ env, "java/lang/UnsupportedOperationException", NULL);
+ break;
+ }
+
+ case BAD_VALUE:
+ {
+ jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
+ break;
+ }
+
+ case BAD_INDEX:
+ {
+ jniThrowException(env, "java/lang/IndexOutOfBoundsException", NULL);
+ break;
+ }
+
+ case BAD_TYPE:
+ {
+ jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
+ break;
+ }
+
+ case NAME_NOT_FOUND:
+ {
+ jniThrowException(env, "java/util/NoSuchElementException", NULL);
+ break;
+ }
+
+ case PERMISSION_DENIED:
+ {
+ jniThrowException(env, "java/lang/SecurityException", NULL);
+ break;
+ }
+
+ case NO_INIT:
+ {
+ jniThrowException(
+ env, "java/lang/RuntimeException", "Not initialized");
+ break;
+ }
+
+ case ALREADY_EXISTS:
+ {
+ jniThrowException(
+ env, "java/lang/RuntimeException", "Item already exists");
+ break;
+ }
+
+ default:
+ {
+ jniThrowException(
+ env, "java/lang/RuntimeException", "Unknown error");
+
+ break;
+ }
+ }
+}
+
+// static
+void JHwParcel::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>", "(Z)V");
+}
+
+// static
+sp<JHwParcel> JHwParcel::SetNativeContext(
+ JNIEnv *env, jobject thiz, const sp<JHwParcel> &context) {
+ sp<JHwParcel> old = (JHwParcel *)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<JHwParcel> JHwParcel::GetNativeContext(JNIEnv *env, jobject thiz) {
+ return (JHwParcel *)env->GetLongField(thiz, gFields.contextID);
+}
+
+JHwParcel::JHwParcel(JNIEnv *env, jobject thiz)
+ : mParcel(NULL),
+ mOwnsParcel(false),
+ mTransactCallback(nullptr),
+ mWasSent(false) {
+ jclass clazz = env->GetObjectClass(thiz);
+ CHECK(clazz != NULL);
+
+ mClass = (jclass)env->NewGlobalRef(clazz);
+ mObject = env->NewWeakGlobalRef(thiz);
+}
+
+JHwParcel::~JHwParcel() {
+ JNIEnv *env = AndroidRuntime::getJNIEnv();
+
+ mStorage.release(env);
+
+ setParcel(NULL, false /* assumeOwnership */);
+
+ env->DeleteWeakGlobalRef(mObject);
+ mObject = NULL;
+
+ env->DeleteGlobalRef(mClass);
+ mClass = NULL;
+}
+
+hardware::Parcel *JHwParcel::getParcel() {
+ return mParcel;
+}
+
+EphemeralStorage *JHwParcel::getStorage() {
+ return &mStorage;
+}
+
+void JHwParcel::setParcel(hardware::Parcel *parcel, bool assumeOwnership) {
+ if (mParcel && mOwnsParcel) {
+ delete mParcel;
+ }
+
+ mParcel = parcel;
+ mOwnsParcel = assumeOwnership;
+}
+
+// static
+jobject JHwParcel::NewObject(JNIEnv *env) {
+ ScopedLocalRef<jclass> clazz(env, FindClassOrDie(env, CLASS_PATH));
+
+ return env->NewObject(
+ clazz.get(), gFields.constructID, false /* allocate */);
+}
+
+void JHwParcel::setTransactCallback(
+ ::android::hardware::IBinder::TransactCallback cb) {
+ mTransactCallback = cb;
+}
+
+void JHwParcel::send() {
+ CHECK(mTransactCallback != nullptr);
+ CHECK(mParcel != nullptr);
+
+ mTransactCallback(*mParcel);
+ mTransactCallback = nullptr;
+
+ mWasSent = true;
+}
+
+bool JHwParcel::wasSent() const {
+ return mWasSent;
+}
+
+} // namespace android
+
+////////////////////////////////////////////////////////////////////////////////
+
+using namespace android;
+
+static void releaseNativeContext(void *nativeContext) {
+ sp<JHwParcel> parcel = (JHwParcel *)nativeContext;
+
+ if (parcel != NULL) {
+ parcel->decStrong(NULL /* id */);
+ }
+}
+
+static jlong JHwParcel_native_init(JNIEnv *env) {
+ JHwParcel::InitClass(env);
+
+ return reinterpret_cast<jlong>(&releaseNativeContext);
+}
+
+static void JHwParcel_native_setup(
+ JNIEnv *env, jobject thiz, jboolean allocate) {
+ sp<JHwParcel> context = new JHwParcel(env, thiz);
+
+ if (allocate) {
+ context->setParcel(new hardware::Parcel, true /* assumeOwnership */);
+ }
+
+ JHwParcel::SetNativeContext(env, thiz, context);
+}
+
+static void JHwParcel_native_writeInterfaceToken(
+ JNIEnv *env, jobject thiz, jstring interfaceNameObj) {
+ if (interfaceNameObj == NULL) {
+ jniThrowException(env, "java/lang/NullPointerException", NULL);
+ return;
+ }
+
+ const jchar *interfaceName = env->GetStringCritical(interfaceNameObj, NULL);
+ if (interfaceName) {
+ hardware::Parcel *parcel =
+ JHwParcel::GetNativeContext(env, thiz)->getParcel();
+
+ status_t err = parcel->writeInterfaceToken(
+ String16(
+ reinterpret_cast<const char16_t *>(interfaceName),
+ env->GetStringLength(interfaceNameObj)));
+
+ env->ReleaseStringCritical(interfaceNameObj, interfaceName);
+ interfaceName = NULL;
+
+ signalExceptionForError(env, err);
+ }
+}
+
+static void JHwParcel_native_enforceInterface(
+ JNIEnv *env, jobject thiz, jstring interfaceNameObj) {
+ // XXX original binder Parcel enforceInterface implementation does some
+ // mysterious things regarding strictModePolicy(), figure out if we need
+ // that here as well.
+ if (interfaceNameObj == NULL) {
+ jniThrowException(env, "java/lang/NullPointerException", NULL);
+ return;
+ }
+
+ const jchar *interfaceName = env->GetStringCritical(interfaceNameObj, NULL);
+ if (interfaceName) {
+ hardware::Parcel *parcel =
+ JHwParcel::GetNativeContext(env, thiz)->getParcel();
+
+ bool valid = parcel->enforceInterface(
+ String16(
+ reinterpret_cast<const char16_t *>(interfaceName),
+ env->GetStringLength(interfaceNameObj)));
+
+ env->ReleaseStringCritical(interfaceNameObj, interfaceName);
+ interfaceName = NULL;
+
+ if (!valid) {
+ jniThrowException(
+ env,
+ "java/lang/SecurityException",
+ "HWBinder invocation to an incorrect interface");
+ }
+ }
+}
+
+#define DEFINE_PARCEL_WRITER(Suffix,Type) \
+static void JHwParcel_native_write ## Suffix( \
+ JNIEnv *env, jobject thiz, Type val) { \
+ hardware::Parcel *parcel = \
+ JHwParcel::GetNativeContext(env, thiz)->getParcel(); \
+ \
+ status_t err = parcel->write ## Suffix(val); \
+ signalExceptionForError(env, err); \
+}
+
+#define DEFINE_PARCEL_READER(Suffix,Type) \
+static Type JHwParcel_native_read ## Suffix( \
+ JNIEnv *env, jobject thiz) { \
+ hardware::Parcel *parcel = \
+ JHwParcel::GetNativeContext(env, thiz)->getParcel(); \
+ \
+ Type val; \
+ status_t err = parcel->read ## Suffix(&val); \
+ signalExceptionForError(env, err); \
+ \
+ return val; \
+}
+
+DEFINE_PARCEL_WRITER(Int8,jbyte)
+DEFINE_PARCEL_WRITER(Int16,jshort)
+DEFINE_PARCEL_WRITER(Int32,jint)
+DEFINE_PARCEL_WRITER(Int64,jlong)
+DEFINE_PARCEL_WRITER(Float,jfloat)
+DEFINE_PARCEL_WRITER(Double,jdouble)
+
+DEFINE_PARCEL_READER(Int8,jbyte)
+DEFINE_PARCEL_READER(Int16,jshort)
+DEFINE_PARCEL_READER(Int32,jint)
+DEFINE_PARCEL_READER(Int64,jlong)
+DEFINE_PARCEL_READER(Float,jfloat)
+DEFINE_PARCEL_READER(Double,jdouble)
+
+static void JHwParcel_native_writeStatus(
+ JNIEnv *env, jobject thiz, jint statusCode) {
+ using hardware::Status;
+
+ Status status;
+ switch (statusCode) {
+ case 0: // kStatusSuccess
+ status = Status::ok();
+ break;
+ case -1: // kStatusError
+ status = Status::fromStatusT(UNKNOWN_ERROR);
+ break;
+ default:
+ CHECK(!"Should not be here");
+ }
+
+ hardware::Parcel *parcel =
+ JHwParcel::GetNativeContext(env, thiz)->getParcel();
+
+ status_t err = status.writeToParcel(parcel);
+ signalExceptionForError(env, err);
+}
+
+static void JHwParcel_native_verifySuccess(JNIEnv *env, jobject thiz) {
+ using hardware::Status;
+
+ hardware::Parcel *parcel =
+ JHwParcel::GetNativeContext(env, thiz)->getParcel();
+
+ Status status;
+ status_t err = status.readFromParcel(*parcel);
+ signalExceptionForError(env, err);
+}
+
+static void JHwParcel_native_releaseTemporaryStorage(
+ JNIEnv *env, jobject thiz) {
+ JHwParcel::GetNativeContext(env, thiz)->getStorage()->release(env);
+}
+
+static void JHwParcel_native_send(JNIEnv *env, jobject thiz) {
+ JHwParcel::GetNativeContext(env, thiz)->send();
+}
+
+static void JHwParcel_native_writeString(
+ JNIEnv *env, jobject thiz, jstring valObj) {
+ if (valObj == NULL) {
+ jniThrowException(env, "java/lang/NullPointerException", NULL);
+ return;
+ }
+
+ sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz);
+
+ const hidl_string *s =
+ impl->getStorage()->allocTemporaryString(env, valObj);
+
+ hardware::Parcel *parcel = impl->getParcel();
+
+ size_t parentHandle;
+ status_t err = parcel->writeBuffer(s, sizeof(*s), &parentHandle);
+
+ if (err == OK) {
+ err = s->writeEmbeddedToParcel(
+ parcel, parentHandle, 0 /* parentOffset */);
+ }
+
+ signalExceptionForError(env, err);
+}
+
+#define DEFINE_PARCEL_ARRAY_WRITER(Suffix,Type) \
+static void JHwParcel_native_write ## Suffix ## Array( \
+ JNIEnv *env, jobject thiz, jint size, Type ## Array 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); \
+ \
+ const Type *val = \
+ impl->getStorage()->allocTemporary ## Suffix ## Array(env, valObj); \
+ \
+ hardware::Parcel *parcel = impl->getParcel(); \
+ \
+ size_t parentHandle; \
+ status_t err = parcel->writeBuffer( \
+ val, size * sizeof(*val), &parentHandle); \
+ \
+ signalExceptionForError(env, err); \
+}
+
+#define DEFINE_PARCEL_VECTOR_WRITER(Suffix,Type) \
+static void JHwParcel_native_write ## Suffix ## Vector( \
+ JNIEnv *env, jobject thiz, Type ## Array valObj) { \
+ if (valObj == NULL) { \
+ jniThrowException(env, "java/lang/NullPointerException", NULL); \
+ return; \
+ } \
+ \
+ sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz); \
+ \
+ const hidl_vec<Type> *vec = \
+ impl->getStorage()->allocTemporary ## Suffix ## Vector(env, valObj); \
+ \
+ 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); \
+}
+
+DEFINE_PARCEL_ARRAY_WRITER(Int8,jbyte)
+DEFINE_PARCEL_ARRAY_WRITER(Int16,jshort)
+DEFINE_PARCEL_ARRAY_WRITER(Int32,jint)
+DEFINE_PARCEL_ARRAY_WRITER(Int64,jlong)
+DEFINE_PARCEL_ARRAY_WRITER(Float,jfloat)
+DEFINE_PARCEL_ARRAY_WRITER(Double,jdouble)
+
+DEFINE_PARCEL_VECTOR_WRITER(Int8,jbyte)
+DEFINE_PARCEL_VECTOR_WRITER(Int16,jshort)
+DEFINE_PARCEL_VECTOR_WRITER(Int32,jint)
+DEFINE_PARCEL_VECTOR_WRITER(Int64,jlong)
+DEFINE_PARCEL_VECTOR_WRITER(Float,jfloat)
+DEFINE_PARCEL_VECTOR_WRITER(Double,jdouble)
+
+static void JHwParcel_native_writeStrongBinder(
+ JNIEnv *env, jobject thiz, jobject binderObj) {
+ sp<hardware::IBinder> binder;
+ if (binderObj != NULL) {
+ ScopedLocalRef<jclass> hwBinderKlass(
+ env, FindClassOrDie(env, PACKAGE_PATH "/HwBinder"));
+
+ ScopedLocalRef<jclass> hwRemoteBinderKlass(
+ env, FindClassOrDie(env, PACKAGE_PATH "/HwRemoteBinder"));
+
+ if (env->IsInstanceOf(binderObj, hwBinderKlass.get())) {
+ binder = JHwBinder::GetNativeContext(env, binderObj);
+ } else if (env->IsInstanceOf(binderObj, hwRemoteBinderKlass.get())) {
+ binder = JHwRemoteBinder::GetNativeContext(
+ env, binderObj)->getBinder();
+ } else {
+ signalExceptionForError(env, INVALID_OPERATION);
+ return;
+ }
+ }
+
+ hardware::Parcel *parcel =
+ JHwParcel::GetNativeContext(env, thiz)->getParcel();
+
+ status_t err = parcel->writeStrongBinder(binder);
+ signalExceptionForError(env, err);
+}
+
+static jstring MakeStringObjFromHidlString(JNIEnv *env, const hidl_string &s) {
+ String16 utf16String(s.c_str(), s.size());
+
+ return env->NewString(
+ reinterpret_cast<const jchar *>(utf16String.string()),
+ utf16String.size());
+}
+
+static jstring JHwParcel_native_readString(JNIEnv *env, jobject thiz) {
+ hardware::Parcel *parcel =
+ JHwParcel::GetNativeContext(env, thiz)->getParcel();
+
+ size_t parentHandle;
+
+ const hidl_string *s = static_cast<const hidl_string *>(
+ parcel->readBuffer(&parentHandle));
+
+ if (s == NULL) {
+ signalExceptionForError(env, UNKNOWN_ERROR);
+ return NULL;
+ }
+
+ status_t err = const_cast<hidl_string *>(s)->readEmbeddedFromParcel(
+ *parcel, parentHandle, 0 /* parentOffset */);
+
+ if (err != OK) {
+ signalExceptionForError(env, err);
+ return NULL;
+ }
+
+ return MakeStringObjFromHidlString(env, *s);
+}
+
+#define DEFINE_PARCEL_ARRAY_READER(Suffix,Type,NewType) \
+static Type ## Array JHwParcel_native_read ## Suffix ## Array( \
+ JNIEnv *env, jobject thiz, jint size) { \
+ hardware::Parcel *parcel = \
+ JHwParcel::GetNativeContext(env, thiz)->getParcel(); \
+ \
+ size_t parentHandle; \
+ const Type *val = static_cast<const Type *>( \
+ parcel->readBuffer(&parentHandle)); \
+ \
+ Type ## Array valObj = env->New ## NewType ## Array(size); \
+ env->Set ## NewType ## ArrayRegion(valObj, 0, size, val); \
+ \
+ return valObj; \
+}
+
+#define DEFINE_PARCEL_VECTOR_READER(Suffix,Type,NewType) \
+static Type ## Array JHwParcel_native_read ## Suffix ## Vector( \
+ JNIEnv *env, jobject thiz) { \
+ hardware::Parcel *parcel = \
+ JHwParcel::GetNativeContext(env, thiz)->getParcel(); \
+ \
+ size_t parentHandle; \
+ \
+ const hidl_vec<Type> *vec = \
+ (const hidl_vec<Type> *)parcel->readBuffer(&parentHandle); \
+ \
+ if (vec == NULL) { \
+ signalExceptionForError(env, UNKNOWN_ERROR); \
+ return NULL; \
+ } \
+ \
+ size_t childHandle; \
+ \
+ status_t err = const_cast<hidl_vec<Type> *>(vec) \
+ ->readEmbeddedFromParcel( \
+ *parcel, \
+ parentHandle, \
+ 0 /* parentOffset */, \
+ &childHandle); \
+ \
+ if (err != OK) { \
+ signalExceptionForError(env, err); \
+ return NULL; \
+ } \
+ \
+ Type ## Array valObj = env->New ## NewType ## Array(vec->size()); \
+ env->Set ## NewType ## ArrayRegion(valObj, 0, vec->size(), &(*vec)[0]); \
+ \
+ return valObj; \
+}
+
+DEFINE_PARCEL_ARRAY_READER(Int8,jbyte,Byte)
+DEFINE_PARCEL_ARRAY_READER(Int16,jshort,Short)
+DEFINE_PARCEL_ARRAY_READER(Int32,jint,Int)
+DEFINE_PARCEL_ARRAY_READER(Int64,jlong,Long)
+DEFINE_PARCEL_ARRAY_READER(Float,jfloat,Float)
+DEFINE_PARCEL_ARRAY_READER(Double,jdouble,Double)
+
+DEFINE_PARCEL_VECTOR_READER(Int8,jbyte,Byte)
+DEFINE_PARCEL_VECTOR_READER(Int16,jshort,Short)
+DEFINE_PARCEL_VECTOR_READER(Int32,jint,Int)
+DEFINE_PARCEL_VECTOR_READER(Int64,jlong,Long)
+DEFINE_PARCEL_VECTOR_READER(Float,jfloat,Float)
+DEFINE_PARCEL_VECTOR_READER(Double,jdouble,Double)
+
+static jobjectArray MakeStringArray(
+ JNIEnv *env, const hidl_string *array, size_t size) {
+ ScopedLocalRef<jclass> stringKlass(
+ env,
+ env->FindClass("java/lang/String"));
+
+ // XXX Why can't I use ScopedLocalRef<> for the arrayObj and the stringObjs?
+
+ jobjectArray arrayObj = env->NewObjectArray(size, stringKlass.get(), NULL);
+
+ for (size_t i = 0; i < size; ++i) {
+ jstring stringObj = MakeStringObjFromHidlString(env, array[i]);
+
+ env->SetObjectArrayElement(
+ arrayObj,
+ i,
+ stringObj);
+ }
+
+ return arrayObj;
+}
+
+static jobjectArray JHwParcel_native_readStringArray(
+ JNIEnv *env, jobject thiz, jint size) {
+ hardware::Parcel *parcel =
+ JHwParcel::GetNativeContext(env, thiz)->getParcel();
+
+ size_t parentHandle;
+ const hidl_string *val = static_cast<const hidl_string *>(
+ parcel->readBuffer(&parentHandle));
+
+ if (val == NULL) {
+ signalExceptionForError(env, UNKNOWN_ERROR);
+ return NULL;
+ }
+
+ status_t err = OK;
+ for (jint i = 0; (err == OK) && (i < size); ++i) {
+ err = const_cast<hidl_string *>(&val[i])
+ ->readEmbeddedFromParcel(
+ *parcel,
+ parentHandle,
+ i * sizeof(hidl_string));
+ }
+
+ if (err != OK) {
+ signalExceptionForError(env, err);
+ return NULL;
+ }
+
+ return MakeStringArray(env, val, size);
+}
+
+static void JHwParcel_native_writeStringArray(
+ JNIEnv *env, jobject thiz, jint size, jobjectArray arrayObj) {
+ if (arrayObj == NULL) {
+ jniThrowException(env, "java/lang/NullPointerException", NULL);
+ return;
+ }
+
+ jsize len = env->GetArrayLength(arrayObj);
+
+ if (len != size) {
+ jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
+ return;
+ }
+
+ sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz);
+
+ hidl_string *strings = impl->getStorage()->allocStringArray(len);
+
+ for (jsize i = 0; i < len; ++i) {
+ ScopedLocalRef<jstring> stringObj(
+ env,
+ (jstring)env->GetObjectArrayElement(arrayObj, i));
+
+ const hidl_string *s =
+ impl->getStorage()->allocTemporaryString(env, stringObj.get());
+
+ strings[i].setToExternal(s->c_str(), s->size());
+ }
+
+ hardware::Parcel *parcel = impl->getParcel();
+
+ size_t parentHandle;
+ status_t err = parcel->writeBuffer(
+ strings, sizeof(hidl_string) * len, &parentHandle);
+
+ for (jsize i = 0; (err == OK) && (i < len); ++i) {
+ err = strings[i].writeEmbeddedToParcel(
+ parcel, parentHandle, i * sizeof(hidl_string));
+ }
+
+ signalExceptionForError(env, err);
+}
+
+static jobjectArray JHwParcel_native_readStringVector(
+ JNIEnv *env, jobject thiz) {
+ typedef hidl_vec<hidl_string> string_vec;
+
+ hardware::Parcel *parcel =
+ JHwParcel::GetNativeContext(env, thiz)->getParcel();
+
+ size_t parentHandle;
+
+ const string_vec *vec=
+ (const string_vec *)parcel->readBuffer(&parentHandle);
+
+ if (vec == NULL) {
+ signalExceptionForError(env, UNKNOWN_ERROR);
+ return NULL;
+ }
+
+ size_t childHandle;
+ status_t err = const_cast<string_vec *>(vec)->readEmbeddedFromParcel(
+ *parcel, parentHandle, 0 /* parentOffset */, &childHandle);
+
+ for (size_t i = 0; (err == OK) && (i < vec->size()); ++i) {
+ err = const_cast<hidl_vec<hidl_string> *>(vec)
+ ->readEmbeddedFromParcel(
+ *parcel,
+ childHandle,
+ i * sizeof(hidl_string),
+ nullptr /* childHandle */);
+ }
+
+ if (err != OK) {
+ signalExceptionForError(env, err);
+ return NULL;
+ }
+
+ return MakeStringArray(env, &(*vec)[0], vec->size());
+}
+
+static void JHwParcel_native_writeStringVector(
+ JNIEnv *env, jobject thiz, jobjectArray arrayObj) {
+ typedef hidl_vec<hidl_string> string_vec;
+
+ if (arrayObj == NULL) {
+ jniThrowException(env, "java/lang/NullPointerException", NULL);
+ return;
+ }
+
+ jsize len = env->GetArrayLength(arrayObj);
+
+ sp<JHwParcel> impl = JHwParcel::GetNativeContext(env, thiz);
+
+ string_vec *vec =
+ (string_vec *)impl->getStorage()->allocTemporaryStorage(
+ sizeof(string_vec));
+
+ hidl_string *strings = impl->getStorage()->allocStringArray(len);
+ vec->setToExternal(strings, len);
+
+ for (jsize i = 0; i < len; ++i) {
+ ScopedLocalRef<jstring> stringObj(
+ env,
+ (jstring)env->GetObjectArrayElement(arrayObj, i));
+
+ const hidl_string *s =
+ impl->getStorage()->allocTemporaryString(env, stringObj.get());
+
+ strings[i].setToExternal(s->c_str(), s->size());
+ }
+
+ 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);
+
+ for (size_t i = 0; (err == OK) && (i < vec->size()); ++i) {
+ err = (*vec)[i].writeEmbeddedToParcel(
+ parcel,
+ childHandle,
+ i * sizeof(hidl_string));
+ }
+ }
+
+ signalExceptionForError(env, err);
+}
+
+static jobject JHwParcel_native_readStrongBinder(JNIEnv *env, jobject thiz) {
+ hardware::Parcel *parcel =
+ JHwParcel::GetNativeContext(env, thiz)->getParcel();
+
+ sp<hardware::IBinder> binder = parcel->readStrongBinder();
+
+ if (binder == NULL) {
+ return NULL;
+ }
+
+ return JHwRemoteBinder::NewObject(env, binder);
+}
+
+static JNINativeMethod gMethods[] = {
+ { "native_init", "()J", (void *)JHwParcel_native_init },
+ { "native_setup", "(Z)V", (void *)JHwParcel_native_setup },
+
+ { "writeInterfaceToken", "(Ljava/lang/String;)V",
+ (void *)JHwParcel_native_writeInterfaceToken },
+
+ { "writeInt8", "(B)V", (void *)JHwParcel_native_writeInt8 },
+ { "writeInt16", "(S)V", (void *)JHwParcel_native_writeInt16 },
+ { "writeInt32", "(I)V", (void *)JHwParcel_native_writeInt32 },
+ { "writeInt64", "(J)V", (void *)JHwParcel_native_writeInt64 },
+ { "writeFloat", "(F)V", (void *)JHwParcel_native_writeFloat },
+ { "writeDouble", "(D)V", (void *)JHwParcel_native_writeDouble },
+
+ { "writeString", "(Ljava/lang/String;)V",
+ (void *)JHwParcel_native_writeString },
+
+ { "writeInt8Array", "(I[B)V", (void *)JHwParcel_native_writeInt8Array },
+ { "writeInt8Vector", "([B)V", (void *)JHwParcel_native_writeInt8Vector },
+ { "writeInt16Array", "(I[S)V", (void *)JHwParcel_native_writeInt16Array },
+ { "writeInt16Vector", "([S)V", (void *)JHwParcel_native_writeInt16Vector },
+ { "writeInt32Array", "(I[I)V", (void *)JHwParcel_native_writeInt32Array },
+ { "writeInt32Vector", "([I)V", (void *)JHwParcel_native_writeInt32Vector },
+ { "writeInt64Array", "(I[J)V", (void *)JHwParcel_native_writeInt64Array },
+ { "writeInt64Vector", "([J)V", (void *)JHwParcel_native_writeInt64Vector },
+ { "writeFloatArray", "(I[F)V", (void *)JHwParcel_native_writeFloatArray },
+ { "writeFloatVector", "([F)V", (void *)JHwParcel_native_writeFloatVector },
+ { "writeDoubleArray", "(I[D)V", (void *)JHwParcel_native_writeDoubleArray },
+
+ { "writeDoubleVector", "([D)V",
+ (void *)JHwParcel_native_writeDoubleVector },
+
+ { "writeStringArray", "(I[Ljava/lang/String;)V",
+ (void *)JHwParcel_native_writeStringArray },
+
+ { "writeStringVector", "([Ljava/lang/String;)V",
+ (void *)JHwParcel_native_writeStringVector },
+
+ { "writeStrongBinder", "(L" PACKAGE_PATH "/IHwBinder;)V",
+ (void *)JHwParcel_native_writeStrongBinder },
+
+ { "enforceInterface", "(Ljava/lang/String;)V",
+ (void *)JHwParcel_native_enforceInterface },
+
+ { "readInt8", "()B", (void *)JHwParcel_native_readInt8 },
+ { "readInt16", "()S", (void *)JHwParcel_native_readInt16 },
+ { "readInt32", "()I", (void *)JHwParcel_native_readInt32 },
+ { "readInt64", "()J", (void *)JHwParcel_native_readInt64 },
+ { "readFloat", "()F", (void *)JHwParcel_native_readFloat },
+ { "readDouble", "()D", (void *)JHwParcel_native_readDouble },
+
+ { "readString", "()Ljava/lang/String;",
+ (void *)JHwParcel_native_readString },
+
+ { "readInt8Array", "(I)[B", (void *)JHwParcel_native_readInt8Array },
+ { "readInt8Vector", "()[B", (void *)JHwParcel_native_readInt8Vector },
+ { "readInt16Array", "(I)[S", (void *)JHwParcel_native_readInt16Array },
+ { "readInt16Vector", "()[S", (void *)JHwParcel_native_readInt16Vector },
+ { "readInt32Array", "(I)[I", (void *)JHwParcel_native_readInt32Array },
+ { "readInt32Vector", "()[I", (void *)JHwParcel_native_readInt32Vector },
+ { "readInt64Array", "(I)[J", (void *)JHwParcel_native_readInt64Array },
+ { "readInt64Vector", "()[J", (void *)JHwParcel_native_readInt64Vector },
+ { "readFloatArray", "(I)[F", (void *)JHwParcel_native_readFloatArray },
+ { "readFloatVector", "()[F", (void *)JHwParcel_native_readFloatVector },
+ { "readDoubleArray", "(I)[D", (void *)JHwParcel_native_readDoubleArray },
+ { "readDoubleVector", "()[D", (void *)JHwParcel_native_readDoubleVector },
+
+ { "readStringArray", "(I)[Ljava/lang/String;",
+ (void *)JHwParcel_native_readStringArray },
+
+ { "readStringVector", "()[Ljava/lang/String;",
+ (void *)JHwParcel_native_readStringVector },
+
+ { "readStrongBinder", "()L" PACKAGE_PATH "/IHwBinder;",
+ (void *)JHwParcel_native_readStrongBinder },
+
+ { "writeStatus", "(I)V", (void *)JHwParcel_native_writeStatus },
+
+ { "verifySuccess", "()V", (void *)JHwParcel_native_verifySuccess },
+
+ { "releaseTemporaryStorage", "()V",
+ (void *)JHwParcel_native_releaseTemporaryStorage },
+
+ { "send", "()V", (void *)JHwParcel_native_send },
+};
+
+namespace android {
+
+int register_android_os_HwParcel(JNIEnv *env) {
+ return RegisterMethodsOrDie(env, CLASS_PATH, gMethods, NELEM(gMethods));
+}
+
+} // namespace android
--- /dev/null
+/*
+ * 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_PARCEL_H
+#define ANDROID_OS_HW_PARCEL_H
+
+#include "hwbinder/EphemeralStorage.h"
+
+#include <android-base/macros.h>
+#include <hwbinder/IBinder.h>
+#include <hwbinder/Parcel.h>
+#include <jni.h>
+#include <utils/RefBase.h>
+
+namespace android {
+
+struct JHwParcel : public RefBase {
+ static void InitClass(JNIEnv *env);
+
+ static sp<JHwParcel> SetNativeContext(
+ JNIEnv *env, jobject thiz, const sp<JHwParcel> &context);
+
+ static sp<JHwParcel> GetNativeContext(JNIEnv *env, jobject thiz);
+
+ static jobject NewObject(JNIEnv *env);
+
+ JHwParcel(JNIEnv *env, jobject thiz);
+
+ void setParcel(hardware::Parcel *parcel, bool assumeOwnership);
+ hardware::Parcel *getParcel();
+
+ EphemeralStorage *getStorage();
+
+ void setTransactCallback(::android::hardware::IBinder::TransactCallback cb);
+
+ void send();
+ bool wasSent() const;
+
+protected:
+ virtual ~JHwParcel();
+
+private:
+ jclass mClass;
+ jobject mObject;
+
+ hardware::Parcel *mParcel;
+ bool mOwnsParcel;
+
+ EphemeralStorage mStorage;
+
+ ::android::hardware::IBinder::TransactCallback mTransactCallback;
+ bool mWasSent;
+
+ DISALLOW_COPY_AND_ASSIGN(JHwParcel);
+};
+
+void signalExceptionForError(JNIEnv *env, status_t err);
+int register_android_os_HwParcel(JNIEnv *env);
+
+} // namespace android
+
+#endif // ANDROID_OS_HW_PARCEL_H
--- /dev/null
+/*
+ * 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 "JHwRemoteBinder"
+#include <android-base/logging.h>
+
+#include "android_os_HwRemoteBinder.h"
+
+#include "android_os_HwParcel.h"
+
+#include <JNIHelp.h>
+#include <android_runtime/AndroidRuntime.h>
+#include <hwbinder/IServiceManager.h>
+#include <hwbinder/Status.h>
+#include <nativehelper/ScopedLocalRef.h>
+
+#include "core_jni_helpers.h"
+
+using android::AndroidRuntime;
+
+#define PACKAGE_PATH "android/os"
+#define CLASS_NAME "HwRemoteBinder"
+#define CLASS_PATH PACKAGE_PATH "/" CLASS_NAME
+
+namespace android {
+
+static struct fields_t {
+ jfieldID contextID;
+ jmethodID constructID;
+
+} gFields;
+
+// static
+void JHwRemoteBinder::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>", "()V");
+}
+
+// static
+sp<JHwRemoteBinder> JHwRemoteBinder::SetNativeContext(
+ JNIEnv *env, jobject thiz, const sp<JHwRemoteBinder> &context) {
+ sp<JHwRemoteBinder> old =
+ (JHwRemoteBinder *)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<JHwRemoteBinder> JHwRemoteBinder::GetNativeContext(
+ JNIEnv *env, jobject thiz) {
+ return (JHwRemoteBinder *)env->GetLongField(thiz, gFields.contextID);
+}
+
+// static
+jobject JHwRemoteBinder::NewObject(
+ JNIEnv *env, const sp<hardware::IBinder> &binder) {
+ ScopedLocalRef<jclass> clazz(env, FindClassOrDie(env, CLASS_PATH));
+
+ // XXX Have to look up the constructor here because otherwise that static
+ // class initializer isn't called and gFields.constructID is undefined :(
+
+ jmethodID constructID = GetMethodIDOrDie(env, clazz.get(), "<init>", "()V");
+
+ jobject obj = env->NewObject(clazz.get(), constructID);
+ JHwRemoteBinder::GetNativeContext(env, obj)->setBinder(binder);
+
+ return obj;
+}
+
+JHwRemoteBinder::JHwRemoteBinder(
+ JNIEnv *env, jobject thiz, const sp<hardware::IBinder> &binder)
+ : mBinder(binder) {
+ jclass clazz = env->GetObjectClass(thiz);
+ CHECK(clazz != NULL);
+
+ mClass = (jclass)env->NewGlobalRef(clazz);
+ mObject = env->NewWeakGlobalRef(thiz);
+}
+
+JHwRemoteBinder::~JHwRemoteBinder() {
+ JNIEnv *env = AndroidRuntime::getJNIEnv();
+
+ env->DeleteWeakGlobalRef(mObject);
+ mObject = NULL;
+
+ env->DeleteGlobalRef(mClass);
+ mClass = NULL;
+}
+
+sp<hardware::IBinder> JHwRemoteBinder::getBinder() {
+ return mBinder;
+}
+
+void JHwRemoteBinder::setBinder(const sp<hardware::IBinder> &binder) {
+ mBinder = binder;
+}
+
+} // namespace android
+
+////////////////////////////////////////////////////////////////////////////////
+
+using namespace android;
+
+static void releaseNativeContext(void *nativeContext) {
+ sp<JHwRemoteBinder> binder = (JHwRemoteBinder *)nativeContext;
+
+ if (binder != NULL) {
+ binder->decStrong(NULL /* id */);
+ }
+}
+
+static jlong JHwRemoteBinder_native_init(JNIEnv *env) {
+ JHwRemoteBinder::InitClass(env);
+
+ return reinterpret_cast<jlong>(&releaseNativeContext);
+}
+
+static void JHwRemoteBinder_native_setup_empty(JNIEnv *env, jobject thiz) {
+ sp<JHwRemoteBinder> context =
+ new JHwRemoteBinder(env, thiz, NULL /* service */);
+
+ JHwRemoteBinder::SetNativeContext(env, thiz, context);
+}
+
+static void JHwRemoteBinder_native_transact(
+ JNIEnv *env,
+ jobject thiz,
+ jint code,
+ jobject requestObj,
+ jobject replyObj,
+ jint flags) {
+ sp<hardware::IBinder> binder =
+ JHwRemoteBinder::GetNativeContext(env, thiz)->getBinder();
+
+ if (requestObj == NULL) {
+ jniThrowException(env, "java/lang/NullPointerException", NULL);
+ return;
+ }
+
+ const hardware::Parcel *request =
+ JHwParcel::GetNativeContext(env, requestObj)->getParcel();
+
+ hardware::Parcel *reply =
+ JHwParcel::GetNativeContext(env, replyObj)->getParcel();
+
+ status_t err = binder->transact(code, *request, reply, flags);
+ signalExceptionForError(env, err);
+}
+
+static JNINativeMethod gMethods[] = {
+ { "native_init", "()J", (void *)JHwRemoteBinder_native_init },
+
+ { "native_setup_empty", "()V",
+ (void *)JHwRemoteBinder_native_setup_empty },
+
+ { "transact",
+ "(IL" PACKAGE_PATH "/HwParcel;L" PACKAGE_PATH "/HwParcel;I)V",
+ (void *)JHwRemoteBinder_native_transact },
+};
+
+namespace android {
+
+int register_android_os_HwRemoteBinder(JNIEnv *env) {
+ return RegisterMethodsOrDie(env, CLASS_PATH, gMethods, NELEM(gMethods));
+}
+
+} // namespace android
+
--- /dev/null
+/*
+ * 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_REMOTE_BINDER_H
+#define ANDROID_OS_HW_REMOTE_BINDER_H
+
+#include <android-base/macros.h>
+#include <hwbinder/Binder.h>
+#include <jni.h>
+#include <utils/RefBase.h>
+
+namespace android {
+
+struct JHwRemoteBinder : public RefBase {
+ static void InitClass(JNIEnv *env);
+
+ static sp<JHwRemoteBinder> SetNativeContext(
+ JNIEnv *env, jobject thiz, const sp<JHwRemoteBinder> &context);
+
+ static sp<JHwRemoteBinder> GetNativeContext(JNIEnv *env, jobject thiz);
+
+ static jobject NewObject(JNIEnv *env, const sp<hardware::IBinder> &binder);
+
+ JHwRemoteBinder(
+ JNIEnv *env, jobject thiz, const sp<hardware::IBinder> &binder);
+
+ sp<hardware::IBinder> getBinder();
+ void setBinder(const sp<hardware::IBinder> &binder);
+
+protected:
+ virtual ~JHwRemoteBinder();
+
+private:
+ jclass mClass;
+ jobject mObject;
+
+ sp<hardware::IBinder> mBinder;
+
+ DISALLOW_COPY_AND_ASSIGN(JHwRemoteBinder);
+};
+
+int register_android_os_HwRemoteBinder(JNIEnv *env);
+
+} // namespace android
+
+#endif // ANDROID_OS_HW_REMOTE_BINDER_H
+
--- /dev/null
+/*
+ * 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_TAG "EphemeralStorage"
+//#define LOG_NDEBUG 0
+
+#include <android-base/logging.h>
+
+#include "EphemeralStorage.h"
+
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+
+namespace android {
+
+EphemeralStorage::EphemeralStorage() {
+}
+
+EphemeralStorage::~EphemeralStorage() {
+ CHECK(mItems.empty())
+ << "All item storage should have been released by now.";
+}
+
+hidl_string *EphemeralStorage::allocStringArray(size_t size) {
+ Item item;
+ item.mType = TYPE_STRING_ARRAY;
+ item.mObj = NULL;
+ item.mPtr = new hidl_string[size];
+ mItems.push_back(item);
+
+ return static_cast<hidl_string *>(item.mPtr);
+}
+
+void *EphemeralStorage::allocTemporaryStorage(size_t size) {
+ Item item;
+ item.mType = TYPE_STORAGE;
+ item.mObj = NULL;
+ item.mPtr = malloc(size);
+ mItems.push_back(item);
+
+ return item.mPtr;
+}
+
+const hidl_string *EphemeralStorage::allocTemporaryString(
+ JNIEnv *env, jstring stringObj) {
+ jstring obj = (jstring)env->NewGlobalRef(stringObj);
+ const char *val = env->GetStringUTFChars(obj, NULL);
+
+ Item item;
+ item.mType = TYPE_STRING;
+ item.mObj = obj;
+ item.mPtr = (void *)val;
+ mItems.push_back(item);
+
+ hidl_string *s = allocStringArray(1 /* size */);
+ s->setToExternal((char *)val, strlen(val));
+
+ return s;
+}
+
+#define DEFINE_ALLOC_ARRAY_METHODS(Suffix,Type,NewType) \
+const Type *EphemeralStorage::allocTemporary ## Suffix ## Array( \
+ JNIEnv *env, Type ## Array arrayObj) { \
+ Type ## Array obj = (Type ## Array)env->NewGlobalRef(arrayObj); \
+ const Type *val = env->Get ## NewType ## ArrayElements(obj, NULL); \
+ \
+ Item item; \
+ item.mType = TYPE_ ## Suffix ## _ARRAY; \
+ item.mObj = obj; \
+ item.mPtr = (void *)val; \
+ mItems.push_back(item); \
+ \
+ return val; \
+}
+
+#define DEFINE_ALLOC_VECTOR_METHODS(Suffix,Type,NewType) \
+const hidl_vec<Type> *EphemeralStorage::allocTemporary ## Suffix ## Vector( \
+ JNIEnv *env, Type ## Array arrayObj) { \
+ Type ## Array obj = (Type ## Array)env->NewGlobalRef(arrayObj); \
+ jsize len = env->GetArrayLength(obj); \
+ const Type *val = env->Get ## NewType ## ArrayElements(obj, NULL); \
+ \
+ Item item; \
+ item.mType = TYPE_ ## Suffix ## _ARRAY; \
+ item.mObj = obj; \
+ item.mPtr = (void *)val; \
+ mItems.push_back(item); \
+ \
+ hidl_vec<Type> *vec = \
+ (hidl_vec<Type> *)allocTemporaryStorage(sizeof(hidl_vec<Type>)); \
+ \
+ vec->setToExternal(const_cast<Type *>(val), len); \
+ \
+ return vec; \
+}
+
+DEFINE_ALLOC_ARRAY_METHODS(Int8,jbyte,Byte)
+DEFINE_ALLOC_ARRAY_METHODS(Int16,jshort,Short)
+DEFINE_ALLOC_ARRAY_METHODS(Int32,jint,Int)
+DEFINE_ALLOC_ARRAY_METHODS(Int64,jlong,Long)
+DEFINE_ALLOC_ARRAY_METHODS(Float,jfloat,Float)
+DEFINE_ALLOC_ARRAY_METHODS(Double,jdouble,Double)
+
+DEFINE_ALLOC_VECTOR_METHODS(Int8,jbyte,Byte)
+DEFINE_ALLOC_VECTOR_METHODS(Int16,jshort,Short)
+DEFINE_ALLOC_VECTOR_METHODS(Int32,jint,Int)
+DEFINE_ALLOC_VECTOR_METHODS(Int64,jlong,Long)
+DEFINE_ALLOC_VECTOR_METHODS(Float,jfloat,Float)
+DEFINE_ALLOC_VECTOR_METHODS(Double,jdouble,Double)
+
+#define DEFINE_RELEASE_ARRAY_CASE(Suffix,Type,NewType) \
+ case TYPE_ ## Suffix ## _ARRAY: \
+ { \
+ env->Release ## NewType ## ArrayElements( \
+ (Type ## Array)item.mObj, \
+ (Type *)item.mPtr, \
+ 0 /* mode */); \
+ \
+ env->DeleteGlobalRef(item.mObj); \
+ break; \
+ }
+
+void EphemeralStorage::release(JNIEnv *env) {
+ for (size_t i = mItems.size(); i--;) {
+ const Item &item = mItems[i];
+
+ switch (item.mType) {
+ case TYPE_STRING_ARRAY:
+ {
+ delete[] static_cast<hidl_string *>(item.mPtr);
+ break;
+ }
+
+ case TYPE_STORAGE:
+ {
+ free(item.mPtr);
+ break;
+ }
+
+ case TYPE_STRING:
+ {
+ env->ReleaseStringUTFChars(
+ (jstring)item.mObj, (const char *)item.mPtr);
+
+ env->DeleteGlobalRef(item.mObj);
+ break;
+ }
+
+ DEFINE_RELEASE_ARRAY_CASE(Int8,jbyte,Byte)
+ DEFINE_RELEASE_ARRAY_CASE(Int16,jshort,Short)
+ DEFINE_RELEASE_ARRAY_CASE(Int32,jint,Int)
+ DEFINE_RELEASE_ARRAY_CASE(Int64,jlong,Long)
+ DEFINE_RELEASE_ARRAY_CASE(Float,jfloat,Float)
+ DEFINE_RELEASE_ARRAY_CASE(Double,jdouble,Double)
+
+ default:
+ CHECK(!"Should not be here");
+ }
+ }
+
+ mItems.clear();
+}
+
+} // namespace android
+
--- /dev/null
+/*
+ * 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 EPHEMERAL_STORAGE_H_
+
+#define EPHEMERAL_STORAGE_H_
+
+#include <android-base/macros.h>
+#include <hwbinder/HidlSupport.h>
+#include <jni.h>
+#include <utils/Vector.h>
+
+namespace android {
+
+#define DECLARE_ALLOC_METHODS(Suffix,Type) \
+ const Type *allocTemporary ## Suffix ## Array( \
+ JNIEnv *env, Type ## Array arrayObj); \
+ \
+ const ::android::hardware::hidl_vec<Type> * \
+ allocTemporary ## Suffix ## Vector( \
+ JNIEnv *env, Type ## Array arrayObj);
+
+struct EphemeralStorage {
+ EphemeralStorage();
+ ~EphemeralStorage();
+
+ void release(JNIEnv *env);
+
+ hardware::hidl_string *allocStringArray(size_t size);
+
+ void *allocTemporaryStorage(size_t size);
+
+ const ::android::hardware::hidl_string *allocTemporaryString(
+ JNIEnv *env, jstring stringObj);
+
+ DECLARE_ALLOC_METHODS(Int8,jbyte)
+ DECLARE_ALLOC_METHODS(Int16,jshort)
+ DECLARE_ALLOC_METHODS(Int32,jint)
+ DECLARE_ALLOC_METHODS(Int64,jlong)
+ DECLARE_ALLOC_METHODS(Float,jfloat)
+ DECLARE_ALLOC_METHODS(Double,jdouble)
+
+private:
+ enum Type {
+ TYPE_STRING_ARRAY,
+ TYPE_STORAGE,
+ TYPE_STRING,
+ TYPE_Int8_ARRAY,
+ TYPE_Int16_ARRAY,
+ TYPE_Int32_ARRAY,
+ TYPE_Int64_ARRAY,
+ TYPE_Float_ARRAY,
+ TYPE_Double_ARRAY,
+ };
+
+ struct Item {
+ Type mType;
+ jobject mObj;
+ void *mPtr;
+ };
+
+ Vector<Item> mItems;
+
+ DISALLOW_COPY_AND_ASSIGN(EphemeralStorage);
+};
+
+#undef DECLARE_ALLOC_METHODS
+
+} // namespace android
+
+#endif // EPHEMERAL_STORAGE_H_