以Hello为例说明设计的几个概念关系:
【注意】实际不只是定义一个接口类,还继承该接口并添加虚接口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
{
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);
};
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;
}
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 */
int main(void)
{
/* 打开biner并mmap进内存 */
sp proc(ProcessState::self());
/* 获得 BnServiceManager */
sp sm = defaultServiceManager();
/* 添加服务 */
sm->addService(String16("hello"), new BnHelloService());
/* 循环体,不断获取服务并处理 */
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
return 0;
}
int main(int argc, char **argv)
{
int cnt;
/* 打开biner并mmap进内存 */
sp proc(ProcessState::self());
/* 获得 BpServiceManager */
sp sm = defaultServiceManager();
/* 获得 根据hello名字 获取服务 */
sp binder =
sm->getService(String16("hello"));
if (binder == 0)
{
ALOGI("can't get hello service\n");
return -1;
}
/* Service肯定是 BpHelloService 指针?? * interface_cast(binder) -> IHelloService::asInterface(binder);(IMPLEMENT_META_INTERFACE宏中定义) *【结果:在下面代码中分配一个BpHelloService实例指针】 */
sp service =
interface_cast(binder);
/* 调用 BpHelloService提供的函数 */
service->sayhello();
ALOGI("client call sayhello");
return 0;
}
BpServiceManager <- HelloClient
|
\ /
BnServiceManager -> HelloServer
frameworks/base/Android.mk 添加一行
core/java/android/os/IHelloService.aidl\
代码:
/** {@hide} */
interface IHelloService
{
void sayhello();
int sayhello_to(String name);
}
【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;
}
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;
}
}
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){}
}
}
}
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);
}
}
}
}