Binder机制初解

论坛 期权论坛 脚本     
匿名技术用户   2021-1-14 16:17   30   0

本文章只是对Binder机制有了初步的了解。想了解更细致的话可参考http://www.cloudchou.com/page/4 Binder系列 对Binder 的详细解析。而且我这里也只不过是对这个博主文章观看后的梳理。里面的Demo都是用的这个博主的。略加了点自己的理解。

文章设计内容:

简述

IPC 与 Binder

Binder IPC 程序结构

Binder层次划分

................ 驱动层

................ 驱动适配层.

................Binder核心框架层

................Binder框架层.

................ Java 框架层与本地Binder框架层的关系

Binder C++ 框架层实现(nativeservice)

Binder Java 框架层实现(frameworkservice)

FrameWork 层 访问native Binderservice

应用层常用的Aidl 与 framework binder service 对比

简述

最近看battery(电池)底层代码的时候牵涉到binder方面的知识,对于Binder没有过过多的了解。只能学习分析了一下。不是很深入,只是明白了大概的流程。这里与大家分享一下。

IPC 与 Binder

IPC(Inter-Process Communication)进程间通信,提供了各种进程间通信的方法。

Binder是android实现的的IPC的一种机制。

例:

A进程如果要使用B进程的服务,B进程首先要注册此服务,A进程通过service mananger获取该服务的handle,通过这个handle,A进程就可以使用该服务了。A进程使用B进程的服务还意味着二者遵循相同的协议,这个协议反映在代码上就是二者要实现IBinder接口。

Binder的本质就是要把对象a从一个进程B映射到另一个进程A中,进程A中调用对象a的方法象调本地方法一样。但实际上进程B和进程A有不同的地址空间,对象a只有在进程B里有意义,但是驱动层可将进程B的对象a映射到进程A,得到对象a在进程A的表示,称之为handle,也叫句柄。这样,对象a在进程B的地址空间里有一个实际地址,在进程A里有对应的句柄,驱动会将这个句柄和对象a的实际地址映射起来。对象a对于进程B来说是本地对象,对象a对于进程A来说是远程对象,而handle对于进程A来说是对象a在进程A的引用。

Binder IPC 程序结构


Binder层次划分

binder layer



驱动层

正如大家所知道的,Binder机制是需要Linux内核支持的,Android因此添加了binder驱动,binder 设备节点为/dev/binder,主设备号为10,binder驱动程序在内核中的头文件和代码路径如下:

kernel/drivers/staging/binder.h

kernel/drivers/staging/binder.c

binder驱动程序的主要作用是完成实际的binder数据传输。

驱动实现时,主要通过binder_ioctl函数与用户空间的进程交换数据(用户进程与驱动交互时使用ioctl函数,对应驱动源码的binder_ioctl函数)



驱动适配层.

主要是IPCThreadState.cpp和ProcessState.cpp,源码位于frameworks/native/libs/binder

这两个类都采用了单例模式,主要负责和驱动直接交互。

ProcessState负责打开binder设备,进行一些初始化设置并做内存映射

IPCThreadState负责直接和binder设备通信,使用ioctl读写binder驱动数据

(关于这两个类,不做过多的讲解,因为我也没细看,想了解的话可以自己查阅资料)


Binder核心框架层

Binder核心框架主要是IBinder及它的两个子类,即BBinder和BpBinder(里面的remote()返回的是一个IBinder指针),分别代表了最基本的服务端及客户端。

binder service服务端实体类会继承BnInterface,而BnInterface会继承自BBinder,利用servicemananger将BBinder对象在servicemananger注册。

客户端程序和驱动交互时只能得到远程对象的句柄handle,然后会调用ProcessState的getStrongProxyForHandle函数,利用句柄handle建立BpBinder对象,然后将它转为IBinder指针返回给调用者。这 样客户端每次调用IBinder指针的transact方法,其实是执行BpBinder的transact方法。


Binder框架层.

本地Binder框架层包含以下类(frameworks/native/libs/binder):

RefBase,IInterface,BnInterface,BpInterface,BpRefBase,Parcel 等等

Java框架层包含以下类(frameworks/base/core/java/android/os):

IBinder,Binder,IInterface,ServiceManagerNative,ServiceManager,BinderInternal,IServiceManager,ServiceManagerProxy

Java框架层的类的部分方法的实现在本地代码里(frameworks/base/core/jni)。

