Binder进程间通讯学习笔记 [Java层]

ServiceManagerProxy对象的获取过程

各个类之间的关系图如下所示:

                      +----------+                                           
                      |IInterface|                                           
                      +-----+----+                                           
                            ^                                                
                            |                                                
                    +-------+-------+                                        
                    |IServiceManager|                                        
                    +-+-----------+-+                                        
                      ^           ^                                          
                      |           |                                          
     +----------------+--+      +-+------------------+       +--------------+
     |ServiceManagerProxy|      |ServiceManagerNative| <-has-+ServiceManager|
     ++------------------+      +-----------------+--+       +--------------+
      |                                           |                          
  (mRemote)                                       |                          
      |                                           |                          
      |  +-------------+           +----------+   |                          
      +> | BinderProxy |           |  Binder  | <-+                          
         ++-----+------+           +--+-----+-+                              
          |     |                     |     |                                
          |     |                     |     |                                
      (mObject) |       +-------+     | (mObject)                            
          |     +-----> |IBinder| <---+     |                                
Java      |             +-------+           |                                
+------------------------------------------------------+                     
C++       v                                 v                                
       BpBinder                           BBinder                            
  • 通常来说我们只跟ServiceManager打交道。对ServiceManager的调用都会转发给其内部成员sServiceManager(ServiceManagerNative对象)。
  • Binder类提供了使用Binder机制的能力,IServiceManager接口定义了ServiceManager的API。

一次获取ServiceManager Proxy对象的调用过程如下图所示:

              +-------------+       +-------------------+      +--------------+            
              |ServerManager|       |ServerManagerNative|      |BinderInternal|            
              +------+------+       +---------+---------+      +-------+------+            
                     |                        |                        |                   
                     |                        |                        |                   
                     |                        |                        |          +        
getIServiceManager() |                        |                        |          |        
 +-----------------> |                        | getContextObject()     |         JNI       
                     +---------------------------------------------->  |          |        
                     |                        |                        +------------>      
                     |                        |                        |          |        
                     |                        |                        |          |        
                     |                        |                        <------------+      
                     |                        | asInterface()          | IBinder  |        
                     |                        | <----------------------+          |        
                     |                        |                        |          |        
                     new ServiceManagerProxy()|                        |          |        
                     | <----------------------+                        |          |        
                     |                        |                        |          |        
                     |                        |                        |          |        
                     |                        |                        |          |        
                     |                        |                        |                   
                     +                        +                        +                   

Java Service接口的定义和解析

Java Service牵涉到的类之间的关系和调用流程大致如下图所示:

+----------------------------------------------------+     
|                                                    |     
|                  [Context Manager]                 |     
|                         ^                          |     
+servicemanager-----------|--------------------------+     
                          |                                
+-----------------------+ |  +----------------------------+
|  +-----------------+  | |  |                            |
|  | [Binder Client] |  | |  | +------------------------+ |
|  +-----------^-----+  | |  | |IBinder                 | |
| +------------|------+ | |  | | +--------------------+ | |
| |AIDL        |      | | |  | | |Binder              | | |
| | +----------|----+ | | |  | | | +----------------+ | | |
| | |Proxy     |    | | | |  | | | |AIDL            | | | |
| | |          |    | | | |  | | | | +------------+ | | | |
| | | +--------|--+ | | | |  | | | | |Stub        | | | | |
| | | |IBinder |  | | | | |  | | | | | +--------+ | | | | |
| | | |        |  | | | | |  | | | | | | Binder | | | | | |
| | | | +------v+ | | | | |  | | | | | |Service | | | | | |
| | | | | Token | | | | | |  | | | | | +----^---+ | | | | |
| | | | +----^--+ | | | | |  | | | | +------|-----+ | | | |
| | | +------|----+ | | | |  | | | +--------|-------+ | | |
| | +--------|------+ | | |  | | +----------|---------+ | |
| +----------|--------+ | |  | +------------|-----------+ |
+Process A---|----------+ |  +Process B+----|-------------+
             |            |                 |              
