在Binde的第一篇文章里面,讲到了service manager启动后,他的binder线程阻塞在等待队列中,要等到有新任务把他唤醒。我们知道一些常用的服务比如AMS,PMS等都是通过addService放到注册到service manager中的,但是在调用addService之前,我们怎么获得service manager呢?他们是在不同的进程中的,所以这本身就是一个跨进程的调用,而我们一般理解的跨进程都是先通过service manager这个根服务找到对应的服务,然后再进场跨进程通信的,但是对于系统启动后,其他进程是怎么获得service manager的,这个我们还不理解。所以这篇文章我们就先分析下其他进程怎么获取这个已经启动的service manager的。
## 获取service manager代理对象入口
如果看过添加系统服务的同学,可能知道是调用Service manager的addService方法来添加的:
``` java
// ServiceManager.java
public static void addService(String name, IBinder service) {
try {
getIServiceManager().addService(name, service);
} catch (RemoteException e) {
Log.e(TAG, "error in addService", e);
}
}
```
可以看到获取service manager是通过getIServiceManager这个方法,我们在跟进去看:
```java
private static IServiceManager sServiceManager;
private static IServiceManager getIServiceManager() { // 获取service manager代理对象
if (sServiceManager != null) {
return sServiceManager;
}
// Find the service manager
// BinderInternal.getContextObject() 是jni方法 public static final native IBinder getContextObject();
// 创建一个service manager代理对象,在android_util_Binder中
// 获取BpBInder封装后的BInderProxy,在调用ServiceManagerNative的asInterface方法最终返回service manager的java代理对象ServiceManagerProxy
sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
return sServiceManager;
}
```
sServiceManager就是需要获取的对象,如果第一次获取肯定是空,所以会执行下面的方法,下面的方法分为两部分,首先调用BinderInternal.getContextObject()获取一个对象,然后通过asInterface方法封装这个对象后返回,这个就是service manager的代理对象。我们先看BinderInternal.getContextObject()这个方法:
```java
public static final native IBinder getContextObject();
```
这个方法是个jni方法,我们到jni那里去看
```c++
// android_util_Binder.cpp
static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
{
// 获取句柄为0的代理对象,即service manager代理对象,即一个BpBinder
sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
return javaObjectForIBinder(env, b); // 转化为BinderProxy
}
```
这里看到首先会调用ProcessState这个类的getContextObject方法。首先说下ProcessState这个类,每个进程启动后都有一个ProcessState来描述这个进程的一些状态,所以这个类的进程起来后就会被初始化,所以我们看下他的构造方法:
```c
#define BINDER_VM_SIZE ((1*1024*1024) - (4096 *2))
ProcessState::ProcessState() // 获取文件描述符,并且映射内核的缓冲区到进程空间
: mDriverFD(open_driver()) // 获取该进程的文件描述符
, mVMStart(MAP_FAILED)
, mManagesContexts(false)
, mBinderContextCheckFunc(NULL)
, mBinderContextUserData(NULL)
, mThreadPoolStarted(false)
, mThreadPoolSeq(1)
{
if (mDriverFD >= 0) {
// XXX Ideally, there should be a specific define for whether we
// have mmap (or whether we could possibly have the kernel module
// availabla).
#if !defined(HAVE_WIN32_IPC)
// mmap the binder, providing a chunk of virtual address space to receive transactions.
mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0); // 映射一片大小为BINDER_VM_SIZE的缓冲区给进程
if (mVMStart == MAP_FAILED) {
// *sigh*
LOGE("Using /dev/binder failed: unable to mmap transaction memory.\n");
close(mDriverFD);
mDriverFD = -1;
}
#else
mDriverFD = -1;
#endif
}
if (mDriverFD < 0) {
// Need to run without the driver, starting our own thread pool.
}
}
```
这个构造方法我们主要关注2个地方,第一个是开始的对mDriverFD这个变量的初始化,他调用的方法是open_driver:
```c++
static int open_driver()
{
if (gSingleProcess) {
return -1;
}
// 打开binder设备文件,这个就是在这个目录下加入一个当前进程id为名字的文件,并且把当前进程结构体保存的这个文件对应的描述符上
int fd = open("/dev/binder", O_RDWR);
if (fd >= 0) {
fcntl(fd, F_SETFD, FD_CLOEXEC);
int vers;
#if defined(HAVE_ANDROID_OS)
status_t result = ioctl(fd, BINDER_VERSION, &vers); // 获取版本号
#else
status_t result = -1;
errno = EPERM;
#endif
if (result == -1) {
LOGE("Binder ioctl to obtain version failed: %s", strerror(errno));
close(fd);
fd = -1;
}
if (result != 0 || vers != BINDER_CURRENT_PROTOCOL_VERSION) {
LOGE("Binder driver protocol does not match user space protocol!");
close(fd);
fd = -1;
}
#if defined(HAVE_ANDROID_OS)
size_t maxThreads = 15;
result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads); // 设置最大线程数量
if (result == -1) {
LOGE("Binder ioctl to set max threads failed: %s", strerror(errno));
}
#endif
} else {
LOGW("Opening '/dev/binder' failed: %s\n", strerror(errno));
}
return fd;
}
```
这个方法里面主要就是调用了open("/dev/binder", O_RDWR)这个方法,在第一篇讲Binder的文章里面,我们在初始化service manager的时候也讲过,每个需要注册到binder的服务都会创建一个文件,这里就在/dev/binder目录下创建了这个文件,然后会调用到binder驱动的binder_open的方法,对该进程做一些初始化工作,这个方法在之前第一篇文章里面说过了,这里也不多赘述,最后内核会返回给该进程一个文件描述符,这个文件描述符就是赋值给ProcessState类mDriverFD变量的值。这里稍微解释下什么是文件描述符,我们知道在linux中一切皆文件,所以这里既然创建了一个文件那当然是文件啦,linux中如果一个进程打开了多个文件,每个打开的文件都是作为一个元素被记录在一个数组中,这个文件描述符就是这个数组的下标,所以只要知道了文件描述符就可以找到具体的文件了。好了,我们回到ProcessState类中,在构造方法中除了打开binder驱动外,我们还看到有mmap函数,即把本进去和内核的内存进行映射。我们看到映射内存的大小是BINDER_VM_SIZE ((1*1024*1024) - (4096 *2)),即1M - 8K,可见进程间通信一次的数据量不到1M。现在知道为什么我们平时通过Activity的Intent传数据为什么这么小了吧,原来是binder进行了限制。这里的映射只不过是在内核和用户进程间他们的虚拟地址在这个大小范围内建立一个联系,具体来说我们知道每个进程都有自己的虚拟地址,可能每个进程的虚拟地址是一样的,但是指向的物理地址是不一样的,所以如果要2个地址建立映射关系,就可以通过一个一个地址找到另一个地址,这个的映射就是他们他们在这片内存大小区域内建立了这种联系,但是具体物理内存还没分配,物理内存的分配是在具体使用的时候。上面大概介绍了下内存映射的过程,下面我们继续看service manager代理对象的获取。
## 开始获取service manager代理对象
好了ProcessState介绍完了,我们回到开始android_os_BinderInternal_getContextObject方法,首先看下ProcessState::self()方法:
```c++
sp<ProcessState> ProcessState::self() // 获取进程的ProcessState对象
{
if (gProcess != NULL) return gProcess;
AutoMutex _l(gProcessMutex);
if (gProcess == NULL) gProcess = new ProcessState;
return gProcess;
}
```
这个方法主要获取ProcessState实例,没有的话会new一个,初始化上面讲过了,我们接着看调用它的getContextObject方法
```c++
sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& caller) // 获得一个ibinder,即BpBinder
{
if (supportsProcesses()) { // 检查是否已经打开了binder驱动,即是否文件描述符 > 0
return getStrongProxyForHandle(0); // 获取代理对象,service manager的句柄是0
} else {
return getContextObject(String16("default"), caller);
}
}
```
这个方法首先调用supportsProcesses来判断是否有文件描述符:
```c
bool ProcessState::supportsProcesses() const // 检查是否打开的了binder驱动
{
return mDriverFD >= 0; // 文件描述符大于等于0
}
```
从前面的介绍中我们已经知道了文件描述符就是数组的小标,所以比如大于等于0,这个做下简单的校验。回到前面继续调用getStrongProxyForHandle,可以看到这里传了参数值是0,从第一篇文件我们知道service manager作为一个特殊的服务,特意给他在内核中对应的引用对象句柄赋值了0来区别其他的服务,所以这里传入0就是来寻找service manager的,我们看方法实现:
```c++
// 根据句柄获取代理对象。ProcessState看成是每个进程的全局类,里面保存了和整个进程有关的信息
sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
sp<IBinder> result;
AutoMutex _l(mLock);
handle_entry* e = lookupHandleLocked(handle); // 从全局类中的代理对象列表中查询是否有该句柄对应的代理对象,返回之。
if (e != NULL) {
// We need to create a new BpBinder if there isn't currently one, OR we
// are unable to acquire a weak reference on this current one. See comment
// in getWeakProxyForHandle() for more info about this.
IBinder* b = e->binder;
// 这里如果b是null,那么说明这个代理对象之前是不存在的,是刚才创建的。所以下面创建BpBinder
// 如果b不是null,就要检查是否还活着,增加代理的对象的弱引用指针,如果能增加成功,说明活着,就跳到else去执行,否则就和b为null一样
if (b == NULL || !e->refs->attemptIncWeak(this)) {
b = new BpBinder(handle); // 创建一个代理对象,这里把句柄保存在了BpBinder中
e->binder = b; // 把刚才创建的代理对象结构体中的binder字段指向b
if (b) e->refs = b->getWeakRefs(); // 同样代理对象弱引用计数指向b的弱引用对象
result = b;
} else { // 进入这里肯定是上面上面b不是null,而且attemptIncWeak增加弱引用成功后,说明代理对象存在,所以这里把b设置给代理对象
// This little bit of nastyness is to allow us to add a primary
// reference to the remote proxy when this team doesn't have one
// but another team is sending the handle to us.
result.force_set(b); // 设置b是强引用
e->refs->decWeak(this); // 上面attemptIncWeak由于增加了一个弱引用,这个要减少
}
}
return result;
}
```
这个方法里首先调用了lookupHandleLocked看下是否之前已经有这个对象了:
```c++
Vector<handle_entry>mHandleToObject; // 代理对象列表
struct handle_entry { // 代理对象结构体
IBinder* binder; // 指向代理对象
RefBase::weakref_type* refs; // 代理对象弱引用计数对象
};
// 查询代理对象列表中是否已经存在,如果不存在先创建一个代理对象结构体,插入列表中
ProcessState::handle_entry* ProcessState::lookupHandleLocked(int32_t handle) // 查询代理对象列表中是否已经存在,如果不存在先创建一个代理对象结构体,插入列表中
{
const size_t N=mHandleToObject.size(); // 该进程代理对象的个数,这里size是vector的mCount值
if (N <= (size_t)handle) { // 句柄值大于等于代理对象个数,说明没有代理对象
handle_entry e;
e.binder = NULL; // 指向的代理对象是空
e.refs = NULL; // 指向的代理对象弱引用计数是空
status_t err = mHandleToObject.insertAt(e, N, handle+1-N); // 插入这个代理对象结构体到mHandleToObject中,参数handle+1-N会更新mCount值
if (err < NO_ERROR) return NULL;
}
return &mHandleToObject.editItemAt(handle); // 返回这个代理对象,句柄值也就是代理对象列表的索引值
}
```
mHandleToObject是个vector,保存了所有这个进程的代理对象相关的结构体,通过代理对象的句柄值handle在mHandleToObject中查找有没有代理对象,如果有则返回,没有就往这个vector插入一个handle_entry。handle_entry是个结构体,他保存了一个BpBinder对象,而这个BpBinder对象又保存了handle,这个我们回到前面的方法getStrongProxyForHandle继续往下看,b == NULL || !e->refs->attemptIncWeak(this)根据这个条件来判断是否当前代理对象存在,b是执行代理对象BpBinder的,如果是空当然不存在,attemptIncWeak方法是增加这个代理对象的弱引用:
```c++
// 尝试增加弱指针引用,如果能增加成功,说明这个对象没有被销毁,下一步可以继续操作
bool RefBase::weakref_type::attemptIncWeak(const void* id)
{
weakref_impl* const impl = static_cast<weakref_impl*>(this);
int32_t curCount = impl->mWeak;
LOG_ASSERT(curCount >= 0, "attemptIncWeak called on %p after underflow",
this);
while (curCount > 0) {
if (android_atomic_cmpxchg(curCount, curCount+1, &impl->mWeak) == 0) {
break;
}
curCount = impl->mWeak;
}
if (curCount > 0) {
impl->addWeakRef(id);
}
return curCount > 0;
}
```
弱引用不像强引用,可能会被清理,这里android_atomic_cmpxchg是用来增加弱引用计数的,如果可以增加说明对象还存在,否则说明已经被销毁。回到上面方法如果当前的代理对象不存在了,那么会new BpBinder(handle),把handle传给他。你看这个其实就是我们需要的service manager代理对象了。我们看下他的构造函数:
```c++
BpBinder::BpBinder(int32_t handle)
: mHandle(handle)
, mAlive(1)
, mObitsSent(0)
, mObituaries(NULL)
{
LOGV("Creating BpBinder %p handle %d\n", this, mHandle);
extendObjectLifetime(OBJECT_LIFETIME_WEAK); // 受弱引用计数影响
IPCThreadState::self()->incWeakHandle(handle); // 增加对应引用对象的弱引用计数
}
```
可以看到这个最主要的就是把句柄值handle赋值给mHandle,另外做一些引用计数的处理。到这里其实我们已经获得了service manager的代理对象了,从代码我们看到其实所谓代理对象就是句柄值,拿到了句柄值就可以顺藤摸瓜,找到具体的服务了。我们回到android_os_BinderInternal_getContextObject这个方法继续看后面的代码:
```c++
static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
{
sp<IBinder> b = ProcessState::self()->getContextObject(NULL); // 获取句柄为0的代理对象,即service manager代理对象,即一个BpBinder
return javaObjectForIBinder(env, b); // 转化为BinderProxy或者FregService
}
```
这里b就是前面获得的代理对象BpBinder,接下去把他传入javaObjectForIBinder方法:
```c++
// 这个方法就是创建一个BInderProxy,然后把BpBinder(即val)加入到BInderProxy的mObject字段中,同时把BInderProxy的的地址和mSelf加入到BpBInder中
jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val) // val要么是BPBinder,跨进程。 要么JavaBBbinder,同进程。这个在addservice的时候调用writeStrongBinder这个方法时候写进去的
{
if (val == NULL) return NULL;
if (val->checkSubclass(&gBinderOffsets)) { // 如果是代理对象会返回false,JavaBBbinder的话会覆写checkSubclass方法,如果是和gBinderOffsets一样的类,就会取出object
// One of our own!
jobject object = static_cast<JavaBBinder*>(val.get())->object(); // 取出javaBBinder的mObject字段,即FregService
//printf("objectForBinder %p: it's our own %p!\n", val.get(), object);
return object;
}
// For the rest of the function we will hold this lock, to serialize
// looking/creation of Java proxies for native Binder proxies.
AutoMutex _l(mProxyLock);
// Someone else's... do we know about it?
jobject object = (jobject)val->findObject(&gBinderProxyOffsets); // 到这里说明要寻找一个代理对象,即BinderProxy的弱引用
if (object != NULL) {
// 获取这个BinderProxy的弱引用,即WeakReference<BinderProxy>,get后得到的是BinderProxy
jobject res = env->CallObjectMethod(object, gWeakReferenceOffsets.mGet);
if (res != NULL) {
LOGV("objectForBinder %p: found existing %p!\n", val.get(), res);
return res;
}
LOGV("Proxy object %p of IBinder %p no longer in working set!!!", object, val.get());
android_atomic_dec(&gNumProxyRefs); // 到这里说明这个java代理对象已经销毁了,清理工作
val->detachObject(&gBinderProxyOffsets);
env->DeleteGlobalRef(object);
}
// 到这里说明要新建这个java代理对象
object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor); // 创建一个BinderProxy类
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.get设置到object的mObject字段中,即把Bpbinder地址设置到BInderProxy中
val->incStrong(object); // val是BpBInder,因为被object即BinderProxy引用了,所以增加计数
// 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.
// 上面把BPBInder地址加入到BInderProxy的mObject中,下面开始把BInderProxy添加到BpBInder中
jobject refObject = env->NewGlobalRef(
env->GetObjectField(object, gBinderProxyOffsets.mSelf)); // 在BInderProxy的mSelf自动创建一个对象,mSelf即BinderProxy的弱引用,WeakReference<Binderproxy>
val->attachObject(&gBinderProxyOffsets, refObject,
jnienv_to_javavm(env), proxy_cleanup); // 把weakReference<BInderProxy>添加到BpBinder的ObjectManager中
// Note that a new object reference has been created.
android_atomic_inc(&gNumProxyRefs);
incRefsCreated(env);
}
return object; // 返回BinderProxy
}
```
这个方法既可以用在client端,又可以用在server,根据他的参数val来判断,如果是client端就是一个BpBinder代理对象,如果是server端就是一个BbBinder。我们这里说到的是BpBinder就先只说和BpBinder相关的,后面说到server端了再说BbBinder。
方法开头会调用传入参数的checkSubclass方法,我们目前是一个BpBinder,所以没有覆写他父类IBinder的这个方法:
```c++
bool IBinder::checkSubclass(const void* /*subclassID*/) const
{
return false;
}
```
可以看到默认返回的是false,所以这里我们跳过先不说。接下去会调用(jobject)val->findObject(&gBinderProxyOffsets)这个方法查询这个BpBinder里面会不会有需要的java层的对象,别忘了我们现在native层,返回到上面java层需要返回一个java对象,所以这里BpBinder里面会保存有java对象,如果有的话就会取出返回,否则就会创建。这里我们先不详细说,因为目前是第一次这个肯定取出来是空,等下面我们保存进去了,在回来看就比较清楚了。
接下去,我们看到env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor)这句代码,到这里就说明没有找打native层BpBinder在java层对应的对象,所以我们通过jni方法来创建这个java对象,先看下gBinderProxyOffsets这个是什么:
```c++
static struct binderproxy_offsets_t // 提供给java用的代理对象
{
// Class state.
jclass mClass; // 指向java的BInderProxy类
jmethodID mConstructor; // 指向BinderProxy类的构造函数
jmethodID mSendDeathNotice; // 指向BinderProxy类的sendDeathNotice函数
// Object state.
jfieldID mObject; // 指向BinderProxy类的成员变量mObject,这个字段表示这个java代理对象引用了哪个BPBInder,这个mObject即BpBInder的地址值
jfieldID mSelf; // // 指向BinderProxy类的成员变量mSelf,即BinderProxy的弱引用
} gBinderProxyOffsets;
```
这是一个和代理对象相关的结构体,系统在运行后会调用JNI方法register_android_os_Binder来运行:
```c++
int register_android_os_Binder(JNIEnv* env)
{
if (int_register_android_os_Binder(env) < 0)
return -1;
if (int_register_android_os_BinderInternal(env) < 0)
return -1;
if (int_register_android_os_BinderProxy(env) < 0)
return -1;
if (int_register_android_os_Parcel(env) < 0)
return -1;
return 0;
}
```
这里运行的几个方法都和Binder有关,我们先看目前和代理带相关的方法int_register_android_os_BinderProxy:
```c++
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");
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", "I");
assert(gBinderProxyOffsets.mObject);
gBinderProxyOffsets.mSelf
= env->GetFieldID(clazz, "mSelf", "Ljava/lang/ref/WeakReference;");
assert(gBinderProxyOffsets.mSelf);
return AndroidRuntime::registerNativeMethods(
env, kBinderProxyPathName,
gBinderProxyMethods, NELEM(gBinderProxyMethods));
}
```
可以看到这个方法里面做了gBinderProxyOffsets的初始化,初始化是和BinderProxy类相关的信息。现在我们回到前面javaObjectForIBinder方法中env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor)这句话现在知道了是创建一个BinderProxy类。然后env->SetIntField(object, gBinderProxyOffsets.mObject, (int)val.get())这句话是把我们之前传进来的BpBinder对象设置到这个BinderProxy的mObject字段上,即BinderProxy的mObject持有BpBinder。然后后面有2句话,我在贴出来一下:
```c++
jobject refObject = env->NewGlobalRef(
env->GetObjectField(object, gBinderProxyOffsets.mSelf));
// 把BInderProxy添加到BpBinder的ObjectManager中
val->attachObject(&gBinderProxyOffsets, refObject,
jnienv_to_javavm(env), proxy_cleanup);
```
第一句话是通过JNI创建一个引用,指向gBinderProxyOffsets的mSelf字段,即gBinderProxyOffsets的弱引用。第二句话调用BpBinder的attachObject方法,把结构体gBinderProxyOffsets和他的弱引用refObject传过去,记得前面我们说每个BpBinder会保存他在java层的对象吗,现在就是做这个事情了,我们跟进去方法看看:
```c++
void BpBinder::attachObject(
const void* objectID, void* object, void* cleanupCookie,
object_cleanup_func func) // 添加一个java代理对象到BpBinder. objectID是BInderProxy的地址
{
AutoMutex _l(mLock);
LOGV("Attaching object %p to binder %p (manager=%p)", object, this, &mObjects);
mObjects.attach(objectID, object, cleanupCookie, func);
}
```
这个方法主要就是最后面的mObjects.attach这句话,我们先看下mObjects是什么:
```c++
ObjectManager mObjects;
class ObjectManager
{
public:
ObjectManager();
~ObjectManager();
void attach( const void* objectID,
void* object,
void* cleanupCookie,
IBinder::object_cleanup_func func);
void* find(const void* objectID) const;
void detach(const void* objectID);
void kill();
private:
ObjectManager(const ObjectManager&);
ObjectManager& operator=(const ObjectManager&);
struct entry_t
{
void* object; // java代理对象,binderProxy的mSelf字段
void* cleanupCookie; // 调用方法的参数
IBinder::object_cleanup_func func; // 删除一个java代理对象是调用的方法
};
KeyedVector<const void*, entry_t> mObjects; // 一个c的代理对象可能被不止一个java代理对象使用,这里用java代理对象地址作为key,保存的c的代理对象里面
};
void BpBinder::ObjectManager::attach(
const void* objectID, void* object, void* cleanupCookie,
IBinder::object_cleanup_func func) // 添加一个java代理对象到BPBinder
{
entry_t e; // 创建java代理对象结构体
e.object = object;
e.cleanupCookie = cleanupCookie;
e.func = func;
if (mObjects.indexOfKey(objectID) >= 0) { // 如果已经有了,return
LOGE("Trying to attach object ID %p to binder ObjectManager %p with object %p, but object ID already in use",
objectID, this, object);
return;
}
mObjects.add(objectID, e); // 添加java代理对象到BPBInder
}
```
可以看到mObjects也是一个类,他内部就有find,attach等方法,其中他内部有个entry_t结构体,里面有个字段object,这个就是指向了前面创建的BinderProxy的mSelf的,现在需要把要保存的BinderProxy转化为entry_t这个结构体,通过attach方法把entry_t保存在BpBinder的KeyedVector上,这样BpBinder等于也持有了BinderProxy。
## 最后返回ServiceManagerProxy
至此一个BpBinder就被转为BinderProxy对象返回给上层。这里需要由于对象比较多,需要注意一下,BpBinder是native层,他的mObject中保存有BinderProxy。同时BinderProxy是java层的,他的mObject字段也持有BpBinder。
至此,我们已经获得了一个java层的BinderProxy,我们回到最开始的getIServiceManager方法:
```java
sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
```
这里BinderInternal.getContextObject()返回的就是BinderProxy,现在调用asInterface方法:
```java
static public IServiceManager asInterface(IBinder obj) //obj是一个BinderProxy
{
if (obj == null) {
return null;
}
IServiceManager in =
(IServiceManager)obj.queryLocalInterface(descriptor);
if (in != null) {
return in;
}
return new ServiceManagerProxy(obj); // 返回service manager的java代理对象
}
```
这里obj就是前面的BinderProxy,他的queryLocalInterface方法默认返回的是null:
```java
final class BinderProxy implements IBinder {
public native boolean pingBinder();
public native boolean isBinderAlive();
public IInterface queryLocalInterface(String descriptor) {
return null;
}
....................
}
```
所以最后会调用new ServiceManagerProxy(obj);把BinderProxy封装为ServiceManagerProxy类:
```java
class ServiceManagerProxy implements IServiceManager { // service manager在java的代理对象
// 这里remote是一个BinderProxy,它封装了BpBInder,BpBinder有右引用对象的句柄,然后在binder驱动中可以找到引用对象然后就可以找到Service manager的实体对象。
public ServiceManagerProxy(IBinder remote) {
mRemote = remote;
}
public IBinder asBinder() {
return mRemote;
}
public IBinder getService(String name) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IServiceManager.descriptor);
data.writeString(name);
mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);
IBinder binder = reply.readStrongBinder(); // 这里获取的binder就是一个BinderProxy或者Fregservice
reply.recycle();
data.recycle();
return binder;
}
....................
public void addService(String name, IBinder service)
throws RemoteException {
Parcel data = Parcel.obtain(); // 向binder驱动请求的数据
Parcel reply = Parcel.obtain(); // binder返回的数据
data.writeInterfaceToken(IServiceManager.descriptor); // 写入请求头
data.writeString(name); // 写入service名字
data.writeStrongBinder(service); // 写入service,这里service实际上是JavaBBinder或者BpBInder
mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0); // 发送请求给binder驱动
reply.recycle();
data.recycle();
}
....................
private IBinder mRemote;
}
```
这个方法就可以看到有具体的getService,addService等操作的了,他们实际是调用mRemote的transact方法来做进程间的请求的,mRemote也就是前面的BinderProxy,至此一个service manager的代理类就获得了。接下去我们就可以给service manager发请求任务了。
这篇文章主要讲了如何获得service manager的流程,其实由于service manager比较特殊,他的引用对象的句柄值我们默认就是0,所以还是比较容易的,然后我们把这个句柄值在native层封装为BpBinder,java层是BinderProxy,最后封装为ServiceManagerProxy,这样就完成了。下一篇我们开始从想service manager请求注册说起,即看看addService这哦方法的流程是怎么样执行的。最后还是上时序图,把service manager的过程梳理一下。

Android进程间通信Binder(二)