123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556 |
- /* Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- * * Neither the name of The Linux Foundation, nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
- * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
- #define LOG_TAG "LocSvc_SystemStatusOsObserver"
- #include <algorithm>
- #include <SystemStatus.h>
- #include <SystemStatusOsObserver.h>
- #include <IDataItemCore.h>
- #include <DataItemsFactoryProxy.h>
- namespace loc_core
- {
- template <typename CINT, typename COUT>
- COUT SystemStatusOsObserver::containerTransfer(CINT& inContainer) {
- COUT outContainer = {};
- for (auto item : inContainer) {
- outContainer.insert(outContainer.begin(), item);
- }
- return outContainer;
- }
- SystemStatusOsObserver::~SystemStatusOsObserver() {
- // Destroy cache
- for (auto each : mDataItemCache) {
- if (nullptr != each.second) {
- delete each.second;
- }
- }
- mDataItemCache.clear();
- }
- void SystemStatusOsObserver::setSubscriptionObj(IDataItemSubscription* subscriptionObj)
- {
- struct SetSubsObj : public LocMsg {
- ObserverContext& mContext;
- IDataItemSubscription* mSubsObj;
- inline SetSubsObj(ObserverContext& context, IDataItemSubscription* subscriptionObj) :
- mContext(context), mSubsObj(subscriptionObj) {}
- void proc() const {
- LOC_LOGi("SetSubsObj::enter");
- mContext.mSubscriptionObj = mSubsObj;
- if (!mContext.mSSObserver->mDataItemToClients.empty()) {
- unordered_set<DataItemId> dis(mContext.mSSObserver->mDataItemToClients.getKeys());
- mContext.mSubscriptionObj->subscribe(dis, mContext.mSSObserver);
- mContext.mSubscriptionObj->requestData(dis, mContext.mSSObserver);
- }
- LOC_LOGi("SetSubsObj::exit");
- }
- };
- if (nullptr == subscriptionObj) {
- LOC_LOGw("subscriptionObj is NULL");
- } else {
- mContext.mMsgTask->sendMsg(new SetSubsObj(mContext, subscriptionObj));
- }
- }
- /******************************************************************************
- IDataItemSubscription Overrides
- ******************************************************************************/
- void SystemStatusOsObserver::subscribe(const unordered_set<DataItemId>& l, IDataItemObserver* client,
- bool toRequestData)
- {
- struct HandleSubscribeReq : public LocMsg {
- inline HandleSubscribeReq(SystemStatusOsObserver* parent,
- const unordered_set<DataItemId>& l, IDataItemObserver* client, bool requestData) :
- mParent(parent), mClient(client),
- mDataItemSet(std::move(l)),
- diItemlist(containerTransfer<const unordered_set<DataItemId>, list<DataItemId>>(l)),
- mToRequestData(requestData) {}
- void proc() const {
- unordered_set<DataItemId> dataItemsToSubscribe = {};
- mParent->mDataItemToClients.add(mDataItemSet, {mClient}, &dataItemsToSubscribe);
- mParent->mClientToDataItems.add(mClient, mDataItemSet);
- mParent->sendCachedDataItems(mDataItemSet, mClient);
- // Send subscription set to framework
- if (nullptr != mParent->mContext.mSubscriptionObj) {
- if (mToRequestData) {
- LOC_LOGd("Request Data sent to framework for the following");
- mParent->mContext.mSubscriptionObj->requestData(dataItemsToSubscribe, mParent);
- } else if (!dataItemsToSubscribe.empty()) {
- LOC_LOGd("Subscribe Request sent to framework for the following");
- mParent->logMe(dataItemsToSubscribe);
- mParent->mContext.mSubscriptionObj->subscribe(dataItemsToSubscribe, mParent);
- }
- }
- }
- mutable SystemStatusOsObserver* mParent;
- IDataItemObserver* mClient;
- const unordered_set<DataItemId> mDataItemSet;
- const list<DataItemId> diItemlist;
- bool mToRequestData;
- };
- if (l.empty() || nullptr == client) {
- LOC_LOGw("Data item set is empty or client is nullptr");
- } else {
- mContext.mMsgTask->sendMsg(
- new HandleSubscribeReq(this, l, client, toRequestData));
- }
- }
- void SystemStatusOsObserver::updateSubscription(
- const unordered_set<DataItemId>& l, IDataItemObserver* client)
- {
- struct HandleUpdateSubscriptionReq : public LocMsg {
- HandleUpdateSubscriptionReq(SystemStatusOsObserver* parent,
- const unordered_set<DataItemId>& l, IDataItemObserver* client) :
- mParent(parent), mClient(client), mDataItemSet(l) {}
- void proc() const {
- unordered_set<DataItemId> dataItemsToSubscribe = {};
- unordered_set<DataItemId> dataItemsToUnsubscribe = {};
- unordered_set<IDataItemObserver*> clients({mClient});
- // below removes clients from all entries keyed with the return of the
- // mClientToDataItems.update() call. If leaving an empty set of clients as the
- // result, the entire entry will be removed. dataItemsToUnsubscribe will be
- // populated to keep the keys of the removed entries.
- mParent->mDataItemToClients.trimOrRemove(
- // this call updates <IDataItemObserver*, DataItemId> map; removes
- // the DataItemId's that are not new to the clietn from mDataItemSet;
- // and returns a set of mDataItemSet's that are no longer used by client.
- // This unused set of mDataItemSet's is passed to trimOrRemove method of
- // <DataItemId, IDataItemObserver*> map to remove the client from the
- // corresponding entries, and gets a set of the entries that are
- // removed from the <DataItemId, IDataItemObserver*> map as a result.
- mParent->mClientToDataItems.update(mClient,
- (unordered_set<DataItemId>&)mDataItemSet),
- clients, &dataItemsToUnsubscribe, nullptr);
- // below adds mClient to <DataItemId, IDataItemObserver*> map, and populates
- // new keys added to that map, which are DataItemIds to be subscribed.
- mParent->mDataItemToClients.add(mDataItemSet, clients, &dataItemsToSubscribe);
- // Send First Response
- mParent->sendCachedDataItems(mDataItemSet, mClient);
- if (nullptr != mParent->mContext.mSubscriptionObj) {
- // Send subscription set to framework
- if (!dataItemsToSubscribe.empty()) {
- LOC_LOGd("Subscribe Request sent to framework for the following");
- mParent->logMe(dataItemsToSubscribe);
- mParent->mContext.mSubscriptionObj->subscribe(dataItemsToSubscribe, mParent);
- }
- // Send unsubscribe to framework
- if (!dataItemsToUnsubscribe.empty()) {
- LOC_LOGd("Unsubscribe Request sent to framework for the following");
- mParent->logMe(dataItemsToUnsubscribe);
- mParent->mContext.mSubscriptionObj->unsubscribe(dataItemsToUnsubscribe,
- mParent);
- }
- }
- }
- SystemStatusOsObserver* mParent;
- IDataItemObserver* mClient;
- unordered_set<DataItemId> mDataItemSet;
- };
- if (l.empty() || nullptr == client) {
- LOC_LOGw("Data item set is empty or client is nullptr");
- } else {
- mContext.mMsgTask->sendMsg(
- new HandleUpdateSubscriptionReq(this, l, client));
- }
- }
- void SystemStatusOsObserver::unsubscribe(
- const unordered_set<DataItemId>& l, IDataItemObserver* client)
- {
- struct HandleUnsubscribeReq : public LocMsg {
- HandleUnsubscribeReq(SystemStatusOsObserver* parent,
- const unordered_set<DataItemId>& l, IDataItemObserver* client) :
- mParent(parent), mClient(client),
- mDataItemSet(std::move(l)) {}
- void proc() const {
- unordered_set<DataItemId> dataItemsUnusedByClient = {};
- unordered_set<IDataItemObserver*> clientToRemove = {};
- unordered_set<DataItemId> dataItemsToUnsubscribe = {};
- mParent->mClientToDataItems.trimOrRemove({mClient}, mDataItemSet, &clientToRemove,
- &dataItemsUnusedByClient);
- mParent->mDataItemToClients.trimOrRemove(dataItemsUnusedByClient, {mClient},
- &dataItemsToUnsubscribe, nullptr);
- if (nullptr != mParent->mContext.mSubscriptionObj && !dataItemsToUnsubscribe.empty()) {
- LOC_LOGd("Unsubscribe Request sent to framework for the following data items");
- mParent->logMe(dataItemsToUnsubscribe);
- // Send unsubscribe to framework
- mParent->mContext.mSubscriptionObj->unsubscribe(dataItemsToUnsubscribe, mParent);
- }
- }
- SystemStatusOsObserver* mParent;
- IDataItemObserver* mClient;
- unordered_set<DataItemId> mDataItemSet;
- };
- if (l.empty() || nullptr == client) {
- LOC_LOGw("Data item set is empty or client is nullptr");
- } else {
- mContext.mMsgTask->sendMsg(new HandleUnsubscribeReq(this, l, client));
- }
- }
- void SystemStatusOsObserver::unsubscribeAll(IDataItemObserver* client)
- {
- struct HandleUnsubscribeAllReq : public LocMsg {
- HandleUnsubscribeAllReq(SystemStatusOsObserver* parent,
- IDataItemObserver* client) :
- mParent(parent), mClient(client) {}
- void proc() const {
- unordered_set<DataItemId> diByClient = mParent->mClientToDataItems.getValSet(mClient);
- if (!diByClient.empty()) {
- unordered_set<DataItemId> dataItemsToUnsubscribe;
- mParent->mClientToDataItems.remove(mClient);
- mParent->mDataItemToClients.trimOrRemove(diByClient, {mClient},
- &dataItemsToUnsubscribe, nullptr);
- if (!dataItemsToUnsubscribe.empty() &&
- nullptr != mParent->mContext.mSubscriptionObj) {
- LOC_LOGd("Unsubscribe Request sent to framework for the following data items");
- mParent->logMe(dataItemsToUnsubscribe);
- // Send unsubscribe to framework
- mParent->mContext.mSubscriptionObj->unsubscribe(dataItemsToUnsubscribe,
- mParent);
- }
- }
- }
- SystemStatusOsObserver* mParent;
- IDataItemObserver* mClient;
- };
- if (nullptr == client) {
- LOC_LOGw("Data item set is empty or client is nullptr");
- } else {
- mContext.mMsgTask->sendMsg(new HandleUnsubscribeAllReq(this, client));
- }
- }
- /******************************************************************************
- IDataItemObserver Overrides
- ******************************************************************************/
- void SystemStatusOsObserver::notify(const unordered_set<IDataItemCore*>& dlist)
- {
- struct HandleNotify : public LocMsg {
- HandleNotify(SystemStatusOsObserver* parent, vector<IDataItemCore*>& v) :
- mParent(parent), mDiVec(std::move(v)) {}
- inline virtual ~HandleNotify() {
- for (auto item : mDiVec) {
- delete item;
- }
- }
- void proc() const {
- // Update Cache with received data items and prepare
- // list of data items to be sent.
- unordered_set<DataItemId> dataItemIdsToBeSent = {};
- for (auto item : mDiVec) {
- if (mParent->updateCache(item)) {
- dataItemIdsToBeSent.insert(item->getId());
- }
- }
- // Send data item to all subscribed clients
- unordered_set<IDataItemObserver*> clientSet = {};
- for (auto each : dataItemIdsToBeSent) {
- auto clients = mParent->mDataItemToClients.getValSetPtr(each);
- if (nullptr != clients) {
- clientSet.insert(clients->begin(), clients->end());
- }
- }
- for (auto client : clientSet) {
- unordered_set<DataItemId> dataItemIdsForThisClient(
- mParent->mClientToDataItems.getValSet(client));
- for (auto itr = dataItemIdsForThisClient.begin();
- itr != dataItemIdsForThisClient.end(); ) {
- if (dataItemIdsToBeSent.find(*itr) == dataItemIdsToBeSent.end()) {
- itr = dataItemIdsForThisClient.erase(itr);
- } else {
- itr++;
- }
- }
- mParent->sendCachedDataItems(dataItemIdsForThisClient, client);
- }
- }
- SystemStatusOsObserver* mParent;
- const vector<IDataItemCore*> mDiVec;
- };
- if (!dlist.empty()) {
- vector<IDataItemCore*> dataItemVec;
- for (auto each : dlist) {
- IDataItemCore* di = DataItemsFactoryProxy::createNewDataItem(each);
- if (nullptr == di) {
- LOC_LOGw("Unable to create dataitem:%d", each->getId());
- continue;
- }
- // add this dataitem if updated from last one
- dataItemVec.push_back(di);
- IF_LOC_LOGD {
- string dv;
- di->stringify(dv);
- LOC_LOGd("notify: DataItem In Value:%s", dv.c_str());
- }
- }
- if (!dataItemVec.empty()) {
- mContext.mMsgTask->sendMsg(new HandleNotify(this, dataItemVec));
- }
- }
- }
- /******************************************************************************
- IFrameworkActionReq Overrides
- ******************************************************************************/
- void SystemStatusOsObserver::turnOn(DataItemId dit, int timeOut)
- {
- if (nullptr == mContext.mFrameworkActionReqObj) {
- LOC_LOGe("Framework action request object is NULL");
- return;
- }
- // Check if data item exists in mActiveRequestCount
- DataItemIdToInt::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<DataItemId, int> cpair(dit, 1);
- mActiveRequestCount.insert(cpair);
- LOC_LOGd("Sending turnOn request");
- // 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);
- }
- IFrameworkActionReq* mFrameworkActionReqObj;
- DataItemId mDataItemId;
- int mTimeOut;
- };
- mContext.mMsgTask->sendMsg(
- new (nothrow) HandleTurnOnMsg(mContext.mFrameworkActionReqObj, dit, timeOut));
- }
- else {
- // Found in map, update reference count
- citer->second++;
- LOC_LOGd("turnOn - Data item:%d Num_refs:%d", dit, citer->second);
- }
- }
- void SystemStatusOsObserver::turnOff(DataItemId dit)
- {
- if (nullptr == mContext.mFrameworkActionReqObj) {
- LOC_LOGe("Framework action request object is NULL");
- return;
- }
- // Check if data item exists in mActiveRequestCount
- DataItemIdToInt::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));
- }
- }
- }
- #ifdef USE_GLIB
- bool SystemStatusOsObserver::connectBackhaul(const BackhaulContext& ctx)
- {
- bool result = false;
- if (mContext.mFrameworkActionReqObj != NULL) {
- struct HandleConnectBackhaul : public LocMsg {
- HandleConnectBackhaul(IFrameworkActionReq* fwkActReq, const BackhaulContext& ctx) :
- mFwkActionReqObj(fwkActReq), mCtx(ctx) {}
- virtual ~HandleConnectBackhaul() {}
- void proc() const {
- LOC_LOGi("HandleConnectBackhaul::enter");
- mFwkActionReqObj->connectBackhaul(mCtx);
- LOC_LOGi("HandleConnectBackhaul::exit");
- }
- IFrameworkActionReq* mFwkActionReqObj;
- BackhaulContext mCtx;
- };
- mContext.mMsgTask->sendMsg(
- new (nothrow) HandleConnectBackhaul(mContext.mFrameworkActionReqObj, ctx));
- result = true;
- } else {
- LOC_LOGe("Framework action request object is NULL.Caching connect request: %s",
- ctx.clientName.c_str());
- LOC_LOGd("Adding client context to BackHaulConnReqCache list");
- mBackHaulConnReqCache[ctx.clientName] = ctx;
- result = false;
- }
- return result;
- }
- bool SystemStatusOsObserver::disconnectBackhaul(const BackhaulContext& ctx)
- {
- bool result = false;
- if (mContext.mFrameworkActionReqObj != NULL) {
- struct HandleDisconnectBackhaul : public LocMsg {
- HandleDisconnectBackhaul(IFrameworkActionReq* fwkActReq, const BackhaulContext& ctx) :
- mFwkActionReqObj(fwkActReq), mCtx(ctx) {}
- virtual ~HandleDisconnectBackhaul() {}
- void proc() const {
- LOC_LOGi("HandleDisconnectBackhaul::enter");
- mFwkActionReqObj->disconnectBackhaul(mCtx);
- LOC_LOGi("HandleDisconnectBackhaul::exit");
- }
- IFrameworkActionReq* mFwkActionReqObj;
- BackhaulContext mCtx;
- };
- mContext.mMsgTask->sendMsg(
- new (nothrow) HandleDisconnectBackhaul(mContext.mFrameworkActionReqObj, ctx));
- }
- else {
- LOC_LOGe("Framework action request object is NULL.Caching disconnect request: %s",
- ctx.clientName.c_str());
- // Check if client has requested for backhaul connection.
- LOC_LOGd("Removing client from BackHaulConnReqCache list");
- mBackHaulConnReqCache.erase(ctx.clientName);
- result = false;
- }
- return result;
- }
- #endif
- /******************************************************************************
- Helpers
- ******************************************************************************/
- void SystemStatusOsObserver::sendCachedDataItems(
- const unordered_set<DataItemId>& s, IDataItemObserver* to)
- {
- if (nullptr == to) {
- LOC_LOGv("client pointer is NULL.");
- } else {
- string clientName;
- to->getName(clientName);
- unordered_set<IDataItemCore*> dataItems = {};
- for (auto each : s) {
- auto citer = mDataItemCache.find(each);
- if (citer != mDataItemCache.end()) {
- string dv;
- citer->second->stringify(dv);
- LOC_LOGi("DataItem: %s >> %s", dv.c_str(), clientName.c_str());
- dataItems.insert(citer->second);
- }
- }
- if (dataItems.empty()) {
- LOC_LOGv("No items to notify.");
- } else {
- to->notify(dataItems);
- }
- }
- }
- bool SystemStatusOsObserver::updateCache(IDataItemCore* d)
- {
- bool dataItemUpdated = false;
- // Request systemstatus to record this dataitem in its cache
- // if the return is false, it means that SystemStatus is not
- // handling it, so SystemStatusOsObserver also doesn't.
- // So it has to be true to proceed.
- if (nullptr != d && mSystemStatus->eventDataItemNotify(d)) {
- dataItemUpdated = true;
- auto citer = mDataItemCache.find(d->getId());
- if (citer == mDataItemCache.end()) {
- // New data item; not found in cache
- IDataItemCore* dataitem = DataItemsFactoryProxy::createNewDataItem(d);
- if (nullptr != dataitem) {
- // Insert in mDataItemCache
- mDataItemCache.insert(std::make_pair(d->getId(), dataitem));
- }
- } else {
- // Found in cache; Update cache if necessary
- citer->second->copyFrom(d);
- }
- }
- if (nullptr != d) {
- LOC_LOGd("DataItem:%d updated:%d", d->getId(), dataItemUpdated);
- }
- return dataItemUpdated;
- }
- } // namespace loc_core
|