+------------|------------v-----------------|--------+     
|            +---->[Binder Driver]<---------+        |     
|                                                    |     
+kernel----------------------------------------------+     

通常来说,我们通过AIDL来定义service接口,系统会自动根据AIDL文件生成一个对应的java接口。

以IMyService为例,系统根据IMyService.aidl生成IMyService.java:

// IMyService.aidl

interface IMyService {
    void hello(String val);
}

// IMyService.java

/*
 * This file is auto-generated.  DO NOT MODIFY.
 * Original file: C:\\Users\\xinyu.he\\workspace\\LayoutTest\\src\\com\\example\\layouttest\\IMyService.aidl
 */
package com.example.layouttest;
public interface IMyService extends android.os.IInterface
{
    /** Local-side IPC implementation stub class. */
    public static abstract class Stub extends android.os.Binder implements com.example.layouttest.IMyService
    {
        private static final java.lang.String DESCRIPTOR = "com.example.layouttest.IMyService";
        /** Construct the stub at attach it to the interface. */
        public Stub()
        {
            this.attachInterface(this  , DESCRIPTOR);
        }
        /**
         * Cast an IBinder object into an com.example.layouttest.IMyService interface,
         * generating a proxy if needed.
         */
        public static com.example.layouttest.IMyService asInterface(android.os.IBinder obj)
        {
            if ((obj==null)) {
                return null;
            }
            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
            if (((iin!=null)&&(iin instanceof com.example.layouttest.IMyService))) {
                return ((com.example.layouttest.IMyService)iin);
            }
            return new com.example.layouttest.IMyService.Stub.Proxy(obj);
        }
        @Override public android.os.IBinder asBinder()
        {
            return this;
        }
        @Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
        {
            switch (code)
            {
                case INTERFACE_TRANSACTION:
                    {
                        reply.writeString(DESCRIPTOR);
                        return true;
                    }
                case TRANSACTION_hello:
                    {
                        data.enforceInterface(DESCRIPTOR);
                        java.lang.String _arg0;
                        _arg0 = data.readString();
                        this.hello(_arg0);
                        reply.writeNoException();
                        return true;
                    }
            }
            return super.onTransact(code, data, reply, flags);
        }
        private static class Proxy implements com.example.layouttest.IMyService
        {
            private android.os.IBinder mRemote;
            Proxy(android.os.IBinder remote)
            {
                mRemote = remote;
            }
            @Override public android.os.IBinder asBinder()
            {
                return mRemote;
            }
            public java.lang.String getInterfaceDescriptor()
            {
                return DESCRIPTOR;
            }
            @Override public void hello(java.lang.String val) throws android.os.RemoteException
            {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    _data.writeString(val);
                    mRemote.transact(Stub.TRANSACTION_hello, _data, _reply, 0);
                    _reply.readException();
                }
                finally {
                    _reply.recycle();
                    _data.recycle();
                }
            }
        }
        static final int TRANSACTION_hello = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
    }
    public void hello(java.lang.String val) throws android.os.RemoteException;
}

可以看到系统自动生成了两个内部类IMyService.Stub和IMyService.Proxy。这两个类都实现了IMyService接口,其作用是对调用者屏蔽了Binder机制。
* IMyService.Stub用来描述一个自定义的Java服务。MyService继承于IMyService.Stub,并实现了hello()方法。
* IMyService.Stub.asInterface方法用来生成一个Proxy对象,Client获取到Proxy对象后,调用其hello()方法,Proxy对象向Service发送TRANSACTION_hello,触发Stub对象的onTransact方法。onTransact方法调用子类实现的hello()方法。

Java服务的启动过程

Java服务一般运行在Android系统进程或者应用程序进程中,需要在启动之前注册到Service Manager。由于android进程自带Binder线程池,所以只需将service注册到servicemanager中即可(不用初始化Binder等)。

注册service的代码一般如下所示:

ServiceManager.addService("MyService", new MyService());
  1. 首先分析一下MyService类的创建过程:MyService继承于IMyService,简介继承于Binder类,因此Binder的初始化方法会被调用。Binder对象初始化时会调用JNI方法init()。init方法会创建一个JavaBBinderHolder对象,然后将其地址保存在Binder对象的mBinder成员变量中。同时也将MyService保存在自身的mObject成员变量中。
    JavaBBinderHolder对象有成员变量mBinder,指向一个JavaBBinder对象。JavaBBinder继承于BBinder。
  2. MyService创建完毕后,通过addService方法注册到servermanager中。addService方法发起一个ADD_SERVICE_TRANSACTION,参数为MyService对象和注册名称name。
  3. servermanager收到ADD_SERVICE_TRANSACTION请求以后,将Parcel中的BBinder取出,并注册到内部。

Java服务代理对象的获取过程

service注册到ServerManager后,Android App便可以通过ServiceManager来获得service的一个proxy对象了。一般来说,获取一个service proxy对象的代码片段如下所示:

...
myService = IMyService.Stub.asInterface(ServiceManager.getService("myService"));
...

该代码片段的内部逻辑如下所示:

+--------+          +----------+     +--------------+      +-------------------+               
|Activity|          |IMyService|     |ServiceManager|      |ServiceManagerProxy|               
+--------+          +-----+----+     +--------+-----+      +---------+---------+               
     |                    |                   |                      |                         
     |                    |   getService(name)|                      |                         
     +---------------------------------------->                      |                         
     |                    |                   |  getService(name)    |                         
     |                    |                   +---------------------->                         
     |                    |                   |                      | GET_SERVICE_TRANSACTION 
     |                    |                   |                      +------------------------>
     |                    |                   |                      |  BinderProxy            
     <----------------------------------------------------------------------------------------+
     |                    |                   |                      |                         
     |                    |                   |                      |                         
     |Stub.asInterface(obj)                   |                      |                         
     +-------------------->                   |                      |                         
     |                    |                   |                      |                         
     |                    |                   |                      |                         
     | Stub.Proxy         |                   |                      |                         
     <--------------------+                   |                      |                         
     |                    |                   |                      |                         
     |                    |                   |                      |                         
     |                    |                   |                      |                         
     |                    |                   |                      |                         

Java服务的调用过程

使用service提供的服务时,直接在Proxy对象上调用AIDL定义好的接口方法即可。其内部逻辑如下所示:

+--------+    +----------------------+   +--------------------+   +-------------+   +----------------------+
|Activity|    |IMySer|ice(Stub.Proxy)|   |mRemote(BinderProxy)|   |Binder Driver|   |MyService(Stub:Binder)|
+---+----+    +---------+------------+   +-----------+--------+   +-----+-------+   +--------+-------------+
    |                   |                            |                  |                    |              
    |                   |                            |                  |                    |              
    |  mySer^ice.hello()|                            |                  |                    |              
    +-----------------> |                            |                  |                    |              
    |                   |transact(Stub.TRANSACTION_hello)               |                    |              
    |                   +--------------------------> |                  |                    |              
    |                   |                            |                  |                    |              
    |                   |                            |   onTransact()...|                    |              
    |                   |                            +----------------> |                    |              
    |                   |                            |                  | execTransact()     |              
    |                   |                            |                  +------------------> |              
    |                   |                            |                  |                    |              
    |                   |                            |                  |       onTransact() |              
    |                   |                            |                  |      +-------------+              
    |                   |                            |                  |      |             |              
    |                   |                            |                  |      +-----------> |              
    |                   |                            |                  |                    |              
    |                   |                            |                  |        hello()     |              
    |                   |                            |                  |      +-------------+              
    |                   |                            |                  |      |             |              
    |                   |                            |                  |      +-----------> |              
    |                   |                            |                  |                    |              
    |                   |                            |                  |                    |              

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据