Android Binder通信学习。
以Hello为例说明设计的几个概念关系:
IhelloService.h : 提供给应用程序使用的类接口,注意是说明服务能够提供的哪些操作接口。
【注意】实际不只是定义一个接口类,还继承该接口并添加虚接口onTransact后定义了一个抽象类BnHelloService
class IHelloService: public IInterface
{
public:
DECLARE_META_INTERFACE(HelloService); /* 此宏声明了接口IHelloService::getInterfaceDescriptor 和 IHelloService::asInterface(这个接口可以生成一个Bp实例) */
virtual void sayhello(void) = 0;
virtual int sayhello_to(const char *name) = 0;
};
class BnHelloService: public BnInterface<IHelloService>
{
public:
virtual status_t onTransact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0);
virtual void sayhello(void);
virtual int sayhello_to(const char *name);
};
BnHelloService.cpp : 为了之后可以用BnHelloService实例化对象,需要对BnHelloService完成接口中定义的虚函数.【这个是实际去干活的服务,’别人‘只是给他发需求】
status_t BnHelloService::onTransact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags)
{
switch (code) {
case HELLO_SVR_CMD_SAYHELLO:
sayhello();
break;
case HELLO_SVR_CMD_SAYHELLO_TO:
sayhello_to(name8.string());
break;
}
return NO_ERROR;
}
void BnHelloService::sayhello(void)
{
static int cnt = 0;
ALOGI("say hello : %d\n", ++cnt);
}
int BnHelloService::sayhello_to(const char *name)
{
static int cnt = 0;
ALOGI("say hello to %s : %d\n", name, ++cnt);
return cnt;
}
BpHelloService.cpp : 继承抽象的接口类,并去实现虚函数,这样才能实例化对象,成为给服务发需求的‘别人’。【BpXXService负责给服务发需求,这么说服务并不是谁叫我干活就干,我只听Bp的】
class BpHelloService: public BpInterface<IHelloService>
{
public:
BpHelloService(const sp<IBinder>& impl)
: BpInterface<IHelloService>(impl)
{
}
void sayhello(void)
{
Parcel data, reply;
data.writeInt32(0);
data.writeString16(String16("IHelloService"));
remote()->transact(HELLO_SVR_CMD_SAYHELLO, data, &reply);
}
int sayhello_to(const char *name)
{
Parcel data, reply;
int exception;
data.writeInt32(0);
data.writeString16(String16("IHelloService"));
data.writeString16(String16(name));
remote()->transact(HELLO_SVR_CMD_SAYHELLO_TO, data, &reply);
exception = reply.readInt32();
if (exception)
return -1;
else
return reply.readInt32();
}
};
IMPLEMENT_META_INTERFACE(HelloService, "android.media.IHelloService");/* 此宏具体实现了接口IHelloService::getInterfaceDescriptor 和 IHelloService::asInterface */
HelloServer.c : 实现的最底层接收请求的服务器,提供怎样的服务呢?只提供这个里面提供的服务BnHelloService!
int main(void)
{
/* 打开biner并mmap进内存 */
sp<ProcessState> proc(ProcessState::self());
/* 获得 BnServiceManager */
sp<IServiceManager> sm = defaultServiceManager();
/* 添加服务 */
sm->addService(String16("hello"), new BnHelloService());
/* 循环体,不断获取服务并处理 */
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
return 0;
}
HelloClient.c : 最底层发请求的客户端,这才是满肚子需求的底层人民啊。
int main(int argc, char **argv)
{
int cnt;
/* 打开biner并mmap进内存 */
sp<ProcessState> proc(ProcessState::self());
/* 获得 BpServiceManager */
sp<IServiceManager> sm = defaultServiceManager();
/* 获得 根据hello名字 获取服务 */
sp<IBinder> binder =
sm->getService(String16("hello"));
if (binder == 0)
{
ALOGI("can't get hello service\n");
return -1;
}
/* Service肯定是 BpHelloService 指针??
* interface_cast<IHelloService>(binder) -> IHelloService::asInterface(binder);(IMPLEMENT_META_INTERFACE宏中定义)
*【结果:在下面代码中分配一个BpHelloService实例指针】
*/
sp<IHelloService> service =
interface_cast<IHelloService>(binder);
/* 调用 BpHelloService提供的函数 */
service->sayhello();
ALOGI("client call sayhello");
return 0;
}
好了,下面来总结下:背景是世界的阶级斗争依然是如此的激烈,因此不管干啥我们都分等级,Binder服务也是如此,有需求只向上级反映,由上级出处理:
BpServiceManager <- HelloClient
|
\ /
BnServiceManager -> HelloServer
Binder的java实现。
IHelloService.aidl : Android接口描述文件,只要用户定义自己需要提供的接口,然后放到frameworks/base/core/java/android/os下,并修改
frameworks/base/Android.mk 添加一行
core/java/android/os/IHelloService.aidl\
代码:
/** {@hide} */
interface IHelloService
{
void sayhello();
int sayhello_to(String name);
}
IHelloService.java : 由aidl文件编译出来的接口类,里面除了用户自定义的接口外还包含一个 stub 的内部类。
【stub】:为屏蔽客户调用远程主机上的对象,必须提供某种方式来模拟本地对象,这种本地对象称为存根(stub),根负责接收本地方法调用,并将它们委派给各自的具体实现对象
代码只保留框架:
public interface IHelloService extends android.os.IInterface
{
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements IHelloService
{
private static final java.lang.String DESCRIPTOR = "IHelloService";
/** Construct the stub at attach it to the interface. */
public Stub()
{
this.attachInterface(this, DESCRIPTOR);
}
/**
* Cast an IBinder object into an IHelloService interface,
* generating a proxy if needed.
*/
public static IHelloService asInterface(android.os.IBinder obj)
{
return new IGoodbyeService.Stub.Proxy(obj); /* 客户端获取服务后,需要转化为proxy才能进行最终的接口调用 */
}
@Override public android.os.IBinder asBinder()
{
return this;
}
/* 实际处理需求的服务端,类似于C++ binder中的BnXxService功能,用于接收需求并实际出执行需求任务 */
@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_saygoodbye:
{
data.enforceInterface(DESCRIPTOR);
this.saygoodbye(); /* 调用本stub中定义的接口函数 */
reply.writeNoException();
return true;
}
case TRANSACTION_saygoodbye_to:
{
data.enforceInterface(DESCRIPTOR);
java.lang.String _arg0;
_arg0 = data.readString();
int _result = this.saygoodbye_to(_arg0); /* 调用本stub中定义的接口函数 */
reply.writeNoException();
reply.writeInt(_result);
return true;
}
}
}
private static class Proxy implements IGoodbyeService /* 代理类,类似于C++ binder中的BpXxService,用于接收需求并封装数据发生需求给服务端 */
{
mRemote.transact(Stub.TRANSACTION_saygoodbye_to, _data, _reply, 0);
}
}
public void sayhello() throws android.os.RemoteException;
public int sayhello_to(java.lang.String name) throws android.os.RemoteException;
}
Helloservice.java : 服务器代码,非常简单,继承IHelloService.Stub的接口,并实现最终干活的代码。
public class HelloService extends IHelloService.Stub {
private static final String TAG = "HelloService";
private int cnt1 = 0;
private int cnt2 = 0;
public void sayhello() throws android.os.RemoteException {
cnt1++;
Slog.i(TAG, "sayhello : cnt = "+cnt1);
}
public int sayhello_to(java.lang.String name) throws android.os.RemoteException {
cnt2++;
Slog.i(TAG, "sayhello_to "+name+" : cnt = "+cnt2);
return cnt2;
}
}
TestServer.java : 用户这边提供服务的代码,目的就是注册一个服务
public class TestServer {
private static final String TAG = "TestServer";
public static void main(String args[])
{
/* add Service */
Slog.i(TAG, "add hello service");
ServiceManager.addService("hello", new HelloService()); /* 此处添加负责服务器任务的类 */
while (true)
{
try {
Thread.sleep(100);
} catch (Exception e){}
}
}
}
TestClient.java : 最底层发需求的用户代码。
public class TestClient {
private static final String TAG = "TestClient";
public static void main(String args[])
{
/* 1. getService */
IBinder binder = ServiceManager.getService("hello");
if (binder == null)
{
System.out.println("can not get hello service");
Slog.i(TAG, "can not get hello service");
return;
}
IHelloService svr = IHelloService.Stub.asInterface(binder); /* 得到接口的代理 */
if (args.length == 1)
{
try {
svr.sayhello();
System.out.println("call sayhello");
Slog.i(TAG, "call sayhello");
} catch (Exception e) {}
}
else
{
try {
int cnt = svr.sayhello_to(args[1]);
System.out.println("call sayhello_to "+args[1]+" : cnt = "+cnt);
Slog.i(TAG, "call sayhello_to "+args[1]+" : cnt = "+cnt);
} catch (Exception e) {
System.out.println("call sayhello_to , err :"+e);
Slog.i(TAG, "call sayhello_to , err : "+e);
}
}
}
}