'); }
'); }
############
//myserver0.c
//myclient0.c
1 #include <stdio.h>
//모든 Proxy안에는 바인더를 인자로 받아서 객체를 만드는 static멤버를 만들기로 약속하자.
static sp<BpCalc> asInterface(const sp<IBinder>& binder)
{
return new BpCalc(binder);
}
};
int main()
//바인더를 객체로 변경하는 코드입니다.
//숙제는 : 바인더로부터 Proxy객체를 만드는 캐스팅
sp<BpCalc> pCalc = my_interface_cast<BpCalc>(svc);
//윗 코드 binder를 proxy로 캐스팅하는 것처럼 보이지만 실제로는 객체를 생성한 것임
//myserver0.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <errno.h>
4 #include <unistd.h>
5 #include <fcntl.h>
6 #include <sys/mman.h>
7 #include "binder.h"
8
9 // myserver0.c
10 //
11 struct binder_state
12 {
13 int fd;
14 void* mapped;
15 unsigned mapsize;
16 };
17
18 unsigned token;
19
20 //do something to do because It is server
21 int Add(int a, int b)
22 {
23 printf("Add(%d, %d)\n", a, b);
24 return a + b;
25 }
26
27 int my_handler(struct binder_state* bs,
28 struct binder_txn* txn,
29 struct binder_io* msg,
30 struct binder_io* reply)
31 {
32 int ret, a, b;
33 switch(txn->code)
34 {
35 case 1:
36 a = bio_get_uint32(msg);
37 b = bio_get_uint32(msg);
38 ret = Add(a, b);
39 bio_put_uint32(reply, ret);
40 return 0;
41 }
42 return 0;
43 }
44
45
46 int main()
47 {
48 int mapsize = 1024 * 128;
49 struct binder_state* bs;
50
51 unsigned int status;
52 char iodata[512];
53 struct binder_io msg;
54 struct binder_io reply;
55
56 // --------------------------------------------------------------
57 // 1. binder driver open
58 //bs = malloc(sizeof(struct binder_state));
59 //bs->fd = open("/dev/binder", O_RDWR);
60 //bs->mapsize = mapsize;
61 //bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);
62 bs = binder_open(mapsize);
63
64
65 // --------------------------------------------------------------
66 // 2. add service
67 bio_init(&msg, iodata, sizeof(iodata), 4);
68
69 //
70 bio_put_string16_x(&msg, SVC_MGR_NAME);
71 bio_put_string16_x(&msg, "myserver0");
72 bio_put_obj(&msg, &token);
73
74 if(binder_call(bs, &msg, &reply, BINDER_SERVICE_MANAGER, SVC_MGR_ADD_SERVICE))
75 {
76 printf("error register service\n");
77 return -1;
78 }
79 status = bio_get_uint32(&reply);
80
81 binder_done(bs, &msg, &reply);
82 //3. binder loop
83 binder_loop(bs, my_handler);
84
85
86
87
88 return 0;
89 }
//myclient0.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <errno.h>
4 #include <unistd.h>
5 #include <fcntl.h>
6 #include <sys/mman.h>
7 #include "binder.h"
8
9 int main(int argc, char** argv)
10 {
11 void* ptr; //var that get service no on server
12 struct binder_state* bs;
13 struct binder_io msg, reply;
14 char iodata[512/4];
15 int ret;
16
17 //1. driver open and make receive ber
18 bs = binder_open(128*1024); // 128k receive buffer
19
20 //2. make packet that will send service manager
21 // work on binder_io but eventually send to driver as binder_write_read
22 bio_init(&msg, iodata, sizeof(iodata), 4);
23 bio_put_string16_x(&msg, SVC_MGR_NAME); // "android.os.IServiceManager"
24 bio_put_string16_x(&msg, argv[1]);
25
26 if(binder_call(bs, &msg, &reply, BINDER_SERVICE_MANAGER, SVC_MGR_CHECK_SERVICE))
27 {
28 printf("can't find service : %s\n", argv[1]);
29 return -1;
30 }
31 ptr = bio_get_ref(&reply);
32
33 printf("find service handle : %d\n", ptr);
34
35 //3. request add function
36 memset(&msg, 0, sizeof(msg));
37 memset(&iodata, 0, sizeof(iodata));
38 memset(&reply, 0, sizeof(reply));
39
40 bio_init(&msg, iodata, sizeof(iodata), 4);
41 bio_put_uint32(&msg, 3);
42 bio_put_uint32(&msg, 4);
43
44 if(binder_call(bs, &msg, &reply, ptr, 1))
45 {
46 printf("can't request : %s\n", argv[1]);
47 return -1;
48 }
49 ret = bio_get_uint32(&reply);
50 printf("result = %d\n", ret);
51
52 //-----------------------------------------
53 binder_done(bs, &msg, &reply);
54
55 return 0;
56 }
57
58
==============================================================================================================
cpp로
//myclient1.cpp
==============================================================
2번째꺼는 transact로 Add, Sub를 호출한다. Add, Sub를 호출하는 것처럼 보이지 않고
client를 만드는 사람은 SUB, ADD라는 코드를 이용해서 실행하는 모양새임
그래서 3번재꺼는 Add, Sub라는 걸 마치 server에서 사용하는 것처럼 할것임
이걸 프락시라고 말하는 것임
다른 서버의 함수를 호출하도록 만듬 Remote Process Call(RPC)를 짠 것임
//myclient2.cpp
==============================================================================================================
cpp로
//myserver1.cpp
서버의 기본 흐름
1. 반드시 BBinder 클래스의 자식클래스로 만들어야 합니다.
2.
1. 반드시 BBinder 클래스의 자식클래스로 만들어야 합니다.
2.
3 #include <sys/types.h>
4 #include <unistd.h>
5 #include <grp.h>
6 #include <binder/IPCThreadState.h>
7 #include <binder/ProcessState.h>
8 #include <binder/IServiceManager.h>
9 #include <utils/Log.h>
10 using namespace android;
11
12 enum {
13 ADD = IBinder::FIRST_CALL_TRANSACTION,
14 SUB,
15 };
16
12 class Calc : public BBinder
13 {
14 public:
15 int Add(int a, int b)
16 {
17 printf("Calc.Add(%d, %d)\n", a, b);
18 return a + b;
19 }
15 int Sub(int a, int b)
16 {
17 printf("Calc.Sub(%d, %d)\n", a, b);
18 return a - b;
19 }
21 virtual status_t onTransact(uint32_t code, // service code
22 const Parcel& data, // data that client sent
23 Parcel* reply, // place that will send return value
24 uint32_t flags = 0)
25 {
26 int ret;
27 int a = data.readInt32();
28 int b = data.readInt32();
29
30 switch(code)
31 {
32 case ADD: ret = Add(a, b);
33 reply->writeInt32(ret);
34 break;
32 case SUB: ret = Sub(a, b);
33 reply->writeInt32(ret);
34 break;
35 }
36 return 0;
37 }
38 };
39
40 int main(int argc, char** argv)
41 {
42 sp<ProcessState> proc(ProcessState::self()); // code that we learn yesterday.
43 sp<IServiceManager> sm = defaultServiceManager();
44 sm->addService(String16("myserver1"), new Calc); //Calc 객체가 token대신 들어가게 됩니다.
45 IPCThreadState::self()->joinThreadPool(); // 이 순간 enter the loop
46
47 return 0;
48 }
49
//myclient1.cpp
1 #include <sys/types.h>
2 #include <unistd.h>
3 #include <grp.h>
4 #include <binder/IPCThreadState.h>
5 #include <binder/ProcessState.h>
6 #include <binder/IServiceManager.h>
7 #include <utils/Log.h>
8
9 using namespace android;
12 enum {
13 ADD = IBinder::FIRST_CALL_TRANSACTION,
14 SUB,
15 };
11 int main(int argc, char** argv)
12 {
13 sp<ProcessState> proc(ProcessState::self()); //드라이버 오픈 // 수신버퍼 생성 // IPCThreadState와는 Friend관계
// 서비스 매니저를 래핑하는 클래스가 IServiceManager입니다.
14 sp<IServiceManager> sm = defaultServiceManager(); //이순간 서비스 매니저를 만들고..
// myserver1을 핸들을 알아냅니다.
// 핸들(번호)를 알아낸 후 해당 번호를 관리하는 BpBinder객체를 만들어 줍니다.
// BpBinder는 내부적으로 transact()함수가 있는데
// 이 함수가 IPCThreadState를 사용해서 ioctl()함수로 드라이버와 통신합니다.
16 sp<IBinder> svc = sm->getService(String16("myserver1")); // 결국 내부적으로 뭘할까요?
17
18 // now call the server func
19 Parcel data, reply;
20
21 data.writeInt32(3);
22 data.writeInt32(5);
23 svc->transact(SUB, data, &reply);
24 printf("result : %d\n", reply.readInt32());
25 return 0;
26
2번째꺼는 transact로 Add, Sub를 호출한다. Add, Sub를 호출하는 것처럼 보이지 않고
client를 만드는 사람은 SUB, ADD라는 코드를 이용해서 실행하는 모양새임
그래서 3번재꺼는 Add, Sub라는 걸 마치 server에서 사용하는 것처럼 할것임
이걸 프락시라고 말하는 것임
다른 서버의 함수를 호출하도록 만듬 Remote Process Call(RPC)를 짠 것임
//myclient2.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,
};
class BpCalc : public RefBase
{
sp<IBinder> mRemote;
public:
BpCalc(sp<IBinder>& p) : mRemote(p) {}
sp<IBinder> remote() const {return mRemote; }
int Add(int a, int b) {
Parcel data, reply;
data.writeInt32(a);
data.writeInt32(b);
int ret = mRemote->transact(ADD, data, &reply);
return reply.readInt32();
}
int Sub(int a, int b) {
Parcel data, reply;
data.writeInt32(a);
data.writeInt32(b);
int ret = mRemote->transact(SUB, data, &reply);
return reply.readInt32();
}
//모든 Proxy안에는 바인더를 인자로 받아서 객체를 만드는 static멤버를 만들기로 약속하자.
static sp<BpCalc> asInterface(const sp<IBinder>& binder)
{
return new BpCalc(binder);
}
};
template<typename T> sp<T> my_interface_cast(const sp<IBinder>& binder)
{
return T::asInterface(binder); //binder를 가지고 proxy를 얻을 수 있음
//return new T(binder); // If Constructor is private? No way~
}
int main()
{
sp<ProcessState> proc( ProcessState::self());
sp<IServiceManager> sm = defaultServiceManager();
sp<IBinder> svc = sm->getService(String16("myserver1"));
//바인더를 객체로 변경하는 코드입니다.
//sp<BpCalc> pCalc = new BpCalc(svc);
//숙제는 : 바인더로부터 Proxy객체를 만드는 캐스팅
sp<BpCalc> pCalc = my_interface_cast<BpCalc>(svc);
//윗 코드 binder를 proxy로 캐스팅하는 것처럼 보이지만 실제로는 객체를 생성한 것임
int ret = pCalc->Add(1,2);
printf("result : %d\n", ret);
return 0;
}
'Tech & IT > 프로그래밍' 카테고리의 다른 글
Binder 2 (Android Framework) (0) | 2012.03.21 |
---|---|
const 상수 함수 (함수가 멤버변수를 바꾸는게 없으면 무조건 꼭 const를 붙이자) (0) | 2012.03.21 |
vi잘쓰기 (ctags활용) (0) | 2012.03.20 |
C++ Template 활용(Android쪽 코드) (0) | 2012.03.19 |
Fast C++ Delegate 한번 읽어보자 (0) | 2011.02.22 |