欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android系统进程间通信Binder机制在应用程序框架层的Java接口源代码分析

程序员文章站 2024-03-07 19:32:03
        在前面几篇文章中,我们详细介绍了android系统进程间通信机制binder...

        在前面几篇文章中,我们详细介绍了android系统进程间通信机制binder的原理,并且深入分析了系统提供的binder运行库和驱动程序的源代码。细心的读者会发现,这几篇文章分析的binder接口都是基于c/c++语言来实现的,但是我们在编写应用程序都是基于java语言的,那么,我们如何使用java语言来使用系统的binder机制来进行进程间通信呢?这就是本文要介绍的android系统应用程序框架层的用java语言来实现的binder接口了。

       熟悉android系统的读者,应该能想到应用程序框架中的基于java语言的binder接口是通过jni来调用基于c/c++语言的binder运行库来为java应用程序提供进程间通信服务的了。jni在android系统中用得相当普遍,sdk中的java接口api很多只是简单地通过jni来调用底层的c/c++运行库从而为应用程序服务的。

       这里,我们仍然是通过具体的例子来说明binder机制在应用程序框架层中的java接口,主要就是service manager、server和client这三个角色的实现了。通常,在应用程序中,我们都是把server实现为service的形式,并且通过iservicemanager.addservice接口来把这个service添加到service manager,client也是通过iservicemanager.getservice接口来获得service接口,接着就可以使用这个service提供的功能了,这个与运行时库的binder接口是一致的。

       前面我们学习android硬件抽象层时,曾经在应用程序框架层中提供了一个硬件访问服务helloservice,这个service运行在一个独立的进程中充当server的角色,使用这个service的client运行在另一个进程中,它们之间就是通过binder机制来通信的了。这里,我们就使用helloservice这个例子来分析android系统进程间通信binder机制在应用程序框架层的java接口源代码。所以希望读者在阅读下面的内容之前,先了解一下前面在ubuntu上为android系统的application frameworks层增加硬件访问服务这篇文章。

       这篇文章通过五个情景来学习android系统进程间通信binder机制在应用程序框架层的java接口:1. 获取service manager的java远程接口的过程;2. helloservice接口的定义;3. helloservice的启动过程;4. client获取helloservice的java远程接口的过程;5.  client通过helloservice的java远程接口来使用helloservice提供的服务的过程。

       一.  获取service manager的java远程接口

       我们要获取的service manager的java远程接口是一个servicemanagerproxy对象的iservicemanager接口。我们现在就来看看servicemanagerproxy类是长什么样子的:

Android系统进程间通信Binder机制在应用程序框架层的Java接口源代码分析

         这里可以看出,servicemanagerproxy类实现了iservicemanager接口,iservicemanager提供了getservice和addservice两个成员函数来管理系统中的service。从servicemanagerproxy类的构造函数可以看出,它需要一个binderproxy对象的ibinder接口来作为参数。因此,要获取service manager的java远程接口servicemanagerproxy,首先要有一个binderproxy对象。下面将会看到这个binderproxy对象是如何获得的。

         再来看一下是通过什么路径来获取service manager的java远程接口servicemanagerproxy的。这个主角就是servicemanager了,我们也先看一下servicemanager是长什么样子的:

Android系统进程间通信Binder机制在应用程序框架层的Java接口源代码分析

        servicemanager类有一个静态成员函数getiservicemanager,它的作用就是用来获取service manager的java远程接口了,而这个函数又是通过servicemanagernative来获取service manager的java远程接口的。

        接下来,我们就看一下servicemanager.getiservicemanager这个函数的实现,这个函数定义在frameworks/base/core/java/android/os/servicemanager.java文件中:

public final class servicemanager { 
  ...... 
  private static iservicemanager sservicemanager; 
  ...... 
  private static iservicemanager getiservicemanager() { 
    if (sservicemanager != null) { 
      return sservicemanager; 
    } 
 
    // find the service manager 
    sservicemanager = servicemanagernative.asinterface(binderinternal.getcontextobject()); 
    return sservicemanager; 
  } 
  ...... 
} 

        如果其静态成员变量sservicemanager尚未创建,那么就调用servicemanagernative.asinterface函数来创建。在调用servicemanagernative.asinterface函数之前,首先要通过binderinternal.getcontextobject函数来获得一个binderproxy对象。

        我们来看一下binderinternal.getcontextobject的实现,这个函数定义在frameworks/base/core/java/com/android/internal/os/binderinternal.java文件中:

public class binderinternal { 
  ...... 
  /** 
  * return the global "context object" of the system. this is usually 
  * an implementation of iservicemanager, which you can use to find 
  * other services. 
  */ 
  public static final native ibinder getcontextobject(); 
   
  ...... 
} 

        这里可以看出,binderinternal.getcontextobject是一个jni方法,它实现在frameworks/base/core/jni/android_util_binder.cpp文件中:

static jobject android_os_binderinternal_getcontextobject(jnienv* env, jobject clazz) 
{ 
  sp<ibinder> b = processstate::self()->getcontextobject(null); 
  return javaobjectforibinder(env, b); 
} 

       这里看到我们熟悉的processstate::self()->getcontextobject函数,具体可以参考浅谈android系统进程间通信(ipc)机制binder中的server和client获得service manager接口之路一文。processstate::self()->getcontextobject函数返回一个bpbinder对象,它的句柄值是0,即下面语句:
              sp<ibinder> b = processstate::self()->getcontextobject(null);  

       相当于是: 

               sp<ibinder> b = new bpbinder(0);  

       接着调用javaobjectforibinder把这个bpbinder对象转换成一个binderproxy对象:

