我们在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
}
class JavaBBinderHolder : public RefBase
{
public:
sp get(JNIEnv* env, jobject obj)
{
AutoMutex _l(mLock);
sp b = mBinder.promote();
if (b == NULL) {
b = new JavaBBinder(env, obj);//[1.1]
mBinder = b;
}
return b;
}
sp getExisting()
{
AutoMutex _l(mLock);
return mBinder.promote();
}
private:
Mutex mLock;
wp mBinder;
};
这里的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(&data), reinterpret_cast(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& 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 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
方法得到的.
其中BpBinder可以调用到BpBinder::transact()->IPCThreadState::self()->transact()
和驱动进行通信.这个方法会调用到IPCThreadState::executeCommand()
这个方法会调用
sp 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到底层完成了整个流程的创建。