Java层到Native层Binder的流程
来源:互联网 发布:百度搜索软件 编辑:程序博客网 时间:2024/05/17 23:51
我们在SystemServer分析
这个文章中已经知道通过ServiceManager.addService("xx", new XXBinder(this));
已经添加了很多服务,这些都是继承Binder的服务,需要跨进程操作。包括我们自己声明的服务也是一个道理,都是继承Binder。
并且我们上一章已经介绍了添加服务和查询服务的底层流程,但是问题来了,他们都是native层的,没有java的代码出现,那么Binder的通信是怎么和Java层建立联系的呢?
带着这个问题,我们就从Binder的构造方法追寻下去。
public Binder() { init(); ... }
其中private native final void init();
然后进入到android_utils_Binder.cpp中
这个分享一个小技巧,我是用Source Insight3查看的源代码,所以使用快捷键Ctrl+?搜索,由于jni文件有个规则,就比如:这个Binder中的init(),进行搜索的内容是包名+类名+方法名称只不过要把.号换成_,所以就是android_os_Binder_init().
static void android_os_Binder_init(JNIEnv* env, jobject obj){ JavaBBinderHolder* jbh = new JavaBBinderHolder();//[1] if (jbh == NULL) { jniThrowException(env, "java/lang/OutOfMemoryError", NULL); return; } ALOGV("Java Binder %p: acquiring first ref on holder %p", obj, jbh); jbh->incStrong((void*)android_os_Binder_init); env->SetLongField(obj, gBinderOffsets.mObject, (jlong)jbh);//将JavaBBinderHolder对象设置给gBinderOffsets.mObject}
1 JavaBBinderHolder()
class JavaBBinderHolder : public RefBase{public: sp<JavaBBinder> get(JNIEnv* env, jobject obj) { AutoMutex _l(mLock); sp<JavaBBinder> b = mBinder.promote(); if (b == NULL) { b = new JavaBBinder(env, obj);//[1.1] mBinder = b; } return b; } sp<JavaBBinder> getExisting() { AutoMutex _l(mLock); return mBinder.promote(); }private: Mutex mLock; wp<JavaBBinder> mBinder;};
1.1 JavaBBinder()
这里的object是Java层继承Binder的服务类
我们在这里看到了gBinderOffsets.mExecTransact
这个是java层方法名字,我们找到赋值的对应代码
static int int_register_android_os_Binder(JNIEnv* env){ jclass clazz = FindClassOrDie(env, kBinderPathName); gBinderOffsets.mClass = MakeGlobalRefOrDie(env, clazz); gBinderOffsets.mExecTransact = GetMethodIDOrDie(env, clazz, "execTransact", "(IJJI)Z"); gBinderOffsets.mObject = GetFieldIDOrDie(env, clazz, "mObject", "J"); return RegisterMethodsOrDie( env, kBinderPathName, gBinderMethods, NELEM(gBinderMethods));}
也就是说在调用int_register_android_os_Binder的时候execTransact
这个java层的方法的id会存到gBinderOffsets.mExecTransac
变量中。
class JavaBBinder : public BBinder{public: JavaBBinder(JNIEnv* env, jobject object) : mVM(jnienv_to_javavm(env)), mObject(env->NewGlobalRef(object)) { android_atomic_inc(&gNumLocalRefs); incRefsCreated(env); } bool checkSubclass(const void* subclassID) const { return subclassID == &gBinderOffsets; } jobject object() const { return mObject; }protected: virtual ~JavaBBinder() { android_atomic_dec(&gNumLocalRefs); JNIEnv* env = javavm_to_jnienv(mVM); env->DeleteGlobalRef(mObject); } virtual status_t onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0) { JNIEnv* env = javavm_to_jnienv(mVM); IPCThreadState* thread_state = IPCThreadState::self(); const int32_t strict_policy_before = thread_state->getStrictModePolicy(); //这个代码调用的是execTransact方法将这些数据传递。 jboolean res = env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact, code, reinterpret_cast<jlong>(&data), reinterpret_cast<jlong>(reply), flags); if (code == SYSPROPS_TRANSACTION) { BBinder::onTransact(code, data, reply, flags); } return res != JNI_FALSE ? NO_ERROR : UNKNOWN_TRANSACTION; } virtual status_t dump(int fd, const Vector<String16>& args) { return 0; }private: JavaVM* const mVM; jobject const mObject;//对应的是Java层的Binder};
到了这里,我们已经将Java层的Binder服务和Native层的BBinder联系起来。,从驱动层上来调用onTransact()方法就可以到达Java层的execTransact()方法。
在这里我们也注意一个问题,由于onTransact()方法是BBinder的函数,而现在JavaBBinder覆写了这个函数,所以调用的时候会调用到execTransact(),那么在那块才调用onTransact()呢?
BpBinder::transact()->
IPCThreadState::transact()->
IPCThreadState::waitForResponse()->
IPCThreadState::executeCommand()
status_t IPCThreadState::executeCommand(int32_t cmd){ BBinder* obj; RefBase::weakref_type* refs; status_t result = NO_ERROR; switch ((uint32_t)cmd) { ... case BR_TRANSACTION: if (tr.target.ptr) { sp<BBinder> b((BBinder*)tr.cookie); error = b->transact(tr.code, buffer, &reply, tr.flags); } } ...}
status_t BBinder::transact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags){ status_t err = NO_ERROR; switch (code) { case PING_TRANSACTION: reply->writeInt32(pingBinder()); break; default: err = onTransact(code, data, reply, flags); break; } ...}
此时的BBinder的派生类是JavaBBinder类,然后调用它的onTransact()这个方法会调用java层的execTransact()方法。
在使用IPCThreadState::transact
发送数据的时候会调用waitForResponse()
然后调用executeCommand()
然后调用transact()
然后调用onTransact()
也就是说在native层回复数据的时候会调用到onTransact()
方法。
Binder.java中
下面我们看一看Java层的execTransact()
private boolean execTransact(int code, long dataObj, long replyObj, int flags) { Parcel data = Parcel.obtain(dataObj); Parcel reply = Parcel.obtain(replyObj); boolean res; try { res = onTransact(code, data, reply, flags);//回调继承java层Binder的onTransact()方法 } catch (RemoteException e) { if ((flags & FLAG_ONEWAY) != 0) { Log.w(TAG, "Binder call failed.", e); } else { reply.setDataPosition(0); reply.writeException(e); } res = true; } catch (RuntimeException e) { if ((flags & FLAG_ONEWAY) != 0) { } else { reply.setDataPosition(0); reply.writeException(e); } res = true; } catch (OutOfMemoryError e) { RuntimeException re = new RuntimeException("Out of memory", e); reply.setDataPosition(0); reply.writeException(re); res = true; } checkParcel(this, code, reply, "Unreasonably large binder reply buffer"); reply.recycle(); data.recycle(); StrictMode.clearGatheredViolations(); return res; }
我们下面将会看到对应java层Binder的方法
应用在Java层的Binder引用是通过Binder的代理完成的。
我们首先看一个aidl产生的文件,然后进行分析:
public interface IHelloService extends android.os.IInterface{ public static abstract class Stub extends android.os.Binder implements IHelloService { private static final java.lang.String DESCRIPTOR = "IHelloService"; public Stub() { this.attachInterface(this, DESCRIPTOR); } public static IHelloService asInterface(android.os.IBinder obj) { if ((obj==null)) { return null; } android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR); if (((iin!=null)&&(iin instanceof IHelloService))) { return ((IHelloService)iin); } return new IHelloService.Stub.Proxy(obj); } @Override public android.os.IBinder asBinder() { return this; } @Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException { switch (code) { case INTERFACE_TRANSACTION: { reply.writeString(DESCRIPTOR); return true; } case TRANSACTION_sayhello: { data.enforceInterface(DESCRIPTOR); this.sayhello(); reply.writeNoException(); return true; } case TRANSACTION_sayhello_to: { data.enforceInterface(DESCRIPTOR); java.lang.String _arg0; _arg0 = data.readString(); int _result = this.sayhello_to(_arg0); reply.writeNoException(); reply.writeInt(_result); return true; } } return super.onTransact(code, data, reply, flags); } private static class Proxy implements IHelloService { private android.os.IBinder mRemote; Proxy(android.os.IBinder remote) { mRemote = remote; } @Override public android.os.IBinder asBinder() { return mRemote; } public java.lang.String getInterfaceDescriptor() { return DESCRIPTOR; } @Override public void sayhello() throws android.os.RemoteException { android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); try { _data.writeInterfaceToken(DESCRIPTOR); mRemote.transact(Stub.TRANSACTION_sayhello, _data, _reply, 0); _reply.readException(); } finally { _reply.recycle(); _data.recycle(); } } @Override public int sayhello_to(java.lang.String name) throws android.os.RemoteException { android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); int _result; try { _data.writeInterfaceToken(DESCRIPTOR); _data.writeString(name); mRemote.transact(Stub.TRANSACTION_sayhello_to, _data, _reply, 0); _reply.readException(); _result = _reply.readInt(); } finally { _reply.recycle(); _data.recycle(); } return _result; } } static final int TRANSACTION_sayhello = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0); static final int TRANSACTION_sayhello_to = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1); } public void sayhello() throws android.os.RemoteException; public int sayhello_to(java.lang.String name) throws android.os.RemoteException;}
下面是调用方法:
/* 1. getService */IBinder binder = ServiceManager.getService("hello");if (binder == null){ System.out.println("can not get hello service"); Slog.i(TAG, "can not get hello service"); return;}IHelloService svr = IHelloService.Stub.asInterface(binder);
我们通过aidl产生的java文件可以看出来通过asInterface方法
public static IHelloService asInterface(android.os.IBinder obj){ if ((obj==null)) { return null; } android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR); if (((iin!=null)&&(iin instanceof IHelloService))) { return ((IHelloService)iin); } return new IHelloService.Stub.Proxy(obj);}private static class Proxy implements IHelloService{ private android.os.IBinder mRemote; Proxy(android.os.IBinder remote) { mRemote = remote; } ...}
当调用的时候svr.sayhello();
就会调用:
@Override public void sayhello() throws android.os.RemoteException{ android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); try { _data.writeInterfaceToken(DESCRIPTOR); mRemote.transact(Stub.TRANSACTION_sayhello, _data, _reply, 0); _reply.readException(); } finally { _reply.recycle(); _data.recycle(); }}
我们都知道mRemote其实就是BpBinder对象。
所以调用BpBinder对象的transact方法
status_t BpBinder::transact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags){ if (mAlive) { status_t status = IPCThreadState::self()->transact( mHandle, code, data, reply, flags); if (status == DEAD_OBJECT) mAlive = 0; return status; } return DEAD_OBJECT;}
这个方法我们之前已经分析过了,是通过BpBinder的写数据,读数据
总结:
我们先从Binder的构造出发,因为Binder服务可以是SystemServer添加的服务,也可以是自己创建的匿名服务,但是都会调用构造方法。发现构造方法中调用native层的init方法,init()方法做的事情就是创建JavaBBinderHolder对象这个对象中get方法会得到JavaBBinder对象,JavaBBinder对象继承BBinder类。并且重写BBinder的onTransact()方法,onTransact()会调用java层的execTransact(),这样就可以将Java层和native层的连接起来。
然后我们分析了从驱动如何调用到BBinder的onTransact()方法,我们的调用顺序是:
BpBinder::transact()-> IPCThreadState::transact()-> IPCThreadState::waitForResponse()-> IPCThreadState::executeCommand()
我们上篇文章分析了BpBinder是BpServiceManager成员变量mRemote也就是native层通过sp<IServiceManager> sm(defaultServiceManager());
方法得到的.
其中BpBinder可以调用到BpBinder::transact()->IPCThreadState::self()->transact()
和驱动进行通信.这个方法会调用到IPCThreadState::executeCommand()
这个方法会调用
sp<BBinder> b((BBinder*)tr.cookie);error = b->transact(tr.code, buffer, &reply, tr.flags);
其中b->transact()
会调用onTransact()
这里注意b是BBinder我们在java代码中看到是JavaBBinder继承与BBinder,所以此时会调用JavaBBinder的onTransact(),在这个回调函数中我们将可以看到调用execTransact(),然后我们在Binder.java的execTransact()方法中看到又调用Binder.java的onTransact()方法,所以回调了我们生成的aidl文件中的onTransact()方法。
最后我们也从java层出发看了是如何通信到底层的,我们在aidl产生的文件中可以看到
sayhello(): mRemote.transact(Stub.TRANSACTION_sayhello, _data, _reply, 0);
其中mRemote就是BpBinder。
这样我们就从java到底层完成了整个流程的创建。
- Java层到Native层Binder的流程
- Binder(native层)
- Android------Binder java层如何与native层交互
- Binder机制3---Native层
- Binder机制3---Native层
- Binder机制3---Native层
- Android系统的Binder机制及其native层应用
- Android5.0中Binder机制相关的native层和java层中的Binder代理和实体的对象的分析
- Android消息机制,从Java层到Native层剖析
- Binder Java层的使用介绍
- Java层的Binder服务实现
- Java 层Binder的使用(Android framework)
- android Binder机制3---Native层
- Binder源码分析之Native层
- MediaRecorder流程分析 java层到stagefright层
- JNI开发中native层与Java层的交互
- Java层Binder机制详解
- Binder java层实现原理
- Leetcode Algorithm 207. Course Schedule
- STL C++ Primer算法总结(一)
- java 多线程技术基础
- [BZOJ3307][雨天的尾巴][树链剖分+线段树]
- PHP获取访问者IP
- Java层到Native层Binder的流程
- 网易18实习生网测题--吃豆子
- ScrollView嵌套TextView文字上部截断下部有空隙
- 使用moy快速开发后台管理系统(四)
- BSI TR-03110
- JavaScript不懂的东西
- Java ClassLoader 类加载器
- #升级Android Studio2.3遇到的奇葩问题及最终解决方法
- 自考学习总结