jobject javaobjectforibinder(jnienv* env, const sp<ibinder>& val) 
{ 
  if (val == null) return null; 
 
  if (val->checksubclass(&gbinderoffsets)) { 
    // one of our own! 
    jobject object = static_cast<javabbinder*>(val.get())->object(); 
    //printf("objectforbinder %p: it's our own %p!\n", val.get(), object); 
    return object; 
  } 
 
  // for the rest of the function we will hold this lock, to serialize 
  // looking/creation of java proxies for native binder proxies. 
  automutex _l(mproxylock); 
 
  // someone else's... do we know about it? 
  jobject object = (jobject)val->findobject(&gbinderproxyoffsets); 
  if (object != null) { 
    jobject res = env->callobjectmethod(object, gweakreferenceoffsets.mget); 
    if (res != null) { 
      logv("objectforbinder %p: found existing %p!\n", val.get(), res); 
      return res; 
    } 
    logv("proxy object %p of ibinder %p no longer in working set!!!", object, val.get()); 
    android_atomic_dec(&gnumproxyrefs); 
    val->detachobject(&gbinderproxyoffsets); 
    env->deleteglobalref(object); 
  } 
 
  object = env->newobject(gbinderproxyoffsets.mclass, gbinderproxyoffsets.mconstructor); 
  if (object != null) { 
    logv("objectforbinder %p: created new %p!\n", val.get(), object); 
    // the proxy holds a reference to the native object. 
    env->setintfield(object, gbinderproxyoffsets.mobject, (int)val.get()); 
    val->incstrong(object); 
 
    // the native object needs to hold a weak reference back to the 
    // proxy, so we can retrieve the same proxy if it is still active. 
    jobject refobject = env->newglobalref( 
        env->getobjectfield(object, gbinderproxyoffsets.mself)); 
    val->attachobject(&gbinderproxyoffsets, refobject, 
        jnienv_to_javavm(env), proxy_cleanup); 
 
    // note that a new object reference has been created. 
    android_atomic_inc(&gnumproxyrefs); 
    increfscreated(env); 
  } 
 
  return object; 
} 

        在介绍这个函数之前,先来看两个变量gbinderoffsets和gbinderproxyoffsets的定义。

        先看gbinderoffsets的定义:

static struct bindernative_offsets_t 
{ 
  // class state. 
  jclass mclass; 
  jmethodid mexectransact; 
 
  // object state. 
  jfieldid mobject; 
 
} gbinderoffsets; 

       简单来说,gbinderoffsets变量是用来记录上面第二个类图中的binder类的相关信息的,它是在注册binder类的jni方法的int_register_android_os_binder函数初始化的:

const char* const kbinderpathname = "android/os/binder"; 
 
static int int_register_android_os_binder(jnienv* env) 
{ 
  jclass clazz; 
 
  clazz = env->findclass(kbinderpathname); 
  log_fatal_if(clazz == null, "unable to find class android.os.binder"); 
 
  gbinderoffsets.mclass = (jclass) env->newglobalref(clazz); 
  gbinderoffsets.mexectransact 
    = env->getmethodid(clazz, "exectransact", "(iiii)z"); 
  assert(gbinderoffsets.mexectransact); 
 
  gbinderoffsets.mobject 
    = env->getfieldid(clazz, "mobject", "i"); 
  assert(gbinderoffsets.mobject); 
 
  return androidruntime::registernativemethods( 
    env, kbinderpathname, 
    gbindermethods, nelem(gbindermethods)); 
} 

       再来看gbinderproxyoffsets的定义:

static struct binderproxy_offsets_t 
{ 
  // class state. 
  jclass mclass; 
  jmethodid mconstructor; 
  jmethodid msenddeathnotice; 
 
  // object state. 
  jfieldid mobject; 
  jfieldid mself; 
 
} gbinderproxyoffsets; 

       简单来说,gbinderproxyoffsets是用来变量是用来记录上面第一个图中的binderproxy类的相关信息的,它是在注册binderproxy类的jni方法的int_register_android_os_binderproxy函数初始化的:

const char* const kbinderproxypathname = "android/os/binderproxy"; 
 
static int int_register_android_os_binderproxy(jnienv* env) 
{ 
  jclass clazz; 
 
  clazz = env->findclass("java/lang/ref/weakreference"); 
  log_fatal_if(clazz == null, "unable to find class java.lang.ref.weakreference"); 
  gweakreferenceoffsets.mclass = (jclass) env->newglobalref(clazz); 
  gweakreferenceoffsets.mget 
    = env->getmethodid(clazz, "get", "()ljava/lang/object;"); 
  assert(gweakreferenceoffsets.mget); 
 
  clazz = env->findclass("java/lang/error"); 
  log_fatal_if(clazz == null, "unable to find class java.lang.error"); 
  gerroroffsets.mclass = (jclass) env->newglobalref(clazz); 
   
  clazz = env->findclass(kbinderproxypathname); 
  log_fatal_if(clazz == null, "unable to find class android.os.binderproxy"); 
 
  gbinderproxyoffsets.mclass = (jclass) env->newglobalref(clazz); 
  gbinderproxyoffsets.mconstructor 
    = env->getmethodid(clazz, "<init>", "()v"); 
  assert(gbinderproxyoffsets.mconstructor); 
  gbinderproxyoffsets.msenddeathnotice 
    = env->getstaticmethodid(clazz, "senddeathnotice", "(landroid/os/ibinder$deathrecipient;)v"); 
  assert(gbinderproxyoffsets.msenddeathnotice); 
 
  gbinderproxyoffsets.mobject 
    = env->getfieldid(clazz, "mobject", "i"); 
  assert(gbinderproxyoffsets.mobject); 
  gbinderproxyoffsets.mself 
    = env->getfieldid(clazz, "mself", "ljava/lang/ref/weakreference;"); 
  assert(gbinderproxyoffsets.mself); 
 
  return androidruntime::registernativemethods( 
    env, kbinderproxypathname, 
    gbinderproxymethods, nelem(gbinderproxymethods)); 
} 

        回到前面的javaobjectforibinder函数中,下面这段代码:

