文章仅仅用于个人的学习记录,基本上内容都是网上各个大神的杰作,此处摘录过来以自己的理解学习方式记录一下。
个人学习参考的大神连接:
1、概述。
Java层的Binder,其实就是对底层的Binder的真正实现的一个封装,最终还是通过JNI技术调用到C/C++代码的实现。
Java层的Binder相关代码的很多的命名规范和C/C++层的基本保持一致。此整理是在对Binder有一定的认识后,个人用于
学习记录。
2、JNI层的知识。
学习Java层的Binder知识的时候了解到是通过JNI调用到运行库的,但是当时并不知道具体是那些库函数的调用。此处作
为学习整理,先把这方面的知识点大概的列举出来,方便后文的分析。
在源码工程的android/frameworks/base/core/jni/android_util_Binder.cpp当中实现了绝大部分的和java层Binder相
关的功能。
下面介绍一下核心的变量和方法:
//native层的一个结构体,用来表示java层的Binder类在JNI层的使用情况。以便对java层的操作。
static struct bindnative_offsets_t
{
jclass mClass //用来连接java层的Binder类
jmethodID mExectransact; //用来连接java层Binder类的execTransact函数
jfieldID mObject //用来连接java层Binder类的成员变量 mObject。
} gBinderOffsets; //这个结构体的名字,感觉上不应该有offsets.
//同理是表示java层的BinderProxy类的。
static struct binderproxy_offsets_t
{
jclass mclass;//连接java中的BinderProxy类。
jmethodID mConstructor;//java中BinderProxy类的构造。
jmethodID mSendDeathNotice //对应的SendDeathNotice方法.
//对应java中的BinderProxy类,成员变量mObject.
jfiledID mObject;
//对应成员变量mSelf. 保存Java层的BinderProxy对象的弱引用,方便,Natvie层管理生命周期。
jfiledID mSelf;
jfiledID mOrgue;//对应成员变量mOrgue.和接受客户端也就是代理端死亡通知消息有关。
}gBinderProxyOffsets;
//同理是表示java层的BinderInternal类的。
static struct binderinternal_offsets_t
{
jclass mclass;//连接java中的BinderInternal类.
jmethodID mForceGC;
}gBinderInternalOffsets;
重要的方法有如下:
先是
register_android_os_Binder这个方法是由AndroidRuntime在进行调用。此方法的内部分别调用另外的三个具体的
方法初始化,我们前面所说的三个结构体,也就是
java中的Binder、BinderProxy、BinderInternal和
Native层中这三个类
的关系。
int register_android_os_Binder(JNIEnv* env)
{
if (int_register_android_os_Binder(env) < 0)//初始化Binder类相关
return -1;
if (int_register_android_os_BinderInternal(env) < 0)//初始化BinderInternal类相关
return -1;
if (int_register_android_os_BinderProxy(env) < 0)//初始化BinderProxy类相关。
return -1;
jclass clazz;
......//省略和Log以及权限等相关的.
return 0;
}
初始化
gBinderOffsets结构体:
const char* const kBinderPathName = "android/os/Binder";
static int int_register_android_os_Binder(JNIEnv* env)
{
jclass clazz;
clazz = env->FindClass(kBinderPathName);//获得一个java中的Binder类对象
LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.Binder");
//下面就是把java层的对象或者方法转换成JNI层的.
gBinderOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
gBinderOffsets.mExecTransact
= env->GetMethodID(clazz, "execTransact", "(IJJI)Z");
assert(gBinderOffsets.mExecTransact);
//两个mObject对应起来.
gBinderOffsets.mObject
= env->GetFieldID(clazz, "mObject", "J");
assert(gBinderOffsets.mObject);
//调用到AndroidRunTime完成最终注册。
return AndroidRuntime::registerNativeMethods(
env, kBinderPathName,
gBinderMethods, NELEM(gBinderMethods));
}
初始化
gBinderProxyOffsets结构体:
const char* const kBinderProxyPathName = "android/os/BinderProxy";
static int int_register_android_os_BinderProxy(JNIEnv* env)
{
jclass clazz;
......//省略错误信息的处理.
clazz = env->FindClass(kBinderProxyPathName);
LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.BinderProxy");
//同样是把Java层的对象、变量、方法保存到相应的JNI层的对应的结构中.
gBinderProxyOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
gBinderProxyOffsets.mConstructor
= env->GetMethodID(clazz, "<init>", "()V");
assert(gBinderProxyOffsets.mConstructor);
gBinderProxyOffsets.mSendDeathNotice
= env->GetStaticMethodID(clazz, "sendDeathNotice", "(Landroid/os/IBinder$DeathRecipient;)V");
assert(gBinderProxyOffsets.mSendDeathNotice);
gBinderProxyOffsets.mObject
= env->GetFieldID(clazz, "mObject", "J");
assert(gBinderProxyOffsets.mObject);
gBinderProxyOffsets.mSelf
= env->GetFieldID(clazz, "mSelf", "Ljava/lang/ref/WeakReference;");
assert(gBinderProxyOffsets.mSelf);
gBinderProxyOffsets.mOrgue
= env->GetFieldID(clazz, "mOrgue", "J");
assert(gBinderProxyOffsets.mOrgue);
clazz = env->FindClass("java/lang/Class");
LOG_FATAL_IF(clazz == NULL, "Unable to find java.lang.Class");
gClassOffsets.mGetName = env->GetMethodID(clazz, "getName", "()Ljava/lang/String;");
assert(gClassOffsets.mGetName);
return AndroidRuntime::registerNativeMethods(
env, kBinderProxyPathName,
gBinderProxyMethods, NELEM(gBinderProxyMethods));
}
初始化
gBinderInternalOffsets结构体
const char* const kBinderInternalPathName = "com/android/internal/os/BinderInternal";
static int int_register_android_os_BinderInternal(JNIEnv* env)
{
jclass clazz;
clazz = env->FindClass(kBinderInternalPathName);
LOG_FATAL_IF(clazz == NULL, "Unable to find class com.android.internal.os.BinderInternal");
gBinderInternalOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
gBinderInternalOffsets.mForceGc
= env->GetStaticMethodID(clazz, "forceBinderGc", "()V");
assert(gBinderInternalOffsets.mForceGc);
return AndroidRuntime::registerNativeMethods(
env, kBinderInternalPathName,
gBinderInternalMethods, NELEM(gBinderInternalMethods));
}
至此介绍完了
android_util_Binder.cpp文件中
主要的变量和方法,以及它们的初始化的过程,分析的过程中还会遇到
一些JNI层的方法,这些具体情况具体在分析。总的来说,AndroidRuntime.cpp中调用了
register_android_os_Binder方
法,进而分别调用到不同的初始化方法中,对相应的结构体进行初始化,以方便native binder和java层binder进行通信。
3、代码架构。
下面这张图是邓平凡,邓老师的博客中图。此处仅仅用做记录:
在Android中要求所有的Android实体(无论什么代理端远程端)都必须实现IBinder接口。在java层还有一个IInter
face在此图中没有体现出来。这两个接口都是用来规范Binder使用时的一些协议和方法名称。让子类具体实现。
IInterface仅仅声明一个抽象方法asBinder()它返回IBinder对象,也就是可以返回Binder和BinderProxy.
public interface IInterface
{
/**
* Retrieve the Binder object associated with this interface.
* You must use this instead of a plain cast, so that proxy objects
* can return the correct result.
*/
public IBinder asBinder();
}
下面我们列出来IBinder的一些重要的方法。
public interface IBinder {
/**
* Attempt to retrieve a local implementation of an interface
* for this Binder object. If null is returned, you will need
* to instantiate a proxy class to marshall calls through
* the transact() method.
*/
public IInterface queryLocalInterface(String descriptor);
/**
* Perform a generic operation with the object.
*
* @param code The action to perform. This should
* be a number between {@link #FIRST_CALL_TRANSACTION} and
* {@link #LAST_CALL_TRANSACTION}.
* @param data Marshalled data to send to the target. Must not be null.
* If you are not sending any data, you must create an empty Parcel
* that is given here.
* @param reply Marshalled data to be received from the target. May be
* null if you are not interested in the return value.
* @param flags Additional operation flags. Either 0 for a normal
* RPC, or {@link #FLAG_ONEWAY} for a one-way RPC.
*/
public boolean transact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException;
/**
* Interface for receiving a callback when the process hosting an IBinder
* has gone away.
*
* @see #linkToDeath
*/
public interface DeathRecipient {
public void binderDied();
}
}
4、实例学习。
下面就以例子学习的方式整理整个流程。此处的例子用的是罗升阳,罗老师博客中的,个人仅仅是为了记录整理学习过程。
从我们使用者的角度来看,实现一个完整的系统及被服务,供别的进程调用的步骤如下:
1、接口的定义。
我们会先写一个aidl文件,然后让自己写的具体的service 继承 aidl文件名.Stub.此处的这个aidl文件会在编译的时
候,由工具为我们生成一个标准的java文件。里面有Binder的一些标准实现。
2、再注册到ServiceManager当中,ServiceManager.addService("hello",new HelloService());
此处是直接完全用的罗老师的,"hello"字符串代表的这个service的名字描述,以后要通过它进行获取。而后面的
HelloService就是我们自己的服务具体实现的地方。这样就完成了注册。
3、别的服务想要是用的时候,必须通过ServiceManager.getService("
hello
");进行获取。
4、最后通过一个如下的转换得到I
HelloService
接口的实例,
private IHelloService helloService = null;
helloService = IHelloService.Stub.asInterface(
ServiceManager.getService("hello"));
从我们的Binder的学习角度来分析。
我们知道java层的binder是对native层的binder的一个封装,那么我们就需要依次获得native层的相应的角色的实
现就可以一步一步的分析出结果了。
1、获取远程service manager 的java层的远程接口。(service manager端)
无论你注册还是取出服务你都需要通过这个管理,这个管理就时我们native
层的service manager。注意千万不
要把它和java层的ServiceManager混为一谈。
2、定义我们服务接口,并且把它注册到service manager当中。(server端)
3、通过service manager获取我们服务的java远程接口,并通过相应的接口调用相应的方法。(client端)
下面我们就来一点点的学习binder java层的具体的实现。前面的可以说都是一些必备的基础知识。
4.1、获取native层的service manager的java远程接口.(service manager)
我们前面一再强调过这个接口的重要性。它是用来管理Binder对象的注册和获取,也就是管理我们的服务。我们的
服务就是要实现成一个binder对象,然后利用Android的binder机制进行跨进程通信。这一步我们在java层使用时
候经常会注意不到,因为我们直接就
ServiceManager.addService()也没看到先获取什么东西啊。其实进入到
ServiceManager的
addService()当中我们就发现,是Android在内部调用了相关的方法。
我们查看ServiceManager的源码中相关的方法如下
public static void addService(String name, IBinder service) {
try {
getIServiceManager().addService(name, service, false);
} catch (RemoteException e) {
Log.e(TAG, "error in addService", e);
}
}
private static IServiceManager sServiceManager;
//获取IServiceManager的对象,IServiceManager是一个接口此处就是获得它的实现类的一个对象,
//其实最终就是ServiceManagerProxy类.(该类和ServiceManagerNative在一个java文件当中)
private static IServiceManager getIServiceManager() {
if (sServiceManager != null) {
return sServiceManager;
}
// Find the service manager
//下面就相当于sServiceManager = ServiceManagerNative.asInterface(new BinderProxy(0));
// sServiceManager = new ServiceManagerProxy(new BinderProxy());
sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
return sServiceManager;
}
由上面首先就可以看出IServiceManager是一个单例模式。此处请忽略代码中的注释,都是自己为了方便理解加上去的
分析到后面就知道这个结论了。现在看来是又调入到了
ServiceManagerNative类当中。但在此之前我们应该把,参数里面
的
BinderInternal.getContextObject().分析一下。
在
BinderInternal.java类中
getContextObject就是一个native的函数如下:
public static final native IBinder getContextObject();
对应到
android_util_Binder.cpp中的方法是
android_os_BinderInternal_getContextObject
static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
{
//BpBinder对象,它的句柄值是0,相当于:sp<IBinder> b = new BpBinder(0);
sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
return javaObjectForIBinder(env, b);
}
可以看到最终是获得了一个句柄值为0的BpBinder对象,注意这个对象是一个native的对象,并且它就是远程的service
manager的代理端。至于这个
ProcessState::self()->getContextObject(NULL);的具体实现分析,请参考罗老师文章。接
下来我们还需要把这个native层的BpBinder对象转换成java层的BinderProxy,然后java层才能正确使用。
//把本地的IBinder对象转换成java层对应的Ibinder对象,val传入的本地Ibinder对象。
jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val)
{
if (val == NULL) return NULL;
//里传进来的参数是一个BpBinder的指针
//而BpBinder::checkSubclass继承于父类IBinder::checkSubclass,它什么也不做就返回false
if (val->checkSubclass(&gBinderOffsets)) {
jobject object = static_cast<JavaBBinder*>(val.get())->object();
LOGDEATH("objectForBinder %p: it's our own %p!\n", val.get(), object);
return object;
}
......//省去一些注释和锁代码,方便观察
//此处就用到了gBinderProxyOffsets,首先来获取一下看看是不是已经有这个object了.
//第一次走到这这里object==null.
jobject object = (jobject)val->findObject(&gBinderProxyOffsets);
if (object != NULL) {
jobject res = jniGetReferent(env, object);
if (res != NULL) {
ALOGV("objectForBinder %p: found existing %p!\n", val.get(), res);
return res;
}
LOGDEATH("Proxy object %p of IBinder %p no longer in working set!!!", object, val.get());
android_atomic_dec(&gNumProxyRefs);
val->detachObject(&gBinderProxyOffsets);
env->DeleteGlobalRef(object);
}
//不存在的话,新建一个.
object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor);
if (object != NULL) {//创建成功的话,做一些赋值的处理.
//要把native的BpBinder对象和java层的BinderProxy对象关联起
//BinderProxy.mObject成员变量记录了这个BpBinder对象的地址(val.get)。
env->SetLongField(object, gBinderProxyOffsets.mObject, (jlong)val.get());
val->incStrong((void*)javaObjectForIBinder);
jobject refObject = env->NewGlobalRef(
env->GetObjectField(object, gBinderProxyOffsets.mSelf));
//接下来放到BpBinder当中那么下次调用findObject就可以得到它了.
val->attachObject(&gBinderProxyOffsets, refObject,
jnienv_to_javavm(env), proxy_cleanup);
// Also remember the death recipients registered on this proxy
sp<DeathRecipientList> drl = new DeathRecipientList;
drl->incStrong((void*)javaObjectForIBinder);
env->SetLongField(object, gBinderProxyOffsets.mOrgue, reinterpret_cast<jlong>(drl.get()));
// Note that a new object reference has been created.
android_atomic_inc(&gNumProxyRefs);
incRefsCreated(env);
}
return object;//最后返回回去.
}
层层返回于是最后
BinderInternal.getContextObject() 就相当于new BinderProxy.(注意这个BinderProxy对应的可
是底层的 service manager远程代理也就是BpBinder(0))最后回到
ServiceManager.java中的
getIServiceManager方
法中来
sServiceManager = ServiceManagerNative.asInterface(new BinderProxy())
调用到
ServiceManagerNative。
static public IServiceManager asInterface(IBinder obj)
{
if (obj == null) {
return null;
}
IServiceManager in =
(IServiceManager)obj.queryLocalInterface(descriptor);
if (in != null) {
return in;
}
return new ServiceManagerProxy(obj);
}
值得提一下的是
ServiceManagerNative 继承Binder实现了IServiceManager接口,而
IServiceManager接口继承自
IInterface。
IInterface前面已说过,此处贴出
IServiceManager声明的接口。
public interface IServiceManager extends IInterface
{
public IBinder getService(String name) throws RemoteException;
public IBinder checkService(String name) throws RemoteException;
public void addService(String name, IBinder service, boolean allowIsolated)
throws RemoteException;
public String[] listServices() throws RemoteException;
public void setPermissionController(IPermissionController controller)
throws RemoteException;
static final String descriptor = "android.os.IServiceManager";
int GET_SERVICE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION;
int CHECK_SERVICE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+1;
int ADD_SERVICE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+2;
int LIST_SERVICES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+3;
int CHECK_SERVICES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+4;
int SET_PERMISSION_CONTROLLER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+5;
}
我们接着分析
ServiceManagerNative的asInterface方法。首先会调用obj.
queryLocalInterface方法,此处传入的是一
个BinderProxy的对象,而在BinderProxy对象中
queryLocalInterface方法什么也没做仅仅是返回null
。
//代理端的这个查询本地接口返回的是null.
public IInterface queryLocalInterface(String descriptor) {
return null;
}
但是假如传入的是Binder对象的话,在调用了一定的方法的时候会返回IInterface一个具体对象.
private IInterface mOwner;
public void attachInterface(IInterface owner, String descriptor) {
mOwner = owner;
mDescriptor = descriptor;
}
public IInterface queryLocalInterface(String descriptor) {
if (mDescriptor.equals(descriptor)) {
return mOwner;
}
return null;
}
此时由于是BinderProxy所以返回null,最终走到
new ServiceManagerProxy(obj);实例化了一个ServiceanagerProxy对
象,并在构造中传入了BinderProxy对象。
class ServiceManagerProxy implements IServiceManager {//位于ServiceManagerNative.java文件中
private IBinder mRemote;
public ServiceManagerProxy(IBinder remote){
mRemote = remote;
}
}
这个在前面的分析中可知BinderProxy的mObject中存放着native的service manager
的远程代理对象ServiceManager
Proxy 也就是在JNI层的BpBinder(0)的地址.这样就算是建立起了java层和native层的
service manager的联系通过JNI层的
gBinderProxyOffsets。
至此获取service manager的java远程接口的过程就算是完成了。
4.2、定义服务接口(服务端)
我们还是以罗老师博客中的服务为例,显示贴出来aidl文件的编写。
package android.os;
interface IHelloService
{
void setVal(int val);
int getVal();
}
此处不用理会里面的函数的具体含义,我们旨在理解整个流程。这个aidl文件编译后会生成IHelloService.java文件。下
面我们来分析一下这个文件。(所有的aidl都会按照一定的标准生成,大概是方便书写吧,减少开发难度)
/*
* This file is auto-generated. DO NOT MODIFY.
* Original file: frameworks/base/core/java/android/os/IHelloService.aidl
*/
package android.os;
public interface IHelloService extends android.os.IInterface
{
//抽象类名字都是这个Stub且是公共的.所以外部就可以 IHelloService.Stub 来得到它
/** Local-side IPC implementation stub class. */
//这个Stub是一个Binder对象,还实现了IHelloService接口.!
//所以new HelloService() 这样实例化你写好的HelloService extends IHelloService.Stub的时候.
//会去实例化Binder类的构造.
public static abstract class Stub extends android.os.Binder implements android.os.IHelloService
{
private static final java.lang.String DESCRIPTOR = "android.os.IHelloService";
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an android.os.IHelloService interface,
* generating a proxy if needed.
*/
public static android.os.IHelloService asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
android.os.IInterface iin = (android.os.IInterface)obj.queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof android.os.IHelloService))) {
return ((android.os.IHelloService)iin);
}
//注意下面传入的这个obj,它此时是BinderProxy.
//返回null那么就会调用到IHelloService远程代理接口Proxy.对象
return new android.os.IHelloService.Stub.Proxy(obj);
}
public android.os.IBinder asBinder()
{
return this;
}
//由于HelloService并没有实现onTransact,所以到这里了.
@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_setVal:
{
data.enforceInterface(DESCRIPTOR);
int _arg0;
_arg0 = data.readInt();
this.setVal(_arg0);
reply.writeNoException();
return true;
}
case TRANSACTION_getVal:
{
data.enforceInterface(DESCRIPTOR);
//public class HelloService extends IHelloService.Stub
//最后由于本身就是Helloservice对象在调用,
// 而他又重写了这个方法,所以会调用到HelloService的具体的getVal().(完成调用).int _result = this.getVal();
reply.writeNoException();
reply.writeInt(_result);
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
//内部私有的代理端的类.所以获得sevice的代理时候应该是这个.并且只能通过
asInterface()private static class Proxy implements android.os.IHelloService
{
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote)
{
mRemote = remote;
}
public android.os.IBinder asBinder()
{
return mRemote;
}
public java.lang.String getInterfaceDescriptor()
{
return DESCRIPTOR;
}
//最后client使用的时候就通过远程接口代理Proxy调用到这里。
public void setVal(int val) 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(val);
//可以看到最终是mRemote调用的,它就是实例化Proxy时候传入的参数.
//最后调用到Binder驱动程序,Binder驱动程序唤醒HelloService这个Server
mRemote.transact(Stub.TRANSACTION_setVal, _data, _reply, 0);
_reply.readException();
}
finally {
_reply.recycle();
_data.recycle();
}
}
public int getVal() 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);
mRemote.transact(Stub.TRANSACTION_getVal, _data, _reply, 0);
_reply.readException();
_result = _reply.readInt();
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
}
static final int TRANSACTION_setVal = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
static final int TRANSACTION_getVal = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
}
//抽象的成员方法.
public void setVal(int val) throws android.os.RemoteException;
public int getVal() throws android.os.RemoteException;
}
在这个自动生成的IHelloService接口继承android.os.IInterface接口,再加上自动生成的内容。此时这个接口中有:
1、静态抽象的类Stub继承Binder实现了
IHelloService。
public static abstract class Stub extends android.os.Binder implements android.os.IHelloService.
注意对于这个Stub类它本身就实现了
IHelloService接口所以需要重写接口中声明的那两个方法。
而在这个类中内容还十分丰富,
1.1、私有的内部类Proxy,这个类就是我们服务的代理端,供别的进程远程获取.
private static class Proxy implements android.os.IHelloService
1.2、方法和变量。
private static final java.lang.String DESCRIPTOR = "android.os.IHelloService";
构造:
在Stub的构造中仅仅调用了
this.attachInterface(this, DESCRIPTOR); 这个就是前面我们分析
queryLocalInterface的时候假如传入的Binder对象的情况用到的。由于Stub继承Binder.就会为Bin
der对象的mOwner赋值。并且在你调用Binder对象的
queryLocalInterface时候,将其返回。
方法:
asInterface(
(android.os.IBinder obj
)是它内部非常非常重要的一个方法,当我们去获取这个接
口时候就会用到了。根据传入的参数要么返回一个本地端的服务引用,要么实例化内部类Proxy(obj)
并返回。后面这种情况非常多,以为请求通信的时候ServiceManager.getService("name")最终
会得到一个BinderProxy,
然后由于
queryLocalInterface为null,
去获取本地端的远程,
代理也就是
Proxy,并且把这个传入的参数传进去。并且把的到的这个
BinderProxy作为mRemote。
onTransact()方法就是在通过asInterface获取到远程代理对象的时候,然后调用相应的接口,会
通过mRemote去和驱动打交道,进而驱动就会唤醒远程的server,然后就会调用的JavaBBinder当中的
onTransact,然后又调用到Binder的
execTransact()在这个函数里面会调用子类或者自己的
onTransact
此时就会调用到Stub的
onTransact.
2、两个方法(就是aidl里面写的那两个)
public void setVal(int val) throws android.os.RemoteException;
public int getVal() throws android.os.RemoteException;
接下来我们就应该分析这个接口的具体的实例化和注册过程了。我们是调用ServiceManager.addService("hello", new
HelloService())来完成实例化和注册的,那么我们先看一下HelloService的实例化过程。
此处一定要注意由于
HelloService extend I
HelloService.Stub.而
I
HelloService.Stub extends Binder.所以会先实例
化Binder对象。我们去看看Binder的构造。
public class Binder implements IBinder {
public Binder() {
init();
......
}
private native final void init();
}
同样也是调用到了android_util_Binder.cpp当中。对应的方法是android_os_Binder_init
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);
}
上述方法就是实例化一个JavaBBinderHolder对象,把这个对象的地址通过gBinderOffsets保存在java层的Bin
der类
的成员变量mObject当中。(至此BinderPorxy的mObject保存的是native 的BpBinder(x)地址,Binder的mObject保
存的是native层的初始化Binder时候的一个
JavaBBinderHolder对象的地址
)
实例化完这些操作后,实例化HelloService的构造.然后去
ServiceManager.addService(..).我们前面分析过addServi
ce的部分过程,当获取到IserviceManager对象以后,调用它的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();
}
利用Parcel来序列化和反序列化数据实现传输.注意此时的mRemote是BinderProxy().接下来就需要分析Pracel的
data.writeStrongBinder(IBinder)这个很重要的方法了,前面的两个都是把相应String、int的写入到Parcel。这个是把
Ibinder的对象写入,此时的这个service是我们new出来的,它是一个Binder对象.
Parcel类中有如下:
public final native void writeStrongBinder(IBinder val);可以看出来也是一个本地方法。
对应到andorid_os_Parcel.cpp文件当中的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);
}
}
}
先是调用parcelForJavaObject()把java层的Parcel对象转换成native层的Parcel对象。然后调用writeStrongBinder
但在这个之前,还调用了ibinderForJavaObject(object)并且把一开始传入的那个IBinder对象service也就是我们HelloSe
r
vice也就是java层Binder传入了进去(此时由于它继承Binder,所以可以传入,也能体现出一点点的Binder味道)转换
成native的JavaBBinderHoler,按理说应该转换成BBinder,这里直接多封装了一层,应该是和一些回收机制.
//把这个Java语言实现的Binder/BinderProxy对象转换为native层的JavaBBinderHolder
sp<IBinder> ibinderForJavaObject(JNIEnv* env, jobject obj)
{
if (obj == NULL) return NULL;
if (env->IsInstanceOf(obj, gBinderOffsets.mClass)) {
JavaBBinderHolder* jbh = (JavaBBinderHolder*)
env->GetLongField(obj, gBinderOffsets.mObject);//在Binder init的时候有赋值.
//取出来当jbh不为null的时候,在JavaBBinderHolder类中,
//有一个成员变量mBinder,它的类型为JavaBBinder,而JavaBBinder类继承于BBinder类
//get就是返回的JavaBBinder.
return jbh != NULL ? jbh->get(env, obj) : NULL;//!obj注意这个参数,就是我们传入的HelloService.
}
if (env->IsInstanceOf(obj, gBinderProxyOffsets.mClass)) {
return (IBinder*)
env->GetLongField(obj, gBinderProxyOffsets.mObject);
}
}
传入的参数首先判断Binder对象,如果是的话取出gBinderoffsets.mObject中存入的JavaBBinderHolder.
在前面实例化
HelloService时候回去实例化Binder,然后会走到
android_util_Binder.cpp中的
android_os_Binder_init方法中,然后实例
化了一个
JavaBBinderHolder赋值到
gBinderoffsets.mObject当中.那么我们必须要了解一下
JavaBBinderHolder了.
class JavaBBinderHolder : public RefBase
{
public:
sp<JavaBBinder> get(JNIEnv* env, jobject obj)
{
AutoMutex _l(mLock);
sp<JavaBBinder> b = mBinder.promote();
if (b == NULL) {//第一调用进入到这里.
//obj就是创建的HelloService对象了,这是一个Java对象.然后用这个对象实例化了JavaBBinder
b = new JavaBBinder(env, obj);
mBinder = b;//存入到自己的成员变量.
}
return b;
}
sp<JavaBBinder> getExisting()
{
AutoMutex _l(mLock);
return mBinder.promote();
}
private:
Mutex mLock;
wp<JavaBBinder> mBinder;//里面存放的是
JavaBBinder对象.};
那么JavaBBinder又是怎么实现的那?
class JavaBBinder : public BBinder
{
public:
//在构造中仅仅把传入的object保存在它的成员变量mObject.
JavaBBinder(JNIEnv* env, jobject object)
: mVM(jnienv_to_javavm(env)), mObject(env->NewGlobalRef(object))
{
ALOGV("Creating JavaBBinder %p\n", this);
android_atomic_inc(&gNumLocalRefs);
incRefsCreated(env);
}
bool checkSubclass(const void* subclassID) const
{
return subclassID == &gBinderOffsets;
}
jobject object() const
{
return mObject;
}
protected:
virtual ~JavaBBinder()
{
ALOGV("Destroying JavaBBinder %p\n", this);
android_atomic_dec(&gNumLocalRefs);
JNIEnv* env = javavm_to_jnienv(mVM);
env->DeleteGlobalRef(mObject);
}
//HelloService这个Server线程被唤醒之后,就会调用JavaBBinder类的onTransact函数!!!!!
virtual status_t onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0)
{
JNIEnv* env = javavm_to_jnienv(mVM);
ALOGV("onTransact() on %p calling object %p in env %p vm %p\n", this, mObject, env, mVM);
IPCThreadState* thread_state = IPCThreadState::self();
const int32_t strict_policy_before = thread_state->getStrictModePolicy();
......
//mObject就是HelloService类的一个实例对象了,就调用了HelloService.execTransact函数
//AIDL生成的文件IHelloService.java里面并没有重写它,所以会走到Binder类中.
//注意此时实例化的是HelloService!!!(不是父类什么的)
jboolean res = env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact,
code, reinterpret_cast<jlong>(&data), reinterpret_cast<jlong>(reply), flags);
jthrowable excep = env->ExceptionOccurred();
......//异常和权限的一些处理.
// Need to always call through the native implementation of
// SYSPROPS_TRANSACTION.
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;
};
JavaBBinder继承了我们Binder本地端对象BBinder.我们最需要关注的就两点:1、成员变量的mObject的赋值,是把传
入的HelloService转换成了本地的对象存入.2、onTransact(),此方法会在服务端被唤醒的时候调用,我们后面分析。
我们总结一下
ibinderForJavaObject(xx)这个方法做的事情.取出我们前面实例化Binder是存入的JavaBBinderHolder对
象然后调用它的get方法获取一个JavaBBinder对象,并且保存在自己的成员变量mBinder当中。而JavaBbinder也把传入的
IBinder也是就是HelloService对象保存在自己的mObject当中.最终返回的是
JavaBBinderHolder的get方法,也就是返回
JavaBBinder对象.
回到android_os_Parcel_writeStrongBinder函数当中.
此时:const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object))那么就相当于如下:
const status_t err = parcel->writeStrongBinder((JavaBBinderHodler*)(obj.mObject)); 最终写入JavaBBinder到
Parcel
对象当中.
执行完写入后,最终回到ServiceManagerProxy对象的addService函数当中,接着往下执行.
mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);至于这个
mRemote我们前面已经分析过是一个Binder
Proxy对象.它对应到native端的BpBinder(0),也就是native 端的ServiceManagerProxy.那么接下来就是BinderProxy的函数
transact()的
实现
了。
final class BinderProxy implements IBinder{
......
public boolean transact(int code, Parcel data, Parcel reply, int flags) throws
RemoteException {
Binder.checkParcel(this, code, data, "Unreasonably large binder buffer");
return transactNative(code, data, reply, flags);
}
......
public native boolean transactNative(int code, Parcel data, Parcel reply,
int flags) throws RemoteException;
......
}
可以看到调用到native方法
transactNative,它有指向了android_util_Binder中的
android_os_BinderProxy_transact方
法。我们只看流程的重要部分,为了方便阅读代码去掉一些不是很重要的代码.
static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,
jint code, jobject dataObj, jobject replyObj, jint flags)
{
//......
//这里传进来的参数dataObj和replyObj是一个Java接口实现的Parcel类,
//由于这里是JNI层,需要把它转换为C++实现的Parcel类,
//它们就是通过android_os_Parcel中的parcelForJavaObject函数进行转换的。
Parcel* data = parcelForJavaObject(env, dataObj);
......
Parcel* reply = parcelForJavaObject(env, replyObj);
......
//分析如何获取Service Manager远程接口时曾经说到,在JNI层中,创建了一个BpBinder对象,它的句柄值为0.
//它的地址保存在gBinderProxyOffsets.mObject中,因此,这里通过下面语句得到这个BpBinder对象.
IBinder* target = (IBinder*)
env->GetLongField(obj, gBinderProxyOffsets.mObject);
......
//target->transact进入到Binder驱动程序,
//然后Binder驱动程序唤醒Service Manager响应这个ADD_SERVICE_TRANSACTION请求
//这里的data包含了一个JavaBBinder类型的Binder实体对象,它的mObject就是我们的HelloService.
//Service Manager收到这个ADD_SERVICE_TRANSACTION请求时,
//就会把这个Binder实体纳入到自己内部进行管理。
//当时调用getservice走到这里的时候!
//这里的reply变量里面就包括了一个HelloService的引用了。
//(类似的可以理解为前面的别的进程放进去,我在这里拿出来,实现跨进程通信)
//注意,这里的reply变量就是我们在ServiceManagerProxy.getService函数里面传进来的参数reply,它是一
//个Parcel对象.
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, true /*canThrowRemoteException*/);
return JNI_FALSE;
}
此方法中的个人注释比较多,都是整体理解是加上去了,不理解的话,看完整个再回来看一下。此时这个方法的主要处理
是先通过gBinderOffsets.mObject取出我们前面存入的BpBinder(0)对象用来和native层的service manager打交道。然后就
调用这个对象的transact(),此处就走到进一步的去和Binder的驱动打交道。然后Binder驱动程序会唤醒本ServiceManager
让它去相应ADD_SERVICE_TRANSACTION这个请求。在本地service manager收到这个请求的时候,会把我们data中包含
的Binder实体也就是HelloService纳入自己的内部进行管理,等人来get。此处和Binder程序的具体交互,不在本文讨论范
围,感兴趣的可以看一下罗老师的博客。
这样我们就定义好了服务接口,并且把它添加到了本地的service manager当中了。接下来就是客户端获取服务的过程了.
4.3、获取服务远程代理端.
系统级别服务的标准使用方式我们前面也提到过:
private IHelloService helloService = null;
helloService = IHelloService.Stub.asInterface(
ServiceManager.getService("hello"));
下面我们来一步步的分析。
首先是ServiceManager.java中的getService()方法.
public static IBinder getService(String name) {
try {
IBinder service = sCache.get(name);
if (service != null) {
return service;
} else {
return getIServiceManager().getService(name);
}
} catch (RemoteException e) {
Log.e(TAG, "error in getService", e);
}
return null;
}
getIServiceManager()我们前面分析过,最终就是new ServiceManagerProxy(new BinderProxy).所以我们再去看看
ServiceManagerProxy的
getService的实现。注意:mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0)
传入的命令码不同此处是
GET_SERVICE_TRANSACTION.
public IBinder getService(String name) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IServiceManager.descriptor);
data.writeString(name);
//通过mRemote.transact来执行实际操作,mRemote是一个BinderProxy.
mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);
//通过下面将你前面add进去的服务的对象的引用取出来,这个HelloService的引用读出来.
IBinder binder = reply.readStrongBinder();
reply.recycle();
data.recycle();
return binder;
}
checkService的前几步一直到transact都和我们前面的addService类似此处不再重述。此处的这个mRemote也和前面一
样最终还是调入到了
android_util_Binder中的
android_os_BinderProxy_transact.此方法也在前面贴了出来。
最关键的一步status_t err = target->transact(code, *data, reply, flags);驱动根据
code去获取service,然后会添加一个
HelloService引用到reply变量当中.reply是一个Parel变量.
回到ServiceManagerProxy.getService()方法中接这往下执行就到了IBinder binder = reply.readStrongBinder()然后把
这个Ibinder返回。我们就可以用这个服务去调用接口了。那么这个IBinder是什么对象那?
reply.readStrongBinder()也就是调用到Parcel.java的相关接口实现如下:
private static native IBinder nativeReadStrongBinder(long nativePtr);
public final IBinder readStrongBinder() {
return nativeReadStrongBinder(mNativePtr);
}
最终对应到android_os_Parcel中的
android_os_Parcel_readStrongBinder()的方法。
static jobject android_os_Parcel_readStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr)
{
//先把Java语言实现的Parcel对象class转换成C++语言实现的Parcel对象parcel.
Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
if (parcel != NULL) {
//接着,通过parcel->readStrongBinder函数来获得一个Binder引用。
//它最终返回来的是一个BpBinder对象.
//因此下面就相当于return javaObjectForIBinder(env, new BpBinder(handle));
//handle就是HelloService这个Binder实体在Client进程中的句柄了.
//这个句柄它是由Binder驱动程序设置的方便管理,上层不用关心它的值具体是多少.
//最后还是调用我们前面分析的javaObjectForIBinder创建一个BinderProxy对象,
//并且把刚才获得的BpBinder对象的地址保存在这个BinderProxy对象的mObject成员变量中然后返回.
return javaObjectForIBinder(env, parcel->readStrongBinder());
}
return NULL;
}
此处parcel->readStrongBinder().内部具体的实现请参考罗老师的博客文章,它最终会返回的就是一个BPBinder(hand)
对象,并且会精准的拿到HelloService对应的(由驱动管理实现).最后就是执行return javaObjectForIBinder(env, new
BpBinder(handle))这个函数。而对于
javaObjectForIBinder我们前面分析service manager的获取过程的时候已经介绍,此
处也是相同的道理它的作用就是创建一个BinderProxy对象,并且把刚才获得的BpBinder对象的地址保存在这个BinderProxy
对象的mObject成员变量中。(主义传入的参数是不同的前面是BpBinder(0),这次是BpBinder(handle),其实service man
ager 就是一个特殊的Binder)
至此ServiceManager.getService()分析完毕,回到最初的标准调用的地方。
helloService = IHelloService.Stub.asInterface(new BinderProxy()))注意此时的
new BinderProxy()是HelloService在
native层的BpBinder(handle)对应过来的。
我们接着分析
IHelloService.Stub.asInterface()函数.前面我们已经把IHelloService的aidl文件自动生成的java文件代码
贴出来了,对比着上面看。
public static android.os.IHelloService asInterface(android.os.IBinder obj)
{
if ((obj==null)) {
return null;
}
//注意此时传入的这个obj,它此时是BinderProxy.
//而在BinderProxy中queryLocalInterface返回null
android.os.IInterface iin = (android.os.IInterface)obj.
queryLocalInterface(DESCRIPTOR);
if (((iin!=null)&&(iin instanceof android.os.IHelloService))) {
return ((android.os.IHelloService)iin);
}
//那么就会会去实例化IHelloService远程代理接口Proxy.对象
return new android.os.IHelloService.Stub.Proxy(obj);
}
然后去实例化Stub内部私有类并且把我们前面ServiceManager.getService("hello")得到的,对应于HelloService
native层的BpBinder(handle)的BinderProxy作为参数去实例化内部Proxy类.(和ServiceManagerProxy一样)最终
返回,这样我们就得到了HelloService服务的远程代理端,然后就可以利用这个代理端去调用相关的接口了.
4.4、通过远程代理端去调用服务的接口.
HelloService的远程接口后,就可以使用它的服务了,此处还是用的罗老师的例子.
int val = helloService.getVal();以这个调用为例子来分析,其它的同理.
前面我们已经拿到了
helloService对象,它是一个Proxy(BinderProxy)对象,位于Stub内部.我们看一下它的实现
public int getVal() 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);
mRemote.transact(Stub.TRANSACTION_getVal, _data, _reply, 0);
_reply.readException();
_result = _reply.readInt();
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
核心就是mRemote.transact(Stub.TRANSACTION_getVal, _data, _reply, 0),而此时的mRemote就是现实实例化Proxy
的时候传入的BinderProxy对象。而
BinderProxy.transact函数是一个JNI方法,最终又到了
android_util_Binder中的
android_os_BinderProxy_transact方法内部,此时它的code是Stub.TRANSACTION_getVal.最终和驱动去打交道,让驱动唤
醒Helloserice的服务端的相应接口去处理我们的请求。
而HelloService这个Server线程被唤醒之后
就会调用JavaBBinder类的onTransact函数,(由驱动实现的),这块就是服务端
着手处理远程代理端(客户端)的JNI层的起始位置.!!!!!!!!很重要!!!!!!!
JavaBBinder的代码实现我们已经在前面介绍过,此处再贴一下代码
//HelloService这个Server线程被唤醒之后,就会调用JavaBBinder类的onTransact函数!!!!!
virtual status_t onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0)
{
JNIEnv* env = javavm_to_jnienv(mVM);
ALOGV("onTransact() on %p calling object %p in env %p vm %p\n", this, mObject, env, mVM);
IPCThreadState* thread_state = IPCThreadState::self();
const int32_t strict_policy_before = thread_state->getStrictModePolicy();
......
//mObject就是HelloService类的一个实例对象了,就调用了HelloService.execTransact函数
//AIDL生成的文件IHelloService.java里面并没有重写它,所以会走到Binder类中.
//注意此时实例化的是HelloService!!!(不是父类什么的)
jboolean res = env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact,
code, reinterpret_cast<jlong>(&data), reinterpret_cast<jlong>(reply), flags);
jthrowable excep = env->ExceptionOccurred();
......//异常和权限的一些处理.
// Need to always call through the native implementation of
// SYSPROPS_TRANSACTION.
if (code == SYSPROPS_TRANSACTION) {
BBinder::onTransact(code, data, reply, flags);
}
//......
return res != JNI_FALSE ? NO_ERROR : UNKNOWN_TRANSACTION;
}
HelloService实例化时,曾经介绍过,JavaBBinder类里面的成员变量mObject就是HelloService类的一个实例对象了 最
终其实就是调用到了HelloService.execTransact函数.而我们在写自己的服务的时候一般都不回去手动重写
execTransact。但
HelloService extends Binder.也就是调用到了Binder的
execTransact。如下:
//AIDL生成的文件IHelloService.java里面并没有重写它,所以会走到这里
// Entry point from android_util_Binder.cpp's onTransact
private boolean execTransact(int code, long dataObj, long replyObj,
int flags) {
Parcel data = Parcel.obtain(dataObj);
Parcel reply = Parcel.obtain(replyObj);
boolean res;
try {
//此时Helloservice子类,有重写就调用自己的onTransact,而public class HelloService
//extends IHelloService.Stub.所以调用到IHelloService.Stub
res = onTransact(code, data, reply, flags);
} catch (RemoteException e) {
......
} catch (RuntimeException e) {
......
} catch (OutOfMemoryError e) {
......
}
......
return res;
}
最终调用到了HelloService的onTransact.而
HelloService并没有自己实现所以是
HelloService.Stub的.
@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:
......
case TRANSACTION_setVal:
......
case TRANSACTION_getVal://前面的code传入的是这个.
{
data.enforceInterface(DESCRIPTOR);
//public class HelloService extends IHelloService.Stub
//最后由于本身就是Helloservice对象在调用,
//而他又重写了这个方法,所以会调用到HelloService的具体的getVal().(完成调用).
int _result = this.getVal();
reply.writeNoException();
reply.writeInt(_result);
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
至此完成调用,调用到我们写的那个HelloService里面。然后一层层的返回,返回到
mRemote.transact(Stub.TRANSACTION_getVal, _data, _reply, 0)调用的地方。驱动的服务端处理完毕后
_reply就有值
了然后_result = _reply.readInt();对出街过并return回去.
这样就完成了整个的client端获取远程服务的代理对象,并调用相应的接口。总的来从应用角度来触发,作为调用端client,
先是通过service manager的java远程接口来获取Helloservice的远程代理接口,进而调用HelloService提供的服务.
4.5、网上整理和个人瞎扯。
a、对aidl的作用感觉就是为了方便开发,客户端这边和服务端其实是需要沟通好的,如我的客户端的某个操作,到你服务端你
需要解析成什么样子的,再比如说我客户端通过Binder往你那边传数据往Parcel里面写入时候的顺序等等,你那边也应该依次读取
而AIDL就是通过工具,自动的帮我们完成一个服务端代理proxy,以及服务端存存根Stub.这两个中介在自己内部很好的解释了每
个语义什么意思等等。而不需要在去到真正的客户端/服务端代码中去做什么特殊的处理.(拉出来放一个类里面,而这个类有系统的
编译脚本来根据一定的规则自动生成).
其实这就是一种代理proxy、存根Stub的结构。client---proxy--Stub---server. 由proxy和Stub去解释进程通信间的一些规范
问题,也实现了屏蔽进程的概念。当然在proxy和Stub之间通过Binder的机制配合Parcel的序列化和反序列化传递数据.
b、asInterface的返回值的问题,我们分析的都是由于是跨进程调用所以传入的参数都是BinderProxy此时就会返回Stub.Proxy
对象。而当我们是在本进程内通信的时候纯如Binder对象,此时就会直接翻会Stub类的对象。无需进行跨进程调用。
c、对于底层的服务实现的时候都会有:
ProcessState::self()-
>startThreadPool();
IPCThreadState::self()->joinThreadPool();
这样就会有线程来处理client端传来的数据,但是我们在java层写服务的时候就不需要关注这些细节了,因为这个服务通过add添
加进去以后它会运行System进程中,System进程在启动的时候会自动的启动一个Binder线程池,在System_init.cpp当中.
d、Binder进程间通信机制中的Service组件和Android应用程序中的Service组件是两个完全不同的概念,Android应用程序中的
Service组件不
是一个Binder对象,即它不是Binder进制间通信机制中的Service组件的概念。
Android应用程序中的Service组件具
有Binder进程间通信能力是因为它可以通过成
员函数onBind来返回一个Binder代理对象给调用者使用.
Android中对于Binder这个对象有特殊的进程通信处理机制。所以可以再进程之间来回传输携带数据等等,并不是service类就可
以而要是binder类。
e、binder机制整理概述。
比如client a 想和 server b通信。client a 先通过server manager获取一个server b的一个代理接口c,注意代理接口中的方法是
和
server中的方法一一对应的,a想要调用某个方法时,代理接口c就会把client 发过来的数据发送给内核中的binder driver。而对
于server b端,它就回去这个binder driver中读取请求的数据进而作出相应的处理,最终通过binder driver实现了跨进程通信。