转载

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()  |       |       |       |      |   +-------------+       |       |       |      |   |    |       |       |       |      |   +-----------> |       |       |       |      |     |       |       |       |      |     |       
正文到此结束
Loading...