'); }
'); }
// froyo/external/여러분폴더/0321/binder3폴더를 만들고 myclient3.cpp로 만드세요
#include <sys/types.h>
#include <unistd.h>
#include <grp.h>
#include <binder/IPCThreadState.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
#include <utils/Log.h>
using namespace android;
enum { ADD = IBinder::FIRST_CALL_TRANSACTION,
SUB
};
// 모든 Proxy를 만들때 공통으로 사용되는 부분은 부모로 뽑아서 사용하자.
class myBpRefBase : public virtual RefBase
{
sp<IBinder> mRemote;
public:
myBpRefBase( const sp<IBinder>& binder ) : mRemote(binder) {}
sp<IBinder> remote() const { return mRemote; }
};
// 이제 서버의 진짜 calc나 클라이언트의 Proxy를 만들때 공통으로 사용할 인터페이스를
// 먼저 설계하자.
class ICalc : public virtual RefBase
{
public:
virtual int Add(int a, int b ) = 0;
virtual int Sub(int a, int b ) = 0;
virtual IBinder* asBinder() const = 0;
static sp<ICalc> asInterface( const sp<IBinder>& binder ); // static이므로 순수 가상함수일수는 없다.
// 그냥 선언만 하자.!!
};
// 이제 모든 Proxy는 자신의 인터페이스와 BpRefBase에서 파생되어야 한다.
class BpCalc : public ICalc, public myBpRefBase
{
public:
BpCalc( const sp<IBinder>& binder) : myBpRefBase( binder ) {}
int Add( int a, int b)
{
Parcel data, reply;
data.writeInt32(a);
data.writeInt32(b);
remote()->transact( ADD, data, &reply); // source ~/froyo/build/envsetup.sh
return reply.readInt32();
}
int Sub( int a, int b)
{
Parcel data, reply;
data.writeInt32(a);
data.writeInt32(b);
remote()->transact( SUB, data, &reply);
return reply.readInt32();
}
// Android.mk 파일 만드세요.
// 객체를 바인더로 변경하는 함수 // 빌드하세요..
IBinder* asBinder() const // myserver1 띄우고 실행해보세요
{
return remote().get();
}
};
// 바인더를 객체로 변경하는 함수
// 이제 이함수는 ICalc의 멤버 함수이다.
sp<ICalc> ICalc::asInterface( const sp<IBinder>& binder )
{
return new BpCalc( binder);
}
int main(int argc, char** argv)
{
sp<ProcessState> proc(ProcessState::self());
sp<IServiceManager> sm = defaultServiceManager();
sp<IBinder> svc = sm->getService(String16("myserver1"));
sp<ICalc> p = ICalc::asInterface(svc);
return 0;
}
// C : 결국 서비스번호(핸들)을 얻게 되고 binder_call()함수 사용=> 결국 ioctl()함수로
// 드라이버를 통해서 서버와 통신.
// C++ : sm->getService()하는 순간 BpBinder라는 객체가 생성되고 포인터를 리턴 받는다.
// 바인더->transact()함수를 사용해서 서버와 통신
// Proxy : Calc를 설계하고 Add(), Sub()함수를 제공한후에 바인더는 Calc의 내부로 감춘다.
//C라면 : 결국 서비스 번호(핸들)을 얻게 되고 binder_call()함수 사용 => 결국 ioctl()함수로 드라이버를 통해서 서버와 통신.
// C++은? : sm->getServeice()하는 순간 BpBinder라는 객체가 생성되고 포인터를 리턴 받는다.
바인더->transact()함수를 사용해서 서버와 통신
바인더를 바로 쓰려면 그 번호 다 알아서 써야 하고 불편(좋은 방법은 아님)
최종적으로 가져다 쓰는 사람입장에서 쉽고 실수하지 않도록 member함수처럼 만들어주면 좋겠다-> proxy
실제 그 멤버는 실제 transaction 을 사용( information 은닉, interface노출)
// proxy는? : Calc를 설계하고 Add(), Sub()함수를 제공한 후에 바인더는 Calc의 내부로 감춘다.
#include <sys/types.h>
#include <unistd.h>
#include <grp.h>
#include <binder/IPCThreadState.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
#include <utils/Log.h>
using namespace android;
// Interface //////////////////////////////////////
// management binder
class myBpRefBase : public virtual RefBase
{
sp<IBinder> mRemote;
public:
myBpRefBase( const sp<IBinder>& p) : mRemote(p) {}
sp<IBinder> remote() const { return mRemote; }
};
//parents of all interface
class myIInterface : public virtual RefBase
{
public:
IBinder* asBinder() { return OnAsBinder(); }
protected:
virtual IBinder* OnAsBinder() = 0;
};
// interface of all user must have as Interface()
#define MY_DECLARE_META_INTERFACE(INTERFACE) \
static sp<I##INTERFACE> asInterface(const sp<IBinder>& binder);
#define MY_IMPLEMENT_META_INTERFACE(INTERFACE, description) \
sp<I##INTERFACE> I##INTERFACE::asInterface(const sp<IBinder>& binder)\
{ \
return new Bp##INTERFACE(binder); \
}
//1. we do not want implement on OnAsBinder() every BpClass
//2. multiple inheritance to mono inheritance
template<typename INTERFACE>
class myBpInterface : public INTERFACE, public myBpRefBase
{
public:
myBpInterface(const sp<IBinder>& binder) : myBpRefBase(binder) {}
protected:
virtual IBinder* OnAsBinder() {return remote().get(); }
};
/////////////////////////////////////////////////
enum {
ADD = IBinder::FIRST_CALL_TRANSACTION,
SUB
};
class ICalc: public myIInterface
{
public:
virtual int Add(int a, int b) = 0;
virtual int Sub(int a, int ) = 0;
MY_DECLARE_META_INTERFACE(Calc)
//static sp<ICalc> asInterface(const sp<IBinder>& binder);
};
class BpCalc : public myBpInterface<ICalc>
{
public:
virtual int Add(int a, int b) {
Parcel data, reply;
data.writeInt32(a);
data.writeInt32(b);
remote()->transact( ADD, data, &reply); // source ~/froyo/build/envsetup.sh
return reply.readInt32();
}
virtual int Sub(int a, int b) {
Parcel data, reply;
data.writeInt32(a);
data.writeInt32(b);
remote()->transact( SUB, data, &reply); // source ~/froyo/build/envsetup.sh
return reply.readInt32();
}
//protected:
// virtual IBinder* OnAsBinder() {return remote().get(); }
};
MY_IMPLEMENT_META_INTERFACE(Calc, "calc.com")
//sp<ICalc> ICalc::asInterface( const sp<IBinder>& binder )
//{
// return new BpCalc( binder);
//}
int main(int argc, char** argv)
{
return 0;
}
'Tech & IT > 프로그래밍' 카테고리의 다른 글
Calling Convention정확히 알아야 함(어셈으로 살펴보는 함수 call의 원리) (0) | 2012.03.22 |
---|---|
Binder5 (Android Framework) (0) | 2012.03.21 |
const 상수 함수 (함수가 멤버변수를 바꾸는게 없으면 무조건 꼭 const를 붙이자) (0) | 2012.03.21 |
Android Franwork Binder(Server, Client) c부터 cpp까지 (0) | 2012.03.20 |
vi잘쓰기 (ctags활용) (0) | 2012.03.20 |