Tech & IT/프로그래밍

Binder 2 (Android Framework)

해피콧 2012. 3. 21. 11:10
'); }
'); }
// 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;
}