• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright (c) 2015-2020, 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 
31 #include <algorithm>
32 #include <SystemStatus.h>
33 #include <SystemStatusOsObserver.h>
34 #include <IDataItemCore.h>
35 #include <DataItemsFactoryProxy.h>
36 
37 namespace loc_core
38 {
39 template <typename CINT, typename COUT>
containerTransfer(CINT & inContainer)40 COUT SystemStatusOsObserver::containerTransfer(CINT& inContainer) {
41     COUT outContainer = {};
42     for (auto item : inContainer) {
43         outContainer.insert(outContainer.begin(), item);
44     }
45     return outContainer;
46 }
47 
~SystemStatusOsObserver()48 SystemStatusOsObserver::~SystemStatusOsObserver() {
49     // Close data-item library handle
50     DataItemsFactoryProxy::closeDataItemLibraryHandle();
51 
52     // Destroy cache
53     for (auto each : mDataItemCache) {
54         if (nullptr != each.second) {
55             delete each.second;
56         }
57     }
58 
59     mDataItemCache.clear();
60 }
61 
setSubscriptionObj(IDataItemSubscription * subscriptionObj)62 void SystemStatusOsObserver::setSubscriptionObj(IDataItemSubscription* subscriptionObj)
63 {
64     struct SetSubsObj : public LocMsg {
65         ObserverContext& mContext;
66         IDataItemSubscription* mSubsObj;
67         inline SetSubsObj(ObserverContext& context, IDataItemSubscription* subscriptionObj) :
68                 mContext(context), mSubsObj(subscriptionObj) {}
69         void proc() const {
70             LOC_LOGi("SetSubsObj::enter");
71             mContext.mSubscriptionObj = mSubsObj;
72 
73             if (!mContext.mSSObserver->mDataItemToClients.empty()) {
74                 list<DataItemId> dis(
75                         containerTransfer<unordered_set<DataItemId>, list<DataItemId>>(
76                                 mContext.mSSObserver->mDataItemToClients.getKeys()));
77                 mContext.mSubscriptionObj->subscribe(dis, mContext.mSSObserver);
78                 mContext.mSubscriptionObj->requestData(dis, mContext.mSSObserver);
79             }
80             LOC_LOGi("SetSubsObj::exit");
81         }
82     };
83 
84     if (nullptr == subscriptionObj) {
85         LOC_LOGw("subscriptionObj is NULL");
86     } else {
87         mContext.mMsgTask->sendMsg(new SetSubsObj(mContext, subscriptionObj));
88     }
89 }
90 
91 /******************************************************************************
92  IDataItemSubscription Overrides
93 ******************************************************************************/
subscribe(const list<DataItemId> & l,IDataItemObserver * client,bool toRequestData)94 void SystemStatusOsObserver::subscribe(const list<DataItemId>& l, IDataItemObserver* client,
95                                        bool toRequestData)
96 {
97     struct HandleSubscribeReq : public LocMsg {
98         inline HandleSubscribeReq(SystemStatusOsObserver* parent,
99                 list<DataItemId>& l, IDataItemObserver* client, bool requestData) :
100                 mParent(parent), mClient(client),
101                 mDataItemSet(containerTransfer<list<DataItemId>, unordered_set<DataItemId>>(l)),
102                 diItemlist(l),
103                 mToRequestData(requestData) {}
104 
105         void proc() const {
106             unordered_set<DataItemId> dataItemsToSubscribe = {};
107             mParent->mDataItemToClients.add(mDataItemSet, {mClient}, &dataItemsToSubscribe);
108             mParent->mClientToDataItems.add(mClient, mDataItemSet);
109 
110             mParent->sendCachedDataItems(mDataItemSet, mClient);
111 
112             // Send subscription set to framework
113             if (nullptr != mParent->mContext.mSubscriptionObj) {
114                 if (mToRequestData) {
115                     LOC_LOGD("Request Data sent to framework for the following");
116                     mParent->mContext.mSubscriptionObj->requestData(diItemlist, mParent);
117                 } else if (!dataItemsToSubscribe.empty()) {
118                     LOC_LOGD("Subscribe Request sent to framework for the following");
119                     mParent->logMe(dataItemsToSubscribe);
120                     mParent->mContext.mSubscriptionObj->subscribe(
121                             containerTransfer<unordered_set<DataItemId>, list<DataItemId>>(
122                                     std::move(dataItemsToSubscribe)),
123                             mParent);
124                 }
125             }
126         }
127         mutable SystemStatusOsObserver* mParent;
128         IDataItemObserver* mClient;
129         const unordered_set<DataItemId> mDataItemSet;
130         const list<DataItemId> diItemlist;
131         bool mToRequestData;
132     };
133 
134     if (l.empty() || nullptr == client) {
135         LOC_LOGw("Data item set is empty or client is nullptr");
136     } else {
137         mContext.mMsgTask->sendMsg(
138                 new HandleSubscribeReq(this, (list<DataItemId>&)l, client, toRequestData));
139     }
140 }
141 
updateSubscription(const list<DataItemId> & l,IDataItemObserver * client)142 void SystemStatusOsObserver::updateSubscription(
143         const list<DataItemId>& l, IDataItemObserver* client)
144 {
145     struct HandleUpdateSubscriptionReq : public LocMsg {
146         HandleUpdateSubscriptionReq(SystemStatusOsObserver* parent,
147                                     list<DataItemId>& l, IDataItemObserver* client) :
148                 mParent(parent), mClient(client),
149                 mDataItemSet(containerTransfer<list<DataItemId>, unordered_set<DataItemId>>(l)) {}
150 
151         void proc() const {
152             unordered_set<DataItemId> dataItemsToSubscribe = {};
153             unordered_set<DataItemId> dataItemsToUnsubscribe = {};
154             unordered_set<IDataItemObserver*> clients({mClient});
155             // below removes clients from all entries keyed with the return of the
156             // mClientToDataItems.update() call. If leaving an empty set of clients as the
157             // result, the entire entry will be removed. dataItemsToUnsubscribe will be
158             // populated to keep the keys of the removed entries.
159             mParent->mDataItemToClients.trimOrRemove(
160                     // this call updates <IDataItemObserver*, DataItemId> map; removes
161                     // the DataItemId's that are not new to the clietn from mDataItemSet;
162                     // and returns a set of mDataItemSet's that are no longer used by client.
163                     // This unused set of mDataItemSet's is passed to trimOrRemove method of
164                     // <DataItemId, IDataItemObserver*> map to remove the client from the
165                     // corresponding entries, and gets a set of the entries that are
166                     // removed from the <DataItemId, IDataItemObserver*> map as a result.
167                     mParent->mClientToDataItems.update(mClient,
168                                                        (unordered_set<DataItemId>&)mDataItemSet),
169                     clients, &dataItemsToUnsubscribe, nullptr);
170             // below adds mClient to <DataItemId, IDataItemObserver*> map, and populates
171             // new keys added to that map, which are DataItemIds to be subscribed.
172             mParent->mDataItemToClients.add(mDataItemSet, clients, &dataItemsToSubscribe);
173 
174             // Send First Response
175             mParent->sendCachedDataItems(mDataItemSet, mClient);
176 
177             if (nullptr != mParent->mContext.mSubscriptionObj) {
178                 // Send subscription set to framework
179                 if (!dataItemsToSubscribe.empty()) {
180                     LOC_LOGD("Subscribe Request sent to framework for the following");
181                     mParent->logMe(dataItemsToSubscribe);
182 
183                     mParent->mContext.mSubscriptionObj->subscribe(
184                             containerTransfer<unordered_set<DataItemId>, list<DataItemId>>(
185                                     std::move(dataItemsToSubscribe)),
186                             mParent);
187                 }
188 
189                 // Send unsubscribe to framework
190                 if (!dataItemsToUnsubscribe.empty()) {
191                     LOC_LOGD("Unsubscribe Request sent to framework for the following");
192                     mParent->logMe(dataItemsToUnsubscribe);
193 
194                     mParent->mContext.mSubscriptionObj->unsubscribe(
195                             containerTransfer<unordered_set<DataItemId>, list<DataItemId>>(
196                                     std::move(dataItemsToUnsubscribe)),
197                             mParent);
198                 }
199             }
200         }
201         SystemStatusOsObserver* mParent;
202         IDataItemObserver* mClient;
203         unordered_set<DataItemId> mDataItemSet;
204     };
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(
210                 new HandleUpdateSubscriptionReq(this, (list<DataItemId>&)l, client));
211     }
212 }
213 
unsubscribe(const list<DataItemId> & l,IDataItemObserver * client)214 void SystemStatusOsObserver::unsubscribe(
215         const list<DataItemId>& l, IDataItemObserver* client)
216 {
217     struct HandleUnsubscribeReq : public LocMsg {
218         HandleUnsubscribeReq(SystemStatusOsObserver* parent,
219                 list<DataItemId>& l, IDataItemObserver* client) :
220                 mParent(parent), mClient(client),
221                 mDataItemSet(containerTransfer<list<DataItemId>, unordered_set<DataItemId>>(l)) {}
222 
223         void proc() const {
224             unordered_set<DataItemId> dataItemsUnusedByClient = {};
225             unordered_set<IDataItemObserver*> clientToRemove = {};
226             unordered_set<DataItemId> dataItemsToUnsubscribe = {};
227             mParent->mClientToDataItems.trimOrRemove({mClient}, mDataItemSet,  &clientToRemove,
228                                                      &dataItemsUnusedByClient);
229             mParent->mDataItemToClients.trimOrRemove(dataItemsUnusedByClient, {mClient},
230                                                      &dataItemsToUnsubscribe, nullptr);
231 
232             if (nullptr != mParent->mContext.mSubscriptionObj && !dataItemsToUnsubscribe.empty()) {
233                 LOC_LOGD("Unsubscribe Request sent to framework for the following data items");
234                 mParent->logMe(dataItemsToUnsubscribe);
235 
236                 // Send unsubscribe to framework
237                 mParent->mContext.mSubscriptionObj->unsubscribe(
238                         containerTransfer<unordered_set<DataItemId>, list<DataItemId>>(
239                                   std::move(dataItemsToUnsubscribe)),
240                         mParent);
241             }
242         }
243         SystemStatusOsObserver* mParent;
244         IDataItemObserver* mClient;
245         unordered_set<DataItemId> mDataItemSet;
246     };
247 
248     if (l.empty() || nullptr == client) {
249         LOC_LOGw("Data item set is empty or client is nullptr");
250     } else {
251         mContext.mMsgTask->sendMsg(new HandleUnsubscribeReq(this, (list<DataItemId>&)l, client));
252     }
253 }
254 
unsubscribeAll(IDataItemObserver * client)255 void SystemStatusOsObserver::unsubscribeAll(IDataItemObserver* client)
256 {
257     struct HandleUnsubscribeAllReq : public LocMsg {
258         HandleUnsubscribeAllReq(SystemStatusOsObserver* parent,
259                 IDataItemObserver* client) :
260                 mParent(parent), mClient(client) {}
261 
262         void proc() const {
263             unordered_set<DataItemId> diByClient = mParent->mClientToDataItems.getValSet(mClient);
264 
265             if (!diByClient.empty()) {
266                 unordered_set<DataItemId> dataItemsToUnsubscribe;
267                 mParent->mClientToDataItems.remove(mClient);
268                 mParent->mDataItemToClients.trimOrRemove(diByClient, {mClient},
269                                                          &dataItemsToUnsubscribe, nullptr);
270 
271                 if (!dataItemsToUnsubscribe.empty() &&
272                     nullptr != mParent->mContext.mSubscriptionObj) {
273 
274                     LOC_LOGD("Unsubscribe Request sent to framework for the following data items");
275                     mParent->logMe(dataItemsToUnsubscribe);
276 
277                     // Send unsubscribe to framework
278                     mParent->mContext.mSubscriptionObj->unsubscribe(
279                             containerTransfer<unordered_set<DataItemId>, list<DataItemId>>(
280                                     std::move(dataItemsToUnsubscribe)),
281                             mParent);
282                 }
283             }
284         }
285         SystemStatusOsObserver* mParent;
286         IDataItemObserver* mClient;
287     };
288 
289     if (nullptr == client) {
290         LOC_LOGw("Data item set is empty or client is nullptr");
291     } else {
292         mContext.mMsgTask->sendMsg(new HandleUnsubscribeAllReq(this, client));
293     }
294 }
295 
296 /******************************************************************************
297  IDataItemObserver Overrides
298 ******************************************************************************/
notify(const list<IDataItemCore * > & dlist)299 void SystemStatusOsObserver::notify(const list<IDataItemCore*>& dlist)
300 {
301     struct HandleNotify : public LocMsg {
302         HandleNotify(SystemStatusOsObserver* parent, vector<IDataItemCore*>& v) :
303                 mParent(parent), mDiVec(std::move(v)) {}
304 
305         inline virtual ~HandleNotify() {
306             for (auto item : mDiVec) {
307                 delete item;
308             }
309         }
310 
311         void proc() const {
312             // Update Cache with received data items and prepare
313             // list of data items to be sent.
314             unordered_set<DataItemId> dataItemIdsToBeSent = {};
315             for (auto item : mDiVec) {
316                 if (mParent->updateCache(item)) {
317                     dataItemIdsToBeSent.insert(item->getId());
318                 }
319             }
320 
321             // Send data item to all subscribed clients
322             unordered_set<IDataItemObserver*> clientSet = {};
323             for (auto each : dataItemIdsToBeSent) {
324                 auto clients = mParent->mDataItemToClients.getValSetPtr(each);
325                 if (nullptr != clients) {
326                     clientSet.insert(clients->begin(), clients->end());
327                 }
328             }
329 
330             for (auto client : clientSet) {
331                 unordered_set<DataItemId> dataItemIdsForThisClient(
332                         mParent->mClientToDataItems.getValSet(client));
333                 for (auto itr = dataItemIdsForThisClient.begin();
334                         itr != dataItemIdsForThisClient.end(); ) {
335                     if (dataItemIdsToBeSent.find(*itr) == dataItemIdsToBeSent.end()) {
336                         itr = dataItemIdsForThisClient.erase(itr);
337                     } else {
338                         itr++;
339                     }
340                 }
341 
342                 mParent->sendCachedDataItems(dataItemIdsForThisClient, client);
343             }
344         }
345         SystemStatusOsObserver* mParent;
346         const vector<IDataItemCore*> mDiVec;
347     };
348 
349     if (!dlist.empty()) {
350         vector<IDataItemCore*> dataItemVec(dlist.size());
351 
352         for (auto each : dlist) {
353 
354             IDataItemCore* di = DataItemsFactoryProxy::createNewDataItem(each->getId());
355             if (nullptr == di) {
356                 LOC_LOGw("Unable to create dataitem:%d", each->getId());
357                 continue;
358             }
359 
360             // Copy contents into the newly created data item
361             di->copy(each);
362 
363             // add this dataitem if updated from last one
364             dataItemVec.push_back(di);
365             IF_LOC_LOGD {
366                 string dv;
367                 di->stringify(dv);
368                 LOC_LOGd("notify: DataItem In Value:%s", dv.c_str());
369             }
370         }
371 
372         if (!dataItemVec.empty()) {
373             mContext.mMsgTask->sendMsg(new HandleNotify(this, dataItemVec));
374         }
375     }
376 }
377 
378 /******************************************************************************
379  IFrameworkActionReq Overrides
380 ******************************************************************************/
turnOn(DataItemId dit,int timeOut)381 void SystemStatusOsObserver::turnOn(DataItemId dit, int timeOut)
382 {
383     if (nullptr == mContext.mFrameworkActionReqObj) {
384         LOC_LOGE("%s:%d]: Framework action request object is NULL", __func__, __LINE__);
385         return;
386     }
387 
388     // Check if data item exists in mActiveRequestCount
389     DataItemIdToInt::iterator citer = mActiveRequestCount.find(dit);
390     if (citer == mActiveRequestCount.end()) {
391         // Data item not found in map
392         // Add reference count as 1 and add dataitem to map
393         pair<DataItemId, int> cpair(dit, 1);
394         mActiveRequestCount.insert(cpair);
395         LOC_LOGD("Sending turnOn request");
396 
397         // Send action turn on to framework
398         struct HandleTurnOnMsg : public LocMsg {
399             HandleTurnOnMsg(IFrameworkActionReq* framework,
400                     DataItemId dit, int timeOut) :
401                     mFrameworkActionReqObj(framework), mDataItemId(dit), mTimeOut(timeOut) {}
402             virtual ~HandleTurnOnMsg() {}
403             void proc() const {
404                 mFrameworkActionReqObj->turnOn(mDataItemId, mTimeOut);
405             }
406             IFrameworkActionReq* mFrameworkActionReqObj;
407             DataItemId mDataItemId;
408             int mTimeOut;
409         };
410         mContext.mMsgTask->sendMsg(
411                 new (nothrow) HandleTurnOnMsg(mContext.mFrameworkActionReqObj, dit, timeOut));
412     }
413     else {
414         // Found in map, update reference count
415         citer->second++;
416         LOC_LOGD("turnOn - Data item:%d Num_refs:%d", dit, citer->second);
417     }
418 }
419 
turnOff(DataItemId dit)420 void SystemStatusOsObserver::turnOff(DataItemId dit)
421 {
422     if (nullptr == mContext.mFrameworkActionReqObj) {
423         LOC_LOGE("%s:%d]: Framework action request object is NULL", __func__, __LINE__);
424         return;
425     }
426 
427     // Check if data item exists in mActiveRequestCount
428     DataItemIdToInt::iterator citer = mActiveRequestCount.find(dit);
429     if (citer != mActiveRequestCount.end()) {
430         // found
431         citer->second--;
432         LOC_LOGD("turnOff - Data item:%d Remaining:%d", dit, citer->second);
433         if(citer->second == 0) {
434             // if this was last reference, remove item from map and turn off module
435             mActiveRequestCount.erase(citer);
436 
437             // Send action turn off to framework
438             struct HandleTurnOffMsg : public LocMsg {
439                 HandleTurnOffMsg(IFrameworkActionReq* framework, DataItemId dit) :
440                     mFrameworkActionReqObj(framework), mDataItemId(dit) {}
441                 virtual ~HandleTurnOffMsg() {}
442                 void proc() const {
443                     mFrameworkActionReqObj->turnOff(mDataItemId);
444                 }
445                 IFrameworkActionReq* mFrameworkActionReqObj;
446                 DataItemId mDataItemId;
447             };
448             mContext.mMsgTask->sendMsg(
449                     new (nothrow) HandleTurnOffMsg(mContext.mFrameworkActionReqObj, dit));
450         }
451     }
452 }
453 
454 #ifdef USE_GLIB
connectBackhaul(const string & clientName)455 bool SystemStatusOsObserver::connectBackhaul(const string& clientName)
456 {
457     bool result = false;
458 
459     if (mContext.mFrameworkActionReqObj != NULL) {
460         struct HandleConnectBackhaul : public LocMsg {
461             HandleConnectBackhaul(IFrameworkActionReq* fwkActReq, const string& clientName) :
462                     mClientName(clientName), mFwkActionReqObj(fwkActReq) {}
463             virtual ~HandleConnectBackhaul() {}
464             void proc() const {
465                 LOC_LOGi("HandleConnectBackhaul::enter");
466                 mFwkActionReqObj->connectBackhaul(mClientName);
467                 LOC_LOGi("HandleConnectBackhaul::exit");
468             }
469             IFrameworkActionReq* mFwkActionReqObj;
470             string mClientName;
471         };
472         mContext.mMsgTask->sendMsg(
473                 new (nothrow) HandleConnectBackhaul(mContext.mFrameworkActionReqObj, clientName));
474         result = true;
475     }
476     else {
477         LOC_LOGe("Framework action request object is NULL.Caching connect request: %s",
478                 clientName.c_str());
479         ClientBackhaulReqCache::const_iterator iter = mBackHaulConnReqCache.find(clientName);
480         if (iter == mBackHaulConnReqCache.end()) {
481             // not found in set. first time receiving from request from client
482             LOC_LOGe("Adding client to BackHaulConnReqCache list");
483             mBackHaulConnReqCache.insert(clientName);
484         }
485         result = false;
486     }
487     return result;
488 
489 }
490 
disconnectBackhaul(const string & clientName)491 bool SystemStatusOsObserver::disconnectBackhaul(const string& clientName)
492 {
493     bool result = false;
494 
495     if (mContext.mFrameworkActionReqObj != NULL) {
496         struct HandleDisconnectBackhaul : public LocMsg {
497             HandleDisconnectBackhaul(IFrameworkActionReq* fwkActReq, const string& clientName) :
498                     mClientName(clientName), mFwkActionReqObj(fwkActReq) {}
499             virtual ~HandleDisconnectBackhaul() {}
500             void proc() const {
501                 LOC_LOGi("HandleDisconnectBackhaul::enter");
502                 mFwkActionReqObj->disconnectBackhaul(mClientName);
503                 LOC_LOGi("HandleDisconnectBackhaul::exit");
504             }
505             IFrameworkActionReq* mFwkActionReqObj;
506             string mClientName;
507         };
508         mContext.mMsgTask->sendMsg(
509                 new (nothrow) HandleDisconnectBackhaul(mContext.mFrameworkActionReqObj,
510                         clientName));
511     }
512     else {
513         LOC_LOGe("Framework action request object is NULL.Caching disconnect request: %s",
514                 clientName.c_str());
515         // Check if client has requested for backhaul connection.
516         ClientBackhaulReqCache::const_iterator iter = mBackHaulConnReqCache.find(clientName);
517         if (iter != mBackHaulConnReqCache.end()) {
518             // client found, remove from set.
519             LOC_LOGd("Removing client from BackHaulConnReqCache list");
520             mBackHaulConnReqCache.erase(iter);
521         }
522         result = false;
523     }
524     return result;
525 }
526 #endif
527 /******************************************************************************
528  Helpers
529 ******************************************************************************/
sendCachedDataItems(const unordered_set<DataItemId> & s,IDataItemObserver * to)530 void SystemStatusOsObserver::sendCachedDataItems(
531         const unordered_set<DataItemId>& s, IDataItemObserver* to)
532 {
533     if (nullptr == to) {
534         LOC_LOGv("client pointer is NULL.");
535     } else {
536         string clientName;
537         to->getName(clientName);
538         list<IDataItemCore*> dataItems = {};
539 
540         for (auto each : s) {
541             auto citer = mDataItemCache.find(each);
542             if (citer != mDataItemCache.end()) {
543                 string dv;
544                 citer->second->stringify(dv);
545                 LOC_LOGI("DataItem: %s >> %s", dv.c_str(), clientName.c_str());
546                 dataItems.push_front(citer->second);
547             }
548         }
549 
550         if (dataItems.empty()) {
551             LOC_LOGv("No items to notify.");
552         } else {
553             to->notify(dataItems);
554         }
555     }
556 }
557 
updateCache(IDataItemCore * d)558 bool SystemStatusOsObserver::updateCache(IDataItemCore* d)
559 {
560     bool dataItemUpdated = false;
561 
562     // Request systemstatus to record this dataitem in its cache
563     // if the return is false, it means that SystemStatus is not
564     // handling it, so SystemStatusOsObserver also doesn't.
565     // So it has to be true to proceed.
566     if (nullptr != d && mSystemStatus->eventDataItemNotify(d)) {
567         auto citer = mDataItemCache.find(d->getId());
568         if (citer == mDataItemCache.end()) {
569             // New data item; not found in cache
570             IDataItemCore* dataitem = DataItemsFactoryProxy::createNewDataItem(d->getId());
571             if (nullptr != dataitem) {
572                 // Copy the contents of the data item
573                 dataitem->copy(d);
574                 // Insert in mDataItemCache
575                 mDataItemCache.insert(std::make_pair(d->getId(), dataitem));
576                 dataItemUpdated = true;
577             }
578         } else {
579             // Found in cache; Update cache if necessary
580             citer->second->copy(d, &dataItemUpdated);
581         }
582 
583         if (dataItemUpdated) {
584             LOC_LOGV("DataItem:%d updated:%d", d->getId(), dataItemUpdated);
585         }
586     }
587 
588     return dataItemUpdated;
589 }
590 
591 } // namespace loc_core
592 
593