1、应用前景
一般的,fdbus的client端的实现是继承CBaseClient,override接口。由于使用CBaseClient的connect去连接Service时,失败不会有通知,只有成功才会有onOnline的通知,这就需要我们引入重连技术。另外假如Service端crash了,Client端会收到onOffline状态通知,收到onOffline也需要触发重连,直到Service进程启动后才会重连成功。
FDBUS Client重连Service依赖于onOnline和onOffline这两个状态,但似乎CBaseClient中没有相应的方法来获取这两个状态值,因此我这边引入了一个父类FdbusClientBase,由它来继承FDBUS的CBaseClient,FdbusClientBase主要增加setOnline和isOnline两个方法,我们的Client只需要继承父类FdbusClientBase,不需要继承CBaseClient。
2、FdbusCluetBase实现
FdbusClientBase有如下几个方法:
class FdbusClientBase : public CBaseClient, public android::RefBase {
public:
FdbusClientBase(const std::string& url, const std::string& name, CBaseWorker *worker)
: CBaseClient(name.c_str(), worker),
mOnline(false),
mUrl(url) {
}
virtual ~FdbusClientBase() {
}
virtual bool isOnline() {
MuxGuard g(mLock);
return mOnline;
}
virtual void setOnline(bool online) {
MuxGuard g(mLock);
mOnline = online;
}
virtual std::string getUrl() {
return mUrl;
}
protected:
bool mOnline;
std::string mUrl;
using MuxGuard = std::lock_guard<std::mutex>;
mutable std::mutex mLock;
};
子类继承它的例子:
.h文件
class CANFdbusClient : public FdbusClientBase {
public:
CANFdbusClient(const string& url, const string& name, CBaseWorker *worker, MessageTransceiver* transceiver);
~CANFdbusClient();
ProxyStatusCode sendMessage(IPC_MODULE_GROUP groupId, const uint8_t * data, int32_t length);
void onReceiveMsg(IPC_MODULE_GROUP groupId, const VehicleMessage& vehicleMsg);
virtual void onOffline(FdbSessionId_t sid, bool is_last) override;
virtual void onOnline(FdbSessionId_t sid, bool is_first) override;
virtual void onBroadcast(CBaseJob::Ptr &msg_ref) override;
virtual void onStatus(CBaseJob::Ptr &msg_ref, int error_code,
const char *description) override;
virtual void onReply(CBaseJob::Ptr &msg_ref);
private:
MessageTransceiver *mTransceiver;
bool mFdbusOnline;
};
重要实现:
保存online和offline状态值:
3、Timer实现类
多个client的情况:
class FdbusConnectionTimer : public android::RefBase{
public:
FdbusConnectionTimer() {
}
virtual ~FdbusConnectionTimer() {
mIsActive = false;
}
void addFdbusClient(android::sp<FdbusClientBase> client) {
std::lock_guard<std::mutex> g(mLock);
mClientList.push_back(client);
}
void startTimer() {
mIsActive = true;
mTimerThread = std::thread(&FdbusConnectionTimer::loop, this);
}
void stopTimer() {
mIsActive = false;
mStopRequested = true;
mCond.notify_one();
if (mTimerThread.joinable()) {
mTimerThread.join();
}
}
bool isDeactive() {
return !mIsActive;
}
private:
void loop() {
int32_t retryCount = 0;
while (!mStopRequested) {
if(mClientList.size() > 0) {
for(android::sp<FdbusClientBase> client : mClientList) {
if(client != nullptr && !client->isOnline()) {
ALOGD("%s retry to connect to %s", __func__, client->getUrl().c_str());
client->connect(client->getUrl().c_str());
retryCount++;
} else if(client != nullptr && client->isOnline()) {
ALOGD("%s client connect to %s successfully", __func__, client->getUrl().c_str());
for(std::vector<android::sp<FdbusClientBase>>::iterator iter = mClientList.begin(); iter != mClientList.end(); iter++){
if(*iter == client){
MuxGuard g(mLock);
mClientList.erase(iter);
break;
}
}
}
}
std::unique_lock<std::mutex> g(mLock);
mCond.wait_for(g, std::chrono::seconds(1)); // wait 1 second
} else {
// All client are online,so stop loop
mIsActive = false;
break;
}
}
ALOGD("%s total retryCount: %d", __func__, retryCount);
}
private:
using MuxGuard = std::lock_guard<std::mutex>;
mutable std::mutex mLock;
std::thread mTimerThread;
std::condition_variable mCond;
std::atomic_bool mStopRequested { false };
std::atomic_bool mIsActive { false };
std::vector<android::sp<FdbusClientBase>> mClientList;
};
单个client的情况:
/*************************************************************************
* Copyright (C) 2020 GWM Automotive Inc.
*
* The copyright notice above does not evidence any actual
* or intended publication of such source code.
* The code contains GWM Confidential Proprietary Information.
*************************************************************************/
/**************************************************************************
* @file FdbusConnectionTimer.h
* FdbusConnectionTimer
*
* @project v3.5
* @subsystem
* @version 0.1
* @author
* @date 2020-7-30
Module-History:
Date(dd.mm.year)| Author | Reason
The latest entry at the head of the history list.
8/4/2020 Fugen Peng Init version
***************************************************************************/
#ifndef vendor_noch_hardware_automotive_vehicle_V1_0_impl_FdbusConnectionTimer_H_
#define vendor_noch_hardware_automotive_vehicle_V1_0_impl_FdbusConnectionTimer_H_
#include <thread>
#include <chrono>
#include <mutex>
#include <condition_variable>
#include <common_base/fdbus.h>
#include "FdbusClientBase.h"
#include <log/log.h>
#include <utils/RefBase.h>
#undef LOG_TAG
#define LOG_TAG "FdbusConnectionTimer"
namespace vendor {
namespace noch {
namespace hardware {
namespace automotive {
namespace vehicle {
namespace V1_0 {
class FdbusConnectionTimer : public android::RefBase{
public:
FdbusConnectionTimer() {
}
virtual ~FdbusConnectionTimer() {
mIsActive = false;
}
void addFdbusClient(android::sp<FdbusClientBase> client) {
std::lock_guard<std::mutex> g(mLock);
mClient = client;
}
void startTimer() {
mIsActive = true;
mTimerThread = std::thread(&FdbusConnectionTimer::loop, this);
}
void stopTimer() {
mIsActive = false;
mStopRequested = true;
mCond.notify_one();
if (mTimerThread.joinable()) {
mTimerThread.join();
}
}
bool isDeactive() {
return !mIsActive;
}
private:
void loop() {
int32_t retryCount = 0;
while (!mStopRequested) {
if ((mClient != nullptr) && !mClient->isOnline()) {
ALOGD("%s retry to connect to %s", __func__, mClient->getUrl().c_str());
mClient->connect(mClient->getUrl().c_str());
retryCount++;
}
else {
mIsActive = false;
ALOGD("%s client connect to %s successfully", __func__, mClient->getUrl().c_str());
break;
}
std::unique_lock<std::mutex> g(mLock);
mCond.wait_for(g, std::chrono::seconds(1)); // wait 1 second
}
ALOGD("%s total retryCount: %d", __func__, retryCount);
}
private:
using MuxGuard = std::lock_guard<std::mutex>;
mutable std::mutex mLock;
std::thread mTimerThread;
std::condition_variable mCond;
std::atomic_bool mStopRequested { false };
std::atomic_bool mIsActive { false };
sp<FdbusClientBase> mClient;
};
}
}
}
}
}
}
#endif
触发Timer
开机触发Timer
void MessageTransceiver::fdbus_init() {
/* start fdbus context thread */
FDB_CONTEXT->start();
/* start worker thread */
CBaseWorker *worker_ptr = &main_worker;
worker_ptr->start();
/* create client to connect mcuipc server */
std::string mcuipcsrv_name = "fdbus_mcu_ipc";
std::string mcuipcsrv_url(FDB_URL_SVC);
mcuipcsrv_url += mcuipcsrv_name;
mCANFdbusClient = new CANFdbusClient(mcuipcsrv_url, mcuipcsrv_name, worker_ptr, this);
assert(mCANFdbusClient != nullptr);
mCANFdbusClient->enableReconnect(true);
mCANFdbusClient->connect(mcuipcsrv_url.c_str());
/* create client to connect display server */
std::string backlightsrv_name = "fdbus_backlight";
std::string backlightsrv_url(FDB_URL_SVC);
backlightsrv_url += backlightsrv_name;
mDisplayFdbusClient = new DisplayFdbusClient(backlightsrv_url, backlightsrv_name, worker_ptr, this);
assert(mDisplayFdbusClient != nullptr);
mDisplayFdbusClient->enableReconnect(true);
mDisplayFdbusClient->connect(backlightsrv_url.c_str());
mConTimer = new FdbusConnectionTimer();
assert(mConTimer != nullptr);
mConTimer->addFdbusClient(mCANFdbusClient);
// display server is not ready
// mConTimer->addFdbusClient(mDisplayFdbusClient);
if(mConTimer->isDeactive()) {
mConTimer->startTimer();
}
}
onOffline时触发
void MessageTransceiver::notifyFdbusOffline(sp<FdbusClientBase> client) {
mConTimer->addFdbusClient(client);
if(mConTimer->isDeactive()) {
mConTimer->startTimer();
}
}
void CANFdbusClient::onOffline(FdbSessionId_t sid, bool is_last) {
ALOGD("%s client session offline: %d", __func__, sid);
setOnline(false);
if(mTransceiver != nullptr) {
mTransceiver->notifyFdbusOffline(this);
}
}