sp<ProcessState> ProcessState::self(){if (gProcess != NULL) return gProcess;//在一个进程中,第一次进来肯定不走这儿AutoMutex _l(gProcessMutex);//锁保护if (gProcess == NULL) gProcess = new ProcessState;//创建一个ProcessState对象return gProcess;//这里返回ProcessState指针。}
ProcessState::ProcessState(): mDriverFD(open_driver())//Android很多代码都是这么写的,稍不留神就没看见这里调用了一个很重要的函数, 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);if (mVMStart == MAP_FAILED) {// *sigh*LOGE("Using /dev/binder failed: unable to mmap transaction memory.\n");close(mDriverFD);mDriverFD = -1;}#elsemDriverFD = -1;#endif}LOG_ALWAYS_FATAL_IF(mDriverFD < 0, "Binder driver could not be opened. Terminating.");}
0);这句话的大概意思是:
static int open_driver(){int fd = open("/dev/binder", O_RDWR);if (fd >= 0) {fcntl(fd, F_SETFD, FD_CLOEXEC);int vers;status_t result = ioctl(fd, BINDER_VERSION, &vers);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;}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));}} else {LOGW("Opening '/dev/binder' failed: %s\n", strerror(errno));}return fd;}
size_t maxThreads = 15;result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);
这句话实际通过ioctl方式告诉Binder驱动,这个fd支持最大线程数是15个。
getStrongProxyForHandle(int32_t handle)用于把一个handle翻译成一个BpBinder 。
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;if (b == NULL || !e->refs->attemptIncWeak(this)) {b = new BpBinder(handle);e->binder = b;if (b) e->refs = b->getWeakRefs();result = b;} else {// 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);e->refs->decWeak(this);}}return result;}
getStrongProxyForHandle函数的作用是根据一个binder句柄(Binder驱动为每个Service维护的一个Binder句柄,客户端可以通过句柄来和Service通讯)创建对应的Service代理对象BpBinder。
wp<IBinder> ProcessState::getWeakProxyForHandle(int32_t handle) { wp<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. The // attemptIncWeak() is safe because we know the BpBinder destructor will always // call expungeHandle(), which acquires the same lock we are holding now. // We need to do this because there is a race condition between someone // releasing a reference on this BpBinder, and a new reference on its handle // arriving from the driver. IBinder* b = e->binder; if (b == NULL || !e->refs->attemptIncWeak(this)) { b = new BpBinder(handle); result = b; e->binder = b; if (b) e->refs = b->getWeakRefs(); } else { result = b; e->refs->decWeak(this); } } return result; }
后面代码就好理解了,如果Service代理对象已经创建过了且当前弱引用数大于0(该值是通过attemptIncWeak返回),直接引用就行了。否则,则需要创建一个新的Service代理对象。
ProcessState::handle_entry* ProcessState::lookupHandleLocked(int32_t handle){const size_t N=mHandleToObject.size();if (N <= (size_t)handle) {handle_entry e;e.binder = NULL;e.refs = NULL;status_t err = mHandleToObject.insertAt(e, N, handle+1-N);if (err < NO_ERROR) return NULL;}return &mHandleToObject.editItemAt(handle);}