if (val->checksubclass(&gbinderoffsets)) { 
  // one of our own! 
  jobject object = static_cast<javabbinder*>(val.get())->object(); 
  //printf("objectforbinder %p: it's our own %p!\n", val.get(), object); 
  return object; 
} 

        前面说过,这里传进来的参数是一个bpbinder的指针,而bpbinder::checksubclass继承于父类ibinder::checksubclass,它什么也不做就返回false。

        于是函数继续往下执行:

                    jobject object = (jobject)val->findobject(&gbinderproxyoffsets);  

       由于这个bpbinder对象是第一创建,它里面什么对象也没有,因此,这里返回的object为null。

        于是函数又继续往下执行:

              object = env->newobject(gbinderproxyoffsets.mclass, gbinderproxyoffsets.mconstructor);  

        这里,就创建了一个binderproxy对象了。创建了之后,要把这个bpbinder对象和这个binderproxy对象关联起来:

                   env->setintfield(object, gbinderproxyoffsets.mobject, (int)val.get());  

        就是通过binderproxy.mobject成员变量来关联的了,binderproxy.mobject成员变量记录了这个bpbinder对象的地址。

        接下去,还要把它放到bpbinder里面去,下次就要使用时,就可以在上一步调用bpbinder::findobj把它找回来了:

               val->attachobject(&gbinderproxyoffsets, refobject, 
                jnienv_to_javavm(env), proxy_cleanup);  

        最后,就把这个binderproxy返回到android_os_binderinternal_getcontextobject函数,最终返回到最开始的servicemanager.getiservicemanager函数中来了,于是,我们就获得一个binderproxy对象了。

        回到servicemanager.getiservicemanager中,从下面语句返回:

                sservicemanager = servicemanagernative.asinterface(binderinternal.getcontextobject());  

        相当于是:

                 sservicemanager = servicemanagernative.asinterface(new binderproxy());  

       接下去就是调用servicemanagernative.asinterface函数了,这个函数定义在frameworks/base/core/java/android/os/servicemanagernative.java文件中:

public abstract class servicemanagernative ...... 
{ 
  ...... 
  static public iservicemanager asinterface(ibinder obj) 
  { 
    if (obj == null) { 
      return null; 
    } 
    iservicemanager in = 
      (iservicemanager)obj.querylocalinterface(descriptor); 
    if (in != null) { 
      return in; 
    } 
 
    return new servicemanagerproxy(obj); 
  } 
  ...... 
} 

       这里的参数obj是一个binderproxy对象,它的querylocalinterface函数返回null。因此,最终以这个binderproxy对象为参数创建一个servicemanagerproxy对象。

       返回到servicemanager.getiservicemanager中,从下面语句返回:

                  sservicemanager = servicemanagernative.asinterface(new binderproxy());  

       就相当于是:

                  sservicemanager = new servicemanagerproxy(new binderproxy());  

      于是,我们的目标终于完成了。

      总结一下,就是在java层,我们拥有了一个service manager远程接口servicemanagerproxy,而这个servicemanagerproxy对象在jni层有一个句柄值为0的bpbinder对象与之通过gbinderproxyoffsets关联起来。

      这样获取service manager的java远程接口的过程就完成了。

      二. helloservice接口的定义

      前面我们在学习android系统的硬件抽象层(hal)时,在在ubuntu上为android系统的application frameworks层增加硬件访问服务这篇文章中,我们编写了一个硬件服务helloservice,它的服务接口定义在frameworks/base/core/java/android/os/ihelloservice.aidl文件中:

package android.os; 
 
interface ihelloservice 
{ 
  void setval(int val); 
  int getval(); 
} 

       这个服务接口很简单,只有两个函数,分别用来读写硬件寄存器。

       注意,这是一个aidl文件,编译后会生成一个ihelloservice.java。我们来看一下这个文件的内容隐藏着什么奥秘,可以这么神奇地支持进程间通信。

/* 
 * this file is auto-generated. do not modify. 
 * original file: frameworks/base/core/java/android/os/ihelloservice.aidl 
 */ 
package android.os; 
public interface ihelloservice extends android.os.iinterface 
{ 
  /** local-side ipc implementation stub class. */ 
  public static abstract class stub extends android.os.binder implements android.os.ihelloservice 
  { 
    private static final java.lang.string descriptor = "android.os.ihelloservice"; 
    /** construct the stub at attach it to the interface. */ 
    public stub() 
    { 
      this.attachinterface(this, descriptor); 
    } 
 
