Android是通过HIDL实现上层与Hal层通信,当业务逻辑有通信需求时去扩展HIDL接口比较麻烦。本文介绍了通过FIFO实现Android FWK/App给hal发送消息的快捷方式。该方式是从FWK/App向Hal层发送消息。
1 Hal层实现
1.1 定义Hal层监听接口
定义FIFO的读端。
#include <utils/Thread.h>
class CameraMSGProcess : public android::Thread {
public:
CameraMSGProcess();
~CameraMSGProcess();
virtual bool threadLoop() override;
private:
bool mExit;
const char* mObservePath;
int mFd;
};
1.2 实现Hal层监听接口
#include <log/log.h>
#include <errno.h>
#include <cutils/properties.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
CameraMSGProcess::CameraMSGProcess() :
Thread(/*canCallJava*/false),
mExit(false),
mObservePath("/data/local/fifo"),
mFd(-1){
//创建fifo,直接调用该函数创建出来的接口权限不是指定的0666。未研究原因。
if(!mkfifo(mObservePath, 0666)) {
ALOGI("create fifo OK");
//通过写属性的方式在.rc文件修改节点权限
property_set("sys.myfifo.hal.fifo_read", "1");
}
}
CameraMSGProcess::~CameraMSGProcess() {
//析构时以写的方式打开写入退出标识
int fd = open(mObservePath, O_WRONLY|O_NONBLOCK);
if(fd != -1) {
write(mFd, "q", 1);
close(fd);
}
mExit = true;
}
bool CameraMSGProcess::threadLoop() {
ALOGI("start to monitor");
while (!mExit) {
//在调试过程中发现每次监听需要重新打开一次。否者下次select函数直接返回。这和linux上不同,未深入研究原因。
mFd = open(mObservePath, O_RDONLY|O_NONBLOCK); //以只读方式打开
if(mFd < 0) {
ALOGE("open %s failed! %s", mObservePath, strerror(errno));
usleep(50000);
return true;
}
fd_set fds;
FD_ZERO(&fds);
FD_SET(this->mFd, &fds);
int ret = select(this->mFd + 1, &fds, NULL, NULL, NULL);
if(ret < 0) {
ALOGE("select %s failed! %s", mObservePath, strerror(errno));
} else {
char value[100] = {0};
ret = read(mFd, value, 100);
if(ret > 0) {
ALOGI("read %s", value);
//退出监听
if(!strncmp(value, "q", 1)) break;
//消息处理
if(!strcmp(value, "doPTZ")) {
//Call doPTZ
} else if(!strcmp(value, "doAWB")) {
//Call doAWB
}
}
}
close(mFd);
mFd = -1;
}
unlink(mObservePath);
return false;
}
void startFIFO() {
sp<CameraMSGProcess> mCameraMSGProcess = new CameraMSGProcess();
mCameraMSGProcess.run("msg_process", PRIORITY_BACKGROUND);
}
1.3 修改fifo节点权限
mkfifo第二个参数指定的权限不生效,可以通过.rc文件修改。因为我是在camera hal中使用,所以在cameraProvider的rc文件添加如下代码。
on property:sys.myfifo.hal.fifo_read=1
chmod 0666 /data/local/fifo
2 在FWK或App中写入消息
写入消息。
void sendMsg() {
android.util.FileUtils.writeFile("/data/local/fifo", "xxx");
}