Initial commit of Java support for hardware binder (DO NOT MERGE)
Change-Id: If1098ab921a11bae8eca2a70a3c3070e4daa0ea2
This commit is contained in:
committed by
Iliyan Malchev
parent
a6b6252d8b
commit
0619b33685
59
core/java/android/os/HwBinder.java
Normal file
59
core/java/android/os/HwBinder.java
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
120
core/java/android/os/HwParcel.java
Normal file
120
core/java/android/os/HwParcel.java
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
|
||||||
56
core/java/android/os/HwRemoteBinder.java
Normal file
56
core/java/android/os/HwRemoteBinder.java
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
28
core/java/android/os/IHwBinder.java
Normal file
28
core/java/android/os/IHwBinder.java
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* 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);
|
||||||
|
}
|
||||||
22
core/java/android/os/IHwInterface.java
Normal file
22
core/java/android/os/IHwInterface.java
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
* 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();
|
||||||
|
}
|
||||||
@@ -80,6 +80,9 @@ LOCAL_SRC_FILES:= \
|
|||||||
android_text_AndroidBidi.cpp \
|
android_text_AndroidBidi.cpp \
|
||||||
android_text_StaticLayout.cpp \
|
android_text_StaticLayout.cpp \
|
||||||
android_os_Debug.cpp \
|
android_os_Debug.cpp \
|
||||||
|
android_os_HwBinder.cpp \
|
||||||
|
android_os_HwParcel.cpp \
|
||||||
|
android_os_HwRemoteBinder.cpp \
|
||||||
android_os_MemoryFile.cpp \
|
android_os_MemoryFile.cpp \
|
||||||
android_os_MessageQueue.cpp \
|
android_os_MessageQueue.cpp \
|
||||||
android_os_Parcel.cpp \
|
android_os_Parcel.cpp \
|
||||||
@@ -177,7 +180,8 @@ LOCAL_SRC_FILES:= \
|
|||||||
com_android_internal_os_PathClassLoaderFactory.cpp \
|
com_android_internal_os_PathClassLoaderFactory.cpp \
|
||||||
com_android_internal_os_Zygote.cpp \
|
com_android_internal_os_Zygote.cpp \
|
||||||
com_android_internal_util_VirtualRefBasePtr.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 += \
|
LOCAL_C_INCLUDES += \
|
||||||
$(JNI_H_INCLUDE) \
|
$(JNI_H_INCLUDE) \
|
||||||
@@ -260,6 +264,7 @@ LOCAL_SHARED_LIBRARIES := \
|
|||||||
libradio_metadata \
|
libradio_metadata \
|
||||||
libnativeloader \
|
libnativeloader \
|
||||||
libmemunreachable \
|
libmemunreachable \
|
||||||
|
libhwbinder \
|
||||||
|
|
||||||
LOCAL_SHARED_LIBRARIES += \
|
LOCAL_SHARED_LIBRARIES += \
|
||||||
libhwui \
|
libhwui \
|
||||||
|
|||||||
@@ -156,6 +156,9 @@ extern int register_android_database_SQLiteGlobal(JNIEnv* env);
|
|||||||
extern int register_android_database_SQLiteDebug(JNIEnv* env);
|
extern int register_android_database_SQLiteDebug(JNIEnv* env);
|
||||||
extern int register_android_nio_utils(JNIEnv* env);
|
extern int register_android_nio_utils(JNIEnv* env);
|
||||||
extern int register_android_os_Debug(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_MessageQueue(JNIEnv* env);
|
||||||
extern int register_android_os_Parcel(JNIEnv* env);
|
extern int register_android_os_Parcel(JNIEnv* env);
|
||||||
extern int register_android_os_SELinux(JNIEnv* env);
|
extern int register_android_os_SELinux(JNIEnv* env);
|
||||||
@@ -1287,6 +1290,9 @@ static const RegJNIRec gRegJNI[] = {
|
|||||||
REG_JNI(register_android_os_SystemProperties),
|
REG_JNI(register_android_os_SystemProperties),
|
||||||
REG_JNI(register_android_os_Binder),
|
REG_JNI(register_android_os_Binder),
|
||||||
REG_JNI(register_android_os_Parcel),
|
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_nio_utils),
|
||||||
REG_JNI(register_android_graphics_Canvas),
|
REG_JNI(register_android_graphics_Canvas),
|
||||||
REG_JNI(register_android_graphics_Graphics),
|
REG_JNI(register_android_graphics_Graphics),
|
||||||
|
|||||||
288
core/jni/android_os_HwBinder.cpp
Normal file
288
core/jni/android_os_HwBinder.cpp
Normal file
@@ -0,0 +1,288 @@
|
|||||||
|
/*
|
||||||
|
* 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
|
||||||
60
core/jni/android_os_HwBinder.h
Normal file
60
core/jni/android_os_HwBinder.h
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
* 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
|
||||||
|
|
||||||
|
|
||||||
913
core/jni/android_os_HwParcel.cpp
Normal file
913
core/jni/android_os_HwParcel.cpp
Normal file
@@ -0,0 +1,913 @@
|
|||||||
|
/*
|
||||||
|
* 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
|
||||||
75
core/jni/android_os_HwParcel.h
Normal file
75
core/jni/android_os_HwParcel.h
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
/*
|
||||||
|
* 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
|
||||||
196
core/jni/android_os_HwRemoteBinder.cpp
Normal file
196
core/jni/android_os_HwRemoteBinder.cpp
Normal file
@@ -0,0 +1,196 @@
|
|||||||
|
/*
|
||||||
|
* 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
|
||||||
|
|
||||||
60
core/jni/android_os_HwRemoteBinder.h
Normal file
60
core/jni/android_os_HwRemoteBinder.h
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
* 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
|
||||||
|
|
||||||
178
core/jni/hwbinder/EphemeralStorage.cpp
Normal file
178
core/jni/hwbinder/EphemeralStorage.cpp
Normal file
@@ -0,0 +1,178 @@
|
|||||||
|
/*
|
||||||
|
* 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
|
||||||
|
|
||||||
84
core/jni/hwbinder/EphemeralStorage.h
Normal file
84
core/jni/hwbinder/EphemeralStorage.h
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
/*
|
||||||
|
* 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_
|
||||||
Reference in New Issue
Block a user