    /** 
    * cast an ibinder object into an android.os.ihelloservice interface, 
    * generating a proxy if needed. 
    */ 
    public static android.os.ihelloservice asinterface(android.os.ibinder obj) 
    { 
      if ((obj==null)) { 
        return null; 
      } 
      android.os.iinterface iin = (android.os.iinterface)obj.querylocalinterface(descriptor); 
      if (((iin!=null)&&(iin instanceof android.os.ihelloservice))) { 
        return ((android.os.ihelloservice)iin); 
      } 
      return new android.os.ihelloservice.stub.proxy(obj); 
    } 
 
    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_setval: 
        { 
          data.enforceinterface(descriptor); 
          int _arg0; 
          _arg0 = data.readint(); 
          this.setval(_arg0); 
          reply.writenoexception(); 
          return true; 
        } 
        case transaction_getval: 
        { 
          data.enforceinterface(descriptor); 
          int _result = this.getval(); 
          reply.writenoexception(); 
          reply.writeint(_result); 
          return true; 
        } 
      } 
      return super.ontransact(code, data, reply, flags); 
    } 
 
    private static class proxy implements android.os.ihelloservice 
    { 
      private android.os.ibinder mremote; 
 
      proxy(android.os.ibinder remote) 
      { 
        mremote = remote; 
      } 
 
      public android.os.ibinder asbinder() 
      { 
        return mremote; 
      } 
 
      public java.lang.string getinterfacedescriptor() 
      { 
        return descriptor; 
      } 
 
      public void setval(int 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.writeint(val); 
          mremote.transact(stub.transaction_setval, _data, _reply, 0); 
          _reply.readexception(); 
        } 
        finally { 
          _reply.recycle(); 
          _data.recycle(); 
        } 
      } 
 
      public int getval() throws android.os.remoteexception 
      { 
        android.os.parcel _data = android.os.parcel.obtain(); 
        android.os.parcel _reply = android.os.parcel.obtain(); 
        int _result; 
        try { 
          _data.writeinterfacetoken(descriptor); 
          mremote.transact(stub.transaction_getval, _data, _reply, 0); 
          _reply.readexception(); 
          _result = _reply.readint(); 
        } 
        finally { 
          _reply.recycle(); 
          _data.recycle(); 
        } 
        return _result; 
      } 
    } 
 
    static final int transaction_setval = (android.os.ibinder.first_call_transaction + 0); 
    static final int transaction_getval = (android.os.ibinder.first_call_transaction + 1); 
  } 
 
  public void setval(int val) throws android.os.remoteexception; 
  public int getval() throws android.os.remoteexception; 
} 

        这里我们可以看到ihelloservice.aidl这个文件编译后的真面目,原来就是根据ihelloservice接口的定义生成相应的stub和proxy类,这个就是我们熟悉的binder机制的内容了,即实现这个helloservice的server必须继续于这里的ihelloservice.stub类,而这个helloservice的远程接口就是这里的ihelloservice.stub.proxy对象获得的ihelloservice接口。接下来的内容,我们就可以看到ihelloservice.stub和ihelloservice.stub.proxy是怎么创建或者使用的。

        三. helloservice的启动过程

        在讨论helloservice的启动过程之前,我们先来看一下实现helloservice接口的server是怎么定义的。

        回忆在ubuntu上为android系统的application frameworks层增加硬件访问服务一文,我们在frameworks/base/services/java/com/android/server目录下新增了一个helloservice.java文件:

package com.android.server; 
 
import android.content.context; 
import android.os.ihelloservice; 
import android.util.slog; 
 
public class helloservice extends ihelloservice.stub { 
  private static final string tag = "helloservice"; 
 
  helloservice() { 
    init_native(); 
  } 
 
  public void setval(int val) { 
    setval_native(val); 
  }   
 
  public int getval() { 
    return getval_native(); 
  } 
   
  private static native boolean init_native(); 
    private static native void setval_native(int val); 
  private static native int getval_native(); 
} 

        这里,我们可以看到,helloservice继续了ihelloservice.stub类,它通过本地方法调用实现了getval和setval两个函数。我们不关心这两个函数的具体实现,有兴趣的读者可以参考在ubuntu上为android系统的application frameworks层增加硬件访问服务一文。

        有了helloservice这个server类后,下一步就是考虑怎么样把它启动起来了。在frameworks/base/services/java/com/android/server/systemserver.java文件中,定义了systemserver类。systemserver对象是在系统启动的时候创建的,它被创建的时候会启动一个线程来创建helloservice,并且把它添加到service manager中去。

       我们来看一下这部份的代码:

class serverthread extends thread { 
  ...... 
 
  @override 
  public void run() { 
 
    ...... 
 
    looper.prepare(); 
 
    ...... 
 
    try { 
      slog.i(tag, "hello service"); 
      servicemanager.addservice("hello", new helloservice()); 
    } catch (throwable e) { 
      slog.e(tag, "failure starting hello service", e); 
    } 
 
    ...... 
 
    looper.loop(); 
 
    ...... 
  } 
} 
 
...... 
 
public class systemserver 
{ 
  ...... 
 
  /** 
  * this method is called from zygote to initialize the system. this will cause the native 
  * services (surfaceflinger, audioflinger, etc..) to be started. after that it will call back 
  * up into init2() to start the android services. 
  */ 
  native public static void init1(string[] args); 
 
  ...... 
 
  public static final void init2() { 
    slog.i(tag, "entered the android system server!"); 
    thread thr = new serverthread(); 
    thr.setname("android.server.serverthread"); 
    thr.start(); 
  } 
  ...... 
} 

        这里,我们可以看到,在serverthread.run函数中,执行了下面代码把helloservice添加到service manager中去。这里我们关注把helloservice添加到service manager中去的代码:

try { 
  slog.i(tag, "hello service"); 
  servicemanager.addservice("hello", new helloservice()); 
} catch (throwable e) { 
  slog.e(tag, "failure starting hello service", e); 
} 

         通过调用servicemanager.addservice把一个helloservice实例添加到service manager中去。

         我们先来看一下helloservice的创建过程:

                      new helloservice();  

         这个语句会调用helloservice类的构造函数,而helloservice类继承于ihelloservice.stub类,ihelloservice.stub类又继承了binder类,因此,最后会调用binder类的构造函数:

public class binder implements ibinder { 
  ...... 
   
  private int mobject; 
   
  ...... 
 
 
  public binder() { 
    init(); 
    ...... 
  } 
 
 
  private native final void init(); 
 
 
  ...... 
} 

        这里调用了一个jni方法init来初始化这个binder对象,这个jni方法定义在frameworks/base/core/jni/android_util_binder.cpp文件中:

