Binder system runs in native environment, not in JAVA VM. So for JAVA VM, it needs some JNI native implementation which lies in libs/android_runtime/android_util_Binder.cpp.
Get IServiceManager
ServiceManager.java manages all JAVA layer services. Any call in ServiceManager.java will first get a JAVA IServiceManager interface.
private static IServiceManager getIServiceManager() {
if (sServiceManager != null) {
return sServiceManager;
}
// Find the service manager
sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
return sServiceManager;
}
BinderInternal.getContextObject is a JNI native function named android_os_BinderInternal_getContextObject. It calls into C++ layer binder system to get an IBinder(Actually it points a C++ layer BpServiceManager object), then call javaObjectForIBinder to create a corresponding JAVA class to represent the C++ IBinder object.
static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
{
sp b = ProcessState::self()->getContextObject(NULL);
return javaObjectForIBinder(env, b);
}
javaObjectForIBinder will determine whether the object is the service provider or a service user. In getIServiceManager scenario, the object is a service user. So it will new a JAVA BinderProxy object to represent the C++ IBinder object.
jobject javaObjectForIBinder(JNIEnv* env, const sp& val)
{
object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor);
if (object != NULL) {
LOGV("objectForBinder %p: created new %p!\n", val.get(), object);
// The proxy holds a reference to the native object.
env->SetIntField(object, gBinderProxyOffsets.mObject, (int)val.get());
val->incStrong(object);
// The native object needs to hold a weak reference back to the
// proxy, so we can retrieve the same proxy if it is still active.
jobject refObject = env->NewGlobalRef(
env->GetObjectField(object, gBinderProxyOffsets.mSelf));
val->attachObject(&gBinderProxyOffsets, refObject,
jnienv_to_javavm(env), proxy_cleanup);
// Note that a new object reference has been created.
android_atomic_inc(&gNumProxyRefs);
incRefsCreated(env);
}
return object;
}
Okay, now we have a JAVA BinderProxy object. Then ServiceManagerNative.asInterface will new a ServiceManagerProxy on the BinderProxy object.
static public IServiceManager asInterface(IBinder obj)
{
return new ServiceManagerProxy(obj);
}
So getIServiceManager call finally returns a ServiceManagerProxy instance.
Service create
When any JAVA service object(derived from Binder) is created, it will call init native function which points to android_os_Binder_init. Here it will new an JavaBBinderHolder, which will be used later.
static void android_os_Binder_init(JNIEnv* env, jobject clazz)
{
JavaBBinderHolder* jbh = new JavaBBinderHolder(env, clazz);
if (jbh == NULL) {
jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
return;
}
LOGV("Java Binder %p: acquiring first ref on holder %p", clazz, jbh);
jbh->incStrong(clazz);
env->SetIntField(clazz, gBinderOffsets.mObject, (int)jbh);
}
Add service RPC call
Any JAVA layer service should call IServiceManager.addService API to register itself. IServiceManager.addService equals to ServiceManagerProxy.addService.
public void addService(String name, IBinder service)
throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IServiceManager.descriptor);
data.writeString(name);
data.writeStrongBinder(service);
mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);
reply.recycle();
data.recycle();
}
During in ServiceManagerProxy.addService, the JAVA service object will be written to Parcel, which finally calls a native function android_os_Parcel_writeStrongBinder.
static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jobject clazz, jobject object)
{
Parcel* parcel = parcelForJavaObject(env, clazz);
if (parcel != NULL) {
const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object));
if (err != NO_ERROR) {
jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
}
}
}
android_os_Parcel_writeStrongBinder call ibinderForJavaObject to generate an C++ layer IBinder object corresponding to the JavaBBinderHolder object.
sp ibinderForJavaObject(JNIEnv* env, jobject obj)
{
if (obj == NULL) return NULL;
if (env->IsInstanceOf(obj, gBinderOffsets.mClass)) {
JavaBBinderHolder* jbh = (JavaBBinderHolder*)
env->GetIntField(obj, gBinderOffsets.mObject);
return jbh != NULL ? jbh->get(env) : NULL;
}
if (env->IsInstanceOf(obj, gBinderProxyOffsets.mClass)) {
return (IBinder*)
env->GetIntField(obj, gBinderProxyOffsets.mObject);
}
LOGW("ibinderForJavaObject: %p is not a Binder object", obj);
return NULL;
}
JavaBBinderHolder will finally new a JavaBBinder instance.
sp get(JNIEnv* env)
{
AutoMutex _l(mLock);
sp b = mBinder.promote();
if (b == NULL) {
b = new JavaBBinder(env, mObject);
mBinder = b;
LOGV("Creating JavaBinder %p (refs %p) for Object %p, weakCount=%d\n",
b.get(), b->getWeakRefs(), mObject, b->getWeakRefs()->getWeakCount());
}
return b;
}
The JavaBBinder object is derived from BBinder. After ibinderForJavaObject, Android has successfully created a C++ layer BBinder object from JAVA layer service class.
ServiceManagerProxy then calls BinderProxy JNI native function android_os_BinderProxy_transact to dispatch the RPC call from JAVA to C++. In this function a C++ IBinder object(Mentioned before, actually it’s a BpServiceManager object) corresponding to the JAVA BinderProxy object is gotten, which is originally saved in javaObjectForIBinder.
static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,
jint code, jobject dataObj,
jobject replyObj, jint flags)
{
IBinder* target = (IBinder*)
env->GetIntField(obj, gBinderProxyOffsets.mObject);
if (target == NULL) {
jniThrowException(env, "java/lang/IllegalStateException", "Binder has been finalized!");
return JNI_FALSE;
}
status_t err = target->transact(code, *data, reply, flags);
if (err == NO_ERROR) {
return JNI_TRUE;
} else if (err == UNKNOWN_TRANSACTION) {
return JNI_FALSE;
}
signalExceptionForError(env, obj, err);
return JNI_FALSE;
}
Okay, until now. Android have successfully send RPC call from JAVA layer to C++ layer. The RPC call will be handled by service_manager process. The C++ layer’s handling is another story, which won’t be included in this topic.You can refer to my C++ layer Binder system introduction.
Get ISensorService
The only way to get an interface is through IServiceManager.getService. Just like the process of IServiceManager.addService, the RPC call is sent from JAVA ServiceManagerProxy to C++ BpServiceManager. BpServiceManager finally delivers the call to service_manager process. After service_manager process this RPC call, BpServiceManager will continue executing. The returned C++ IBinder object actually is a BpBinder instance.
virtual sp getService(const String16& name) const
{
unsigned n;
for (n = 0; n < 5; n++){
sp svc = checkService(name);
if (svc != NULL) return svc;
LOGI("Waiting for sevice %s...\n", String8(name).string());
sleep(1);
}
return NULL;
}
virtual sp checkService( const String16& name) const
{
Parcel data, reply;
data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
data.writeString16(name);
remote()->transact(CHECK_SERVICE_TRANSACTION, data, &reply);
return reply.readStrongBinder();
}
Then ServiceManagerProxy will get executed after transact, it calls a JNI native function android_os_Parcel_readStrongBinder. android_os_Parcel_readStrongBinder will call javaObjectForIBinder to generate a JAVA object for the returned C++ IBinder object.
static jobject android_os_Parcel_readStrongBinder(JNIEnv* env, jobject clazz)
{
Parcel* parcel = parcelForJavaObject(env, clazz);
if (parcel != NULL) {
return javaObjectForIBinder(env, parcel->readStrongBinder());
}
return NULL;
}
javaObjectForIBinder will determine whether the object is the service provider or a service user. In this scenario, the object is a service user. So it will new a JAVA BinderProxy object to represent the C++ IBinder object just like the scenario to get IServiceManager. Okay, now we have a JAVA BinderProxy object. Then ISensorService.Stub.asInterface will new a ISensorService.Stub.Proxy on the BinderProxy object.
/**
* Cast an IBinder object into an ISensorService interface,
* generating a proxy if needed.
*/
public static android.hardware.ISensorService asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.hardware.ISensorService in = (android.hardware.ISensorService)obj.queryLocalInterface(DESCRIPTOR);
if ((in!=null)) {
return in;
}
return new android.hardware.ISensorService.Stub.Proxy(obj);
}
So we finally get an ISensorService.Stub.Proxy instance.
ISensorService.reportAccuracy RPC Call
It equals to call ISensorService.Stub.Proxy.reportAccuracy. The corresponding code is generated by aidl. It calls BinderProxy JNI native function android_os_BinderProxy_transact to dispatch the RPC call from JAVA to C++. Okay, until now. Android have successfully send RPC call from JAVA layer to C++ layer.
Handle ISensorService.reportAccuracy RPC Call
The RPC call will be first handled by C++ JavaBBinder object (This step is introduced in my Binder system introduction.), which is generated during IServiceManager.addService call.
virtual status_t onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0)
{
JNIEnv* env = javavm_to_jnienv(mVM);
jboolean res = env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact,
code, (int32_t)&data, (int32_t)reply, flags);
jthrowable excep = env->ExceptionOccurred();
if (excep) {
report_exception(env, excep,
"*** Uncaught remote exception! "
"(Exceptions are not yet supported across processes.)");
res = JNI_FALSE;
/* clean up JNI local ref -- we don't return to Java */
env->DeleteLocalRef(excep);
}
JavaBBinder will call JAVA layer’s function through JNI. The function is Binder.executeTransact.
private boolean execTransact(int code, int dataObj, int replyObj,
int flags) {
Parcel data = Parcel.obtain(dataObj);
Parcel reply = Parcel.obtain(replyObj);
// theoretically, we should call transact, which will call onTransact,
// but all that does is rewind it, and we just got these from an IPC,
// so we'll just call it directly.
boolean res;
try {
res = onTransact(code, data, reply, flags);
} catch (RemoteException e) {
reply.writeException(e);
res = true;
} catch (RuntimeException e) {
reply.writeException(e);
res = true;
}
reply.recycle();
data.recycle();
return res;
}
Finally Binder.executeTransact will call ISensorService.onTransact. ISensorService.onTransact will call SensorService.reportAccuracy to do the real work。
分享到:
相关推荐
模拟实现android的binder机制在java层、c++层的模型最小例子。实现在不同进程中的通信。
Android.mk BnComTestService.h BpComTestService.h ComTestService.h IComTestService.h BnComTestService.cpp BpComTestService.cpp ComTestService.cpp IComTestService.cpp 两个program, 一个client, 一个...
android 的ipc通信机制,详细说明了IPC的通信原理
Deep Dive into Android IPC-Binder Framework 深入Android IPB/Binder 框架
4 Android JAVA Binder IPC System 20 5 Android Media Scanner Process 27 5.1 JAVA layer initialize 27 5.2 JAVA layer prescan 28 5.3 C++ layer processDirectory 28 5.4 JAVA layer scanFile 29 5.5 JAVA ...
Deep Dive into Android IPC & Binder.pdf Deep Dive into Android IPC/Binder Framework at Android Builders Summit 2013 Binder Overview IPC Advantages of Binder Binder vs Intent/ContentProvider/...
Android 的 Binder IPC 系统完全调解所有应用程序间消息,包括应用程序对私人用户数据的请求。我们通过我们的开源 BinderFilter 项目为用户提供对所有此类 IPC 消息的控制和可见性,包括动态权限阻止。这包括 ...
简要介绍Android IPC机制Binder
高焕堂编著AndroidIPC和binder框架
此是android binder IPC机制了解有帮助
《android-binder-arch》
Android的binder机制~~~~~~~~~~~~~~
Binder Android IPC Linux 内核 驱动
android应用程序理所当然可以应用JAVA的IPC机制实现进程间的通信, 取而代之的是Binder通信。Google为什么要采用这种方式呢,这取决于Binder通信方式的高效率。 Binder通信是通过linux的binder driver来实现的。...
Andrid系统中基于Binder的IPC流程框架分析_V1.0_201407251755.pdf
Android AIDL Binder 实现与详解。此资源实现了 Android AIDL 通信,自定义 AIDL 数据类型。同时演示了定向 Tag 『inout in out』的区别。并且配有博文详细解释相关知识点以及需要注意的细节。
代码为博客示例代码,有问题请博客留言:http://blog.csdn.net/lmj623565791/article/details/38461079
android binder的学习实例,仅供大家学习参考,麻雀虽小,五脏俱全。
将android的binder框架移植到linux下面,同时写了一个点灯硬件服务进行测试,还包括android logger系统 测试半年未发现问题
java binder资料java binder资料java binder资料java binder资料java binder资料java binder资料java binder资料java binder资料java binder资料java binder资料java binder资料java binder资料java binder资料