SystemStatusOsObserver.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556
  1. /* Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
  2. *
  3. * Redistribution and use in source and binary forms, with or without
  4. * modification, are permitted provided that the following conditions are
  5. * met:
  6. * * Redistributions of source code must retain the above copyright
  7. * notice, this list of conditions and the following disclaimer.
  8. * * Redistributions in binary form must reproduce the above
  9. * copyright notice, this list of conditions and the following
  10. * disclaimer in the documentation and/or other materials provided
  11. * with the distribution.
  12. * * Neither the name of The Linux Foundation, nor the names of its
  13. * contributors may be used to endorse or promote products derived
  14. * from this software without specific prior written permission.
  15. *
  16. * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
  17. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  18. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
  19. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
  20. * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  21. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  22. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
  23. * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  24. * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
  25. * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
  26. * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27. *
  28. */
  29. #define LOG_TAG "LocSvc_SystemStatusOsObserver"
  30. #include <algorithm>
  31. #include <SystemStatus.h>
  32. #include <SystemStatusOsObserver.h>
  33. #include <IDataItemCore.h>
  34. #include <DataItemsFactoryProxy.h>
  35. namespace loc_core
  36. {
  37. template <typename CINT, typename COUT>
  38. COUT SystemStatusOsObserver::containerTransfer(CINT& inContainer) {
  39. COUT outContainer = {};
  40. for (auto item : inContainer) {
  41. outContainer.insert(outContainer.begin(), item);
  42. }
  43. return outContainer;
  44. }
  45. SystemStatusOsObserver::~SystemStatusOsObserver() {
  46. // Destroy cache
  47. for (auto each : mDataItemCache) {
  48. if (nullptr != each.second) {
  49. delete each.second;
  50. }
  51. }
  52. mDataItemCache.clear();
  53. }
  54. void SystemStatusOsObserver::setSubscriptionObj(IDataItemSubscription* subscriptionObj)
  55. {
  56. struct SetSubsObj : public LocMsg {
  57. ObserverContext& mContext;
  58. IDataItemSubscription* mSubsObj;
  59. inline SetSubsObj(ObserverContext& context, IDataItemSubscription* subscriptionObj) :
  60. mContext(context), mSubsObj(subscriptionObj) {}
  61. void proc() const {
  62. LOC_LOGi("SetSubsObj::enter");
  63. mContext.mSubscriptionObj = mSubsObj;
  64. if (!mContext.mSSObserver->mDataItemToClients.empty()) {
  65. unordered_set<DataItemId> dis(mContext.mSSObserver->mDataItemToClients.getKeys());
  66. mContext.mSubscriptionObj->subscribe(dis, mContext.mSSObserver);
  67. mContext.mSubscriptionObj->requestData(dis, mContext.mSSObserver);
  68. }
  69. LOC_LOGi("SetSubsObj::exit");
  70. }
  71. };
  72. if (nullptr == subscriptionObj) {
  73. LOC_LOGw("subscriptionObj is NULL");
  74. } else {
  75. mContext.mMsgTask->sendMsg(new SetSubsObj(mContext, subscriptionObj));
  76. }
  77. }
  78. /******************************************************************************
  79. IDataItemSubscription Overrides
  80. ******************************************************************************/
  81. void SystemStatusOsObserver::subscribe(const unordered_set<DataItemId>& l, IDataItemObserver* client,
  82. bool toRequestData)
  83. {
  84. struct HandleSubscribeReq : public LocMsg {
  85. inline HandleSubscribeReq(SystemStatusOsObserver* parent,
  86. const unordered_set<DataItemId>& l, IDataItemObserver* client, bool requestData) :
  87. mParent(parent), mClient(client),
  88. mDataItemSet(std::move(l)),
  89. diItemlist(containerTransfer<const unordered_set<DataItemId>, list<DataItemId>>(l)),
  90. mToRequestData(requestData) {}
  91. void proc() const {
  92. unordered_set<DataItemId> dataItemsToSubscribe = {};
  93. mParent->mDataItemToClients.add(mDataItemSet, {mClient}, &dataItemsToSubscribe);
  94. mParent->mClientToDataItems.add(mClient, mDataItemSet);
  95. mParent->sendCachedDataItems(mDataItemSet, mClient);
  96. // Send subscription set to framework
  97. if (nullptr != mParent->mContext.mSubscriptionObj) {
  98. if (mToRequestData) {
  99. LOC_LOGd("Request Data sent to framework for the following");
  100. mParent->mContext.mSubscriptionObj->requestData(dataItemsToSubscribe, mParent);
  101. } else if (!dataItemsToSubscribe.empty()) {
  102. LOC_LOGd("Subscribe Request sent to framework for the following");
  103. mParent->logMe(dataItemsToSubscribe);
  104. mParent->mContext.mSubscriptionObj->subscribe(dataItemsToSubscribe, mParent);
  105. }
  106. }
  107. }
  108. mutable SystemStatusOsObserver* mParent;
  109. IDataItemObserver* mClient;
  110. const unordered_set<DataItemId> mDataItemSet;
  111. const list<DataItemId> diItemlist;
  112. bool mToRequestData;
  113. };
  114. if (l.empty() || nullptr == client) {
  115. LOC_LOGw("Data item set is empty or client is nullptr");
  116. } else {
  117. mContext.mMsgTask->sendMsg(
  118. new HandleSubscribeReq(this, l, client, toRequestData));
  119. }
  120. }
  121. void SystemStatusOsObserver::updateSubscription(
  122. const unordered_set<DataItemId>& l, IDataItemObserver* client)
  123. {
  124. struct HandleUpdateSubscriptionReq : public LocMsg {
  125. HandleUpdateSubscriptionReq(SystemStatusOsObserver* parent,
  126. const unordered_set<DataItemId>& l, IDataItemObserver* client) :
  127. mParent(parent), mClient(client), mDataItemSet(l) {}
  128. void proc() const {
  129. unordered_set<DataItemId> dataItemsToSubscribe = {};
  130. unordered_set<DataItemId> dataItemsToUnsubscribe = {};
  131. unordered_set<IDataItemObserver*> clients({mClient});
  132. // below removes clients from all entries keyed with the return of the
  133. // mClientToDataItems.update() call. If leaving an empty set of clients as the
  134. // result, the entire entry will be removed. dataItemsToUnsubscribe will be
  135. // populated to keep the keys of the removed entries.
  136. mParent->mDataItemToClients.trimOrRemove(
  137. // this call updates <IDataItemObserver*, DataItemId> map; removes
  138. // the DataItemId's that are not new to the clietn from mDataItemSet;
  139. // and returns a set of mDataItemSet's that are no longer used by client.
  140. // This unused set of mDataItemSet's is passed to trimOrRemove method of
  141. // <DataItemId, IDataItemObserver*> map to remove the client from the
  142. // corresponding entries, and gets a set of the entries that are
  143. // removed from the <DataItemId, IDataItemObserver*> map as a result.
  144. mParent->mClientToDataItems.update(mClient,
  145. (unordered_set<DataItemId>&)mDataItemSet),
  146. clients, &dataItemsToUnsubscribe, nullptr);
  147. // below adds mClient to <DataItemId, IDataItemObserver*> map, and populates
  148. // new keys added to that map, which are DataItemIds to be subscribed.
  149. mParent->mDataItemToClients.add(mDataItemSet, clients, &dataItemsToSubscribe);
  150. // Send First Response
  151. mParent->sendCachedDataItems(mDataItemSet, mClient);
  152. if (nullptr != mParent->mContext.mSubscriptionObj) {
  153. // Send subscription set to framework
  154. if (!dataItemsToSubscribe.empty()) {
  155. LOC_LOGd("Subscribe Request sent to framework for the following");
  156. mParent->logMe(dataItemsToSubscribe);
  157. mParent->mContext.mSubscriptionObj->subscribe(dataItemsToSubscribe, mParent);
  158. }
  159. // Send unsubscribe to framework
  160. if (!dataItemsToUnsubscribe.empty()) {
  161. LOC_LOGd("Unsubscribe Request sent to framework for the following");
  162. mParent->logMe(dataItemsToUnsubscribe);
  163. mParent->mContext.mSubscriptionObj->unsubscribe(dataItemsToUnsubscribe,
  164. mParent);
  165. }
  166. }
  167. }
  168. SystemStatusOsObserver* mParent;
  169. IDataItemObserver* mClient;
  170. unordered_set<DataItemId> mDataItemSet;
  171. };
  172. if (l.empty() || nullptr == client) {
  173. LOC_LOGw("Data item set is empty or client is nullptr");
  174. } else {
  175. mContext.mMsgTask->sendMsg(
  176. new HandleUpdateSubscriptionReq(this, l, client));
  177. }
  178. }
  179. void SystemStatusOsObserver::unsubscribe(
  180. const unordered_set<DataItemId>& l, IDataItemObserver* client)
  181. {
  182. struct HandleUnsubscribeReq : public LocMsg {
  183. HandleUnsubscribeReq(SystemStatusOsObserver* parent,
  184. const unordered_set<DataItemId>& l, IDataItemObserver* client) :
  185. mParent(parent), mClient(client),
  186. mDataItemSet(std::move(l)) {}
  187. void proc() const {
  188. unordered_set<DataItemId> dataItemsUnusedByClient = {};
  189. unordered_set<IDataItemObserver*> clientToRemove = {};
  190. unordered_set<DataItemId> dataItemsToUnsubscribe = {};
  191. mParent->mClientToDataItems.trimOrRemove({mClient}, mDataItemSet, &clientToRemove,
  192. &dataItemsUnusedByClient);
  193. mParent->mDataItemToClients.trimOrRemove(dataItemsUnusedByClient, {mClient},
  194. &dataItemsToUnsubscribe, nullptr);
  195. if (nullptr != mParent->mContext.mSubscriptionObj && !dataItemsToUnsubscribe.empty()) {
  196. LOC_LOGd("Unsubscribe Request sent to framework for the following data items");
  197. mParent->logMe(dataItemsToUnsubscribe);
  198. // Send unsubscribe to framework
  199. mParent->mContext.mSubscriptionObj->unsubscribe(dataItemsToUnsubscribe, mParent);
  200. }
  201. }
  202. SystemStatusOsObserver* mParent;
  203. IDataItemObserver* mClient;
  204. unordered_set<DataItemId> mDataItemSet;
  205. };
  206. if (l.empty() || nullptr == client) {
  207. LOC_LOGw("Data item set is empty or client is nullptr");
  208. } else {
  209. mContext.mMsgTask->sendMsg(new HandleUnsubscribeReq(this, l, client));
  210. }
  211. }
  212. void SystemStatusOsObserver::unsubscribeAll(IDataItemObserver* client)
  213. {
  214. struct HandleUnsubscribeAllReq : public LocMsg {
  215. HandleUnsubscribeAllReq(SystemStatusOsObserver* parent,
  216. IDataItemObserver* client) :
  217. mParent(parent), mClient(client) {}
  218. void proc() const {
  219. unordered_set<DataItemId> diByClient = mParent->mClientToDataItems.getValSet(mClient);
  220. if (!diByClient.empty()) {
  221. unordered_set<DataItemId> dataItemsToUnsubscribe;
  222. mParent->mClientToDataItems.remove(mClient);
  223. mParent->mDataItemToClients.trimOrRemove(diByClient, {mClient},
  224. &dataItemsToUnsubscribe, nullptr);
  225. if (!dataItemsToUnsubscribe.empty() &&
  226. nullptr != mParent->mContext.mSubscriptionObj) {
  227. LOC_LOGd("Unsubscribe Request sent to framework for the following data items");
  228. mParent->logMe(dataItemsToUnsubscribe);
  229. // Send unsubscribe to framework
  230. mParent->mContext.mSubscriptionObj->unsubscribe(dataItemsToUnsubscribe,
  231. mParent);
  232. }
  233. }
  234. }
  235. SystemStatusOsObserver* mParent;
  236. IDataItemObserver* mClient;
  237. };
  238. if (nullptr == client) {
  239. LOC_LOGw("Data item set is empty or client is nullptr");
  240. } else {
  241. mContext.mMsgTask->sendMsg(new HandleUnsubscribeAllReq(this, client));
  242. }
  243. }
  244. /******************************************************************************
  245. IDataItemObserver Overrides
  246. ******************************************************************************/
  247. void SystemStatusOsObserver::notify(const unordered_set<IDataItemCore*>& dlist)
  248. {
  249. struct HandleNotify : public LocMsg {
  250. HandleNotify(SystemStatusOsObserver* parent, vector<IDataItemCore*>& v) :
  251. mParent(parent), mDiVec(std::move(v)) {}
  252. inline virtual ~HandleNotify() {
  253. for (auto item : mDiVec) {
  254. delete item;
  255. }
  256. }
  257. void proc() const {
  258. // Update Cache with received data items and prepare
  259. // list of data items to be sent.
  260. unordered_set<DataItemId> dataItemIdsToBeSent = {};
  261. for (auto item : mDiVec) {
  262. if (mParent->updateCache(item)) {
  263. dataItemIdsToBeSent.insert(item->getId());
  264. }
  265. }
  266. // Send data item to all subscribed clients
  267. unordered_set<IDataItemObserver*> clientSet = {};
  268. for (auto each : dataItemIdsToBeSent) {
  269. auto clients = mParent->mDataItemToClients.getValSetPtr(each);
  270. if (nullptr != clients) {
  271. clientSet.insert(clients->begin(), clients->end());
  272. }
  273. }
  274. for (auto client : clientSet) {
  275. unordered_set<DataItemId> dataItemIdsForThisClient(
  276. mParent->mClientToDataItems.getValSet(client));
  277. for (auto itr = dataItemIdsForThisClient.begin();
  278. itr != dataItemIdsForThisClient.end(); ) {
  279. if (dataItemIdsToBeSent.find(*itr) == dataItemIdsToBeSent.end()) {
  280. itr = dataItemIdsForThisClient.erase(itr);
  281. } else {
  282. itr++;
  283. }
  284. }
  285. mParent->sendCachedDataItems(dataItemIdsForThisClient, client);
  286. }
  287. }
  288. SystemStatusOsObserver* mParent;
  289. const vector<IDataItemCore*> mDiVec;
  290. };
  291. if (!dlist.empty()) {
  292. vector<IDataItemCore*> dataItemVec;
  293. for (auto each : dlist) {
  294. IDataItemCore* di = DataItemsFactoryProxy::createNewDataItem(each);
  295. if (nullptr == di) {
  296. LOC_LOGw("Unable to create dataitem:%d", each->getId());
  297. continue;
  298. }
  299. // add this dataitem if updated from last one
  300. dataItemVec.push_back(di);
  301. IF_LOC_LOGD {
  302. string dv;
  303. di->stringify(dv);
  304. LOC_LOGd("notify: DataItem In Value:%s", dv.c_str());
  305. }
  306. }
  307. if (!dataItemVec.empty()) {
  308. mContext.mMsgTask->sendMsg(new HandleNotify(this, dataItemVec));
  309. }
  310. }
  311. }
  312. /******************************************************************************
  313. IFrameworkActionReq Overrides
  314. ******************************************************************************/
  315. void SystemStatusOsObserver::turnOn(DataItemId dit, int timeOut)
  316. {
  317. if (nullptr == mContext.mFrameworkActionReqObj) {
  318. LOC_LOGe("Framework action request object is NULL");
  319. return;
  320. }
  321. // Check if data item exists in mActiveRequestCount
  322. DataItemIdToInt::iterator citer = mActiveRequestCount.find(dit);
  323. if (citer == mActiveRequestCount.end()) {
  324. // Data item not found in map
  325. // Add reference count as 1 and add dataitem to map
  326. pair<DataItemId, int> cpair(dit, 1);
  327. mActiveRequestCount.insert(cpair);
  328. LOC_LOGd("Sending turnOn request");
  329. // Send action turn on to framework
  330. struct HandleTurnOnMsg : public LocMsg {
  331. HandleTurnOnMsg(IFrameworkActionReq* framework,
  332. DataItemId dit, int timeOut) :
  333. mFrameworkActionReqObj(framework), mDataItemId(dit), mTimeOut(timeOut) {}
  334. virtual ~HandleTurnOnMsg() {}
  335. void proc() const {
  336. mFrameworkActionReqObj->turnOn(mDataItemId, mTimeOut);
  337. }
  338. IFrameworkActionReq* mFrameworkActionReqObj;
  339. DataItemId mDataItemId;
  340. int mTimeOut;
  341. };
  342. mContext.mMsgTask->sendMsg(
  343. new (nothrow) HandleTurnOnMsg(mContext.mFrameworkActionReqObj, dit, timeOut));
  344. }
  345. else {
  346. // Found in map, update reference count
  347. citer->second++;
  348. LOC_LOGd("turnOn - Data item:%d Num_refs:%d", dit, citer->second);
  349. }
  350. }
  351. void SystemStatusOsObserver::turnOff(DataItemId dit)
  352. {
  353. if (nullptr == mContext.mFrameworkActionReqObj) {
  354. LOC_LOGe("Framework action request object is NULL");
  355. return;
  356. }
  357. // Check if data item exists in mActiveRequestCount
  358. DataItemIdToInt::iterator citer = mActiveRequestCount.find(dit);
  359. if (citer != mActiveRequestCount.end()) {
  360. // found
  361. citer->second--;
  362. LOC_LOGd("turnOff - Data item:%d Remaining:%d", dit, citer->second);
  363. if(citer->second == 0) {
  364. // if this was last reference, remove item from map and turn off module
  365. mActiveRequestCount.erase(citer);
  366. // Send action turn off to framework
  367. struct HandleTurnOffMsg : public LocMsg {
  368. HandleTurnOffMsg(IFrameworkActionReq* framework, DataItemId dit) :
  369. mFrameworkActionReqObj(framework), mDataItemId(dit) {}
  370. virtual ~HandleTurnOffMsg() {}
  371. void proc() const {
  372. mFrameworkActionReqObj->turnOff(mDataItemId);
  373. }
  374. IFrameworkActionReq* mFrameworkActionReqObj;
  375. DataItemId mDataItemId;
  376. };
  377. mContext.mMsgTask->sendMsg(
  378. new (nothrow) HandleTurnOffMsg(mContext.mFrameworkActionReqObj, dit));
  379. }
  380. }
  381. }
  382. #ifdef USE_GLIB
  383. bool SystemStatusOsObserver::connectBackhaul(const BackhaulContext& ctx)
  384. {
  385. bool result = false;
  386. if (mContext.mFrameworkActionReqObj != NULL) {
  387. struct HandleConnectBackhaul : public LocMsg {
  388. HandleConnectBackhaul(IFrameworkActionReq* fwkActReq, const BackhaulContext& ctx) :
  389. mFwkActionReqObj(fwkActReq), mCtx(ctx) {}
  390. virtual ~HandleConnectBackhaul() {}
  391. void proc() const {
  392. LOC_LOGi("HandleConnectBackhaul::enter");
  393. mFwkActionReqObj->connectBackhaul(mCtx);
  394. LOC_LOGi("HandleConnectBackhaul::exit");
  395. }
  396. IFrameworkActionReq* mFwkActionReqObj;
  397. BackhaulContext mCtx;
  398. };
  399. mContext.mMsgTask->sendMsg(
  400. new (nothrow) HandleConnectBackhaul(mContext.mFrameworkActionReqObj, ctx));
  401. result = true;
  402. } else {
  403. LOC_LOGe("Framework action request object is NULL.Caching connect request: %s",
  404. ctx.clientName.c_str());
  405. LOC_LOGd("Adding client context to BackHaulConnReqCache list");
  406. mBackHaulConnReqCache[ctx.clientName] = ctx;
  407. result = false;
  408. }
  409. return result;
  410. }
  411. bool SystemStatusOsObserver::disconnectBackhaul(const BackhaulContext& ctx)
  412. {
  413. bool result = false;
  414. if (mContext.mFrameworkActionReqObj != NULL) {
  415. struct HandleDisconnectBackhaul : public LocMsg {
  416. HandleDisconnectBackhaul(IFrameworkActionReq* fwkActReq, const BackhaulContext& ctx) :
  417. mFwkActionReqObj(fwkActReq), mCtx(ctx) {}
  418. virtual ~HandleDisconnectBackhaul() {}
  419. void proc() const {
  420. LOC_LOGi("HandleDisconnectBackhaul::enter");
  421. mFwkActionReqObj->disconnectBackhaul(mCtx);
  422. LOC_LOGi("HandleDisconnectBackhaul::exit");
  423. }
  424. IFrameworkActionReq* mFwkActionReqObj;
  425. BackhaulContext mCtx;
  426. };
  427. mContext.mMsgTask->sendMsg(
  428. new (nothrow) HandleDisconnectBackhaul(mContext.mFrameworkActionReqObj, ctx));
  429. }
  430. else {
  431. LOC_LOGe("Framework action request object is NULL.Caching disconnect request: %s",
  432. ctx.clientName.c_str());
  433. // Check if client has requested for backhaul connection.
  434. LOC_LOGd("Removing client from BackHaulConnReqCache list");
  435. mBackHaulConnReqCache.erase(ctx.clientName);
  436. result = false;
  437. }
  438. return result;
  439. }
  440. #endif
  441. /******************************************************************************
  442. Helpers
  443. ******************************************************************************/
  444. void SystemStatusOsObserver::sendCachedDataItems(
  445. const unordered_set<DataItemId>& s, IDataItemObserver* to)
  446. {
  447. if (nullptr == to) {
  448. LOC_LOGv("client pointer is NULL.");
  449. } else {
  450. string clientName;
  451. to->getName(clientName);
  452. unordered_set<IDataItemCore*> dataItems = {};
  453. for (auto each : s) {
  454. auto citer = mDataItemCache.find(each);
  455. if (citer != mDataItemCache.end()) {
  456. string dv;
  457. citer->second->stringify(dv);
  458. LOC_LOGi("DataItem: %s >> %s", dv.c_str(), clientName.c_str());
  459. dataItems.insert(citer->second);
  460. }
  461. }
  462. if (dataItems.empty()) {
  463. LOC_LOGv("No items to notify.");
  464. } else {
  465. to->notify(dataItems);
  466. }
  467. }
  468. }
  469. bool SystemStatusOsObserver::updateCache(IDataItemCore* d)
  470. {
  471. bool dataItemUpdated = false;
  472. // Request systemstatus to record this dataitem in its cache
  473. // if the return is false, it means that SystemStatus is not
  474. // handling it, so SystemStatusOsObserver also doesn't.
  475. // So it has to be true to proceed.
  476. if (nullptr != d && mSystemStatus->eventDataItemNotify(d)) {
  477. dataItemUpdated = true;
  478. auto citer = mDataItemCache.find(d->getId());
  479. if (citer == mDataItemCache.end()) {
  480. // New data item; not found in cache
  481. IDataItemCore* dataitem = DataItemsFactoryProxy::createNewDataItem(d);
  482. if (nullptr != dataitem) {
  483. // Insert in mDataItemCache
  484. mDataItemCache.insert(std::make_pair(d->getId(), dataitem));
  485. }
  486. } else {
  487. // Found in cache; Update cache if necessary
  488. citer->second->copyFrom(d);
  489. }
  490. }
  491. if (nullptr != d) {
  492. LOC_LOGd("DataItem:%d updated:%d", d->getId(), dataItemUpdated);
  493. }
  494. return dataItemUpdated;
  495. }
  496. } // namespace loc_core