static void android_os_binder_init(jnienv* env, jobject clazz) 
{ 
  javabbinderholder* jbh = new javabbinderholder(env, clazz); 
  if (jbh == null) { 
    jnithrowexception(env, "java/lang/outofmemoryerror", null); 
    return; 
  } 
  logv("java binder %p: acquiring first ref on holder %p", clazz, jbh); 
  jbh->incstrong(clazz); 
  env->setintfield(clazz, gbinderoffsets.mobject, (int)jbh); 
} 

        它实际上只做了一件事情,就是创建一个javabbinderholder对象jbh,然后把这个对象的地址保存在上面的binder类的mobject成员变量中,后面我们会用到。

        回到serverthread.run函数中,我们再来看一下servicemanager.addservice函数的实现:

public final class servicemanager { 
  ...... 
 
  private static iservicemanager sservicemanager; 
 
  ...... 
 
  public static void addservice(string name, ibinder service) { 
    try { 
      getiservicemanager().addservice(name, service); 
    } catch (remoteexception e) { 
      log.e(tag, "error in addservice", e); 
    } 
  } 
 
  ...... 
 
} 

         这里的getiservicemanager函数我们在前面已经分析过了,它返回的是一个servicemanagerproxy对象的iservicemanager接口。因此,我们进入到servicemanagerproxy.addservice中去看看:

class servicemanagerproxy implements iservicemanager { 
  public servicemanagerproxy(ibinder remote) { 
    mremote = remote; 
  } 
 
  ...... 
 
  public void addservice(string name, ibinder service) 
    throws remoteexception { 
      parcel data = parcel.obtain(); 
      parcel reply = parcel.obtain(); 
      data.writeinterfacetoken(iservicemanager.descriptor); 
      data.writestring(name); 
      data.writestrongbinder(service); 
      mremote.transact(add_service_transaction, data, reply, 0); 
      reply.recycle(); 
      data.recycle(); 
  } 
 
  ...... 
 
  private ibinder mremote; 
} 

       这里的parcel类是用java来实现的,它跟我们前面几篇文章介绍binder机制时提到的用c++实现的parcel类的作用是一样的,即用来在两个进程之间传递数据。

       这里我们关注是如何把参数service写到data这个parcel对象中去的:

                            data.writestrongbinder(service);  

      我们来看看parcel.writestrongbinder函数的实现:

public final class parcel { 
  ...... 
 
  /** 
  * write an object into the parcel at the current dataposition(), 
  * growing datacapacity() if needed. 
  */ 
  public final native void writestrongbinder(ibinder val); 
 
  ...... 
} 

        这里的writestrongbinder函数又是一个jni方法,它定义在frameworks/base/core/jni/android_util_binder.cpp文件中:

static void android_os_parcel_writestrongbinder(jnienv* env, jobject clazz, jobject object) 
{ 
  parcel* parcel = parcelforjavaobject(env, clazz); 
  if (parcel != null) { 
    const status_t err = parcel->writestrongbinder(ibinderforjavaobject(env, object)); 
    if (err != no_error) { 
      jnithrowexception(env, "java/lang/outofmemoryerror", null); 
    } 
  } 
} 

       这里的clazz参数是一个java语言实现的parcel对象,通过parcelforjavaobject把它转换成c++语言实现的parcel对象。这个函数的实现我们就不看了,有兴趣的读者可以研究一下,这个函数也是实现在frameworks/base/core/jni/android_util_binder.cpp这个文件中。

       这里的object参数是一个java语言实现的binder对象,在调用c++语言实现的parcel::writestrongbinder把这个对象写入到parcel对象时,首先通过ibinderforjavaobject函数把这个java语言实现的binder对象转换为c++语言实现的javabbinderholder对象:

sp<ibinder> ibinderforjavaobject(jnienv* env, jobject obj) 
{ 
  if (obj == null) return null; 
 
  if (env->isinstanceof(obj, gbinderoffsets.mclass)) { 
    javabbinderholder* jbh = (javabbinderholder*) 
      env->getintfield(obj, gbinderoffsets.mobject); 
    return jbh != null ? jbh->get(env) : null; 
  } 
 
  if (env->isinstanceof(obj, gbinderproxyoffsets.mclass)) { 
    return (ibinder*) 
      env->getintfield(obj, gbinderproxyoffsets.mobject); 
  } 
 
  logw("ibinderforjavaobject: %p is not a binder object", obj); 
  return null; 
} 

         我们知道,这里的obj参数是一个binder类的实例,因此,这里会进入到第一个if语句中去。

         在前面创建helloservice对象,曾经在调用到helloservice的父类binder中,曾经在jni层创建了一个javabbinderholder对象,然后把这个对象的地址保存在binder类的mobject成员变量中,因此,这里把obj对象的mobject成员变量强制转为javabbinderholder对象。

         到了这里,这个函数的功课还未完成,还剩下最后关键的一步:

                        return jbh != null ? jbh->get(env) : null;  

        这里就是jbh->get这个语句了。

        在javabbinderholder类中,有一个成员变量mbinder,它的类型为javabbinder,而javabbinder类继承于bbinder类。在前面学习binder机制的c++语言实现时,我们在android系统进程间通信(ipc)机制binder中的server启动过程源代码分析这篇文章中,曾经介绍过,ipcthreadstate类负责与binder驱动程序进行交互,它把从binder驱动程序读出来的请求作简单的处理后,最后把这个请求扔给bbinder的ontransact函数来进一步处理。

        这里,我们就是要把javabbinderholder里面的javabbinder类型binder实体添加到service manager中去,以便使得这个helloservice有client来请求服务时,由binder驱动程序来唤醒这个server线程,进而调用这个javabbinder类型binder实体的ontransact函数来进一步处理,这个函数我们在后面会继续介绍。

       先来看一下javabbinderholder::get函数的实现:

