Android的进程间通信(六)之 Binder的客户端发送数据到服务端的流程
上一篇文章,介绍了Binder 内核层的注册代码以及ServiceManager初始化的过程。
而我们平时在使用进程间通信时,只需要关注的“客户端”,“服务端”等概念。今天,就让我们来看一下,我们平时在使用AIDL的背后,是如何涉及到Binder内核和ServiceManager的。
AIDL的使用过程:
第一:我们定义一个AIDL文件
interface IAIDLService {
void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,double aDouble, String aString);
}
第二:在我们的页面上,通过 bindService 的方式启动服务,并且在onServiceConnected方法中,把IBinder接口通过IAIDLService.Stub.asInterface(service)转化成IAIDLService接口,然后就可以通过IAIDLService接口调用对应的接口即可。
bindService(intent, new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
IAIDLService iaidlService = IAIDLService.Stub.asInterface(service);
try {
iaidlService.basicTypes(1,2,true,4,5,"6");
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
}, Context.BIND_AUTO_CREATE);
第三:在我们的服务端,需要实现 IBinder onBind(Intent intent) 方法,然后实例化new IAIDLService.Stub() 并且再onBind中返回回去。注意:Service要配置运行在另外一个进程。
private IAIDLService.Stub binder = new IAIDLService.Stub() {
@Override
public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {
Log.e("TAG","basicTypes:anInt:" + anInt + " aLong:" + aLong + " aBoolean:" + aBoolean + " aFloat:" + aFloat
+ " aDouble:" + aDouble + " aString:" + aString);
}
};
这样,我们就实现了从客户端进程发送数据到服务端进程了。
平时,我们使用的AIDL是经过层层封装,那么背后它的原理是什么样子的呢?
我们首先看到 IAIDLService iaidlService = IAIDLService.Stub.asInterface(service);这一行代码。IAIDLService是一个接口,所以我们先要知道,IAIDLService的具体实现是谁。所以,我们看一下asInterface方法。
public static com.bzl.a929demo.service.aidl.IAIDLService asInterface(android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
if (((iin != null) && (iin instanceof com.bzl.a929demo.service.aidl.IAIDLService))) {
return ((com.bzl.a929demo.service.aidl.IAIDLService) iin);
}
return new com.bzl.a929demo.service.aidl.IAIDLService.Stub.Proxy(obj);
}
这里主要做了客户端和服务端是否在同一个进程的判断,如果不是,就创建IAIDLService.Stub.Proxy(obj)类。也就是说 IAIDLService 的具体实现是 IAIDLService.Stub.Proxy。
我们在客户端发送数据的时候,是调用了 iaidlService.basicTypes 这个方法,看一下 Proxy.basicTypes这个方法的具体实现。
@Override
public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, java.lang.String aString) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeInt(anInt);
_data.writeLong(aLong);
_data.writeInt(((aBoolean) ? (1) : (0)));
_data.writeFloat(aFloat);
_data.writeDouble(aDouble);
_data.writeString(aString);
boolean _status = mRemote.transact(Stub.TRANSACTION_basicTypes, _data, _reply, 0);
if (!_status && getDefaultImpl() != null) {
getDefaultImpl().basicTypes(anInt, aLong, aBoolean, aFloat, aDouble, aString);
return;
}
_reply.readException();
} finally {
_reply.recycle();
_data.recycle();
}
}
这里的最要操作,就是把数据装载到Parcel中,然后通过 mRemote.transact 方法发送出去。那么,mRemote又是谁呢?我们来到Proxy的构造方法。
Proxy(android.os.IBinder remote) {
mRemote = remote;
}
可以看到,mRemote 就是在bindService的onServiceConnected回调方法中IBinder service接口。到这里,我们便遇到第一个难题:IBinder接口是在启动服务时系统回调的。我们如果要从代码里分析出来IBinder的具体实现是谁,还需要去走一遍启动服务的流程。
我们这里采用debug的方式来看出IBinder的具体实现。
从debug的结果上来看,mRemote的具体是BinderProxy,所以,我们来到BinderProxy.transact()这个方法。
public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
省略代码。。。。
try {
return transactNative(code, data, reply, flags);
} finally {
if (transactListener != null) {
transactListener.onTransactEnded(session);
}
if (tracingEnabled) {
Trace.traceEnd(Trace.TRACE_TAG_ALWAYS);
}
}
}
transact 调用了 transactNative方法,transactNative是一个本地方法,我们看一下对应的JNI实现。
我们在 android_util_Binder 中,找到了 transactNative的实现。
static const JNINativeMethod gBinderProxyMethods[] = {
/* name, signature, funcPtr */
{"pingBinder", "()Z", (void*)android_os_BinderProxy_pingBinder},
{"isBinderAlive", "()Z", (void*)android_os_BinderProxy_isBinderAlive},
{"getInterfaceDescriptor", "()Ljava/lang/String;", (void*)android_os_BinderProxy_getInterfaceDescriptor},
{"transactNative", "(ILandroid/os/Parcel;Landroid/os/Parcel;I)Z", (void*)android_os_BinderProxy_transact},
{"linkToDeath", "(Landroid/os/IBinder$DeathRecipient;I)V", (void*)android_os_BinderProxy_linkToDeath},
{"unlinkToDeath", "(Landroid/os/IBinder$DeathRecipient;I)Z", (void*)android_os_BinderProxy_unlinkToDeath},
{"getNativeFinalizer", "()J", (void*)android_os_BinderProxy_getNativeFinalizer},
};
从这个结构体中,可以看到 transactNative 对应 android_os_BinderProxy_transact方法。看一下 android_os_BinderProxy_transact的实现。
static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,
jint code, jobject dataObj, jobject replyObj, jint flags) // throws RemoteException
{
省略代码 ...
IBinder* target = getBPNativeData(env, obj)->mObject.get();
省略代码 ...
//printf("Transact from Java code to %p sending: ", target); data->print();
status_t err = target->transact(code, *data, reply, flags);
省略代码 ...
return JNI_FALSE;
}
这个方法,主要有两行我们需要看的代码。
第一行是:
IBinder* target = getBPNativeData(env, obj)->mObject.get();
我们需要确定,IBinder的具体实现。所以,看一下getBPNativeData的代码。
BinderProxyNativeData* getBPNativeData(JNIEnv* env, jobject obj) {
return (BinderProxyNativeData *) env->GetLongField(obj, gBinderProxyOffsets.mNativeData);
}
getBPNativeData 返回一个 BinderProxyNativeData 的结构体,这个结构体已经提前初始化并且存在JNIEnv里,在JNI层会缓存在gNativeDataCache 上。我们先看一下 BinderProxyNativeData 结构体的定义。
struct BinderProxyNativeData {
// Both fields are constant and not null once javaObjectForIBinder returns this as
// part of a BinderProxy.
// The native IBinder proxied by this BinderProxy.
sp<IBinder> mObject;
// Death recipients for mObject. Reference counted only because DeathRecipients
// hold a weak reference that can be temporarily promoted.
sp<DeathRecipientList> mOrgue; // Death recipients for mObject.
};
所以,我们需要知道,mObject是在哪里初始化的,就首先需要知道 gNativeDataCache 在哪里被初始化。
gNativeDataCache 在 javaObjectForIBinder 中被初始化,javaObjectForIBinder 在 android_os_BinderInternal_getContextObject中被调用,而 android_os_BinderInternal_getContextObject 是一个JNI方法,由Java层调用。
看一下 android_os_BinderInternal_getContextObject 的实现。
static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
{
sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
return javaObjectForIBinder(env, b);
}
mObject 就是这个 ProcessState::self()->getContextObject(NULL); 。重点看一下这个方法。
我们来到了 ProcessState.cpp 文件,找到getContextObject这个方法的实现。
sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
{
return getStrongProxyForHandle(0);
}
可以看到这里获得一个 handle = 0 的IBinder 接口。
sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
......
if (handle == 0) {
Parcel data;
status_t status = IPCThreadState::self()->transact(
0, IBinder::PING_TRANSACTION, data, NULL, 0);
if (status == DEAD_OBJECT)
return NULL;
}
b = BpBinder::create(handle);
e->binder = b;
if (b) e->refs = b->getWeakRefs();
result = b;
....
return result;
}
所以 ProcessState::self()->getContextObject(NULL) 返回的是一个 BpBinder
所以,在从java层到JNI的 android_os_BinderProxy_transact,本质上是 BpBinder->transact()。
看一下 BpBinder->transact这个方法的实现。
status_t BpBinder::transact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
// Once a binder has died, it will never come back to life.
if (mAlive) {
status_t status = IPCThreadState::self()->transact(
mHandle, code, data, reply, flags);
if (status == DEAD_OBJECT) mAlive = 0;
return status;
}
return DEAD_OBJECT;
}
继续看一下 IPCThreadState的transact的实现。
status_t IPCThreadState::transact(int32_t handle,uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags)
{
.....
err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);
.....
if ((flags & TF_ONE_WAY) == 0) {
.....
if (reply) {
err = waitForResponse(reply);
} else {
Parcel fakeReply;
err = waitForResponse(&fakeReply);
}
.....
} else {
err = waitForResponse(NULL, NULL);
}
return err;
}
writeTransactionData 进行数据的封装,要记得 BC_TRANSACTION 这个type
waitForResponse 把数据发送出去,继续看一下这个方法的实现。
status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult){
..... 省略代码
while (1) {
..... 省略代码
if ((err=talkWithDriver()) < NO_ERROR) break;
..... 省略代码
}
..... 省略代码
}
waitForResponse 最主要调用了 talkWithDriver 方法,继续看 talkWithDriver 的实现。
status_t IPCThreadState::talkWithDriver(bool doReceive)
{
..... 省略
do {
IF_LOG_COMMANDS() {
alog << "About to read/write, write size = " << mOut.dataSize() << endl;
}
#if defined(__ANDROID__)
if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)
err = NO_ERROR;
else
err = -errno;
#else
err = INVALID_OPERATION;
#endif
if (mProcess->mDriverFD <= 0) {
err = -EBADF;
}
IF_LOG_COMMANDS() {
alog << "Finished read/write, write size = " << mOut.dataSize() << endl;
}
} while (err == -EINTR);
.... 省略
return err;
}
到了这里,终于看到 ioctl 了。到了这里,就把数据发到了Binder内核。
Binder内核会把数据转发给对应的服务端,就不继续往下走了。
这一篇代码分析,里面可能存在一些错误,但是我的目的就是从代码层面去验证前面几篇的理论分析。但是好累啊,哈哈哈。
Binder的学习就告一段落。
本文地址:https://blog.csdn.net/s2311307/article/details/111868681
上一篇: Java并发编程之Java内存模型