代码结构
.
├── Android.bp
├── Client
│ └── main.cpp
├── Interface
│ ├── IDemo.cpp
│ └── IDemo.h
├── README.markdown
└── Server
├── DemoServer.cpp
├── DemoServer.h
└── main.cpp
Android.bp
cc_binary{
name : "mybinderC",
srcs : [
"Client/main.cpp",
"Interface/IDemo.cpp",
],
shared_libs : [
"libbinder",
"libutils",
"libcutils",
"liblog",
],
include_dirs : [
"frameworks/native/include",
"system/core/include",
],
}
cc_binary {
name:
"mybinderS",
srcs:[
"Server/main.cpp",
"Interface/IDemo.cpp",
"Server/DemoServer.cpp",
],
shared_libs:[
"libbinder",
"libutils",
"libcutils",
"liblog",
],
include_dirs: [
"frameworks/native/include",
"system/core/include",
],
}
Client/main.cpp
#define LOG_TAG "IDemoC"
#include "../Interface/IDemo.h"
#include <binder/IBinder.h>
#include <binder/IInterface.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#include <binder/ProcessState.h>
#include <stdlib.h>
#include <utils/Log.h>
#include <utils/RefBase.h>
sp<IDemo> getDemoServ() {
sp<IServiceManager> sm = defaultServiceManager();
sp<IBinder> binder = sm->getService(String16("DemoServer.service"));
sp<IDemo> demo = interface_cast<IDemo>(binder);
return demo;
}
int main(int argc, char **argv) {
ALOGD("Client start: %s", argv[1]);
if (argc != 2) {
ALOGD("Wrong argc %d", argc);
return -1;
}
int v = atoi(argv[1]);
sp<IDemo> demo = getDemoServ();
const int32_t adder = 5;
int32_t sum = demo->add(v, adder);
ALOGD("Addition result: %i + %i = %i", v, adder, sum);
ALOGD("Client end");
return 0;
}
Interface/IDemo.h
#pragma once
#include <binder/IInterface.h>
#include <binder/Parcel.h>
#include <binder/TextOutput.h>
using namespace android;
class IDemo : public android::IInterface {
public:
enum { ADD = IBinder::FIRST_CALL_TRANSACTION };
virtual int32_t add(int32_t v1, int32_t v2) = 0;
DECLARE_META_INTERFACE(Demo);
};
class BnDemo : public BnInterface<IDemo> {
public:
virtual status_t onTransact(uint32_t code, const Parcel &data, Parcel *reply,
uint32_t flags = 0);
};
Interface/IDemo.cpp
#define LOG_TAG "IDemoI"
#include "IDemo.h"
#include <utils/Log.h>
class BpDemo : public BpInterface<IDemo> {
public:
explicit BpDemo(const sp<IBinder> &impl) : BpInterface<IDemo>(impl) {
ALOGD("BpDemo::BpDemo()");
}
// Requests the service to perform an addition and return the result
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(aout);
endl(aout);
remote()->transact(ADD, data, &reply);
aout << "BpDemo::add transact reply:\n";
reply.print(aout);
endl(aout);
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");
//========================================================
status_t BnDemo::onTransact(uint32_t code, const Parcel &data, Parcel *reply,
uint32_t flags) {
/*!!!
dont forget this sentence , this sentence not only do check job, but also
move the pointer to payload offset if lack of this sentence , readXXX will
get Interface as value.
*/
data.checkInterface(this);
/*!!!*/
switch (code) {
case ADD: {
aout << "-------- BnDemo::onTransact ADD enter, message :";
data.print(aout);
endl(aout);
int32_t inV1 = data.readInt32();
int32_t inV2 = data.readInt32();
aout << "-------- BnDemo::onTransact readValue, " << inV1 << " | " << inV2;
int32_t sum = add(inV1, inV2);
reply->print(aout);
endl(aout);
reply->writeInt32(sum);
return NO_ERROR;
} break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
}
Server/DemoServer.h
#pragma once
#include "../Interface/IDemo.h"
class DemoServer : public BnDemo {
public:
int32_t add(int32_t v1, int32_t v2);
};
Server/DemoServer.cpp
#define LOG_TAG "IDemoS"
#include "DemoServer.h"
int32_t DemoServer::add(int32_t v1, int32_t v2) {
ALOGD("DemoServer::add(%i, %i)", v1, v2);
return v1 + v2;
}
Server/main.cpp
#define LOG_TAG "IDemoS"
#include <stdlib.h>
#include <utils/Log.h>
#include <utils/RefBase.h>
#include <binder/IBinder.h>
#include <binder/IInterface.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#include <binder/ProcessState.h>
#include "DemoServer.h"
int main() {
ALOGD("We're the service");
defaultServiceManager()->addService(String16("DemoServer.service"),
new DemoServer());
android::ProcessState::self()->startThreadPool();
ALOGD("DemoServer.service is now ready");
IPCThreadState::self()->joinThreadPool();
ALOGD("DemoServer.service thread joined");
ALOGD("Server end");
return 0;
}
README.markdown
usage :
clone into $AndroidSrcRoot/external
cd BinderDemo
mm
adb push $AndroidSrcRoot\out\target\product\waydroid_arm\system\bin\mybinderC /data/local adb push $AndroidSrcRoot\out\target\product\waydroid_arm\system\bin\mybinderS /data/local
adb shell chmod +x /data/local/mybinder*
adb logcat IDemoI:* IDemoC:* IDemoS:* *:S
adb shell ./data/local/mybinderS
adb shell ./data/local/mybinderC
PS:
服务端如何查找service的标识字符串?
代码中搜索 addService
客户端如何查找连接了哪个Binder服务端?
代码中搜索 getService
记住上面两点,能够快速定位客户端和服务端的关联关系。
参考:
https://ebixio.com/blog/2012/07/07/using-android-ipc-binders-from-native-code/