Publishing publishBinderService and getting getService of AIDL service

Using the AIDL service in the Framework, its release and acquisition are two important methods. This article attempts to explore the implementation of its source code.

We know that when the mobile phone is turned on, it will start a ServiceManger service, which is the big housekeeper of the service. The release and acquisition of AIDL services are also operated through this big housekeeper. The following is the path of the big housekeeper.

/frameworks/native/cmds/servicemanager/ServiceManager.cpp

1 How to publish AIDL

publishBinderService

This method is defined in SystemService.java, there are multiple overloaded methods, and finally they are transferred to the following method.

/frameworks/base/services/core/java/com/android/server/SystemService.java
429      /**
430       * Publish the service so it is accessible to other services and apps.
431       *
432       * @param name the name of the new service
433       * @param service the service object
434       * @param allowIsolated set to true to allow isolated sandboxed processes
435       * to access this service
436       * @param dumpPriority supported dump priority levels as a bitmask
437       *
438       * @hide
439       */
440      protected final void publishBinderService(String name, IBinder service,
441              boolean allowIsolated, int dumpPriority) {
    
    
442          ServiceManager.addService(name, service, allowIsolated, dumpPriority);
443      }

Further transfer ServiceManager.addService, the ServiceManager here is still in the java layer. Let's continue to look at its internal implementation

194      public static void addService(String name, IBinder service, boolean allowIsolated,
195              int dumpPriority) {
    
    
196          try {
    
    
197              getIServiceManager().addService(name, service, allowIsolated, dumpPriority);
198          } catch (RemoteException e) {
    
    
199              Log.e(TAG, "error in addService", e);
200          }
201      }

After getIServiceManagerreading , it will finally get ServiceManagerProxy, the proxy object of ServiceManger through binder.

110      private static IServiceManager getIServiceManager() {
    
    
111          if (sServiceManager != null) {
    
    
112              return sServiceManager;
113          }
114          //要获取一个binder服务,serviceManger
115          // Find the service manager
116          sServiceManager = ServiceManagerNative
117                  .asInterface(Binder.allowBlocking(BinderInternal.getContextObject()));
118          return sServiceManager;
119      }

About parameters ServiceManagerNative.asInterface(Binder.allowBlocking(BinderInternal.getContextObject()))in . It is very important that the BinderInternal.getContextObject function finally returns a BinderProxy object, which 该 BinderProxy 对象对应于 BpBinder(0),其作为 binder代理端,指向 native 层大管家 service Manager。must be remembered here! ! !

This object contains a ProxyMap object named sProxyMap, the BpBinder object of the Native layer is used as the key, and the BinderProxy object is used as the Value, which is stored in the ProxyMap object. BpBinder and BinderProxy are actually one thing: the entity of the remote binder , the difference is the former Native layer and the latter Java layer. As for Binder.allowBlocking, after an operation, the returned BinderProxy object is still passed in, so don't pay attention.

For details of this part, please refer to the following article. https://juejin.cn/post/7058834333963911205#heading-2

We continue to focus on the implementation of ServiceManagerNative.asInterface.

27  public final class ServiceManagerNative {
    
    
28      private ServiceManagerNative() {
    
    }
...
        //上面的代码就是调用到了这个方法
37      @UnsupportedAppUsage
38      public static IServiceManager asInterface(IBinder obj) {
    
    
39          if (obj == null) {
    
    
40              return null;
41          }
42  
43          // ServiceManager is never local
44          return new ServiceManagerProxy(obj);//new 一个代理对象,要代理我们的 ServiceManager
45      }
46  }
47  
48  // This class should be deleted and replaced with IServiceManager.Stub whenever
49  // mRemote is no longer used
50  class ServiceManagerProxy implements IServiceManager {
    
    
51      public ServiceManagerProxy(IBinder remote) {
    
    
52          mRemote = remote;
			//下面这行是不是很熟悉,这不就是我们获取 binder 服务的操作嘛
			//所以这里是要获取 IServiceManager
53          mServiceManager = IServiceManager.Stub.asInterface(remote);
54      }
123  }

The above code is to convert the BinderProxy object passed in ServiceManger.java into ServiceManger, so as to obtain the service manager of the native layer.

After the above analysis, we know that registering the AIDL service is also a process of cross-process communication, and the ServiceManger of the native layer is called through the binder.

It is not difficult to find that the calling work of the framework layer is actually handed over to ServiceMangerProxy; and ServiceMangerProxy relies on its member variable BinderProxy, and BinderProxy walks to the native layer through jni, and finally completes the call.

See this article for the detailed process.
http://gityuan.com/2015/11/21/binder-framework/

2 How to get the service

getService

First of all, it also starts from the ServiceManger of the java layer, and the returned result is an IBinder type object, which needs to be transformed into the corresponding service through .Stub.asInterface(IBinder)operations .

/frameworks/base/core/java/android/os/ServiceManager.java
121      /**
122       * Returns a reference to a service with the given name.
123       *
124       * @param name the name of the service to get
125       * @return a reference to the service, or <code>null</code> if the service doesn't exist
126       */
127      @UnsupportedAppUsage
128      public static IBinder getService(String name) {
    
    
129          try {
    
    
130              IBinder service = sCache.get(name);
131              if (service != null) {
    
    
132                  return service;
133              } else {
    
    
134                  return Binder.allowBlocking(rawGetService(name));
135              }
136          } catch (RemoteException e) {
    
    
137              Log.e(TAG, "error in getService", e);
138          }
139          return null;
140      }
141  

First try to get the required IBinder object from the cache.

38      /**
39       * Cache for the "well known" services, such as WM and AM.
40       */
41      @UnsupportedAppUsage
42      private static Map<String, IBinder> sCache = new ArrayMap<String, IBinder>();

When there is none in the cache, use Binder.allowBlocking(rawGetService(name))the method , the point is rawGetService(name).

  private static IBinder rawGetService(String name) throws RemoteException {
    
    
...
334          
335          final IBinder binder = getIServiceManager().getService(name);
...
384          return binder;
385      }
386  }

Here we come to getIServiceManager, which is the same place as publishing services. After a short operation, we get the client binder of the service manager ServiceManger, and realize the cross-process call getService method.

3 ServiceManger related class diagram

In order to facilitate understanding, I made a simple class diagram, which is not complete, mainly to help understand the above content.
insert image description here
ServiceManagerProxy : Only this class implements the ServiceManager interface, so the related calls of the framework layer will find it in the end. His mRemote is a BinderProxy type object.
ServiceManagerNative : The ServiceManagerProxy class is placed under the package of this class and is not visible to the outside world. Therefore, it is necessary to indirectly obtain the ServiceManagerProxy class object through this class.
ServiceManager : This is the ServiceManager of the java layer. It is not a big butler. It feels like it is the person in charge of reception. If you have anything to do, you can find him, and he will find the boss. It obtains the ServiceManagerProxy object through ServiceManagerNative, and the operation of BinderInternal.getContextObject() to obtain the real housekeeper IBinder is passed in as a parameter at this time.
BinderProxy : For the time being, we only know that it can be called to the native layer, and how it is implemented has not yet been explored.

Guess you like

Origin blog.csdn.net/hejnhong/article/details/124534580