This article is based on the source code Scenario Analysis of the Android system, by Luo shengyang.
I. Test code:
~ /Android/external/binder/server
---- FregServer. cpp
~ /Android/external/binder/common
---- IFregService. cpp
---- IFregService. h
~ /Android/external/binder/client
---- FregClient. cpp
Binder Library (libbinder) code:
~ /Android/frameworks/base/libs/binder
---- BpBinder. cpp
---- Parcel. cpp
---- ProcessState. cpp
---- Binder. cpp
---- IInterface. cpp
---- IPCThreadState. cpp
---- IServiceManager. cpp
---- Static. cpp
~ /Android/frameworks/base/include/binder
---- Binder. h
---- BpBinder. h
---- IInterface. h
---- IPCThreadState. h
---- IServiceManager. h
---- IBinder. h
---- Parcel. h
---- ProcessState. h
Driver Layer Code:
~ /Android // kernel/goldfish/drivers/staging/android
---- Binder. c
---- Binder. h
Ii. Source Code Analysis
1. The program starts to execute the main function of the Service process FregServer. cpp.
~ /Android/external/binder/server
---- FregServer. cpp
class FregService : public BnFregService{ ...........public:static void instantiate(){defaultServiceManager()->addService(String16(FREG_SERVICE), new FregService());} ...........};int main(int argc, char** argv){FregService::instantiate();ProcessState::self()->startThreadPool();IPCThreadState::self()->joinThreadPool();return 0;}
The main function first calls the static method instantiate. In instantiate, The defaultServiceManager () and defaultServiceManager () functions are called as follows:
~ /Android/frameworks/base/libs/binder
---- IServiceManager. cpp
Sp
Defaservicservicemanager () {if (gdefaservicservicemanager! = NULL) return gdefaservicservicemanager; // If a proxy object has been created, {AutoMutex _ l (gdefaservicservicemanagerlock) is returned directly; // use the lock, to implement the singleton mode. if (gDefaultServiceManager = NULL) {gdefaservicservicemanager = interface_cast
(// Get Service Manager Proxy object ProcessState: self ()-> getContextObject (NULL) ;}return gdefaservicservicemanager ;}
Gdefaservicservicemanagerlock and gdefaservicservicemanager are all defined in Static. cpp.
~ /Android/frameworks/base/libs/binder
---- Static. cpp
Mutex gdefaservicservicemanagerlock; // lock sp
Gdefaservicservicemanager; // strong pointer of IServiceManager
The global variable gdefaservicservicemanager is a strong pointer of the IServiceManager type. It points to a BpServiceManager object in the process, that is, the Service Manager Proxy object; the global variable gdefaservicservicemanagerlock is used to ensure that a process has at most one Service Manager Proxy object. The combination of the locking mechanism ensures the uniqueness of objects in the process, which is a classic implementation of the Singleton design mode.
If a proxy object has been created, return directly. If not, you can create one in three steps:
(1) Call the static member function self of the ProcessState class to obtain a ProcessState object in the process.
(2) Call the member function getContextObject of the ProcessState object obtained earlier to create a Binder proxy object.
(3) Call the template function interface_cast Encapsulate the previously obtained Binder proxy object into a Service Manager Proxy object.
2. Call the static member function self of the ProcessState class to obtain a ProcessState object in the process.
~ /Android/frameworks/base/libs/binder
---- ProcessState. cpp
Sp
ProcessState: self () {if (gProcess! = NULL) return gProcess; // if it has already been created, AutoMutex _ l (gProcessMutex) is returned directly; if (gProcess = NULL) gProcess = new ProcessState; // create the ProcessState object return gProcess ;}
GProcess and gProcessMutex are both in Static. cpp.
Mutex gProcessMutex;sp
gProcess;
The global variable gProcess is a strong pointer of the ProcessState type and points to a ProcessState object in the process. The global variable gProcessMutex is a mutex lock, is used to ensure that a process has at most one ProcessState object, also a singleton mode.
For the first time, create a ProcessState object.
~ /Android/frameworks/base/libs/binder
---- ProcessState. cpp
ProcessState::ProcessState() : mDriverFD(open_driver()) , mVMStart(MAP_FAILED) .....{ if (mDriverFD >= 0) { ........... // 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); ...........}
The open_driver method is called in the initialization constructor.
~ /Android/frameworks/base/libs/binder
---- ProcessState. cpp
Static int open_driver () {if (gSingleProcess) {return-1;} int fd = open ("/dev/binder", O_RDWR ); // another process opens the device file. binder_procs has an additional process struct 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_driver first calls open to open the device file. Call ioctl to pass in the BINDER_VERSION parameter to obtain vers. Finally, call ioctl to input the BINDER_SET_MAX_THREADS parameter to display the maximum number of threads supported by the process.
Call mmap in the initialization list to map the device file/dev/binder to the address space of the process, in fact, the address space that maps/dev/binder to the process is actually requesting the Binder driver to allocate the kernel buffer for the process.
3. Call the member function getContextObject of the ProcessState object obtained earlier to create a Binder proxy object.
~ /Android/frameworks/base/libs/binder
---- ProcessState. cpp
sp
ProcessState::getContextObject(const sp
& caller){ if (supportsProcesses()) { return getStrongProxyForHandle(0); } else { return getContextObject(String16("default"), caller); }}