写给使用开发的 Android Framework 教程是一个系列教程,目前已更新以下内容:
-
Android Framework 学习道路攻略
-
系统开发基础
-
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 查看实行结果: