Android System interprocess Communication (IPC) mechanism binder server and client Get Service Manager interface _android

Source: Internet
Author: User

In the previous article talking about Service Manager as the path of Binder daemon of the Android interprocess communication (IPC) mechanism, this paper introduces how Service Manager becomes the daemon of binder mechanism. As a daemon, Service Manager's job is, of course, to serve the server and the client. So how does server and client get a Service Manager interface to enjoy the services it provides? This article will briefly analyze the process of server and client access to Service Manager.

Before reading this article, I hope that readers will read the Android interprocess communication (IPC) Mechanism Binder Brief introduction and Learning Plan of the reference to Android simple binder mechanism, which can deepen the understanding of this article.

As we know, Service Manager serves as a daemon role in the binder mechanism, and it acts as a server role, but it is not the same as a typical server. For ordinary servers, if a client wants to obtain a remote interface to the server, it must be obtained through the GetService interface provided by the Service Manager remote interface, which is itself a process of using the binder mechanism for interprocess communication. For Service Manager This server, if a client wants to obtain a Service Manager remote interface, it does not have to be obtained through interprocess communication mechanism, because the Service Manager remote interface is a special binder reference, Its reference handle must be 0.

The function to obtain the Service Manager remote interface is Defaultservicemanager, which is declared in the Frameworks/base/include/binder/iservicemanager.h file:

sp<iservicemanager> Defaultservicemanager ();

Implemented in Frameworks/base/libs/binder/iservicemanager.cpp file:

