From ff8b31761cff3098444c41c8daa7baa6dff92ccd Mon Sep 17 00:00:00 2001 From: Harikrishnan Hariharan Date: Fri, 11 Aug 2017 17:36:10 +0530 Subject: Integrate XtraSysStatObs with SystemStatusObserver Use SystemStatusObserver to subscribe for dataitems in XtraSystemStatusObserver. Change-Id: Ib1828b9025c9c5bb5194a36014249472ed3f6f9e CRs-Fixed: 2093290 --- core/SystemStatus.cpp | 74 ++- core/SystemStatus.h | 182 +++++++ core/SystemStatusOsObserver.cpp | 991 ++++++++++++++++++-------------------- core/SystemStatusOsObserver.h | 294 ++--------- gnss/GnssAdapter.cpp | 3 +- gnss/GnssAdapter.h | 6 +- gnss/XtraSystemStatusObserver.cpp | 121 ++++- gnss/XtraSystemStatusObserver.h | 31 +- gnss/location_gnss.cpp | 2 +- 9 files changed, 914 insertions(+), 790 deletions(-) diff --git a/core/SystemStatus.cpp b/core/SystemStatus.cpp index dc03604..52d28c7 100644 --- a/core/SystemStatus.cpp +++ b/core/SystemStatus.cpp @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -1212,7 +1213,8 @@ IOsObserver* SystemStatus::getOsObserver() } SystemStatus::SystemStatus(const MsgTask* msgTask) : - mSysStatusObsvr(msgTask) + mSysStatusObsvr(msgTask), + mConnected(false) { int result = 0; ENTRY_LOG (); @@ -1413,6 +1415,28 @@ bool SystemStatus::setPositionFailure(const SystemStatusPQWS1& nmea) return true; } +/****************************************************************************** + SystemStatus - storing dataitems +******************************************************************************/ +bool SystemStatus::setNetworkInfo(IDataItemCore* dataitem) +{ + SystemStatusNetworkInfo* data = reinterpret_cast(dataitem); + SystemStatusNetworkInfo s(data->mType,data->mTypeName,data->mSubTypeName, + data->mAvailable,data->mConnected,data->mRoaming); + s.dump(); + mConnected = data->mConnected; + + if (!mCache.mNetworkInfo.empty() && mCache.mNetworkInfo.back().equals(s)) { + mCache.mNetworkInfo.back().mUtcReported = s.mUtcReported; + } else { + mCache.mNetworkInfo.push_back(s); + if (mCache.mNetworkInfo.size() > maxNetworkInfo) { + mCache.mNetworkInfo.erase(mCache.mNetworkInfo.begin()); + } + } + return true; +} + /****************************************************************************** @brief API to set report data into internal buffer @@ -1533,6 +1557,26 @@ bool SystemStatus::eventPosition(const UlpLocation& location, return true; } +/****************************************************************************** +@brief API to set report DataItem event into internal buffer + +@param[In] DataItem + +@return true when successfully done +******************************************************************************/ +bool SystemStatus::eventDataItemNotify(IDataItemCore* dataitem) +{ + pthread_mutex_lock(&mMutexSystemStatus); + switch(dataitem->getId()) + { + case NETWORKINFO_DATA_ITEM_ID: + setNetworkInfo(dataitem); + break; + } + pthread_mutex_unlock(&mMutexSystemStatus); + return true; +} + /****************************************************************************** @brief API to get report data into a given buffer @@ -1712,5 +1756,33 @@ bool SystemStatus::setDefaultReport(void) return true; } +/****************************************************************************** +@brief API to handle connection status update event from GnssRil + +@param[In] Connection status + +@return true when successfully done +******************************************************************************/ +bool SystemStatus::eventConnectionStatus(bool connected, uint8_t type) +{ + if (connected != mConnected) { + mConnected = connected; + + // send networkinof dataitem to systemstatus observer clients + SystemStatusNetworkInfo s(type, "", "", false, connected, false); + IDataItemCore *networkinfo = + DataItemsFactoryProxy::createNewDataItem(NETWORKINFO_DATA_ITEM_ID); + if (nullptr == networkinfo) { + LOC_LOGE("Unable to create dataitemd"); + return false; + } + networkinfo->copy(&s); + list dl(0); + dl.push_back(networkinfo); + mSysStatusObsvr.notify(dl); + } + return true; +} + } // namespace loc_core diff --git a/core/SystemStatus.h b/core/SystemStatus.h index 8cf75b5..5dc2d9f 100644 --- a/core/SystemStatus.h +++ b/core/SystemStatus.h @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -367,19 +368,183 @@ public: void dump(void); }; +/****************************************************************************** + SystemStatus report data structure - from DataItem observer +******************************************************************************/ +class SystemStatusGpsState : public SystemStatusItemBase, public IDataItemCore +{ +public: + inline SystemStatusGpsState() : + mEnabled(false) {} + inline SystemStatusGpsState(bool enabled) : + mEnabled(enabled) {} + + bool mEnabled; + + inline bool equals(SystemStatusGpsState& peer) { + return (mEnabled == peer.mEnabled); + } + inline void dump(void) { + LOC_LOGD("GpsState: state=%u", mEnabled); + } + inline DataItemId getId() { + return GPSSTATE_DATA_ITEM_ID; + } + inline void stringify(string& valueStr) { + valueStr.clear(); + valueStr += "GpsState: enabled="; + valueStr += to_string(mEnabled); + } + inline int32_t copy(IDataItemCore* src, bool* dataItemCopied = nullptr) { + SystemStatusGpsState* gpsstate = static_cast(src); + mEnabled = gpsstate->mEnabled; + if (dataItemCopied) { + *dataItemCopied = true; + } + return 1; + } +}; + +class SystemStatusNetworkInfo : public SystemStatusItemBase, public IDataItemCore +{ +public: + inline SystemStatusNetworkInfo() : + mType(0), + mTypeName(""), + mSubTypeName(""), + mAvailable(false), + mConnected(false), + mRoaming(false) {} + inline SystemStatusNetworkInfo( + uint32_t type, + std::string typeName, + std::string subTypeName, + bool available, + bool connected, + bool roaming) : + mType(type), + mTypeName(typeName), + mSubTypeName(subTypeName), + mAvailable(available), + mConnected(connected), + mRoaming(roaming) {} + + uint32_t mType; + std::string mTypeName; + std::string mSubTypeName; + bool mAvailable; + bool mConnected; + bool mRoaming; + + inline bool equals(SystemStatusNetworkInfo& peer) { + if ((mType != peer.mType) || + (mTypeName != peer.mTypeName) || + (mSubTypeName != peer.mSubTypeName) || + (mAvailable != peer.mAvailable) || + (mConnected != peer.mConnected) || + (mRoaming != peer.mRoaming)) { + return false; + } + return true; + } + inline void dump(void) { + LOC_LOGD("NetworkInfo: type=%u connected=%u", mType, mConnected); + } + inline DataItemId getId() { + return NETWORKINFO_DATA_ITEM_ID; + } + inline void stringify(string& /*valueStr*/) { } + inline int32_t copy(IDataItemCore* src, bool* dataItemCopied = nullptr) { + SystemStatusNetworkInfo* networkinfo = static_cast(src); + mType = networkinfo->mType; + mTypeName = networkinfo->mTypeName; + mSubTypeName = networkinfo->mSubTypeName; + mAvailable = networkinfo->mAvailable; + mConnected = networkinfo->mConnected; + mRoaming = networkinfo->mRoaming; + if (dataItemCopied) { + *dataItemCopied = true; + } + return 1; + } +}; + +class SystemStatusTac : public SystemStatusItemBase, public IDataItemCore +{ +public: + inline SystemStatusTac() : + mValue("") {} + inline SystemStatusTac(std::string value) : + mValue(value) {} + + std::string mValue; + + inline bool equals(SystemStatusTac& peer) { + return (mValue == peer.mValue); + } + inline void dump(void) { + LOC_LOGD("Tac: value=%s", mValue.c_str()); + } + inline DataItemId getId() { + return TAC_DATA_ITEM_ID; + } + inline void stringify(string& /*valueStr*/) { } + inline int32_t copy(IDataItemCore* src, bool* dataItemCopied = nullptr) { + SystemStatusTac* tac = static_cast(src); + mValue = tac->mValue; + if (dataItemCopied) { + *dataItemCopied = true; + } + return 1; + } +}; + +class SystemStatusMccMnc : public SystemStatusItemBase, public IDataItemCore +{ +public: + inline SystemStatusMccMnc() : + mValue("") {} + inline SystemStatusMccMnc(std::string value) : + mValue(value) {} + + std::string mValue; + + inline bool equals(SystemStatusMccMnc& peer) { + return (mValue == peer.mValue); + } + inline void dump(void) { + LOC_LOGD("TacMccMnc value=%s", mValue.c_str()); + } + inline DataItemId getId() { + return MCCMNC_DATA_ITEM_ID; + } + inline void stringify(string& /*valueStr*/) { } + inline int32_t copy(IDataItemCore* src, bool* dataItemCopied = nullptr) { + SystemStatusMccMnc* mccmnc = static_cast(src); + mValue = mccmnc->mValue; + if (dataItemCopied) { + *dataItemCopied = true; + } + return 1; + } +}; + /****************************************************************************** SystemStatusReports ******************************************************************************/ class SystemStatusReports { public: + // from QMI_LOC indication std::vector mLocation; + // from ME debug NMEA std::vector mTimeAndClock; std::vector mXoState; std::vector mRfAndParams; std::vector mErrRecovery; + // from PE debug NMEA std::vector mInjectedPosition; std::vector mBestPosition; std::vector mXtra; @@ -388,7 +553,14 @@ public: std::vector mPdr; std::vector mNavData; + // from SM debug NMEA std::vector mPositionFailure; + + // from dataitems observer + std::vector mGpsState; + std::vector mNetworkInfo; + std::vector mTac; + std::vector mMccMnc; }; /****************************************************************************** @@ -424,7 +596,13 @@ private: static const uint32_t maxPositionFailure = 5; + static const uint32_t maxGpsState = 5; + static const uint32_t maxNetworkInfo = 5; + static const uint32_t maxTac = 5; + static const uint32_t maxMccMnc = 5; + SystemStatusReports mCache; + bool mConnected; bool setLocation(const UlpLocation& location); @@ -443,6 +621,8 @@ private: bool setPositionFailure(const SystemStatusPQWS1& nmea); + bool setNetworkInfo(IDataItemCore* dataitem); + public: // Static methods static SystemStatus* getInstance(const MsgTask* msgTask); @@ -451,9 +631,11 @@ public: // Helpers bool eventPosition(const UlpLocation& location,const GpsLocationExtended& locationEx); + bool eventDataItemNotify(IDataItemCore* dataitem); bool setNmeaString(const char *data, uint32_t len); bool getReport(SystemStatusReports& reports, bool isLatestonly = false) const; bool setDefaultReport(void); + bool eventConnectionStatus(bool connected, uint8_t type); }; } // namespace loc_core diff --git a/core/SystemStatusOsObserver.cpp b/core/SystemStatusOsObserver.cpp index e327f93..319f1d7 100644 --- a/core/SystemStatusOsObserver.cpp +++ b/core/SystemStatusOsObserver.cpp @@ -28,618 +28,565 @@ */ #define LOG_TAG "LocSvc_SystemStatusOsObserver" -#include -#include -#include -#include -#include -#include -#include #include - -#include +#include #include - -#include #include #include #include #include - #include -#include - namespace loc_core { -#define BREAK_IF_ZERO(ERR,X) if(0==(X)) {result = (ERR); break;} -#define BREAK_IF_NON_ZERO(ERR,X) if(0!=(X)) {result = (ERR); break;} - SystemStatusOsObserver::SystemStatusOsObserver(const MsgTask* msgTask) : - mAddress ("SystemStatusOsObserver"), - mClientIndex(IndexFactory :: createClientIndex ()), - mDataItemIndex(IndexFactory :: createDataItemIndex ()) + mAddress("SystemStatusOsObserver"), + mClientIndex(IndexFactory :: createClientIndex()), + mDataItemIndex(IndexFactory :: createDataItemIndex()) { - int result = -1; - ENTRY_LOG (); - do { - BREAK_IF_ZERO (1, mClientIndex); - BREAK_IF_ZERO (2, mDataItemIndex); - mContext.mMsgTask = msgTask; - result = 0; - } while (0); - EXIT_LOG_WITH_ERROR ("%d",result); + mContext.mMsgTask = msgTask; } -SystemStatusOsObserver :: ~SystemStatusOsObserver () +SystemStatusOsObserver::~SystemStatusOsObserver() { // Close data-item library handle DataItemsFactoryProxy::closeDataItemLibraryHandle(); // Destroy cache - map :: iterator citer = mDataItemCache.begin (); - for (; citer != mDataItemCache.end (); ++citer) { - if (citer->second != NULL) { delete citer->second; } + for (auto each : mDataItemCache) { + if (nullptr != each.second) { + delete each.second; + } } - mDataItemCache.clear (); + + mDataItemCache.clear(); delete mClientIndex; delete mDataItemIndex; - mClientIndex = NULL; - mDataItemIndex = NULL; } -/****************************************************************************** - Message proc -******************************************************************************/ -void SystemStatusOsObserver :: HandleSubscribeReq :: proc () const { - - int result = 0; - ENTRY_LOG (); - do { - if (mDataItemList.empty ()) { - LOC_LOGV("mDataItemList is empty. Nothing to do. Exiting"); - result = 0; - break; - } - //mDataItemList.sort (); - // Handle First Response - list pendingFirstResponseList; - this->mParent->mClientIndex->add (this->mClient, mDataItemList, pendingFirstResponseList); - - // Do not send first response for only pendingFirstResponseList, - // instead send for all the data items (present in the cache) that - // have been subscribed for each time. - this->mParent->sendFirstResponse (mDataItemList, this->mClient); - - list yetToSubscribeDataItemsList; - this->mParent->mDataItemIndex->add (this->mClient, mDataItemList, yetToSubscribeDataItemsList); - // Send subscription list to framework - if (!yetToSubscribeDataItemsList.empty ()) { - this->mParent->mContext.mSubscriptionObj->subscribe - ( - yetToSubscribeDataItemsList, - this->mParent - ); - LOC_LOGD ("Subscribe Request sent to framework for the following data items"); - this->mParent->logMe (yetToSubscribeDataItemsList); - } +void SystemStatusOsObserver::setSubscriptionObj(IDataItemSubscription* subscriptionObj) +{ + mContext.mSubscriptionObj = subscriptionObj; + + LOC_LOGD("Request cache size - Subscribe:%zu RequestData:%zu", + mSubscribeReqCache.size(), mReqDataCache.size()); - } while (0); - EXIT_LOG_WITH_ERROR ("%d", result); - return; + // we have received the subscription object. process cached requests + // process - subscribe request cache + for (auto each : mSubscribeReqCache) { + subscribe(each.second, each.first); + } + // process - requestData request cache + for (auto each : mReqDataCache) { + requestData(each.second, each.first); + } } -void SystemStatusOsObserver :: HandleUpdateSubscriptionReq :: proc () const { - int result = 0; - ENTRY_LOG (); - do { - if (mDataItemList.empty ()) { - LOC_LOGV("mDataItemList is empty. Nothing to do. Exiting"); - result = 0; - break; - } - //mDataItemList.sort (); - list currentlySubscribedList; - this->mParent->mClientIndex->getSubscribedList (this->mClient, currentlySubscribedList); - list removeDataItemList; - set_difference (currentlySubscribedList.begin (), currentlySubscribedList.end (), - mDataItemList.begin (), mDataItemList.end (), - inserter (removeDataItemList,removeDataItemList.begin ())); - // Handle First Response - list pendingFirstResponseList; - this->mParent->mClientIndex->add (this->mClient, mDataItemList, pendingFirstResponseList); - // Send First Response - this->mParent->sendFirstResponse (pendingFirstResponseList, this->mClient); - - list yetToSubscribeDataItemsList; - this->mParent->mDataItemIndex->add (this->mClient, mDataItemList, yetToSubscribeDataItemsList); - // Send subscription list to framework - if (!yetToSubscribeDataItemsList.empty ()) { - this->mParent->mContext.mSubscriptionObj->subscribe - ( - yetToSubscribeDataItemsList, - this->mParent - ); - LOC_LOGD ("Subscribe Request sent to framework for the following data items"); - this->mParent->logMe (yetToSubscribeDataItemsList); +// Helper to cache requests subscribe and requestData till subscription obj is obtained +void SystemStatusOsObserver::cacheObserverRequest(ObserverReqCache& reqCache, + const list& l, IDataItemObserver* client) +{ + ObserverReqCache::iterator dicIter = reqCache.find(client); + if (dicIter != reqCache.end()) { + // found + list difference(0); + set_difference(l.begin(), l.end(), + dicIter->second.begin(), dicIter->second.end(), + inserter(difference, difference.begin())); + if (!difference.empty()) { + difference.sort(); + dicIter->second.merge(difference); + dicIter->second.unique(); } + } + else { + // not found + reqCache[client] = l; + } +} - list unsubscribeList; - list unused; - this->mParent->mClientIndex->remove (this->mClient, removeDataItemList, unused); +/****************************************************************************** + IDataItemSubscription Overrides +******************************************************************************/ +void SystemStatusOsObserver::subscribe( + const list& l, IDataItemObserver* client) +{ + if (nullptr == mContext.mSubscriptionObj) { + LOC_LOGD("%s]: Subscription object is NULL. Caching requests", __func__); + cacheObserverRequest(mSubscribeReqCache, l, client); + return; + } - if (!this->mParent->mClientIndex->isSubscribedClient (this->mClient)) { - this->mParent->mDataItemIndex->remove (list (1,this->mClient), unsubscribeList); - } - if (!unsubscribeList.empty ()) { - // Send unsubscribe to framework - this->mParent->mContext.mSubscriptionObj->unsubscribe - ( - unsubscribeList, - this->mParent - ); - LOC_LOGD ("Unsubscribe Request sent to framework for the following data items"); - this->mParent->logMe (unsubscribeList); - } - } while (0); - EXIT_LOG_WITH_ERROR ("%d",result); -} + struct HandleSubscribeReq : public LocMsg { + HandleSubscribeReq(SystemStatusOsObserver* parent, + const list& l, IDataItemObserver* client) : + mParent(parent), mClient(client), mDataItemList(l) {} + virtual ~HandleSubscribeReq() {} + void proc() const { -void SystemStatusOsObserver :: HandleRequestData :: proc () const { - int result = 0; - ENTRY_LOG (); + if (mDataItemList.empty()) { + LOC_LOGV("mDataItemList is empty. Nothing to do. Exiting"); + return; + } - do { - if (mDataItemList.empty ()) { - LOC_LOGV("mDataItemList is empty. Nothing to do. Exiting"); - result = 0; - break; - } - //mDataItemList.sort (); - list yetToSubscribeDataItemsList; - this->mParent->mClientIndex->add (this->mClient, mDataItemList, yetToSubscribeDataItemsList); - this->mParent->mDataItemIndex->add (this->mClient, mDataItemList, yetToSubscribeDataItemsList); - // Send subscription list to framework - if (!mDataItemList.empty ()) { - this->mParent->mContext.mSubscriptionObj->requestData - ( - mDataItemList, - this->mParent - ); - LOC_LOGD ("Subscribe Request sent to framework for the following data items"); - this->mParent->logMe (yetToSubscribeDataItemsList); - } + // Handle First Response + list pendingFirstResponseList(0); + mParent->mClientIndex->add(mClient, mDataItemList, pendingFirstResponseList); - } while (0); - EXIT_LOG_WITH_ERROR ("%d",result); -} + // Do not send first response for only pendingFirstResponseList, + // instead send for all the data items (present in the cache) that + // have been subscribed for each time. + mParent->sendFirstResponse(mDataItemList, mClient); -void SystemStatusOsObserver :: HandleUnsubscribeReq :: proc () const { - int result = 0; - ENTRY_LOG (); - do { - if (mDataItemList.empty ()) { - LOC_LOGV("mDataItemList is empty. Nothing to do. Exiting"); - result = 0; - break; - } - //mDataItemList.sort (); - list unsubscribeList; - list unused; - this->mParent->mClientIndex->remove (this->mClient, mDataItemList, unused); - - list :: const_iterator it = mDataItemList.begin (); - for (; it != mDataItemList.end (); ++it) { - list clientListSubs; - list clientListOut; - this->mParent->mDataItemIndex->remove ((*it), - list (1,this->mClient), clientListOut); - // check if there are any other subscribed client for this data item id - this->mParent->mDataItemIndex->getListOfSubscribedClients ( (*it), clientListSubs); - if (clientListSubs.empty()) - { - LOC_LOGD ("Client list subscribed is empty for dataitem - %d",(*it)); - unsubscribeList.push_back((*it)); - } - } - if (!unsubscribeList.empty ()) { - // Send unsubscribe to framework - this->mParent->mContext.mSubscriptionObj->unsubscribe - ( - unsubscribeList, - this->mParent - ); - LOC_LOGD ("Unsubscribe Request sent to framework for the following data items"); - this->mParent->logMe (unsubscribeList); - } - } while (0); - EXIT_LOG_WITH_ERROR ("%d",result); -} + list yetToSubscribeDataItemsList(0); + mParent->mDataItemIndex->add(mClient, mDataItemList, yetToSubscribeDataItemsList); -void SystemStatusOsObserver :: HandleUnsubscribeAllReq :: proc () const { - int result = 0; - ENTRY_LOG (); - do { - list clients (1, this->mClient); - list unsubscribeList; - BREAK_IF_NON_ZERO (2, this->mParent->mClientIndex->remove (this->mClient)); - - - this->mParent->mDataItemIndex->remove (clients, unsubscribeList); - if (!unsubscribeList.empty ()) { - // Send unsubscribe to framework - this->mParent->mContext.mSubscriptionObj->unsubscribe - ( - unsubscribeList, - this->mParent - ); - LOC_LOGD ("Unsubscribe Request sent to framework for the following data items"); - this->mParent->logMe (unsubscribeList); + // Send subscription list to framework + if (!yetToSubscribeDataItemsList.empty()) { + mParent->mContext.mSubscriptionObj->subscribe(yetToSubscribeDataItemsList, mParent); + LOC_LOGD("Subscribe Request sent to framework for the following"); + mParent->logMe(yetToSubscribeDataItemsList); + } } - } while (0); - EXIT_LOG_WITH_ERROR ("%d",result); + SystemStatusOsObserver* mParent; + IDataItemObserver* mClient; + const list mDataItemList; + }; + mContext.mMsgTask->sendMsg(new (nothrow) HandleSubscribeReq(this, l, client)); } -void SystemStatusOsObserver :: HandleNotify :: getListOfClients - (const list & dlist, list & clients ) const { - - list :: const_iterator it = dlist.begin (); - for (; it != dlist.end (); ++it) { - list clientList; - this->mParent->mDataItemIndex->getListOfSubscribedClients ( (*it), clientList); - list :: iterator citer = clientList.begin (); - for (; citer != clientList.end (); ++citer) { - clients.push_back (*citer); - } - clientList.clear (); - } - // remove duplicates - clients.unique (); -} +void SystemStatusOsObserver::updateSubscription( + const list& l, IDataItemObserver* client) +{ + if (nullptr == mContext.mSubscriptionObj) { + LOC_LOGE("%s:%d]: Subscription object is NULL", __func__, __LINE__); + return; + } -void SystemStatusOsObserver :: HandleNotify :: proc () const { - int result = 0; - ENTRY_LOG (); - do { - // Update Cache with received data items and prepare - // list of data items to be sent. - list :: const_iterator it = mDList.begin (); - list dataItemIdsToBeSent; - for (; it != mDList.end (); ++it) { - bool dataItemUpdated = false; - this->mParent->updateCache (*it, dataItemUpdated); - if (dataItemUpdated) { - dataItemIdsToBeSent.push_back ( (*it)->getId ()); + struct HandleUpdateSubscriptionReq : public LocMsg { + HandleUpdateSubscriptionReq(SystemStatusOsObserver* parent, + const list& l, IDataItemObserver* client) : + mParent(parent), mClient(client), mDataItemList(l) {} + virtual ~HandleUpdateSubscriptionReq() {} + void proc() const { + if (mDataItemList.empty()) { + LOC_LOGV("mDataItemList is empty. Nothing to do. Exiting"); + return; } - } - list clientList; - this->getListOfClients (dataItemIdsToBeSent, clientList); - list :: iterator citer = clientList.begin (); - // Send data item to all subscribed clients - LOC_LOGD ("LocTech-Label :: SystemStatusOsObserver :: Data Items Out"); - for (; citer != clientList.end (); ++citer) { - do { - list dataItemIdsSubscribedByThisClient; - list dataItemIdsToBeSentForThisClient; - this->mParent->mClientIndex->getSubscribedList (*citer, dataItemIdsSubscribedByThisClient); - dataItemIdsSubscribedByThisClient.sort (); - dataItemIdsToBeSent.sort (); - set_intersection (dataItemIdsToBeSent.begin (), - dataItemIdsToBeSent.end (), - dataItemIdsSubscribedByThisClient.begin (), - dataItemIdsSubscribedByThisClient.end (), - inserter (dataItemIdsToBeSentForThisClient, - dataItemIdsToBeSentForThisClient.begin ())); - BREAK_IF_NON_ZERO (4,this->mParent->sendCachedDataItems (dataItemIdsToBeSentForThisClient, *citer)); - dataItemIdsSubscribedByThisClient.clear (); - dataItemIdsToBeSentForThisClient.clear (); - } while (0); - } - } while (0); - EXIT_LOG_WITH_ERROR ("%d", result); -} + list currentlySubscribedList(0); + mParent->mClientIndex->getSubscribedList(mClient, currentlySubscribedList); -void SystemStatusOsObserver :: HandleTurnOn :: proc () const { - int result = 0; - ENTRY_LOG (); - do { - // Send action turn on to framework - this->mParent->mContext.mFrameworkActionReqObj->turnOn(mDataItemId, mTimeOut); - } while (0); - EXIT_LOG_WITH_ERROR ("%d", result); -} + list removeDataItemList(0); + set_difference(currentlySubscribedList.begin(), currentlySubscribedList.end(), + mDataItemList.begin(), mDataItemList.end(), + inserter(removeDataItemList,removeDataItemList.begin())); -void SystemStatusOsObserver :: HandleTurnOff :: proc () const { - int result = 0; - ENTRY_LOG (); - do { - // Send action turn off to framework - this->mParent->mContext.mFrameworkActionReqObj->turnOff(mDataItemId); - } while (0); - EXIT_LOG_WITH_ERROR ("%d", result); -} + // Handle First Response + list pendingFirstResponseList(0); + mParent->mClientIndex->add(mClient, mDataItemList, pendingFirstResponseList); -/****************************************************************************** - IDataItemSubscription Overrides -******************************************************************************/ -void SystemStatusOsObserver :: subscribe (const list & l, IDataItemObserver * client) { - int result = 0; - ENTRY_LOG (); - do { - if (mContext.mSubscriptionObj != NULL) { - HandleSubscribeReq * msg = new (nothrow) HandleSubscribeReq (this, l, client); - mContext.mMsgTask->sendMsg (msg); - } - else { - LOC_LOGE("%s:%d]: Subscription object is NULL", __func__, __LINE__); - result = 1; - } - } while (0); - EXIT_LOG_WITH_ERROR ("%d",result); -} + // Send First Response + mParent->sendFirstResponse(pendingFirstResponseList, mClient); -void SystemStatusOsObserver :: updateSubscription (const list & l, IDataItemObserver * client) { - int result = 0; - ENTRY_LOG (); - do { - if (mContext.mSubscriptionObj != NULL) { - mContext.mMsgTask->sendMsg (new (nothrow) HandleUpdateSubscriptionReq (this, l, client)); - } - else { - LOC_LOGE("%s:%d]: Subscription object is NULL", __func__, __LINE__); - result = 1; + list yetToSubscribeDataItemsList(0); + mParent->mDataItemIndex->add( + mClient, mDataItemList, yetToSubscribeDataItemsList); + + // Send subscription list to framework + if (!yetToSubscribeDataItemsList.empty()) { + mParent->mContext.mSubscriptionObj->subscribe( + yetToSubscribeDataItemsList, mParent); + LOC_LOGD("Subscribe Request sent to framework for the following"); + mParent->logMe(yetToSubscribeDataItemsList); + } + + list unsubscribeList(0); + list unused(0); + mParent->mClientIndex->remove(mClient, removeDataItemList, unused); + + if (!mParent->mClientIndex->isSubscribedClient(mClient)) { + mParent->mDataItemIndex->remove( + list (1,mClient), unsubscribeList); + } + if (!unsubscribeList.empty()) { + // Send unsubscribe to framework + mParent->mContext.mSubscriptionObj->unsubscribe(unsubscribeList, mParent); + LOC_LOGD("Unsubscribe Request sent to framework for the following"); + mParent->logMe(unsubscribeList); + } } - } while (0); - EXIT_LOG_WITH_ERROR ("%d",result); + SystemStatusOsObserver* mParent; + IDataItemObserver* mClient; + const list mDataItemList; + }; + mContext.mMsgTask->sendMsg(new (nothrow) HandleUpdateSubscriptionReq(this, l, client)); } -void SystemStatusOsObserver :: requestData (const list & l, IDataItemObserver * client) { - int result = 0; - ENTRY_LOG (); - do { - if (mContext.mSubscriptionObj != NULL) { - mContext.mMsgTask->sendMsg (new (nothrow) HandleRequestData (this, l, client)); - } - else { - LOC_LOGE("%s:%d]: Subscription object is NULL", __func__, __LINE__); - result = 1; - } - } while (0); +void SystemStatusOsObserver::requestData( + const list& l, IDataItemObserver* client) +{ + if (nullptr == mContext.mSubscriptionObj) { + LOC_LOGD("%s]: Subscription object is NULL. Caching requests", __func__); + cacheObserverRequest(mReqDataCache, l, client); + return; + } - EXIT_LOG_WITH_ERROR ("%d",result); -} + struct HandleRequestData : public LocMsg { + HandleRequestData(SystemStatusOsObserver* parent, + const list& l, IDataItemObserver* client) : + mParent(parent), mClient(client), mDataItemList(l) {} + virtual ~HandleRequestData() {} + void proc() const { + if (mDataItemList.empty()) { + LOC_LOGV("mDataItemList is empty. Nothing to do. Exiting"); + return; + } -void SystemStatusOsObserver :: unsubscribe (const list & l, IDataItemObserver * client) { - int result = 0; - ENTRY_LOG (); - do { - if (mContext.mSubscriptionObj != NULL) { - mContext.mMsgTask->sendMsg (new (nothrow) HandleUnsubscribeReq (this, l, client)); - } - else { - LOC_LOGE("%s:%d]: Subscription object is NULL", __func__, __LINE__); - result = 1; + list yetToSubscribeDataItemsList(0); + mParent->mClientIndex->add( + mClient, mDataItemList, yetToSubscribeDataItemsList); + mParent->mDataItemIndex->add( + mClient, mDataItemList, yetToSubscribeDataItemsList); + + // Send subscription list to framework + if (!mDataItemList.empty()) { + mParent->mContext.mSubscriptionObj->requestData(mDataItemList, mParent); + LOC_LOGD("Subscribe Request sent to framework for the following"); + mParent->logMe(yetToSubscribeDataItemsList); + } } - } while (0); - EXIT_LOG_WITH_ERROR ("%d",result); + SystemStatusOsObserver* mParent; + IDataItemObserver* mClient; + const list mDataItemList; + }; + mContext.mMsgTask->sendMsg(new (nothrow) HandleRequestData(this, l, client)); } -void SystemStatusOsObserver :: unsubscribeAll (IDataItemObserver * client) { - int result = 0; - ENTRY_LOG (); - do { - if (mContext.mSubscriptionObj != NULL) { - mContext.mMsgTask->sendMsg (new (nothrow) HandleUnsubscribeAllReq (this, client)); - } - else { - LOC_LOGE("%s:%d]: Subscription object is NULL", __func__, __LINE__); - result = 1; +void SystemStatusOsObserver::unsubscribe( + const list& l, IDataItemObserver* client) +{ + if (nullptr == mContext.mSubscriptionObj) { + LOC_LOGE("%s:%d]: Subscription object is NULL", __func__, __LINE__); + return; + } + struct HandleUnsubscribeReq : public LocMsg { + HandleUnsubscribeReq(SystemStatusOsObserver* parent, + const list& l, IDataItemObserver* client) : + mParent(parent), mClient(client), mDataItemList(l) {} + virtual ~HandleUnsubscribeReq() {} + void proc() const { + if (mDataItemList.empty()) { + LOC_LOGV("mDataItemList is empty. Nothing to do. Exiting"); + return; + } + + list unsubscribeList(0); + list unused(0); + mParent->mClientIndex->remove(mClient, mDataItemList, unused); + + for (auto each : mDataItemList) { + list clientListSubs(0); + list clientListOut(0); + mParent->mDataItemIndex->remove( + each, list (1,mClient), clientListOut); + // check if there are any other subscribed client for this data item id + mParent->mDataItemIndex->getListOfSubscribedClients(each, clientListSubs); + if (clientListSubs.empty()) + { + LOC_LOGD("Client list subscribed is empty for dataitem - %d", each); + unsubscribeList.push_back(each); + } + } + + if (!unsubscribeList.empty()) { + // Send unsubscribe to framework + mParent->mContext.mSubscriptionObj->unsubscribe(unsubscribeList, mParent); + LOC_LOGD("Unsubscribe Request sent to framework for the following data items"); + mParent->logMe(unsubscribeList); + } } - } while (0); - EXIT_LOG_WITH_ERROR ("%d",result); + SystemStatusOsObserver* mParent; + IDataItemObserver* mClient; + const list mDataItemList; + }; + mContext.mMsgTask->sendMsg(new (nothrow) HandleUnsubscribeReq(this, l, client)); } -/****************************************************************************** - IDataItemObserver Overrides -******************************************************************************/ -void SystemStatusOsObserver::getName(string & name) { - name = mAddress; -} +void SystemStatusOsObserver::unsubscribeAll(IDataItemObserver* client) +{ + if (nullptr == mContext.mSubscriptionObj) { + LOC_LOGE("%s:%d]: Subscription object is NULL", __func__, __LINE__); + return; + } + + struct HandleUnsubscribeAllReq : public LocMsg { + HandleUnsubscribeAllReq(SystemStatusOsObserver* parent, + IDataItemObserver* client) : + mParent(parent), mClient(client) {} + virtual ~HandleUnsubscribeAllReq() {} + void proc() const { + list clients(1, mClient); + list unsubscribeList(0); + if(0 == mParent->mClientIndex->remove(mClient)) { + return; + } + mParent->mDataItemIndex->remove(clients, unsubscribeList); -void SystemStatusOsObserver::notify(const std::list & dlist) { - int result = 0; - ENTRY_LOG (); - do { - list :: const_iterator it = dlist.begin (); - list dataItemList; - list ids; - LOC_LOGD("LocTech-Label :: SystemStatusOsObserver :: Data Items In"); - for (; it != dlist.end (); ++it) { - if (*it != NULL) { - string dv; - (*it)->stringify(dv); - LOC_LOGD("LocTech-Value :: Data Item Value: %s", dv.c_str ()); - IDataItemCore * dataitem = DataItemsFactoryProxy::createNewDataItem((*it)->getId()); - BREAK_IF_ZERO (2, dataitem); - // Copy contents into the newly created data item - dataitem->copy(*it); - dataItemList.push_back(dataitem); - ids.push_back((*it)->getId()); + if (!unsubscribeList.empty()) { + // Send unsubscribe to framework + mParent->mContext.mSubscriptionObj->unsubscribe(unsubscribeList, mParent); + LOC_LOGD("Unsubscribe Request sent to framework for the following data items"); + mParent->logMe(unsubscribeList); } } - mContext.mMsgTask->sendMsg(new (nothrow) HandleNotify (this, dataItemList)); - } while (0); - EXIT_LOG_WITH_ERROR ("%d", result); + SystemStatusOsObserver* mParent; + IDataItemObserver* mClient; + }; + mContext.mMsgTask->sendMsg(new (nothrow) HandleUnsubscribeAllReq(this, client)); } /****************************************************************************** - IFrameworkActionReq Overrides + IDataItemObserver Overrides ******************************************************************************/ -void SystemStatusOsObserver :: turnOn (DataItemId dit, int timeOut) { - int result = 0; - ENTRY_LOG (); - do { - if (mContext.mFrameworkActionReqObj != NULL) { - // Check if data item exists in mActiveRequestCount - map :: iterator citer = mActiveRequestCount.find (dit); - if (citer == mActiveRequestCount.end ()) { - // Data item not found in map - // Add reference count as 1 and add dataitem to map - pair cpair (dit, 1); - mActiveRequestCount.insert (cpair); - LOC_LOGD("Sending turnOn request"); - // Send action turn on to framework - mContext.mMsgTask->sendMsg (new (nothrow) HandleTurnOn (this, dit, timeOut)); - } else { - // Found in map, update reference count - citer->second++; - LOC_LOGD("HandleTurnOn - Data item:%d Num_refs:%d",dit,citer->second); - } +void SystemStatusOsObserver::notify(const list& dlist) +{ + list dataItemList(0); + + for (auto each : dlist) { + string dv; + each->stringify(dv); + LOC_LOGD("notify: DataItem In Value:%s", dv.c_str()); + + IDataItemCore* di = DataItemsFactoryProxy::createNewDataItem(each->getId()); + if (nullptr == di) { + LOC_LOGE("Unable to create dataitem:%d", each->getId()); + return; } - else { - LOC_LOGE("%s:%d]: Framework action request object is NULL", __func__, __LINE__); - result = 1; + + // Copy contents into the newly created data item + di->copy(each); + dataItemList.push_back(di); + // Request systemstatus to record this dataitem in its cache + SystemStatus* systemstatus = SystemStatus::getInstance(mContext.mMsgTask); + if(nullptr != systemstatus) { + systemstatus->eventDataItemNotify(di); } - } while (0); + } - EXIT_LOG_WITH_ERROR ("%d", result); -} + struct HandleNotify : public LocMsg { + HandleNotify(SystemStatusOsObserver* parent, const list& l) : + mParent(parent), mDList(l) {} + virtual ~HandleNotify() { + for (auto each : mDList) { + delete each; + } + } + void proc() const { + // Update Cache with received data items and prepare + // list of data items to be sent. + list dataItemIdsToBeSent(0); + for (auto item : mDList) { + bool dataItemUpdated = false; + mParent->updateCache(item, dataItemUpdated); + if (dataItemUpdated) { + dataItemIdsToBeSent.push_back(item->getId()); + } + } -void SystemStatusOsObserver :: turnOff (DataItemId dit) { - int result = 0; - ENTRY_LOG (); - do { - if (mContext.mFrameworkActionReqObj != NULL) { - // Check if data item exists in mActiveRequestCount - map :: iterator citer = mActiveRequestCount.find (dit); - if (citer != mActiveRequestCount.end ()) { - citer->second--; - LOC_LOGD("HandleTurnOff - Data item:%d Remaining Num_refs:%d",dit,citer->second); - - if(citer->second == 0) { - LOC_LOGD("Sending turnOff request"); - // if this was last reference, remove item from map and turn off module - mActiveRequestCount.erase(citer); - // Send action turn off to framework - mContext.mMsgTask->sendMsg (new (nothrow) HandleTurnOff (this, dit)); + // Send data item to all subscribed clients + list clientList(0); + for (auto each : dataItemIdsToBeSent) { + list clients(0); + mParent->mDataItemIndex->getListOfSubscribedClients(each, clients); + for (auto each_cient: clients) { + clientList.push_back(each_cient); } - } else { - // Not found in map - LOC_LOGD ("Data item id %d not found in FrameworkModuleMap",dit); + } + clientList.unique(); + + for (auto client : clientList) { + list dataItemIdsSubscribedByThisClient(0); + list dataItemIdsToBeSentForThisClient(0); + mParent->mClientIndex->getSubscribedList( + client, dataItemIdsSubscribedByThisClient); + dataItemIdsSubscribedByThisClient.sort(); + dataItemIdsToBeSent.sort(); + + set_intersection(dataItemIdsToBeSent.begin(), + dataItemIdsToBeSent.end(), + dataItemIdsSubscribedByThisClient.begin(), + dataItemIdsSubscribedByThisClient.end(), + inserter(dataItemIdsToBeSentForThisClient, + dataItemIdsToBeSentForThisClient.begin())); + + mParent->sendCachedDataItems(dataItemIdsToBeSentForThisClient, client); + dataItemIdsSubscribedByThisClient.clear(); + dataItemIdsToBeSentForThisClient.clear(); } } - else { - LOC_LOGE("%s:%d]: Framework action request object is NULL", __func__, __LINE__); - result = 1; - } - } while (0); - EXIT_LOG_WITH_ERROR ("%d", result); + SystemStatusOsObserver* mParent; + const list mDList; + }; + mContext.mMsgTask->sendMsg(new (nothrow) HandleNotify(this, dataItemList)); } /****************************************************************************** - Helpers + IFrameworkActionReq Overrides ******************************************************************************/ -void SystemStatusOsObserver :: logMe (const list & l) { - list :: const_iterator it = l.begin (); - for (;it != l.end (); ++it) { - LOC_LOGD ("DataItem %d",*it); +void SystemStatusOsObserver::turnOn(DataItemId dit, int timeOut) +{ + if (nullptr == mContext.mFrameworkActionReqObj) { + LOC_LOGE("%s:%d]: Framework action request object is NULL", __func__, __LINE__); + return; } -} -int SystemStatusOsObserver :: sendFirstResponse (const list & l, IDataItemObserver * to) { - int result = 0; - ENTRY_LOG (); - do { - if (l.empty ()) { - LOC_LOGV("list is empty. Nothing to do. Exiting"); - result = 0; - break; - } + // Check if data item exists in mActiveRequestCount + map::iterator citer = mActiveRequestCount.find(dit); + if (citer == mActiveRequestCount.end()) { + // Data item not found in map + // Add reference count as 1 and add dataitem to map + pair cpair(dit, 1); + mActiveRequestCount.insert(cpair); + LOC_LOGD("Sending turnOn request"); - string clientName; - to->getName (clientName); - LOC_LOGD ("First response sent for the following data items To Client: %s", clientName.c_str()); - - list dataItems; - list :: const_iterator diditer = l.begin (); - for (; diditer != l.end (); ++diditer) { - map :: const_iterator citer = mDataItemCache.find (*diditer); - if (citer != mDataItemCache.end ()) { - string dv; - IDataItemCore * di = citer->second; - di->stringify (dv); - LOC_LOGD ("LocTech-Value :: Data Item: %s", dv.c_str ()); - dataItems.push_back (citer->second); + // Send action turn on to framework + struct HandleTurnOnMsg : public LocMsg { + HandleTurnOnMsg(IFrameworkActionReq* framework, + DataItemId dit, int timeOut) : + mFrameworkActionReqObj(framework), mDataItemId(dit), mTimeOut(timeOut) {} + virtual ~HandleTurnOnMsg() {} + void proc() const { + mFrameworkActionReqObj->turnOn(mDataItemId, mTimeOut); } - } - if (dataItems.empty ()) { - LOC_LOGV("No items to notify. Nothing to do. Exiting"); - result = 0; - break; - } + IFrameworkActionReq* mFrameworkActionReqObj; + DataItemId mDataItemId; + int mTimeOut; + }; + mContext.mMsgTask->sendMsg(new (nothrow) HandleTurnOnMsg(this, dit, timeOut)); + } + else { + // Found in map, update reference count + citer->second++; + LOC_LOGD("turnOn - Data item:%d Num_refs:%d", dit, citer->second); + } +} - // Notify Client - to->notify (dataItems); +void SystemStatusOsObserver::turnOff(DataItemId dit) +{ + if (nullptr == mContext.mFrameworkActionReqObj) { + LOC_LOGE("%s:%d]: Framework action request object is NULL", __func__, __LINE__); + return; + } - } while (0); - EXIT_LOG_WITH_ERROR ("%d", result); - return result; + // Check if data item exists in mActiveRequestCount + map::iterator citer = mActiveRequestCount.find(dit); + if (citer != mActiveRequestCount.end()) { + // found + citer->second--; + LOC_LOGD("turnOff - Data item:%d Remaining:%d", dit, citer->second); + if(citer->second == 0) { + // if this was last reference, remove item from map and turn off module + mActiveRequestCount.erase(citer); + + // Send action turn off to framework + struct HandleTurnOffMsg : public LocMsg { + HandleTurnOffMsg(IFrameworkActionReq* framework, DataItemId dit) : + mFrameworkActionReqObj(framework), mDataItemId(dit) {} + virtual ~HandleTurnOffMsg() {} + void proc() const { + mFrameworkActionReqObj->turnOff(mDataItemId); + } + IFrameworkActionReq* mFrameworkActionReqObj; + DataItemId mDataItemId; + }; + mContext.mMsgTask->sendMsg( + new (nothrow) HandleTurnOffMsg(mContext.mFrameworkActionReqObj, dit)); + } + } } -int SystemStatusOsObserver :: sendCachedDataItems (const list & l, IDataItemObserver * to) { - int result = 0; - ENTRY_LOG (); - do { - list dataItems; - list :: const_iterator it = l.begin (); - string clientName; - to->getName (clientName); - LOC_LOGD ("LocTech-Value :: To Client: %s", clientName.c_str ()); - for (; it != l.end (); ++it) { +/****************************************************************************** + Helpers +******************************************************************************/ +void SystemStatusOsObserver::sendFirstResponse( + const list& l, IDataItemObserver* to) +{ + if (l.empty()) { + LOC_LOGV("list is empty. Nothing to do. Exiting"); + return; + } + + string clientName; + to->getName(clientName); + list dataItems(0); + + for (auto each : l) { + map::const_iterator citer = mDataItemCache.find(each); + if (citer != mDataItemCache.end()) { string dv; - IDataItemCore * di = this->mDataItemCache [ (*it) ]; - di->stringify (dv); - LOC_LOGI("LocTech-Value :: Data Item: %s >> %s", dv.c_str(), clientName.c_str()); - dataItems.push_back (di); + citer->second->stringify(dv); + LOC_LOGI("DataItem: %s >> %s", dv.c_str(), clientName.c_str()); + dataItems.push_back(citer->second); } + } + if (dataItems.empty()) { + LOC_LOGV("No items to notify. Nothing to do. Exiting"); + return; + } + to->notify(dataItems); +} - to->notify (dataItems); - - } while (0); - EXIT_LOG_WITH_ERROR ("%d", result); - return result; +void SystemStatusOsObserver::sendCachedDataItems( + const list& l, IDataItemObserver* to) +{ + string clientName; + to->getName(clientName); + list dataItems(0); + + for (auto each : l) { + string dv; + IDataItemCore* di = mDataItemCache[each]; + di->stringify(dv); + LOC_LOGI("DataItem: %s >> %s", dv.c_str(), clientName.c_str()); + dataItems.push_back(di); + } + to->notify(dataItems); } -int SystemStatusOsObserver :: updateCache (IDataItemCore * d, bool &dataItemUpdated) { - int result = 0; - ENTRY_LOG (); - do { - BREAK_IF_ZERO (1, d); - // Check if data item exists in cache - map :: iterator citer = mDataItemCache.find (d->getId ()); - if (citer == mDataItemCache.end ()) { - // New data item; not found in cache - IDataItemCore * dataitem = DataItemsFactoryProxy::createNewDataItem(d->getId()); - BREAK_IF_ZERO (2, dataitem); - // Copy the contents of the data item - dataitem->copy (d); - pair cpair (d->getId (), dataitem); - // Insert in mDataItemCache - mDataItemCache.insert (cpair); - dataItemUpdated = true; - } else { - // Found in cache; Update cache if necessary - BREAK_IF_NON_ZERO(3, citer->second->copy (d, &dataItemUpdated)); - } +void SystemStatusOsObserver::updateCache(IDataItemCore* d, bool& dataItemUpdated) +{ + if (nullptr == d) { + return; + } - if (dataItemUpdated) { - LOC_LOGV("DataItem:%d updated:%d", d->getId (), dataItemUpdated); + // Check if data item exists in cache + map::iterator citer = + mDataItemCache.find(d->getId()); + if (citer == mDataItemCache.end()) { + // New data item; not found in cache + IDataItemCore* dataitem = DataItemsFactoryProxy::createNewDataItem(d->getId()); + if (nullptr == dataitem) { + return; + } + + // Copy the contents of the data item + dataitem->copy(d); + pair cpair(d->getId(), dataitem); + // Insert in mDataItemCache + mDataItemCache.insert(cpair); + dataItemUpdated = true; + } + else { + // Found in cache; Update cache if necessary + if(0 == citer->second->copy(d, &dataItemUpdated)) { + return; } - } while (0); + } - EXIT_LOG_WITH_ERROR ("%d", result); - return result; + if (dataItemUpdated) { + LOC_LOGV("DataItem:%d updated:%d", d->getId(), dataItemUpdated); + } } } // namespace loc_core diff --git a/core/SystemStatusOsObserver.h b/core/SystemStatusOsObserver.h index 8e42d21..985e5c9 100644 --- a/core/SystemStatusOsObserver.h +++ b/core/SystemStatusOsObserver.h @@ -29,36 +29,34 @@ #ifndef __SYSTEM_STATUS_OSOBSERVER__ #define __SYSTEM_STATUS_OSOBSERVER__ -#include +#include #include #include #include #include #include -#include -#include + #include +#include #include +#include namespace loc_core { - /****************************************************************************** SystemStatusOsObserver ******************************************************************************/ +using namespace std; + // Forward Declarations class IDataItemCore; - -template -class IClientIndex; - -template -class IDataItemIndex; +template class IClientIndex; +template class IDataItemIndex; struct SystemContext { - IDataItemSubscription *mSubscriptionObj; - IFrameworkActionReq *mFrameworkActionReqObj; - const MsgTask *mMsgTask; + IDataItemSubscription* mSubscriptionObj; + IFrameworkActionReq* mFrameworkActionReqObj; + const MsgTask* mMsgTask; inline SystemContext() : mSubscriptionObj(NULL), @@ -66,6 +64,8 @@ struct SystemContext { mMsgTask(NULL) {} }; +typedef map> ObserverReqCache; + // Clients wanting to get data from OS/Framework would need to // subscribe with OSObserver using IDataItemSubscription interface. // Such clients would need to implement IDataItemObserver interface @@ -80,252 +80,54 @@ public: ~SystemStatusOsObserver(); // To set the subscription object - inline void setSubscriptionObj(IDataItemSubscription *subscriptionObj) { - mContext.mSubscriptionObj = subscriptionObj; - }; + virtual void setSubscriptionObj(IDataItemSubscription* subscriptionObj); // To set the framework action request object - inline void setFrameworkActionReqObj(IFrameworkActionReq *frameworkActionReqObj) { + inline void setFrameworkActionReqObj(IFrameworkActionReq* frameworkActionReqObj) { mContext.mFrameworkActionReqObj = frameworkActionReqObj; } - // IDataItemObserver Overrides - virtual void getName (string & name); - virtual void notify (const std::list & dlist); - // IDataItemSubscription Overrides - virtual void subscribe (const std :: list & l, IDataItemObserver * client); - virtual void updateSubscription - ( - const std :: list & l, - IDataItemObserver * client - ); - virtual void requestData - ( - const std :: list & l, - IDataItemObserver * client - ); - virtual void unsubscribe (const std :: list & l, IDataItemObserver * client); - virtual void unsubscribeAll (IDataItemObserver * client); + virtual void subscribe(const list& l, IDataItemObserver* client); + virtual void updateSubscription(const list& l, IDataItemObserver* client); + virtual void requestData(const list& l, IDataItemObserver* client); + virtual void unsubscribe(const list& l, IDataItemObserver* client); + virtual void unsubscribeAll(IDataItemObserver* client); + + // IDataItemObserver Overrides + virtual void notify(const list& dlist); + inline virtual void getName(string& name) { + name = mAddress; + } // IFrameworkActionReq Overrides - virtual void turnOn (DataItemId dit, int timeOut = 0); - virtual void turnOff (DataItemId dit); + virtual void turnOn(DataItemId dit, int timeOut = 0); + virtual void turnOff(DataItemId dit); private: - - SystemContext mContext; - const string mAddress; - IClientIndex *mClientIndex; - IDataItemIndex *mDataItemIndex; - map < DataItemId, IDataItemCore * > mDataItemCache; - map < DataItemId, int > mActiveRequestCount; - - // Nested types - // Messages - struct HandleMsgBase : public LocMsg { - HandleMsgBase (SystemStatusOsObserver * parent); - virtual ~HandleMsgBase (); - // Data members - SystemStatusOsObserver * mParent; - }; + SystemContext mContext; + const string mAddress; + IClientIndex* mClientIndex; + IDataItemIndex* mDataItemIndex; + map mDataItemCache; + map mActiveRequestCount; + + // Cache the subscribe and requestData till subscription obj is obtained + ObserverReqCache mSubscribeReqCache; + ObserverReqCache mReqDataCache; + void cacheObserverRequest(ObserverReqCache& reqCache, + const list& l, IDataItemObserver* client); // Helpers - int sendFirstResponse - ( - const list & l, - IDataItemObserver * to - ); - - int sendCachedDataItems - ( - const list & l, - IDataItemObserver * to - ); - - int updateCache (IDataItemCore * d, bool &dataItemUpdated); - void logMe (const list & l); - - // Messages - struct HandleClientMsg : public LocMsg { - HandleClientMsg (SystemStatusOsObserver * parent, IDataItemObserver * client); - virtual ~HandleClientMsg (); - // Data Members - SystemStatusOsObserver * mParent; - IDataItemObserver * mClient; - }; - - struct HandleSubscribeReq : public HandleClientMsg { - HandleSubscribeReq (SystemStatusOsObserver * parent, - const list & l, - IDataItemObserver * client); - virtual ~HandleSubscribeReq (); - void proc () const; - // Data members - const list mDataItemList; - }; - - struct HandleUpdateSubscriptionReq : public HandleClientMsg { - HandleUpdateSubscriptionReq (SystemStatusOsObserver * parent, - const list & l, - IDataItemObserver * client); - virtual ~HandleUpdateSubscriptionReq (); - void proc () const; - // Data members - const list mDataItemList; - }; - - struct HandleRequestData : public HandleClientMsg { - HandleRequestData (SystemStatusOsObserver * parent, - const list & l, - IDataItemObserver * client); - virtual ~HandleRequestData (); - void proc () const; - const list mDataItemList; - }; - - struct HandleUnsubscribeReq : public HandleClientMsg { - HandleUnsubscribeReq (SystemStatusOsObserver * parent, - const list & l, - IDataItemObserver * client); - virtual ~HandleUnsubscribeReq (); - void proc () const; - // Data members - const list mDataItemList; - }; - - struct HandleUnsubscribeAllReq : public HandleClientMsg { - HandleUnsubscribeAllReq - ( - SystemStatusOsObserver * parent, - IDataItemObserver * client - ); - virtual ~HandleUnsubscribeAllReq (); - void proc () const; - }; - - struct HandleNotify : public HandleMsgBase { - HandleNotify (SystemStatusOsObserver * parent, list dlist); - virtual ~HandleNotify (); - void getListOfClients - ( - const list & dlist, - list & clients - ) const; - void proc () const; - // Data members - list mDList; - }; - - struct HandleTurnOn : public HandleMsgBase { - HandleTurnOn (SystemStatusOsObserver * parent, - const DataItemId dit, - const int timeOut); - virtual ~HandleTurnOn (); - void proc () const; - // Data members - DataItemId mDataItemId; - int mTimeOut; - }; - - struct HandleTurnOff : public HandleMsgBase { - HandleTurnOff (SystemStatusOsObserver * parent,const DataItemId dit); - virtual ~HandleTurnOff (); - void proc () const; - // Data members - DataItemId mDataItemId; - }; - -}; - - -/****************************************************************************** - Messages -******************************************************************************/ -// Ctors -inline SystemStatusOsObserver :: HandleMsgBase :: HandleMsgBase (SystemStatusOsObserver * parent) -: -mParent (parent) -{} - -inline SystemStatusOsObserver :: HandleClientMsg :: HandleClientMsg -( - SystemStatusOsObserver * parent, - IDataItemObserver * client -) -: -mParent (parent), -mClient (client) -{} - -inline SystemStatusOsObserver :: HandleSubscribeReq :: HandleSubscribeReq - (SystemStatusOsObserver * parent, const list & l, IDataItemObserver * client) -: -HandleClientMsg (parent, client), mDataItemList (l) -{} - -inline SystemStatusOsObserver :: HandleUpdateSubscriptionReq :: HandleUpdateSubscriptionReq - (SystemStatusOsObserver * parent, const list & l, IDataItemObserver * client) -: -HandleClientMsg (parent, client), mDataItemList (l) -{} - -inline SystemStatusOsObserver :: HandleRequestData :: HandleRequestData - (SystemStatusOsObserver * parent, const list & l, IDataItemObserver * client) -: -HandleClientMsg (parent, client), mDataItemList (l) -{} - -inline SystemStatusOsObserver :: HandleUnsubscribeReq :: HandleUnsubscribeReq - (SystemStatusOsObserver * parent, const list & l, IDataItemObserver * client) -: -HandleClientMsg (parent, client), mDataItemList (l) -{} - -inline SystemStatusOsObserver :: HandleUnsubscribeAllReq :: HandleUnsubscribeAllReq - (SystemStatusOsObserver * parent, IDataItemObserver * client) -: -HandleClientMsg (parent, client) -{} - -inline SystemStatusOsObserver :: HandleNotify :: HandleNotify - (SystemStatusOsObserver * parent, list dlist) -: -HandleMsgBase (parent), mDList (dlist) -{} - -inline SystemStatusOsObserver :: HandleTurnOn :: HandleTurnOn - (SystemStatusOsObserver * parent, const DataItemId dit,const int timeOut) -: -HandleMsgBase (parent), mDataItemId (dit), mTimeOut (timeOut) -{} - -inline SystemStatusOsObserver :: HandleTurnOff :: HandleTurnOff - (SystemStatusOsObserver * parent, const DataItemId dit) -: -HandleMsgBase (parent), mDataItemId (dit) -{} - -// Dtors -inline SystemStatusOsObserver :: HandleMsgBase :: ~HandleMsgBase () {} -inline SystemStatusOsObserver :: HandleClientMsg :: ~HandleClientMsg () {} -inline SystemStatusOsObserver :: HandleSubscribeReq :: ~HandleSubscribeReq () {} -inline SystemStatusOsObserver :: HandleUpdateSubscriptionReq :: ~HandleUpdateSubscriptionReq() {} -inline SystemStatusOsObserver :: HandleRequestData :: ~HandleRequestData() {} -inline SystemStatusOsObserver :: HandleUnsubscribeReq :: ~HandleUnsubscribeReq () {} -inline SystemStatusOsObserver :: HandleUnsubscribeAllReq :: ~HandleUnsubscribeAllReq () {} - -inline SystemStatusOsObserver :: HandleNotify :: ~HandleNotify () { - list :: iterator it = mDList.begin (); - for (; it != mDList.end (); ++it) { - delete *it; - *it = NULL; + void sendFirstResponse(const list& l, IDataItemObserver* to); + void sendCachedDataItems(const list& l, IDataItemObserver* to); + void updateCache(IDataItemCore* d, bool& dataItemUpdated); + inline void logMe(const list& l) { + for (auto id : l) { + LOC_LOGD("DataItem %d", id); + } } -} - -inline SystemStatusOsObserver :: HandleTurnOn :: ~HandleTurnOn () {} -inline SystemStatusOsObserver :: HandleTurnOff :: ~HandleTurnOff () {} - +}; } // namespace loc_core diff --git a/gnss/GnssAdapter.cpp b/gnss/GnssAdapter.cpp index d4ffcb2..809e27d 100644 --- a/gnss/GnssAdapter.cpp +++ b/gnss/GnssAdapter.cpp @@ -67,7 +67,8 @@ GnssAdapter::GnssAdapter() : mAgpsManager(), mAgpsCbInfo(), mSystemStatus(SystemStatus::getInstance(mMsgTask)), - mServerUrl("") + mServerUrl(""), + mXtraObserver(mSystemStatus->getOsObserver(), mMsgTask) { LOC_LOGD("%s]: Constructor %p", __func__, this); mUlpPositionMode.mode = LOC_POSITION_MODE_INVALID; diff --git a/gnss/GnssAdapter.h b/gnss/GnssAdapter.h index 3cb2c64..fb50f28 100644 --- a/gnss/GnssAdapter.h +++ b/gnss/GnssAdapter.h @@ -106,11 +106,11 @@ class GnssAdapter : public LocAdapterBase { // This must be initialized via initAgps() AgpsManager mAgpsManager; AgpsCbInfo mAgpsCbInfo; - XtraSystemStatusObserver mXtraObserver; /* === SystemStatus ===================================================================== */ SystemStatus* mSystemStatus; std::string mServerUrl; + XtraSystemStatusObserver mXtraObserver; /*==== CONVERSION ===================================================================*/ static void convertOptions(LocPosMode& out, const LocationOptions& options); @@ -280,10 +280,6 @@ public: void injectLocationCommand(double latitude, double longitude, float accuracy); void injectTimeCommand(int64_t time, int64_t timeReference, int32_t uncertainty); - inline void updateConnectionStatusCommand(bool connected, uint8_t type) { - mXtraObserver.updateConnectionStatus(connected, type); - } - }; #endif //GNSS_ADAPTER_H diff --git a/gnss/XtraSystemStatusObserver.cpp b/gnss/XtraSystemStatusObserver.cpp index 58a8522..ce08f64 100644 --- a/gnss/XtraSystemStatusObserver.cpp +++ b/gnss/XtraSystemStatusObserver.cpp @@ -45,40 +45,55 @@ #include #include #include +#include +#include -using namespace std; using namespace loc_core; #define XTRA_HAL_SOCKET_NAME "/data/vendor/location/xtra/socket_hal_xtra" bool XtraSystemStatusObserver::updateLockStatus(uint32_t lock) { - std::stringstream ss; + stringstream ss; ss << "gpslock"; ss << " " << lock; ss << "\n"; // append seperator return ( sendEvent(ss) ); } -bool XtraSystemStatusObserver::updateConnectionStatus(bool connected, uint8_t type) { - std::stringstream ss; +bool XtraSystemStatusObserver::updateConnectionStatus(bool connected, uint32_t type) { + stringstream ss; ss << "connection"; ss << " " << (connected ? "1" : "0"); ss << " " << (int)type; ss << "\n"; // append seperator return ( sendEvent(ss) ); } +bool XtraSystemStatusObserver::updateTac(const string& tac) { + stringstream ss; + ss << "tac"; + ss << " " << tac.c_str(); + ss << "\n"; // append seperator + return ( sendEvent(ss) ); +} + +bool XtraSystemStatusObserver::updateMccMnc(const string& mccmnc) { + stringstream ss; + ss << "mncmcc"; + ss << " " << mccmnc.c_str(); + ss << "\n"; // append seperator + return ( sendEvent(ss) ); +} -bool XtraSystemStatusObserver::sendEvent(std::stringstream& event) { +bool XtraSystemStatusObserver::sendEvent(const stringstream& event) { int socketFd = createSocket(); if (socketFd < 0) { LOC_LOGe("XTRA unreachable. sending failed."); return false; } - const std::string& data = event.str(); + const string& data = event.str(); int remain = data.length(); ssize_t sent = 0; - while (remain > 0 && (sent = ::send(socketFd, data.c_str() + (data.length() - remain), remain, MSG_NOSIGNAL)) > 0) { @@ -125,3 +140,95 @@ void XtraSystemStatusObserver::closeSocket(const int socketFd) { } } } + +void XtraSystemStatusObserver::subscribe(bool yes) +{ + // Subscription data list + list subItemIdList; + subItemIdList.push_back(NETWORKINFO_DATA_ITEM_ID); + subItemIdList.push_back(MCCMNC_DATA_ITEM_ID); + + if (yes) { + mSystemStatusObsrvr->subscribe(subItemIdList, this); + + list reqItemIdList; + reqItemIdList.push_back(TAC_DATA_ITEM_ID); + + mSystemStatusObsrvr->requestData(reqItemIdList, this); + + } else { + mSystemStatusObsrvr->unsubscribe(subItemIdList, this); + } +} + +// IDataItemObserver overrides +void XtraSystemStatusObserver::getName(string& name) +{ + name = "XtraSystemStatusObserver"; +} + +void XtraSystemStatusObserver::notify(const list& dlist) +{ + struct handleOsObserverUpdateMsg : public LocMsg { + XtraSystemStatusObserver* mXtraSysStatObj; + list mDataItemList; + + inline handleOsObserverUpdateMsg(XtraSystemStatusObserver* xtraSysStatObs, + const list& dataItemList) : + mXtraSysStatObj(xtraSysStatObs) { + for (auto eachItem : dataItemList) { + IDataItemCore* dataitem = DataItemsFactoryProxy::createNewDataItem( + eachItem->getId()); + if (NULL == dataitem) { + break; + } + // Copy the contents of the data item + dataitem->copy(eachItem); + + mDataItemList.push_back(dataitem); + } + } + + inline ~handleOsObserverUpdateMsg() { + for (auto each : mDataItemList) { + delete each; + } + } + + inline void proc() const { + for (auto each : mDataItemList) { + switch (each->getId()) + { + case NETWORKINFO_DATA_ITEM_ID: + { + SystemStatusNetworkInfo* networkInfo = + reinterpret_cast(each); + mXtraSysStatObj->updateConnectionStatus(networkInfo->mConnected, + networkInfo->mType); + } + break; + + case TAC_DATA_ITEM_ID: + { + SystemStatusTac* tac = reinterpret_cast(each); + mXtraSysStatObj->updateTac(tac->mValue); + } + break; + + case MCCMNC_DATA_ITEM_ID: + { + SystemStatusMccMnc* mccmnc = reinterpret_cast(each); + mXtraSysStatObj->updateMccMnc(mccmnc->mValue); + } + break; + + default: + break; + } + } + } + }; + mMsgTask->sendMsg(new (nothrow) handleOsObserverUpdateMsg(this, dlist)); +} + + diff --git a/gnss/XtraSystemStatusObserver.h b/gnss/XtraSystemStatusObserver.h index e49f17b..42f49b5 100644 --- a/gnss/XtraSystemStatusObserver.h +++ b/gnss/XtraSystemStatusObserver.h @@ -29,25 +29,42 @@ #ifndef XTRA_SYSTEM_STATUS_OBS_H #define XTRA_SYSTEM_STATUS_OBS_H -#include +#include +#include +using namespace std; +using loc_core::IOsObserver; +using loc_core::IDataItemObserver; +using loc_core::IDataItemCore; -class XtraSystemStatusObserver { + +class XtraSystemStatusObserver : public IDataItemObserver { public : // constructor & destructor - XtraSystemStatusObserver() { + inline XtraSystemStatusObserver(IOsObserver* sysStatObs, const MsgTask* msgTask): + mSystemStatusObsrvr(sysStatObs), mMsgTask(msgTask) { + subscribe(true); } + inline XtraSystemStatusObserver() {}; + inline virtual ~XtraSystemStatusObserver() { subscribe(false); } - virtual ~XtraSystemStatusObserver() { - } + // IDataItemObserver overrides + inline virtual void getName(string& name); + virtual void notify(const list& dlist); bool updateLockStatus(uint32_t lock); - bool updateConnectionStatus(bool connected, uint8_t type); + bool updateConnectionStatus(bool connected, uint32_t type); + bool updateTac(const string& tac); + bool updateMccMnc(const string& mccmnc); + inline const MsgTask* getMsgTask() { return mMsgTask; } + void subscribe(bool yes); private: int createSocket(); void closeSocket(const int32_t socketFd); - bool sendEvent(std::stringstream& event); + bool sendEvent(const stringstream& event); + IOsObserver* mSystemStatusObsrvr; + const MsgTask* mMsgTask; }; diff --git a/gnss/location_gnss.cpp b/gnss/location_gnss.cpp index a99d8ef..19399de 100644 --- a/gnss/location_gnss.cpp +++ b/gnss/location_gnss.cpp @@ -253,6 +253,6 @@ static void getDebugReport(GnssDebugReport& report) { static void updateConnectionStatus(bool connected, uint8_t type) { if (NULL != gGnssAdapter) { - gGnssAdapter->updateConnectionStatusCommand(connected, type); + gGnssAdapter->getSystemStatus()->eventConnectionStatus(connected, type); } } \ No newline at end of file -- cgit v1.2.3