class javabbinderholder : public refbase 
{ 
  ...... 
 
  javabbinderholder(jnienv* env, jobject object) 
    : mobject(object) 
  { 
    ...... 
  } 
 
  ...... 
 
  sp<javabbinder> get(jnienv* env) 
  { 
    automutex _l(mlock); 
    sp<javabbinder> b = mbinder.promote(); 
    if (b == null) { 
      b = new javabbinder(env, mobject); 
      mbinder = b; 
      ...... 
    } 
 
    return b; 
  } 
 
  ...... 
 
  jobject     mobject; 
  wp<javabbinder> mbinder; 
}; 

       这里是第一次调用get函数,因此,会创建一个javabbinder对象,并且保存在mbinder成员变量中。注意,这里的mobject就是上面创建的helloservice对象了,这是一个java对象。这个helloservice对象最终也会保存在javabbinder对象的成员变量mobject中。

       回到android_os_parcel_writestrongbinder函数中,下面这个语句:

                    const status_t err = parcel->writestrongbinder(ibinderforjavaobject(env, object));  

       相当于是:

                    const status_t err = parcel->writestrongbinder((javabbinderhodler*)(obj.mobject));  

       因此,这里的效果相当于是写入了一个javabbinder类型的binder实体到parcel中去。这与我们前面介绍的binder机制的c++实现是一致的。

       接着,再回到servicemanagerproxy.addservice这个函数中,最后它通过其成员变量mremote来执行进程间通信操作。前面我们在介绍如何获取service manager远程接口时提到,这里的mremote成员变量实际上是一个binderproxy对象,因此,我们再来看看binderproxy.transact函数的实现:

final class binderproxy implements ibinder { 
  ...... 
 
  public native boolean transact(int code, parcel data, parcel reply, 
                int flags) throws remoteexception; 
 
  ...... 
} 

       这里的transact成员函数又是一个jni方法,它定义在frameworks/base/core/jni/android_util_binder.cpp文件中:

static jboolean android_os_binderproxy_transact(jnienv* env, jobject obj, 
            jint code, jobject dataobj, 
            jobject replyobj, jint flags) 
{ 
  ...... 
 
  parcel* data = parcelforjavaobject(env, dataobj); 
  if (data == null) { 
    return jni_false; 
  } 
  parcel* reply = parcelforjavaobject(env, replyobj); 
  if (reply == null && replyobj != null) { 
    return jni_false; 
  } 
 
  ibinder* target = (ibinder*) 
    env->getintfield(obj, gbinderproxyoffsets.mobject); 
  if (target == null) { 
    jnithrowexception(env, "java/lang/illegalstateexception", "binder has been finalized!"); 
    return jni_false; 
  } 
 
  ...... 
 
  status_t err = target->transact(code, *data, reply, flags); 
 
  ...... 
 
  if (err == no_error) { 
    return jni_true; 
  } else if (err == unknown_transaction) { 
    return jni_false; 
  } 
 
  signalexceptionforerror(env, obj, err); 
  return jni_false; 
} 

        这里传进来的参数dataobj和replyobj是一个java接口实现的parcel类,由于这里是jni层,需要把它转换为c++实现的parcel类,它们就是通过我们前面说的parcelforjavaobject函数进行转换的。

        前面我们在分析如何获取service manager远程接口时,曾经说到,在jni层中,创建了一个bpbinder对象,它的句柄值为0,它的地址保存在gbinderproxyoffsets.mobject中,因此,这里通过下面语句得到这个bpbinder对象的ibinder接口:

                   ibinder* target = (ibinder*) 
                   env->getintfield(obj, gbinderproxyoffsets.mobject);  

        有了这个ibinder接口后,就和我们前面几篇文章介绍binder机制的c/c++实现一致了。

        最后,通过bpbinder::transact函数进入到binder驱动程序,然后binder驱动程序唤醒service manager响应这个add_service_transaction请求:

                   status_t err = target->transact(code, *data, reply, flags);  

       具体可以参考android系统进程间通信(ipc)机制binder中的server启动过程源代码分析一文。需要注意的是,这里的data包含了一个javabbinderholder类型的binder实体对象,它就代表了我们上面创建的helloservice。service manager收到这个add_service_transaction请求时,就会把这个binder实体纳入到自己内部进行管理。

       这样,实现helloservice的server的启动过程就完成了。

       四. client获取helloservice的java远程接口的过程

        前面我们在学习android系统硬件抽象层(hal)时,在在ubuntu上为android系统内置java应用程序测试application frameworks层的硬件服务这篇文章中,我们创建了一个应用程序,这个应用程序作为一个client角色,借助service manager这个java远程接口来获得helloservice的远程接口,进而调用helloservice提供的服务。

        我们看看它是如何借助service manager这个java远程接口来获得helloservice的远程接口的。在hello这个activity的oncreate函数,通过iservicemanager.getservice函数来获得helloservice的远程接口:

public class hello extends activity implements onclicklistener {  
  ......  
 
  private ihelloservice helloservice = null;  
 
  ...... 
 
  @override  
  public void oncreate(bundle savedinstancestate) {  
 
    helloservice = ihelloservice.stub.asinterface(  
              servicemanager.getservice("hello")); 
  } 
 
  ...... 
} 

        我们先来看servicemanager.getservice的实现。前面我们说过,这里实际上是调用了servicemanagerproxy.getservice函数:

