写给使用开发的 Android Framework 教程是一个系列教程,目前已更新以下内容:

  • Android Framework 学习道路攻略

  • 系统开发基础

    • Ubuntu 运用快速入门
    • Make 构建东西入门
    • 了解 Unicode UTF-8 UTF-16 UTF-32
    • Linux Shell 脚本编程入门——核心基础语法
    • SEAndroid 运用极速上手
    • 了解 C++ 的 Memory Order
  • AOSP 上手攻略

    • AOSP 极速上手
    • 系统开发东西引荐
    • 添加 Product
    • 添加 C/C++、Java 可实行程序
    • 添加 C/C++、Java 库
    • 添加配置文件与删去已有模块
    • 系统 App 源码添加
    • 运用 Android Studio 开发系统 App
    • 添加开机自启动 Shell 脚本
  • 学穿 Binder 系列

    • Binder 基本原理
    • Binder 程序示例之 C 言语篇
    • Binder 服务注册进程景象分析之C言语篇
    • Binder 服务获取与运用进程景象分析之C言语篇
    • Binder C++ 程序示例
    • Binder C++ 程序分析之首要类解析
    • Binder 服务注册进程景象分析之 C++ 篇
  • HAL 与硬件服务

    • Kernel 下载与编译
    • Linux 驱动开发入门

本文根据 Android10 源码环境

Android 源码中供应了一系列的 C++ 类来简化 Binder 驱动的运用。使得开发者能快速在 Android 系统源码中添加 Binder 服务和运用 Binder 服务。接下来咱们运用 Android 源码中供应的辅助类和 C++ 言语来编写一个 Binder C++ 示例程序。

能够在这里下载到示例程序。

运用 C++ 完结一个 Binder 服务分为以下几步:

  • 界说协议
  • 完结服务端协议
  • 完结客户端协议
  • 服务端程序完结
  • 客户端程序完结

1. 界说通信协议

通信协议由三部分组成:

  • 通信协议接口
  • 通信协议服务端完结
  • 通信协议客户端完结

接下来咱们来完结通信协议接口 IHelloService, 接口继承自 IInterface,描述了名为 Hello 的 Binder 服务对外供应的功用。

//IHelloService.h
class IHelloService: public IInterface {
public:
    //DECLARE_META_INTERFACE 是一个宏,声明晰一些变量和函数
    DECLARE_META_INTERFACE(HelloService);
    //Binder 服务对外供应的功用
    virtual void sayHello() = 0;
    virtual int sayHelloTo(const char *name) = 0;
};

2. 通信协议服务端完结

通信协议服务端完结是一个继承自 BnInterface<IHelloService> 的类:

//声明
//IHelloService.h
class BnHelloService: public BnInterface<IHelloService> {
public:
    //服务端收到数据后的回调
    status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0);
    void sayHello();
    int sayHelloTo(const char *name);
};
//完结
//BnHelloService.cpp
#define LOG_TAG "HelloService"
#include <log/log.h>
#include "IHelloService.h"
namespace android {
//服务端收到数据的回调
status_t BnHelloService::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
    //code 表明客户端需求调用哪个函数
    switch(code) {
        //调用 sayhello
        case HELLO_SVR_CMD_SAYHELLO:  {
            //调用 sayhello 函数
            sayHello();
            //写入回复给客户端的数据
            reply->writeInt32(0);
            return NO_ERROR;
        } break;
        //调用 sayhelloto
        case HELLO_SVR_CMD_SAYHELLO_TO: {
            //取出客户端发送的参数
            int32_t policy =  data.readInt32();
			String16 name16_tmp = data.readString16(); 
			String16 name16 = data.readString16();
			String8 name8(name16);
            //调用 sayHelloTo 函数
			int cnt = sayHelloTo(name8.string());
            //写入回复给客户端的数据
			reply->writeInt32(0); 
			reply->writeInt32(cnt);
            return NO_ERROR;
        } break;
        default:
            return BBinder::onTransact(code, data, reply, flags);
    }
}
//服务端函数的具体完结
void BnHelloService::sayHello() {
    static int count = 0;
    ALOGI("say hello :%d\n ", ++count);
}
int BnHelloService::sayHelloTo(const char *name) {
    static int cnt = 0;
	ALOGI("say hello to %s : %d\n", name, ++cnt);
	return cnt;
}
}

