Android中Native向System Service进行Binder通信的示例
Native向System Service Binder通信实现:SensorService.cpp 将应用使用sensor enable和disable事件通过binder方式上报到System server的示例。
Client端实现实例
1 调用示例:例如SensorService.cpp
appRecordSdk.sendEvent(212,connection->getUid(),String16(ss.str().c_str()))
// 引入Binder客户端SDK头文件
#include "../../include/binder/FadiRecordSdk.h"
android::FadiRecordSdk fadiRecordSdk; // 全局单例
status_t SensorService::enable(...) {
...
// 构造事件数据:传感器句柄|PID|UID|包名|类型|采样周期
std::ostringstream ss;
ss << handle << "|" << (thread ? thread->getCallingPid() : -1)
<< "|" << uid << "|" << connection->getPackageName()
<< "|" << (sensor ? sensor->getSensor().getType() : -1)
<< "|" << samplingPeriodNs;
// 通过Binder发送事件到SystemServer(消息ID=212)
fadiRecordSdk.sendEvent(212, connection->getUid(), String16(ss.str().c_str()));
}
}
2 FadiRecordSdk.h
#ifndef ANDROID_FADIRECORD
#define ANDROID_FADIRECORD
#include <binder/IInterface.h>
#include <binder/Parcel.h>
#include <utils/String16.h>
namespace android {
class FadiRecordSdk {
public:
/**
* @brief 发送事件到SystemServer
* @param msgId 事件类型(如212=传感器事件)
* @param arg0 附加参数(如调用方UID)
* @param str 序列化的事件数据
*/
void sendEvent(int32_t msgId, int32_t arg0, const String16& str);
// Binder事务码定义(需与AIDL接口TRANSACTION_*对齐)
enum {
SEND_EVENT = IBinder::FIRST_CALL_TRANSACTION + 1 // 对应TRANSACTION_sendEvent
};
private:
static sp<IBinder> remote; // 远程服务代理(缓存在客户端)
};
} // namespace android
#endif // ANDROID_FADIRECORD
备注这里的SEND_EVENT 对应 IFadiRecordInterface 中的TRANSACTION_sendEvent
public abstract static class Stub extends Binder implements IFadiRecordInterface {
private static final String DESCRIPTOR = "com.fadi.fadirecord.IFadiRecordInterface";
static final int TRANSACTION_setEnable = 1;
static final int TRANSACTION_sendEvent = 2;
3 FadiRecordSdk.cpp
通过Parcel序列化数据将事件通过IAppRecordInterface.aidl接口上报到systemServe的AppRecordService服务,Parcel机制:跨进程传递的数据需序列化,支持基本类型、String、Parcelable对象等
#include "binder/FadiRecordSdk.h"
#include <binder/IServiceManager.h>
namespace android {
sp<IBinder> FadiRecordSdk::remote = nullptr;
void FadiRecordSdk::sendEvent(int32_t msgId, int32_t arg0, const String16& str) {
Parcel data, reply;
// 写入接口令牌(需与服务端DESCRIPTOR一致)
data.writeInterfaceToken(String16("com.fadi.fadiRecord.IFadiRecordInterface"));
data.writeInt32(msgId); // 事件ID
data.writeInt32(arg0); // 参数1
data.writeString16(str); // 参数2(序列化数据)
// 延迟初始化:首次调用时获取远程服务代理
if (!remote) {
remote = defaultServiceManager()->getService(String16("FadiRecordService"));
}
// 异步调用(FLAG_ONEWAY不等待返回)
if (remote) {
remote->transact(SEND_EVENT, data, &reply, IBinder::FLAG_ONEWAY);
}
}
} // namespace android
4 Android.bp
cc_defaults {
name: "libbinder_common_defaults",
host_supported: true,
srcs: [
"Binder.cpp",
...
"FadiRecordSdk.cpp",
...
],
服务端实现实例
1. FadiRecordService 服务注册(SystemServer)
public class FadiRecordService extends SystemService {
private final IFadiRecordInterface.Stub mBinder = new FadiRecordStub();
@Override
public void onStart() {
// 注册Binder服务到ServiceManager
publishBinderService("FadiRecordService", mBinder);
// 添加内部API(可选)
LocalServices.addService(FadiRecordInternal.class, new FadiRecordInternal());
}
}
2.AIDL接口定义(IFadiRecordInterface.aidl)
FLAG_ONEWAY表示“不用等回信”
// 包名需与writeInterfaceToken()一致
package com.fadi.fadiRecord;
interface IFadiRecordInterface {
/**
* @param eventId 事件类型(如212)
* @param arg 附加参数(UID等)
* @param msg 格式化数据(由Native层拼接)
*/
oneway void sendEvent(int eventId, int arg, String msg);
}
3. AppRecordService的SE-linux权限配置
相关SE-linux也是需要配置
# service_contexts.te
FadiRecordService u:object_r:fadi_record_service:s0
# service.te
type fadi_record_service, system_server_service, service_manager_type;
运行结果
打开一个运动app,就可以看到使用sensor的事件被从native中传递到system server中了哈
sensorDisableEvent:pid=10228,message=19|7396|10228|com.tencent.mm.plugin.sport.model.a0|19
sensorEnableEvent:pid=10228,message=19|7396|10228|com.tencent.mm.plugin.sport.model.a0|19|600000000