Android Binder inter-process communication --- ServiceManager agent object acquisition process

Source: Internet
Author: User

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);    }}
  
 























Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.