class servicemanagerproxy implements iservicemanager { 
  public servicemanagerproxy(ibinder remote) { 
    mremote = remote; 
  } 
 
  ...... 
 
  public ibinder getservice(string name) throws remoteexception { 
    parcel data = parcel.obtain(); 
    parcel reply = parcel.obtain(); 
    data.writeinterfacetoken(iservicemanager.descriptor); 
    data.writestring(name); 
    mremote.transact(get_service_transaction, data, reply, 0); 
    ibinder binder = reply.readstrongbinder(); 
    reply.recycle(); 
    data.recycle(); 
    return binder; 
  } 
 
  ...... 
 
  private ibinder mremote; 
} 

         最终通过mremote.transact来执行实际操作。我们在前面已经介绍过了,这里的mremote实际上是一个binderproxy对象,它的transact成员函数是一个jni方法,实现在frameworks/base/core/jni/android_util_binder.cpp文件中的android_os_binderproxy_transact函数中。

        这个函数前面我们已经看到了,这里就不再列出来了。不过,当这个函数从:

                     status_t err = target->transact(code, *data, reply, flags);  

       这里的reply变量里面就包括了一个helloservice的引用了。注意,这里的reply变量就是我们在servicemanagerproxy.getservice函数里面传进来的参数reply,它是一个parcel对象。

       回到servicemanagerproxy.getservice函数中,从下面语句返回:

                 mremote.transact(get_service_transaction, data, reply, 0);  

       接着,就通过下面语句将这个helloservice的引用读出来:

                       ibinder binder = reply.readstrongbinder();  

       我们看看parcel.readstrongbinder的实现:

public final class parcel { 
  ...... 
 
  /** 
  * read an object from the parcel at the current dataposition(). 
  */ 
  public final native ibinder readstrongbinder(); 
 
  ...... 
} 

        它也是一个jni方法,实现在frameworks/base/core/jni/android_util_binder.cpp文件中:

static jobject android_os_parcel_readstrongbinder(jnienv* env, jobject clazz) 
{ 
  parcel* parcel = parcelforjavaobject(env, clazz); 
  if (parcel != null) { 
    return javaobjectforibinder(env, parcel->readstrongbinder()); 
  } 
  return null; 
} 

       这里首先把java语言实现的parcel对象class转换成c++语言实现的parcel对象parcel,接着,通过parcel->readstrongbinder函数来获得一个binder引用。

       我们在前面学习binder机制时,在android系统进程间通信(ipc)机制binder中的client获得server远程接口过程源代码分析这篇文章中,曾经分析过这个函数,它最终返回来的是一个bpbinder对象,因此,下面的语句:

               return javaobjectforibinder(env, parcel->readstrongbinder());  

       就相当于是:

              return javaobjectforibinder(env, new bpbinder(handle));  

       这里的handle就是helloservice这个binder实体在client进程中的句柄了,它是由binder驱动程序设置的,上层不用关心它的值具体是多少。至于javaobjectforibinder这个函数,我们前面介绍如何获取service manager的java远程接口时已经有详细介绍,这里就不累述了,它的作用就是创建一个binderproxy对象,并且把刚才获得的bpbinder对象的地址保存在这个binderproxy对象的mobject成员变量中。

       最后返回到hello.oncreate函数中,从下面语句返回:

                       helloservice = ihelloservice.stub.asinterface( servicemanager.getservice("hello"));  

      就相当于是:

                      helloservice = ihelloservice.stub.asinterface(new binderproxy()));  

      回忆一下前面介绍ihelloservice接口的定义时,ihelloservice.stub.asinterface是这样定义的:

public interface ihelloservice extends android.os.iinterface 
{ 
  /** local-side ipc implementation stub class. */ 
  public static abstract class stub extends android.os.binder implements android.os.ihelloservice 
  { 
    ...... 
 
    public static android.os.ihelloservice asinterface(android.os.ibinder obj) 
    { 
      if ((obj==null)) { 
        return null; 
      } 
      android.os.iinterface iin = (android.os.iinterface)obj.querylocalinterface(descriptor); 
      if (((iin!=null)&&(iin instanceof android.os.ihelloservice))) { 
        return ((android.os.ihelloservice)iin); 
      } 
      return new android.os.ihelloservice.stub.proxy(obj); 
    } 
 
    ...... 
  } 
} 

        这里的obj是一个binderproxy对象,它的querylocalinterface返回null,于是调用下面语句获得helloservice的远程接口:

                    return new android.os.ihelloservice.stub.proxy(obj);  

        相当于是:

                     return new android.os.ihelloservice.stub.proxy(new binderproxy());  

        这样,我们就获得了helloservice的远程接口了,它实质上是一个实现了ihelloservice接口的ihelloservice.stub.proxy对象。

        五. client通过helloservice的java远程接口来使用helloservice提供的服务的过程

        上面介绍的hello这个activity获得了helloservice的远程接口后,就可以使用它的服务了。

        我们以使用ihelloservice.getval函数为例详细说明。在hello::onclick函数中调用了ihelloservice.getval函数:

public class hello extends activity implements onclicklistener { 
  ...... 
 
  @override 
  public void onclick(view v) { 
    if(v.equals(readbutton)) { 
      int val = helloservice.getval();  
      ...... 
    } 
    else if(v.equals(writebutton)) { 
      ...... 
    } 
    else if(v.equals(clearbutton)) { 
      ...... 
    } 
  } 
 
  ...... 
} 

        通知前面的分析,我们知道,这里的helloservice接口实际上是一个ihelloservice.stub.proxy对象,因此,我们进入到ihelloservice.stub.proxy类的getval函数中:


public interface ihelloservice extends android.os.iinterface 
{ 
  /** local-side ipc implementation stub class. */ 
  public static abstract class stub extends android.os.binder implements android.os.ihelloservice 
  { 
     