Java 框架层与本地Binder框架层的关系

Java层框架中的类Binder,BinderProxy,BinderInternal的native方法的实现是在源码 frameworks/base/core/jni/android_util_Binder.cpp里,Java层框架中Parcel类native方法的实现是在frameworks/base/core/jni/android_os_Parcel.cpp里。重点

frameworks/base/core/jni/android_util_Binder.cpp 文件中,这个文件中有两个类,JavaBBinder和JavaBBinderHolder相关类。JavaBBinder继承自本地框架的BBinder,代表binder service服务端实体,而JavaBBinderHolder保存JavaBBinder指针,Java层Binder的mObject保存的是 JavaBBinderHolder指针的值,故此这里用聚合关系表示。BinderProxy的mObject保存的是BpBinder对象指针的值

图如下

然后frameworks/base/core/jni/android_util_Binder.cpp 文件中有两个重要的函数:

jobjectjavaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val) :将本地IBinder对象转为Java层的IBinder对象,实际类型是BinderProxy

sp<IBinder>ibinderForJavaObject(JNIEnv* env, jobject obj) :将Java层的IBinder对象转为本地IBinder对象


Binder C++ 框架层实现(nativeservice)

注:此例子摘抄于互联网(http://www.cloudchou.com/android/post-332.html

例子下载地址:(https://github.com/cloudchou/NativeBinderTest

Test.h :包含需要用到的头文件,声明接口,定义操作枚举,声明binder引用类

ITestService.cpp: 接口类方法的实现

TestServer.cpp: 声明并实现binder实体类,启动binder服务,并在service manager里注册

TestClient.cpp: 声明并实现binder 引用类,测试binder服务的client

关系图:


Test.h文件 :声明接口,定义操作枚举

#ifndef TEST_H_H
#define TEST_H_H
#include <stdio.h>
#include <binder/IInterface.h>
#include <binder/Parcel.h>
#include <binder/IBinder.h>
#include <binder/Binder.h>
#include <binder/ProcessState.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
using namespace android;
namespace android
{
    class ITestService : public IInterface
    {
    public:
        DECLARE_META_INTERFACE(TestService); // declare macro
        virtual void test()=0;
    };

    enum
    {
        TEST = IBinder::FIRST_CALL_TRANSACTION,
    };

    class BpTestService: public BpInterface<ITestService> {
    public:
     BpTestService(const sp<IBinder>& impl);
     virtual void test();
    };
}
#endif


解析:

(1)使用DECLARE_META_INTERFACE(TestService);相当于添加了下述代码:

static const android::String16 descriptor;
static android::sp<ITestService> asInterface(  
        const android::sp<android::IBinder>& obj);
virtual const android::String16& getInterfaceDescriptor() const;
ITestService ();
virtual ~ITestService();

也就说添加了字段descriptor,也添加了两个成员函数asInterface,getInterfaceDescriptor, 还添加了构造器和析构器。

(2)为ITestService接口的所有方法声明枚举,一个枚举值对应ITestService接口的一个方法(Test.h)

enum{
   TEST = IBinder::FIRST_CALL_TRANSACTION,
};

TEST相当于ITestService接口里的test方法,后续会为该枚举值调用test方法(Test.h)

(3)声明binder引用类BpTestService(代理类声明)

class BpTestService: public BpInterface<ITestService> {
    public:
     BpTestService(const sp<IBinder>& impl);
     virtual void test();
};

因为实现ItestService宏定义接口DECLARE_META_INTERFACE(TestService);方法时,必须使用binder引用类,所以binder引用类需要在Test.h里声明。(注①)。

ITestService.cpp文件:实现宏定义接口DECLARE_META_INTERFACE(TestService);

#include "Test.h"
namespace android
{
    IMPLEMENT_META_INTERFACE(TestService, "android.TestServer.ITestService");
}

使用IMPLEMENT_META_INTERFACE(TestService,“android.TestServer.ITestService”);相当于添加了下述代码:


 /*初始化用宏DECLARE_META_INTERFACE声明的静态字段descriptor*/
const android::String16 ITestService::descriptor("android.TestServer.ITestService");
/*实现用宏DECLARE_META_INTERFACE声明的方法getInterfaceDescriptor */
const android::String16&                                          
        ITestService::getInterfaceDescriptor() const { 
    return ITestService::descriptor;                   
}                                                                   
/*实现用宏DECLARE_META_INTERFACE声明的方法asInterface */
android::sp<ITestService> ITestService::asInterface(   
        const android::sp<android::IBinder>& obj)      
{                                                      
    android::sp<ITestService> intr;                    
    if (obj != NULL) {           
        /*在binder实体类BnInterface里会执行queryLocalInterface*/                      
        intr = static_cast<ITestService*>(             
            obj->queryLocalInterface(                  
                    ITestService::descriptor).get());  
        /*在binder引用类BpInterface里会创建BpInterface的子类对象*/            
        if (intr == NULL) {                            
            intr = new BpTestService(obj);  <strong><span style="color:red;">注①</span></strong>           
        }                                              
    }                                                  
    return intr;                                       
}                                                      
/*实现用宏DECLARE_META_INTERFACE声明的构造器和析构器 */
ITestService::ITestService() { }                     
ITestService::~ITestService() { }

TestServer.cpp 文件:声明并实现binder实体类BnInterface

#include "Test.h"
namespace android {
class BnTestService: public BnInterface<ITestService> {
public:
 virtual status_t
 onTransact(uint32_t code, const Parcel& data, Parcel* reply,
   uint32_t flags = 0);
 virtual void test() {
  printf("Now get test\n");
 }

};
status_t BnTestService::onTransact(uint_t code, const Parcel& data,
  Parcel* reply, uint32_t flags) {
 switch (code) {
 case TEST: {
  printf("got the client msg\n");
  CHECK_INTERFACE(ITest, data, reply);
  test();
  reply->writeInt32(100);
  return NO_ERROR;
 }
  break;
 default:
  break;
 }
 return NO_ERROR;
}
}
int main() {
 sp < ProcessState > proc(ProcessState::self());
 sp < IServiceManager > sm = defaultServiceManager();
 sm->addService(String16("service.testservice"), new BnTestService());
 ProcessState::self()->startThreadPool();
 IPCThreadState::self()->joinThreadPool();
 return 0;
}

BnInterface也是binder核心库和框架中的类,表示binder实体类,在onTransact函数里,会根据客户端提交的操作代码调用不同的函数,而操作代码就是Test.h里声明的枚举值,在本实例里是TEST,我们收到test后会调用test方法。

Mian()函数里面获取servicemanager然后把本列的testservice添加进去。

TestClient.cpp文件:

#include "Test.h"
namespace android {
BpTestService::BpTestService(const sp<IBinder>& impl) :
  BpInterface<ITestService>(impl) {
}
void BpTestService::test() {
 printf("in the get Test\n");
 Parcel data, reply;
 data.writeInterfaceToken(ITestService::getInterfaceDescriptor());
 remote()->transact(TEST, data, &reply);
 printf("send Print %d\n", reply.readInt32());
}
}
int main() {
 sp < IServiceManager > sm = defaultServiceManager();
 sp < IBinder > binder = sm->getService(String16("service.testservice"));
 sp<ITestService> cs = interface_cast < ITestService > (binder);
 cs->test();
 return 0;
}

interface_cast(binder); 实际上调用的方法是用宏DECLARE_META_INTERFACE声明的方法ITestService::asInterface,这里用了内联函数模版。

ProcessState和IPCThreadState是真正直接和binder驱动交互的类,核心库和框架层都是通过和这两个类交互才能和驱动间接交互。它们通过ioctl和binder驱动交互,ProcessState主要负责管理所有的binder引用,IPCThreadState则和 binder传输数据。(前面说过了)

测试:

流程是这样的。

TestClient.cpp -----> mian()---> getService-->interface_cast<ITestService>--> BpTestService的一个实例(BpBinder代理)---> remote发送数据给 TestServer.cpp --->

---- onTransact根据不同的方法请求,执行实际的方法,并在reply中返回值给TestClient.cpp。

注:onTransact(uint_t code, const Parcel& data, Parcel* reply,uint32_t flags)

· // code :是请求的ID号

· // data :客户端请求发送的参数

· // reply:服务器端返回的结果

· // flags:一些额外的标识,如FLAG_ONEWAY等,通常为0.


Binder Java 框架层实现(frameworkservice)

注:此例子摘抄于互联网(http://www.cloudchou.com/android/post-447.html

例子下载地址:(https://github.com/cloudchou/FrameworkBinderTest

ICloudManager.java:服务端和客户端共用同一个接口文件,该接口声明了binder service供外界调用的方法。

CloudManager:binder service实体类,接收客户端的调用,进行相关逻辑处理后返回结果给客户端

BServer: 创建CloudManage对象,并调用ServiceManager注册binder service

客户端:

ICloudManager.java:通过软链接实现服务端与客户端共用

CloudManagerProxy: binder service引用类,其实是binder service在客户端的代理,客户端通过该类调用服务端的操作

BClient: 测试binderservice的客户端,先通过ServiceManager获取binder对象,然后再利用它创建CloudManagerProxy对象,通过CloudManagerProxy对象调用服务端的操

Service 端:

ICloudManager.java:

package com.cloud.test;

import android.os.IInterface;
import android.os.RemoteException;

public interface ICloudManager extends IInterface {
 static final java.lang.String DESCRIPTOR = "com.cloud.test.BServer";
 public void print(String str) throws RemoteException ;
 public int add(int a, int b) throws RemoteException ;
    static final int TRANSACTION_print = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
    static final int TRANSACTION_add = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
}

IcloudManager 继承Iinterface接口,而这个接口类如下:

IInterface声明了asBinder方法,用于转为IBinder对象。

CloudManager:

/*
 **
 ** Copyright 2007, The Android Open Source Project
 **
 ** Licensed under the Apache License, Version 2.0 (the "License");
 ** you may not use this file except in compliance with the License.
 ** You may obtain a copy of the License at
 **
 **     http://www.apache.org/licenses/LICENSE-2.0
 **
 ** Unless required by applicable law or agreed to in writing, software
 ** distributed under the License is distributed on an "AS IS" BASIS,
 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 ** See the License for the specific language governing permissions and
 ** limitations under the License.
 */

package com.cloud.test;

import android.os.Binder;
import android.os.IBinder;
import android.os.Parcel;
import android.os.RemoteException;

public class CloudManager extends Binder implements ICloudManager { 
 

 public CloudManager() {
  this.attachInterface(this, DESCRIPTOR);
 }

 @Override
 public IBinder asBinder() {
  return this;
 }

 public static com.cloud.test.ICloudManager asInterface(
   android.os.IBinder obj) {
  if ((obj == null)) {
   return null;
  }
  android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
  if (((iin != null) && (iin instanceof com.cloud.test.ICloudManager))) {
   return ((com.cloud.test.ICloudManager) iin);
  }
  return null;
 }

 @Override
 protected boolean onTransact(int code, Parcel data, Parcel reply, int flags)
   throws RemoteException {
  switch (code) {
  case INTERFACE_TRANSACTION: {
   reply.writeString(DESCRIPTOR);
   return true;
  }
  case TRANSACTION_print: {
   data.enforceInterface(DESCRIPTOR);
   String str = data.readString();
   print(str);
   reply.writeNoException();
   return true;
  }
  case TRANSACTION_add: {
   data.enforceInterface(DESCRIPTOR);
   int a = data.readInt();
   int b = data.readInt();
   int c = add(a, b);
   reply.writeNoException();
   reply.writeInt(c);
   return true;
  }
  }
  return super.onTransact(code, data, reply, flags);
 }

 @Override
 public void print(String str) {
  System.out.println(str);
 }

 @Override
 public int add(int a, int b) {
  return a + b;
 }

}

注意必须从Binder继承,并实现ICloudManager接口

Bserver:

package com.cloud.test;

import android.os.Looper;
import android.os.ServiceManager;

public class BServer {

 public static void main(String[] args) {
  System.out.println("Cloud Manager Service Starts");
  Looper.prepareMainLooper();
  android.os.Process
    .setThreadPriority(android.os.Process.THREAD_PRIORITY_FOREGROUND);
  ServiceManager.addService("CloudService", new CloudManager());
  Looper.loop();
 }

}

实现服务端 BServer,创建CloudManager对象,并通过ServiceManager注册服务

Client端:

ICloudManager.java

客户端的ICloudManager.java里面的内容是相对地址,其实指向的服务端的ICloudManager.java。 以软连接的形式公用同一个文件。

CloudManagerProxy:

package com.cloud.test;

import android.os.IBinder;
import android.os.RemoteException;

public class CloudManagerProxy implements ICloudManager {
 private android.os.IBinder mRemote;

 public CloudManagerProxy(android.os.IBinder remote) {
  mRemote = remote;
 }

 public java.lang.String getInterfaceDescriptor() {
  return DESCRIPTOR;
 }

 @Override
 public void print(String str) throws RemoteException {
  android.os.Parcel _data = android.os.Parcel.obtain();
  android.os.Parcel _reply = android.os.Parcel.obtain();
  try {
   _data.writeInterfaceToken(DESCRIPTOR);
   _data.writeString(str);
   mRemote.transact(TRANSACTION_print, _data, _reply, 0);
   _reply.readException();
  } finally {
   _reply.recycle();
   _data.recycle();
  }
 }

 @Override
 public int add(int a, int b) throws RemoteException {
  android.os.Parcel _data = android.os.Parcel.obtain();
  android.os.Parcel _reply = android.os.Parcel.obtain();
  int result=0;
  try {
   _data.writeInterfaceToken(DESCRIPTOR);
   _data.writeInt(a);
   _data.writeInt(b);
   mRemote.transact(TRANSACTION_add, _data, _reply, 0);
   _reply.readException();
   result=_reply.readInt();
  } finally {
   _reply.recycle();
   _data.recycle();
  }
  return result;
 }

 @Override
 public IBinder asBinder() {
  return mRemote;
 }

}

代理类,在 asBinder()类里面返回IBinder. 接口方法的实现实际上是通过调用IBinder对象mRemote的transact方法将调用参数传递给服务端,然后服务端onTransact处理数据,并在 repley 参数中把参数返回。客户端再通过 repley读取服务端返回的结果,再通过返回值返回给接口方法的调用者。

Bclient:

package com.cloud.test;

import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;

public class BClient {
 

 /**
  * Command-line entry point.
  * 
  * @param args
  *            The command-line arguments
  * @throws RemoteException
  */
 public static void main(String[] args) throws RemoteException {
  System.out.println("==========Client starts===========");
  IBinder binder = ServiceManager.getService("CloudService");
  ICloudManager manager = new CloudManagerProxy(binder);
  manager.print("Hello world");
  int result = manager.add(2, 3);
  System.out.println("manager.add(2, 3)=" + result);
 }
}

测试:

流程是这样的。

BClient -----> mian()---> getService--> new CloudManagerProxy(binder)-->print()与add()方法àremote发送数据给CloudManager--->

---- onTransact根据不同的方法请求,执行实际的方法,并在reply中返回值给TestClient.cpp。

注:onTransact(int code, Parcel data, Parcel reply, int flags)

· // code :是请求的ID号

· // data :客户端请求发送的参数

· // reply:服务器端返回的结果

· // flags:一些额外的标识,如FLAG_ONEWAY等,通常为0.

总结:通过这两个例子,大家可以很清晰的看到如何实现nativebinder service 与 framework binder service 。两个层“概念上类别关系是这样的。Java 层的IBinder 接口对应C++层的 BpInterface接口(里面的remote()返回的是一个IBinder指针),Java层的Binder 对应的BnInterface 实现 onTransact方法来响应客户端的请求。


FrameWork 层 访问native Binderservice

注:此例子摘抄于互联网(http://www.cloudchou.com/android/post-468.html

例子下载地址:(https://github.com/cloudchou/NativeBinderJavaClientDemo

Native service文件:

ICloudManager.h , ICloudManager.cpp TestServer.cppTestClient.cpp(这个文件我们将忽略,这个是nativebinder 的客户端)

framework client文件:

ICloudManager.java CloudManagerProxy.java FClient.java

文件详情:

服务端

ICloudManager.h

#ifndef ICLOUDMANAGER_H_H
#define ICLOUDMANAGER_H_H
#include <stdio.h>
#include <binder/IInterface.h>
#include <binder/Parcel.h>
#include <binder/IBinder.h>
#include <binder/Binder.h>
#include <binder/ProcessState.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
using namespace android;
namespace android
{
    class ICloudManager : public IInterface
    {
    public:
        DECLARE_META_INTERFACE(CloudManager); // declare macro
        virtual void test()=0;
        virtual void print(const char* str)=0;
        virtual int add(int a, int b)=0;
    };

    enum
    {
        TEST = IBinder::FIRST_CALL_TRANSACTION+1,
        PRINT = IBinder::FIRST_CALL_TRANSACTION+2,
        ADD = IBinder::FIRST_CALL_TRANSACTION+3,
    };

    class BpCloudManager: public BpInterface<ICloudManager> {
    public:
        BpCloudManager(const sp<IBinder>& impl);
     virtual void test();
     virtual void print(const char* str);
     virtual int add(int a, int b);
    };
}
#endif


binder service接口IcloudManager ,这里请参考上面 Binder C++ 框架层实现(nativeservice)例子

ICloudManager.cpp

#include "ICloudManager.h"
namespace android
{
    IMPLEMENT_META_INTERFACE(CloudManager, "com.cloud.test.ICloudManager");
}

ICloudManager接口的方法,这里请参考上面 Binder C++ 框架层实现(nativeservice)例子

TestServer.cpp

#include "ICloudManager.h"
namespace android
{
    class BnCloudManager : public BnInterface<ICloudManager>
    {
    public:
        virtual status_t
        onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0);
        virtual void   test();
        virtual void   print(const char* str);
        virtual int   add(int a, int b);
    };

    status_t
    BnCloudManager::onTransact(uint_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
        switch (code)
            {
        case TEST:
            {
                CHECK_INTERFACE(ICloudManager, data, reply);
                test();
                reply->writeInt32(0);
                return NO_ERROR;
            }
            break;
        case PRINT:
            {
                CHECK_INTERFACE(ICloudManager, data, reply);
                String16 str = data.readString16();
                String8 str8 = String8(str);
                print(str8.string());
                reply->writeInt32(0);
                return NO_ERROR;
            }
            break;
        case ADD:
            {
                CHECK_INTERFACE(ITest, data, reply);
                int a;
                int b;
                data.readInt32(&a);
                data.readInt32(&b);
                int c = add(a,b);
                reply->writeInt32(0);
                reply->writeInt32(c);
                return NO_ERROR;
            }
            break;
        default:
            break;
            }
        return NO_ERROR;
    }

    void
    BnCloudManager::test() {
        printf("Now server receive requset from client: [call test]\n");
    }

    void
    BnCloudManager::print(const char* str) {
        printf("Now server receive requset from client: [call print %s]\n", str);
    }

    int
    BnCloudManager::add(int a, int b) {
        printf("Now server receive requset from client: [call add %d %d]\n", a, b);
        return a + b;
    }

}
int
main() {
    sp<ProcessState> proc(ProcessState::self());
    sp<IServiceManager> sm = defaultServiceManager();
    sm->addService(String16("cloudservice"), new BnCloudManager());
    printf("Native binder server starts to work\n");
    ProcessState::self()->startThreadPool();
    IPCThreadState::self()->joinThreadPool();
    return 0;
}

实现服务端(TestServer.cpp) 这里请参考上面 Binder C++ 框架层实现(nativeservice)例子


框架层客户端

ICloudManager.java

package com.cloud.test;

import android.os.IInterface;
import android.os.RemoteException;

public interface ICloudManager extends IInterface {
 static final java.lang.String DESCRIPTOR = "com.cloud.test.ICloudManager";

 void test() throws RemoteException;

 void print(String str) throws RemoteException;

 int add(int a, int b) throws RemoteException;

 static final int TRANSACTION_test = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
 static final int TRANSACTION_print = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);
 static final int TRANSACTION_add = (android.os.IBinder.FIRST_CALL_TRANSACTION + 3);
}
定义接口类,这里请参考上面 Binder Java 框架层实现(framework service) 例子。 这个ICloudManager.java文件对应 ICloudManager.h 可以看到 都是定义服务方法 test(),print(),add()并且定义方法对应的常量 TEST ,PRINT,ADD. ICloudManager.java文件


对应ICloudManager.cpp 文件中的。


DESCRIPTOR :描述符号。用此描述符,标记服务。

CloudManagerProxy.java

package com.cloud.test;

import android.os.IBinder;
import android.os.RemoteException;

public class CloudManagerProxy implements ICloudManager {
 private android.os.IBinder mRemote;

 public CloudManagerProxy(android.os.IBinder remote) {
  mRemote = remote;
 }

 public java.lang.String getInterfaceDescriptor() {
  return DESCRIPTOR;
 }

 @Override
 public void print(String str) throws RemoteException {
  android.os.Parcel _data = android.os.Parcel.obtain();
  android.os.Parcel _reply = android.os.Parcel.obtain();
  try {
   _data.writeInterfaceToken(DESCRIPTOR);
   _data.writeString(str);
   mRemote.transact(TRANSACTION_print, _data, _reply, 0);
   _reply.readException();
  } finally {
   _reply.recycle();
   _data.recycle();
  }
 }

 @Override
 public int add(int a, int b) throws RemoteException {
  android.os.Parcel _data = android.os.Parcel.obtain();
  android.os.Parcel _reply = android.os.Parcel.obtain();
  int result = 0;
  try {
   _data.writeInterfaceToken(DESCRIPTOR);
   _data.writeInt(a);
   _data.writeInt(b);
   mRemote.transact(TRANSACTION_add, _data, _reply, 0);
   _reply.readException();
   result = _reply.readInt();
  } finally {
   _reply.recycle();
   _data.recycle();
  }
  return result;
 }

 @Override
 public IBinder asBinder() {
  return mRemote;
 }

 @Override
 public void test() throws RemoteException {
  android.os.Parcel _data = android.os.Parcel.obtain();
  android.os.Parcel _reply = android.os.Parcel.obtain(); 
  try {
   _data.writeInterfaceToken(DESCRIPTOR); 
   mRemote.transact(TRANSACTION_test, _data, _reply, 0);
   _reply.readException(); 
  } finally {
   _reply.recycle();
   _data.recycle();
  }

 }

}
定义接口代理类,这里通过 IBinder 的实例remote 与服务端通讯。这里请参考上面 Binder Java 框架层实现(framework service) 例子



FClient.java

package com.cloud.test;

import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;

public class FClient { 

 /**
  * Command-line entry point.
  * 
  * @param args
  *            The command-line arguments
  * @throws RemoteException
  */
 public static void main(String[] args) throws RemoteException {
  System.out.println("==========Client starts===========");
  IBinder binder = ServiceManager.getService("cloudservice");
  ICloudManager manager = new CloudManagerProxy(binder);
  System.out.println("========== client call server  test ===========");
  manager.test();
  System.out.println("========== client call server print ===========");
  manager.print("Hello world");
  System.out.println("========== client call server add ===========");
  int result = manager.add(2, 3);
  System.out.println("manager.add(2, 3)=" + result);
 }
}

客户端调用:这里请参考上面 Binder Java 框架层实现(framework service) 例子

测试:


应用层常用的Aidl 与 framework binder service 对比

实现应用层的话,我们一般是写一个 aidl文件 ,比如ICloudManager.aidl ,用使用eclipse开发时,它会被自动编译成ICloudManager.java,放在gen目录下

注:此例子摘抄于互联网(http://www.cloudchou.com/android/post-458.html

例子下载地址:(http://developer.android.com/guide/components/aidl.html

源代码结构如下所示:



AndroidManifeset.xml:声明用到的activity,service组件

ICloudManager.aidl: binder service接口

CloudService: 创建binder service,并返回给客户端

TestAc: 测试binder service的客户端

ICloudManager.aidl 文件

package com.cloud.test;
interface ICloudManager{
 void print(String str) ;
 int add(int a, int b);
}

CloudService.java

package com.cloud.test;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.Process;
import android.os.RemoteException;
import android.util.Log;


public class CloudService extends Service {
    private final static String TAG = CloudService.class.getSimpleName();

    class CloudMananger extends ICloudManager.Stub {

        @Override
        public void print(String str) throws RemoteException {
            Log.d(TAG, "[ThreadId " + Thread.currentThread().getId() + "] [ProcessId" + Process.myPid()
                    + "]CloudService receive client print msg request: " + str);
        }

        @Override
        public int add(int a, int b) throws RemoteException {
            Log.d(TAG, "[ThreadId " + Thread.currentThread().getId() + "] [ProcessId" + Process.myPid()
                    + "[CloudService receive client add request : ");
            return a + b;
        }
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(TAG, "[ThreadId " + Thread.currentThread().getId() + "] [ProcessId" + Process.myPid() + "]  onCreate");
    }

    private CloudMananger manager = new CloudMananger();

    @Override
    public IBinder onBind(Intent intent) {
        Log.d(TAG, "[ThreadId " + Thread.currentThread().getId() + "] [ProcessId" + Process.myPid() + "]  onBind");
        return manager;
    }

}

实现Service,覆盖onBind方法,返回binder service实体类对象

TestAc

package com.cloud.test;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Process;
import android.os.RemoteException;
import android.util.Log;
import android.view.View;


public class TestAc extends Activity {
    private static final String TAG = TestAc.class.getSimpleName();
    private ICloudManager manager = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        Log.d(TAG, "[ThreadId " + Thread.currentThread().getId() + "] [ProcessId" + Process.myPid() + "]  onCreate");
        findViewById(R.id.btn_print).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    Log.d(TAG, "=========== Client call CloudService print function");
                    manager.print("Hello world");
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        });
        findViewById(R.id.btn_add).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    Log.d(TAG, "======Client call CloudService add function");
                    int a = manager.add(3, 2);
                    Log.d(TAG, "======Client add function reuslt : " + a);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        });
    }

    @Override
    protected void onStart() {
        super.onStart();
        Intent intent = new Intent(this, CloudService.class);
        bindService(intent, connection, BIND_AUTO_CREATE);
    }

    @Override
    protected void onStop() {
        super.onStop();
        unbindService(connection);
    }

    private ServiceConnection connection = new ServiceConnection() {

        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.d(TAG, "[ThreadId " + Thread.currentThread().getId() + "] [ProcessId" + Process.myPid()
                    + "]  onServiceDisconnected");
        }

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.d(TAG, "[ThreadId " + Thread.currentThread().getId() + "] [ProcessId" + Process.myPid()
                    + "]  onServiceConnected");
            manager = ICloudManager.Stub.asInterface(service);
            findViewById(R.id.btn_print).setEnabled(true);
            findViewById(R.id.btn_add).setEnabled(true);
        }
    };

    @Override
    protected void onDestroy() {

        // TODO Auto-generated method stub
        super.onDestroy();

    }

}

