[Android] BinderDemo

代码结构

.
├── 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/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值