写给应用开发的 Android Framework 教程——学穿 Binder 篇之程序示例 aidl-cpp

2,072 阅读3分钟

这是一个 Binder 相关的系列教程,持续更新中:

上文中手动去写这些模板代码还是有点繁琐,google 提供了 aidl-cpp 工具来简化我们的开发工作,接下来我们就来看看如何使用 aidl-cpp:

本文源码可以在 github.com/yuandaimaah… 下载到

定义协议文件

device/jelly/rice14/ 目录下创建如下的目录与文件:

AIDLCppDemo
├── Android.bp
├── com
│   └── yuandaima
│       └── IHello.aidl
├── HelloClient.cpp
└── HelloServer.cpp

其中 IHello.aidl 就是我们定义的协议文件:

package com.yuandaima;

interface IHello
{
    void hello();
    int sum(int x, int y);
}

定义了两个远程调用函数 hello 和 sum。

接着我们使用 aidl-cpp 命令生成必要的 cpp 代码:

aidl-cpp com/yuandaima/IHello.aidl ./ ./IHello.cpp

生成如下的代码:

AIDLCppDemo
├── Android.bp
├── com
│   └── yuandaima
│       ├── BnHello.h
│       ├── BpHello.h
│       ├── IHello.aidl
│       └── IHello.h
├── HelloClient.cpp
├── HelloServer.cpp
└── IHello.cpp

服务端实现

接着我们来实现我们的服务端 HelloServer.cpp:

#define LOG_TAG "aidl_cpp"

#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>

#include "com/yuandaima/IHello.h"
#include "com/yuandaima/BnHello.h"

using namespace android;

class IHelloServer : public com::yuandaima::BnHello
{
public:
    binder::Status hello()
    {
        ALOGI("hello");
        return binder::Status();
    }

    binder::Status sum(int32_t v1, int32_t v2, int32_t *_aidl_return) override
    {
        ALOGI("server: sum: %d + %d", v1, v2);
        *_aidl_return = v1 + v2;
        return binder::Status();
    }
};

int main(int argc, char const *argv[])
{
    defaultServiceManager()->addService(String16("IHello"), new IHelloServer());
    ProcessState::self()->startThreadPool();
    IPCThreadState::self()->joinThreadPool();
    return 0;
}

具体实现和我们前文中介绍的基本一致。

客户端实现

接着我们来实现客户端代码 HelloClient.cpp:

#define LOG_TAG "aidl_cpp"

#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>

#include "com/yuandaima/IHello.h"
#include "com/yuandaima/BnHello.h"

using namespace android;

int main(int argc, char const *argv[])
{
    sp<IServiceManager> sm = defaultServiceManager();
    sp<IBinder> binder = sm->getService(String16("IHello"));
    sp<com::yuandaima::IHello> hello = interface_cast<com::yuandaima::IHello>(binder);

    hello->hello();
    int ret = 0;
    hello->sum(1, 2, &ret);

    return 0;
}

具体实现和我们前文中介绍的基本一致。

编译与运行

接着我们编写 Android.bp 文件:

cc_defaults {
    name: "BinderCppAidlDemoflags",

    cflags: [
        "-Wall",
        "-Wextra",
        "-Werror",
        "-Wno-unused-parameter",
        "-Wno-missing-field-initializers",
        "-Wno-unused-parameter",
        "-Wno-unused-variable",
        "-Wno-incompatible-pointer-types",
        "-Wno-sign-compare",
    ],
    product_variables: {
        binder32bit: {
            cflags: ["-DBINDER_IPC_32BIT=1"],
        },
    },
}

cc_binary {
    name: "IHelloClient",
    defaults: ["BinderCppAidlDemoflags"],
    srcs: ["HelloClient.cpp","IHello.cpp"],

    shared_libs: [
        "liblog",
        "libcutils",
        "libandroidfw",
        "libutils",
        "libbinder",
    ],
}

cc_binary {
    name: "IHelloServer",
    defaults: ["BinderCppAidlDemoflags"],
    srcs: ["HelloServer.cpp","IHello.cpp"],
    shared_libs: [
        "liblog",
        "libcutils",
        "libandroidfw",
        "libutils",
        "libbinder",
    ],
}

最后编译运行:

# 启动模拟器
source build/envsetup.sh
lunch rice14-eng #选择合适的 product 版本
# 在 device/jelly/rice14/AIDLCppDemo 目录下
mm #模块编译
# push 可执行文件到设备上
adb push out/target/product/rice14/system/bin/IHellServer /data/local/tmp
adb push out/target/product/rice14/system/bin/IHellClient /data/local/tmp

接着执行可执行文件:

adb shell
cd /data/local/tmp
./IHelloServer &
./IHelloClient

接着查看 log:

logcat | grep "aidl_cpp"

至此我们的示例程序就完成了。

关于

我叫阿豪,2015 年本科毕业于国防科技大学指挥自动化专业,毕业后,从事信息化装备的研发工作。主要研究方向为 Android Framework 与 Linux Kernel,2023年春节后开始做 Android Framework 相关的技术分享。

如果你对 Framework 感兴趣或者正在学习 Framework,可以参考我总结的Android Framework 学习路线指南,也可关注我的微信公众号,我会在公众号上持续分享我的经验,帮助正在学习的你少走一些弯路。学习过程中如果你有疑问或者你的经验想要分享给大家可以添加我的微信,我拉你进技术交流群。