Sp<iservicemanager> Defaultservicemanager () 
{ 
 
 if (Gdefaultservicemanager!= NULL) return Gdefaultservicemanager; 
 
 { 
  Automutex _l (gdefaultservicemanagerlock); 
  if (Gdefaultservicemanager = = NULL) { 
   Gdefaultservicemanager = interface_cast<iservicemanager> ( 
    Processstate::self ()->getcontextobject (NULL)); 
  } 
 
 return gdefaultservicemanager; 
} 

Gdefaultservicemanagerlock and Gdefaultservicemanager are global variables, defined in the Frameworks/base/libs/binder/static.cpp file:

Mutex Gdefaultservicemanagerlock; 
Sp<iservicemanager> Gdefaultservicemanager; 

As you can see from this function, Gdefaultservicemanager is a single case pattern, and when you call the Defaultservicemanager function, if Gdefaultservicemanager has already been created, return directly. Otherwise, the interface_cast<iservicemanager> (Processstate::self ()->getcontextobject (NULL)) is used to create a and is saved in the Gdefaultservicemanager global variable.

Before continuing with the implementation of Interface_cast<iservicemanager> (Processstate::self ()->getcontextobject (NULL)), let's look at a class diagram, This can help us understand the creation process of the Service Manager remote interface.


As a reader of the binder mechanism of Android, it should be easier to understand this figure. This diagram shows that the Bpservicemanager class inherits the Bpinterface<iservicemanager> class, and Bpinterface is a template class that is defined in frameworks/base/include/ Binder/iinterface.h file:

Template<typename interface> 
class Bpinterface:public INTERFACE, public bprefbase 
{public 
: 
 Bpinterface (const sp<ibinder>& remote); 
 
Protected: 
 virtual ibinder* onasbinder (); 
 

The Iservicemanager class inherits the IInterface class, and the IInterface class and the Bprefbase class inherit the Refbase class, respectively. In the Bprefbase class, there is a member variable mremote, its type is ibinder*, the implementation class is Bpbinder, it represents a binder reference, and the reference handle value is saved in the Bpbinder member variable of the Mhandle class. The Bpbinder class opens mprocess device files by ipcthreadstate classes and binder drivers, and ipcthreadstate through its member variable/dev/binder. The type of the mprocess member variable is processstate. After the Processstate class opens the device/dev/binder, the file description is opened Fu Paocun in the MDRIVERFD member variable for subsequent use.

Having understood these concepts, you can continue to analyze the process of creating a Service Manager remote interface, with the ultimate goal of creating a Bpservicemanager instance and returning its Iservicemanager interface. Creating a Service Manager remote interface is primarily the following statement:

Gdefaultservicemanager = interface_cast<iservicemanager> (
Processstate::self ()->getcontextobject (NULL));

It looks short, but it's a mystery, and you can read the reference to Android's binder mechanism, which is briefly described here.

The first is to call the Processstate::self function, which is the static member function of the processstate, and its function is to return a globally unique processstate instance variable, which is the singleton pattern, which is named Gprocess. If Gprocess has not yet been created, the create operation is performed, and the device file/dev/binder is opened through the Open File action function in the Processstate constructor, and the returned device file description Fu Paocun in the member variable MDRIVERFD.

Then call the Gprocess->getcontextobject function to get a binder reference with a handle value of 0, that is, bpbinder, so the statement that creates the Service Manager remote interface can be simplified to:

Gdefaultservicemanager = interface_cast<iservicemanager> (new Bpbinder (0));

To see the implementation of the function interface_cast<iservicemanager>, it is a template function, defined in the Framework/base/include/binder/iinterface.h file:

Template<typename interface> 
Inline sp<interface> interface_cast (const sp<ibinder>& obj) 
{return 
 interface::asinterface (obj); 
} 

The interface here is Iservicemanager, so the Iservicemanager::asinterface function is called. Iservicemanager::asinterface is declared in the Iservicemanager class by the Declare_meta_interface (SERVICEMANAGER) macro, located in the framework/base/ Include/binder/iservicemanager.h file:

Declare_meta_interface (ServiceManager);

The expansion is:

#define DECLARE_META_INTERFACE (ServiceManager)        \ 
 static const ANDROID::STRING16 descriptor;       \ 
 static android::sp<iservicemanager> asinterface (     \ 
 Const android::sp<android::ibinder> & obj);       \ 
 Virtual const android::string16& getinterfacedescriptor () const; \ 
 Iservicemanager ();             \ 
 virtual ~iservicemanager ();           
  

The implementation of Iservicemanager::asinterface is defined by Implement_meta_interface (ServiceManager, "Android.os.IServiceManager") macros, It is located in the Framework/base/libs/binder/iservicemanager.cpp file:

Implement_meta_interface (ServiceManager, "Android.os.IServiceManager");

The expansion is:

#define IMPLEMENT_META_INTERFACE (ServiceManager, "Android.os.IServiceManager") \ Const ANDROID::STRING16 Iservicema  Nager::d escriptor ("Android.os.IServiceManager"); \ const android::string16& \ iservicemanager::getinterfacedescriptor () const {\ return Iservic             Emanager::d escriptor; \} \ android::sp<iservicemanager> Iservicemanager::asinterface (\ Const Android::              sp<android::ibinder>& obj) \ {\ android::sp<iservicemanager> intr; \ if (obj!= NULL) {\ intr = static_cast<iservicemanager*> (\ OBJ-&G             T;querylocalinterface (\ Iservicemanager::d escriptor). get ());              \ if (intr = = NULL) {\ intr = new Bpservicemanager (obj);                   \} \ return intr; \} \ IservIcemanager::iservicemanager () {} \ Iservicemanager::~iservicemanager () {}  
 

It is estimated that the employee who wrote this code has changed jobs from Microsoft to Google. Here we focus on the implementation of Iservicemanager::asinterface:

Android::sp<iservicemanager> Iservicemanager::asinterface (const android::sp<android::ibinder>& obj)            
{                      
 android::sp<iservicemanager> intr;              
  
 if (obj!= NULL) {                  
  intr = static_cast<iservicemanager*> (             
     obj->querylocalinterface Iservicemanager:: Descriptor). get ()); 
   
  if (intr = = NULL) {     
   intr = new Bpservicemanager (obj);           
  }           
 return 
 intr;         
}  

The parameter obj passed in here is the new Bpbinder (0) just created, and the member function in the Bpbinder class inherits from the base class Ibinder,ibinder:: The Querylocalinterface function is located in the Framework/base/libs/binder/binder.cpp file:

Sp<iinterface> ibinder::querylocalinterface (const string16& Descriptor) 
{return 
 NULL; 
} 

Thus, in the Iservicemanager::asinterface function, the following statement is eventually invoked:

intr = new Bpservicemanager (obj);

That is:

intr = new Bpservicemanager (new Bpbinder (0));

Back to the Defaultservicemanager function, the end result is:

Gdefaultservicemanager = new Bpservicemanager (new Bpbinder (0));

In this way, the Service manager remote interface is created, which is essentially a bpservicemanager, containing a binder reference with a handle value of 0.

In the binder mechanism of the Android system, how does server and client get the Service Manager remote interface?

For the server, it is invoking the Iservicemanager::addservice interface to interact with the binder driver, that is, call Bpservicemanager::addservice. Bpservicemanager::addservice then invokes the Bpbinder instance that was originally created by the member function remote from its base class Bprefbase, and then invokes the Bpbinder::transact member function. In the Bpbinder::transact function, the Ipcthreadstate::transact member function is called, where the final interaction with the binder driver is made. Recall the previous class diagram, Ipcthreadstate has a porcessstate type of variable mprocess, and mprocess has a member variable MDRIVERFD, which is the device file/dev/binder Open file descriptor, therefore, Ipcthreadstate is equivalent to an open file descriptor that has a device file/dev/binder, so you can interact with the binder driver.

For the client, it is to invoke the Iservicemanager::getservice interface to interact with the binder driver. The process described above in the server using Service Manager is the same, and here is no longer a tiring statement.

The concrete implementations of these two functions, Iservicemanager::addservice and Iservicemanager::getservice, go deep into the binder driver layer for detailed source code analysis in the following two articles, In order to better understand the binder process communication mechanism, please be concerned.

The above is to the Android Binder communication data collation, follow-up continue to supplement the relevant information, thank you for your support of this site!

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.