对应的界面:

测试:


过程分析:Activity-->oncreate()-->onstart()-->CloudService-->onCreate()-->onBind()-->ServiceConnection-->onServiceConnected()

这样级连接到服务了。然后点击Test Print 按钮 ,再点击Test ADD 按钮。

下面附上ICloudManager.aidl自动生成的ICloudManager.java 代码:

package com.cloud.test;

public interface ICloudManager extends android.os.IInterface {
 /** Local-side IPC implementation stub class. */
 public static abstract class Stub extends android.os.Binder implements
   com.cloud.test.ICloudManager {
  private static final java.lang.String DESCRIPTOR = "com.cloud.test.ICloudManager";

  /** Construct the stub at attach it to the interface. */
  public Stub() {
   this.attachInterface(this, DESCRIPTOR);
  }

  /**
   * Cast an IBinder object into an com.cloud.test.ICloudManager
   * interface, generating a proxy if needed.
   */
  public static com.cloud.test.ICloudManager asInterface(
    android.os.IBinder obj) {
   if ((obj == null)) {
    return null;
   }
   android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
   if (((iin != null) && (iin instanceof com.cloud.test.ICloudManager))) {
    return ((com.cloud.test.ICloudManager) iin);
   }
   return new com.cloud.test.ICloudManager.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_print: {
    data.enforceInterface(DESCRIPTOR);
    java.lang.String _arg0;
    _arg0 = data.readString();
    this.print(_arg0);
    reply.writeNoException();
    return true;
   }
   case TRANSACTION_add: {
    data.enforceInterface(DESCRIPTOR);
    int _arg0;
    _arg0 = data.readInt();
    int _arg1;
    _arg1 = data.readInt();
    int _result = this.add(_arg0, _arg1);
    reply.writeNoException();
    reply.writeInt(_result);
    return true;
   }
   }
   return super.onTransact(code, data, reply, flags);
  }

  private static class Proxy implements com.cloud.test.ICloudManager {
   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 print(java.lang.String str)
     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(str);
     mRemote.transact(Stub.TRANSACTION_print, _data, _reply, 0);
     _reply.readException();
    } finally {
     _reply.recycle();
     _data.recycle();
    }
   }

   @Override
   public int add(int a, int b) 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);
     _data.writeInt(a);
     _data.writeInt(b);
     mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0);
     _reply.readException();
     _result = _reply.readInt();
    } finally {
     _reply.recycle();
     _data.recycle();
    }
    return _result;
   }
  }

  static final int TRANSACTION_print = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
  static final int TRANSACTION_add = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
 }

 public void print(java.lang.String str) throws android.os.RemoteException;

 public int add(int a, int b) throws android.os.RemoteException;
}

通过此文件,可对比Binder Java 框架层实现(framework service) 例子,通过对比,可以发现跟Framework binder service 差不多,个人感觉就是把复杂模块化的部分用工具代替了

总结:android通过 Binder来实现IPC通信的。native service 与 framework service 都是相同的原理。

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:7942463
帖子:1588486
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP