本文介绍通过socket实现Framework和Hal双向通信。在hal层实现socket server端,并随着hal层服务启动而启动。FWK/App端创建客户端并和socket server连接。
1. hal层实现socket server
1.1 socket server接口定义
该类实现socket server相关功能。
#include <stdio.h>
#include <unistd.h>
#include <poll.h>
#include <utils/Thread.h>
#include <utils/Mutex.h>
class MyCameraSocketServer : public Thread {
public:
MyCameraSocketServer();
virtual ~MyCameraSocketServer();
void sendExitThreadSignal();
//发送消息到客户端
void sendResponse(CamHalMessage& msg);
private:
int mFd;
bool mIsExit;
size_t mConnectCount;
static const size_t kMaxClientSize = 2;
struct pollfd mPollFds[kMaxClientSize];
virtual status_t readyToRun();
virtual bool threadLoop(); //监听和处理消息
};
1.2 socket server接口实现
主要调用:
a. 调用socket_local_server创建socket服务,socket名字要唯一。
b. 调用listen监听事件
c. 创建线程调用poll等待事件:
i. POLLRDHUP或POLLERR事件表明连接断开,需要清除相关信息
ii. POLLIN事件。如果是socket fd返回的,说明有新的连接请求。调用accept接受请求,并保存该函数返回的fd,标记对应client。
iii. POLLIN事件。其他fd返回为消息内容。调用recv读取消息内容,并处理消息。
d. 调用write给客户端发送消息
#include <cutils/sockets.h>
#include <cutils/properties.h>
#define BUFFER_SIZE (512)
#define MAX_CONNECT_NUM 1
MyCameraSocketServer::MyCameraSocketServer()
{
mConnectCount = 0;
mIsExit = false;
ALOGI("%s enter!", __FUNCTION__);
run("my_camera_socket");
}
MyCameraSocketServer::~MyCameraSocketServer()
{
if(mRequestProcessThread != NULL){
mRequestProcessThread.clear();
}
if (mFd > 0)
close(mFd);
}
status_t MyCameraSocketServer::readyToRun()
{
//创建socket server
char socketName[256] = {"camera_hal_server"};
ALOGI("%s : , socket name:%s", __FUNCTION__, socketName);
mFd = socket_local_server(socketName, ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
if (-1 == mFd) {
ALOGE("Create local socket server error: %d, %s.", errno, strerror(errno));
return -1;
}
//监听
if (-1 == listen(mFd, kMaxClientSize)) {
ALOGE("Local socket server listen error: %d, %s.", errno, strerror(errno));
return -1;
}
mConnectCount = 0;
mPollFds[mConnectCount].fd = mFd;
mPollFds[mConnectCount].events = POLLIN | POLLERR;
mPollFds[mConnectCount].revents = 0;
ALOGI("%s : X", __FUNCTION__);
return res;
}
void MyCameraSocketServer::sendExitThreadSignal(){
mIsExit = true;
requestExitAndWait();
if(mFd > 0){
close(mFd);
}
mFd = 0;
}
bool MyCameraSocketServer::threadLoop()
{
if(mIsExit) {
return false;
}
int ret = poll(mPollFds, mConnectCount + 1, 1000);
if (ret < 0) {
ALOGE("poll: %d, %s.", errno, strerror(errno));
return false;
} else if(ret == 0) { //超时
return true;
}
for (size_t i = 0; i <= mConnectCount; i++) {
// 连接关闭或出错,删除连接
if ((mPollFds[i].revents & POLLRDHUP) || (mPollFds[i].revents & POLLERR)) {
int fd = mPollFds[i].fd;
mPollFds[i] = mPollFds[mConnectCount];
i--;
mConnectCount--;
close(fd);
ALOGI("delete connection: %d", fd);
continue;
}
// 读取输入
if (mPollFds[i].revents & POLLIN) {
//如果fd等于socket fd,该消息为新的连接请求
if(mPollFds[i].fd == mFd) {
int conn = accept(mFd, NULL, NULL);
if (-1 == conn) {
ALOGE("accept error, %s.", strerror(errno));
return true;
} else if(mConnectCount > MAX_CONNECT_NUM) {
close(conn);
} else {
ALOGI("get connection %d. mConnectCount=%d", conn, mConnectCount);
mConnectCount++;
mPollFds[mConnectCount].fd = conn;
mPollFds[mConnectCount].events = POLLIN | POLLRDHUP | POLLERR;
mPollFds[mConnectCount].revents = 0;
}
} else {
//接受新消息
uint8_t buf[BUFFER_SIZE] = {0};
int recv_size = recv(mPollFds[i].fd, buf, BUFFER_SIZE - 1, 0);
if (recv_size > 0) {
ALOGI("MainLoop:recvSize: %d, buf:%s", recv_size, buf);
//处理消息
//doProcessRequest
}
}
}
}
ALOGI("MainLoop:%s : X", __FUNCTION__);
return true;
}
//发送消息到客户端
int MyCameraSocketServer::SendResponse(int fd, uint8_t* buf, int size) {
//调试过程中发现buf需要添加'\n'结束符,要不客户端收不到消息。
int ret;
ret = write(fd, buf, size);
if(ret < 0) {
ALOGE("response failed. buf:%s, err=%s", (char*)buf, strerror(errno));
return ret;
}
ALOGI(response success. buf:%s", (char*)buf);
return 0;
}
2. 客户端实现
实现java客户端。
主要调用:
a. 创建LocalSocket对象,并调用connect连接server
b. 获取socket输入输出流。
c. 创建线程调用BufferedReader.readLine读取输入内容。无消息时阻塞。返回NULL表明连接可能断开需要做异常处理。
d. 调用PrintWriter相关接口发送数据
Handler.Callback mHandlerCb = new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
switch(msg.what) {
//重新连接socket
case MSG_RECONNECT_SOCKET: {
if(mConnect != null) {
mConnect.interrupt();
mConnect = null;
}
mConnect = new CameraSocket();
}
break;
}
return true;
}
};
private class SocketClient extends Thread {
private LocalSocket mClientSocket;
private String mSocketName;
private PrintWriter mWriter;
private BufferedReader mReader;
SocketClient() {
mSocketName = "camera_hal_server";
Slog.i(TAG, "socket name:" + mSocketName);
connect();
}
void connect() {
try {
mClientSocket = new LocalSocket();
mClientSocket.connect(new LocalSocketAddress(mSocketName));
Slog.i(TAG, "Client=======connect success=========");
mWriter = new PrintWriter(mClientSocket.getOutputStream());
mReader = new BufferedReader(new InputStreamReader(mClientSocket.getInputStream()));
this.start();
} catch (IOException e) {
}
}
void close() {
try {
if(mReader != null) {
mReader.close();
mReader = null;
}
if(mWriter != null) {
mWriter.close();
mWriter = null;
}
mClientSocket.close();
} catch (IOException e) {
}
}
@Override
public void run() {
super.run();
//receive message
receive();
//Socket client over. close it.
close();
}
void receive() {
String result="";
while (mReader != null) {
try {
result = mReader.readLine();
Slog.i(TAG, "receive:" + result);
if (result == null) {
//连接可能断开,重新连接
mHandle.sendMessageDelayed(mHandle.obtainMessage(MSG_RECONNECT_SOCKET), 1000);
}
//处理服务端发来的消息
//processServerMessage
} catch (IOException e) {
e.printStackTrace();
}
}
}
//发送数据到server
void send() {
if (mWriter!=null) {
String value = "Hello server!";
mWriter.println(value);
mWriter.flush();
}
}
};