    ...... 
 
    private static class proxy implements android.os.ihelloservice 
    { 
      private android.os.ibinder mremote; 
 
      ...... 
 
      public int getval() throws android.os.remoteexception 
      { 
        android.os.parcel _data = android.os.parcel.obtain(); 
        android.os.parcel _reply = android.os.parcel.obtain(); 
        int _result; 
        try { 
          _data.writeinterfacetoken(descriptor); 
          mremote.transact(stub.transaction_getval, _data, _reply, 0); 
          _reply.readexception(); 
          _result = _reply.readint(); 
        } 
        finally { 
          _reply.recycle(); 
          _data.recycle(); 
        } 
        return _result; 
      } 
    } 
 
    ...... 
    static final int transaction_getval = (android.os.ibinder.first_call_transaction + 1); 
  } 
 
  ...... 
} 

        这里我们可以看出,实际上是通过mremote.transact来请求helloservice执行transaction_getval操作。这里的mremote是一个binderproxy对象,这是我们在前面获取helloservice的java远程接口的过程中创建的。

        binderproxy.transact函数是一个jni方法,我们在前面已经介绍过了,这里不再累述。最过调用到binder驱动程序,binder驱动程序唤醒helloservice这个server。前面我们在介绍helloservice的启动过程时,曾经提到,helloservice这个server线程被唤醒之后,就会调用javabbinder类的ontransact函数:

class javabbinder : public bbinder 
{ 
  javabbinder(jnienv* env, jobject object) 
    : mvm(jnienv_to_javavm(env)), mobject(env->newglobalref(object)) 
  { 
    ...... 
  } 
 
  ...... 
 
  virtual status_t ontransact( 
    uint32_t code, const parcel& data, parcel* reply, uint32_t flags = 0) 
  { 
    jnienv* env = javavm_to_jnienv(mvm); 
 
    ...... 
 
    jboolean res = env->callbooleanmethod(mobject, gbinderoffsets.mexectransact, 
      code, (int32_t)&data, (int32_t)reply, flags); 
 
    ...... 
 
    return res != jni_false ? no_error : unknown_transaction; 
  } 
 
  ...... 
 
    javavm* const  mvm; 
  jobject const  mobject; 
}; 

         前面我们在介绍helloservice的启动过程时,曾经介绍过,javabbinder类里面的成员变量mobject就是helloservice类的一个实例对象了。因此,这里通过语句:

             jboolean res = env->callbooleanmethod(mobject, gbinderoffsets.mexectransact, 
            code, (int32_t)&data, (int32_t)reply, flags);  

         就调用了helloservice.exectransact函数,而helloservice.exectransact函数继承了binder类的exectransact函数:

public class binder implements ibinder { 
  ...... 
 
  // entry point from android_util_binder.cpp's ontransact 
  private boolean exectransact(int code, int dataobj, int replyobj, int flags) { 
    parcel data = parcel.obtain(dataobj); 
    parcel reply = parcel.obtain(replyobj); 
    // theoretically, we should call transact, which will call ontransact, 
    // but all that does is rewind it, and we just got these from an ipc, 
    // so we'll just call it directly. 
    boolean res; 
    try { 
      res = ontransact(code, data, reply, flags); 
    } catch (remoteexception e) { 
      reply.writeexception(e); 
      res = true; 
    } catch (runtimeexception e) { 
      reply.writeexception(e); 
      res = true; 
    } catch (outofmemoryerror e) { 
      runtimeexception re = new runtimeexception("out of memory", e); 
      reply.writeexception(re); 
      res = true; 
    } 
    reply.recycle(); 
    data.recycle(); 
    return res; 
  } 
} 

         这里又调用了ontransact函数来作进一步处理。由于helloservice类继承了ihelloservice.stub类,而ihelloservice.stub类实现了ontransact函数,helloservice类没有实现,因此,最终调用了ihelloservice.stub.ontransact函数:

public interface ihelloservice extends android.os.iinterface 
{ 
  /** local-side ipc implementation stub class. */ 
  public static abstract class stub extends android.os.binder implements android.os.ihelloservice 
  { 
    ...... 
 
    @override  
    public boolean ontransact(int code, android.os.parcel data, android.os.parcel reply, int flags) throws android.os.remoteexception 
    { 
      switch (code) 
      { 
      ...... 
      case transaction_getval: 
        { 
          data.enforceinterface(descriptor); 
          int _result = this.getval(); 
          reply.writenoexception(); 
          reply.writeint(_result); 
          return true; 
        } 
      } 
      return super.ontransact(code, data, reply, flags); 
    } 
 
    ...... 
 
  } 
} 

         函数最终又调用了helloservice.getval函数:

public class helloservice extends ihelloservice.stub { 
  ...... 
 
  public int getval() { 
    return getval_native(); 
  } 
   
  ...... 
  private static native int getval_native(); 
} 

       最终,经过层层返回,就回到ihelloservice.stub.proxy.getval函数中来了,从下面语句返回:

                  mremote.transact(stub.transaction_getval, _data, _reply, 0);  

       并将结果读出来:

                    _result = _reply.readint();  

       最后将这个结果返回到hello.onclick函数中。

       这样,client通过helloservice的java远程接口来使用helloservice提供的服务的过程就介绍完了。

       至此,android系统进程间通信binder机制在应用程序框架层的java接口源代码分析也完成了,整个binder机制的学习就结束了。

       重新学习android系统进程间通信binder机制,请回到android进程间通信(ipc)机制binder简要介绍和学习计划一文。

       以上就是android 系统进程通信binder 机制java接口的源码分析,谢谢大家对本站的支持,后续继续补充相关知识!