为叙说便利咱们称 BnHelloService 以及同类型的类为 Binder 服务类

3. 通信协议客户端协议完结

客户端协议完结是一个继承自 BpInterface<IHelloService> 的类

//客户端
//IHelloService.h
class BpHelloService: public BpInterface<IHelloService> {
public:
    BpHelloService(const sp<IBinder>& impl);
    void sayHello();
    int sayHelloTo(const char *name);
};
//BpHelloService.cpp
#include "IHelloService.h"
namespace android {
BpHelloService::BpHelloService(const sp<IBinder>& impl):BpInterface<IHelloService>(impl) {
}
void BpHelloService::sayHello() {
    Parcel data, reply;
    data.writeInt32(0);
    data.writeString16(String16("IHelloService"));
    //主张远程调用
    remote()->transact(HELLO_SVR_CMD_SAYHELLO, data, &reply);
}
int BpHelloService::sayHelloTo(const char *name) {
    Parcel data, reply;
    int exception;
    data.writeInt32(0);
    data.writeString16(String16("IHelloService"));
    data.writeString16(String16(name));
    //主张远程调用
    remote()->transact(HELLO_SVR_CMD_SAYHELLO_TO, data, &reply);
    exception = reply.readInt32();
	if (exception)
		return -1;
	else
		return reply.readInt32();
}
    IMPLEMENT_META_INTERFACE(HelloService, "android.media.IHelloService");
}

为叙说便利咱们称 BpHelloService 以及同类型的类为 Binder 署理类

4. 服务端程序完结

int main(int argc, char const *argv[])
{
    //运用 ProcessState 类完结 binder 驱动的初始化
    sp<ProcessState> proc(ProcessState::self());
    //注册服务
    sp<IServiceManager> sm = defaultServiceManager();
    sm->addService(String16("hello"), new BnHelloService());
    //打开 binder 线程池
	ProcessState::self()->startThreadPool();
	IPCThreadState::self()->joinThreadPool();
    return 0;
}

5. 客户端程序完结

int main(int argc, char const *argv[])
{
    //运用 ProcessState 类完结 binder 驱动的初始化
    sp<ProcessState> proc(ProcessState::self());
    //获取 hello 服务
    sp<IServiceManager> sm = defaultServiceManager();
    //回来的是 BpBinder 指针
    sp<IBinder> binder = sm->getService(String16("hello"));
    sp<IHelloService> service =
		    interface_cast<IHelloService>(binder);
    if (binder == 0)
	{
		ALOGI("can't get hello service\n");
		return -1;
	}
    //主张远程调用
    service->sayHello();
    int cnt = service->sayHelloTo("nihao");
	ALOGI("client call sayhello_to, cnt = %d", cnt);
    return 0;
}

6. 编译运转

项目根目录下添加 Android.bp

cc_defaults {
    name: "BinderCppDemoflags",
    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: "CppBinderClient",
    defaults: ["BinderCppDemoflags"],
    srcs: ["BinderClient.cpp", "BpHelloService.cpp"],
    shared_libs: [
        "liblog",
        "libcutils",
        "libutils",
        "libbinder",
    ],
}
cc_binary {
    name: "CppBinderServer",
    defaults: ["BinderCppDemoflags"],
    srcs: ["BinderServer.cpp", "BnHelloService.cpp","BpHelloService.cpp"],
    shared_libs: [
        "liblog",
        "libcutils",
        "libutils",
        "libbinder",
    ],
}

将项目放到 aosp 任意目录下,然后实行以下指令:

source build/envsetup.sh
lunch aosp_x86_64-eng
emulator

进入到项目目录,然后实行单编指令:

mm

编译完结后,将程序上传到模拟器并实行。

传输可实行文件到模拟器:

adb push out/target/product/generic_x86_64/symbols/system/bin/CppBinderServer /data/local/tmp
adb push out/target/product/generic_x86_64/symbols/system/bin/CppBinderClient /data/local/tmp

接下来 adb shell 进入模拟器 shell 环境:

adb shell
cd /data/local/tmp
./CppBinderServer
# 从头开一个终端进入 adb shell
cd /data/local/tmp
./CppBinderClient

最后通过 logcat 查看实行结果:

写给使用开发的 Android Framework 教程——学穿 Binder 篇之Binder C++ 程序示例