FazBrowse GitHub Viewer
|
Trending
|
URL:
|
Home
Tools:
[Download Repo ZIP]
[View Raw Code]
[Original HTTPS Page]
BinderDemo/binder.cpp at master · gburca/BinderDemo · GitHub
gburca
/
BinderDemo
Public
Notifications
You must be signed in to change notification settings
Fork
124
Star
313
Code
Issues
5
Pull requests
0
Actions
Projects
Wiki
Security and quality
0
Insights
Additional navigation options
Code
Issues
Pull requests
Actions
Projects
Wiki
Security and quality
Insights
Expand file tree
Breadcrumbs
BinderDemo
/
binder.cpp
Copy path
More file actions
More file actions
Latest commit
History
History
History
257 lines (216 loc) · 7.84 KB
Breadcrumbs
BinderDemo
/
binder.cpp
Copy path
File metadata and controls
257 lines (216 loc) · 7.84 KB
Raw
Copy raw file
Download raw file
Open symbols panel
Edit and raw actions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
/*
-*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*-
vi:ai:tabstop=8:shiftwidth=4:softtabstop=4:expandtab
*/
/*
* Author: Gabriel Burca <gburca dash binder at ebixio dot com>
*
* Sample code for using binders in Android from C++
*
* The Demo service provides 3 operations: push(), alert(), add(). See
* the IDemo class documentation to see what they do.
*
* Both the server and client code are included below.
*
* To view the log output:
* adb logcat -v time binder_demo:* *:S
*
* To run, create 2 adb shell sessions. In the first one run "binder" with no
* arguments to start the service. In the second one run "binder N" where N is
* an integer, to start a client that connects to the service and calls push(N),
* alert(), and add(N, 5).
*/
#
define
LOG_TAG
"
binder_demo
"
/*
For relevant code see:
frameworks/native/{include,libs}/binder/{IInterface,Parcel}.{h,cpp}
system/core/include/utils/{Errors,RefBase}.h
*/
#
include
<
stdlib.h
>
#
include
<
utils/RefBase.h
>
#
include
<
utils/Log.h
>
#
include
<
binder/TextOutput.h
>
#
include
<
binder/IInterface.h
>
#
include
<
binder/IBinder.h
>
#
include
<
binder/ProcessState.h
>
#
include
<
binder/IServiceManager.h
>
#
include
<
binder/IPCThreadState.h
>
using
namespace
android
;
#
define
INFO
(...) \
do
{ \
printf
(__VA_ARGS__); \
printf
(
"
\n
"
); \
ALOGD
(__VA_ARGS__); \
}
while
(
0
)
void
assert_fail
(
const
char
*file,
int
line,
const
char
*func,
const
char
*expr) {
INFO
(
"
assertion failed at file %s, line %d, function %s:
"
,
file, line, func);
INFO
(
"
%s
"
, expr);
abort
();
}
#
define
ASSERT
(
e
) \
do
{ \
if
(!(e)) \
assert_fail
(__FILE__, __LINE__, __func__, #e); \
}
while
(
0
)
//
Where to print the parcel contents: aout, alog, aerr. alog doesn't seem to work.
#
define
PLOG
aout
//
Interface (our AIDL) - Shared by server and client
class
IDemo
:
public
IInterface
{
public:
enum
{
ALERT
= IBinder::
FIRST_CALL_TRANSACTION
,
PUSH
,
ADD
};
//
Sends a user-provided value to the service
virtual
void
push
(
int32_t
data) = 0;
//
Sends a fixed alert string to the service
virtual
void
alert
() = 0;
//
Requests the service to perform an addition and return the result
virtual
int32_t
add
(
int32_t
v1,
int32_t
v2) = 0;
DECLARE_META_INTERFACE
(Demo);
//
Expands to 5 lines below:
//
static const android::String16 descriptor;
//
static android::sp<IDemo> asInterface(const android::sp<android::IBinder>& obj);
//
virtual const android::String16& getInterfaceDescriptor() const;
//
IDemo();
//
virtual ~IDemo();
};
//
Client
class
BpDemo
:
public
BpInterface
<IDemo> {
public:
BpDemo
(
const
sp<IBinder>& impl) : BpInterface<IDemo>(impl) {
ALOGD
(
"
BpDemo::BpDemo()
"
);
}
virtual
void
push
(
int32_t
push_data) {
Parcel data, reply;
data.
writeInterfaceToken
(
IDemo::getInterfaceDescriptor
());
data.
writeInt32
(push_data);
aout <<
"
BpDemo::push parcel to be sent:
\n
"
;
data.
print
(
PLOG
);
endl
(
PLOG
);
remote
()->
transact
(
PUSH
, data, &reply);
aout <<
"
BpDemo::push parcel reply:
\n
"
;
reply.
print
(
PLOG
);
endl
(
PLOG
);
ALOGD
(
"
BpDemo::push(%i)
"
, push_data);
}
virtual
void
alert
() {
Parcel data, reply;
data.
writeInterfaceToken
(
IDemo::getInterfaceDescriptor
());
data.
writeString16
(
String16
(
"
The alert string
"
));
remote
()->
transact
(
ALERT
, data, &reply, IBinder::
FLAG_ONEWAY
);
//
asynchronous call
ALOGD
(
"
BpDemo::alert()
"
);
}
virtual
int32_t
add
(
int32_t
v1,
int32_t
v2) {
Parcel data, reply;
data.
writeInterfaceToken
(
IDemo::getInterfaceDescriptor
());
data.
writeInt32
(v1);
data.
writeInt32
(v2);
aout <<
"
BpDemo::add parcel to be sent:
\n
"
;
data.
print
(
PLOG
);
endl
(
PLOG
);
remote
()->
transact
(
ADD
, data, &reply);
ALOGD
(
"
BpDemo::add transact reply
"
);
reply.
print
(
PLOG
);
endl
(
PLOG
);
int32_t
res;
status_t
status = reply.
readInt32
(&res);
ALOGD
(
"
BpDemo::add(%i, %i) = %i (status: %i)
"
, v1, v2, res, status);
return
res;
}
};
//
IMPLEMENT_META_INTERFACE(Demo, "Demo");
//
Macro above expands to code below. Doing it by hand so we can log ctor and destructor calls.
const
android::String16
IDemo::descriptor
(
"
Demo
"
);
const
android::String16&
IDemo::getInterfaceDescriptor
()
const
{
return
IDemo::descriptor;
}
android::sp<IDemo>
IDemo::asInterface
(
const
android::sp<android::IBinder>& obj) {
android::sp<IDemo> intr;
if
(obj !=
NULL
) {
intr =
static_cast
<IDemo*>(obj->
queryLocalInterface
(IDemo::descriptor).
get
());
if
(intr ==
NULL
) {
intr =
new
BpDemo
(obj);
}
}
return
intr;
}
IDemo::IDemo
() {
ALOGD
(
"
IDemo::IDemo()
"
); }
IDemo::~IDemo
() {
ALOGD
(
"
IDemo::~IDemo()
"
); }
//
End of macro expansion
//
Server
class
BnDemo
:
public
BnInterface
<IDemo> {
virtual
status_t
onTransact
(
uint32_t
code,
const
Parcel& data, Parcel* reply,
uint32_t
flags =
0
);
};
status_t
BnDemo::onTransact
(
uint32_t
code,
const
Parcel& data, Parcel* reply,
uint32_t
flags) {
ALOGD
(
"
BnDemo::onTransact(%i) %i
"
, code, flags);
data.
checkInterface
(
this
);
data.
print
(
PLOG
);
endl
(
PLOG
);
switch
(code) {
case
ALERT
: {
alert
();
//
Ignoring the fixed alert string
return
NO_ERROR
;
}
break
;
case
PUSH
: {
int32_t
inData = data.
readInt32
();
ALOGD
(
"
BnDemo::onTransact got %i
"
, inData);
push
(inData);
ASSERT
(reply !=
0
);
reply->
print
(
PLOG
);
endl
(
PLOG
);
return
NO_ERROR
;
}
break
;
case
ADD
: {
int32_t
inV1 = data.
readInt32
();
int32_t
inV2 = data.
readInt32
();
int32_t
sum =
add
(inV1, inV2);
ALOGD
(
"
BnDemo::onTransact add(%i, %i) = %i
"
, inV1, inV2, sum);
ASSERT
(reply !=
0
);
reply->
print
(
PLOG
);
endl
(
PLOG
);
reply->
writeInt32
(sum);
return
NO_ERROR
;
}
break
;
default
:
return
BBinder::onTransact
(code, data, reply, flags);
}
}
class
Demo
:
public
BnDemo
{
virtual
void
push
(
int32_t
data) {
INFO
(
"
Demo::push(%i)
"
, data);
}
virtual
void
alert
() {
INFO
(
"
Demo::alert()
"
);
}
virtual
int32_t
add
(
int32_t
v1,
int32_t
v2) {
INFO
(
"
Demo::add(%i, %i)
"
, v1, v2);
return
v1 + v2;
}
};
//
Helper function to get a hold of the "Demo" service.
sp<IDemo>
getDemoServ
() {
sp<IServiceManager> sm =
defaultServiceManager
();
ASSERT
(sm !=
0
);
sp<IBinder> binder = sm->
getService
(
String16
(
"
Demo
"
));
//
TODO: If the "Demo" service is not running, getService times out and binder == 0.
ASSERT
(binder !=
0
);
sp<IDemo> demo = interface_cast<IDemo>(binder);
ASSERT
(demo !=
0
);
return
demo;
}
int
main
(
int
argc,
char
**argv) {
if
(argc ==
1
) {
ALOGD
(
"
We're the service
"
);
defaultServiceManager
()->
addService
(
String16
(
"
Demo
"
),
new
Demo
());
android::ProcessState::self
()->
startThreadPool
();
ALOGD
(
"
Demo service is now ready
"
);
IPCThreadState::self
()->
joinThreadPool
();
ALOGD
(
"
Demo service thread joined
"
);
}
else
if
(argc ==
2
) {
INFO
(
"
We're the client: %s
"
, argv[
1
]);
int
v =
atoi
(argv[
1
]);
sp<IDemo> demo =
getDemoServ
();
demo->
alert
();
demo->
push
(v);
const
int32_t
adder =
5
;
int32_t
sum = demo->
add
(v, adder);
ALOGD
(
"
Addition result: %i + %i = %i
"
, v, adder, sum);
}
return
0
;
}
/*
Single-threaded service, single-threaded client.
*/
Back
|
FazBrowse Home
|
New Git URL