1 /* Copyright (c) 2015-2017, 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 #ifndef __SYSTEM_STATUS_OSOBSERVER__
30 #define __SYSTEM_STATUS_OSOBSERVER__
31 
32 #include <cinttypes>
33 #include <string>
34 #include <list>
35 #include <map>
36 #include <new>
37 #include <vector>
38 
39 #include <MsgTask.h>
40 #include <DataItemId.h>
41 #include <IOsObserver.h>
42 #include <loc_pla.h>
43 #include <log_util.h>
44 #include <LocUnorderedSetMap.h>
45 
46 namespace loc_core
47 {
48 /******************************************************************************
49  SystemStatusOsObserver
50 ******************************************************************************/
51 using namespace std;
52 using namespace loc_util;
53 
54 // Forward Declarations
55 class IDataItemCore;
56 class SystemStatus;
57 class SystemStatusOsObserver;
58 typedef map<IDataItemObserver*, list<DataItemId>> ObserverReqCache;
59 typedef LocUnorderedSetMap<IDataItemObserver*, DataItemId> ClientToDataItems;
60 typedef LocUnorderedSetMap<DataItemId, IDataItemObserver*> DataItemToClients;
61 typedef unordered_map<DataItemId, IDataItemCore*> DataItemIdToCore;
62 typedef unordered_map<DataItemId, int> DataItemIdToInt;
63 
64 struct ObserverContext {
65     IDataItemSubscription* mSubscriptionObj;
66     IFrameworkActionReq* mFrameworkActionReqObj;
67     const MsgTask* mMsgTask;
68     SystemStatusOsObserver* mSSObserver;
69 
ObserverContextObserverContext70     inline ObserverContext(const MsgTask* msgTask, SystemStatusOsObserver* observer) :
71             mSubscriptionObj(NULL), mFrameworkActionReqObj(NULL),
72             mMsgTask(msgTask), mSSObserver(observer) {}
73 };
74 
75 // Clients wanting to get data from OS/Framework would need to
76 // subscribe with OSObserver using IDataItemSubscription interface.
77 // Such clients would need to implement IDataItemObserver interface
78 // to receive data when it becomes available.
79 class SystemStatusOsObserver : public IOsObserver {
80 
81 public:
82     // ctor
SystemStatusOsObserver(SystemStatus * systemstatus,const MsgTask * msgTask)83     inline SystemStatusOsObserver(SystemStatus* systemstatus, const MsgTask* msgTask) :
84             mSystemStatus(systemstatus), mContext(msgTask, this),
85             mAddress("SystemStatusOsObserver"),
86             mClientToDataItems(MAX_DATA_ITEM_ID), mDataItemToClients(MAX_DATA_ITEM_ID)
87 #ifdef USE_GLIB
88             , mBackHaulConnectReqCount(0)
89 #endif
90     {
91     }
92 
93     // dtor
94     ~SystemStatusOsObserver();
95 
96     template <typename CINT, typename COUT>
97     static COUT containerTransfer(CINT& s);
98     template <typename CINT, typename COUT>
containerTransfer(CINT && s)99     inline static COUT containerTransfer(CINT&& s) {
100         return containerTransfer<CINT, COUT>(s);
101     }
102 
103     // To set the subscription object
104     virtual void setSubscriptionObj(IDataItemSubscription* subscriptionObj);
105 
106     // To set the framework action request object
setFrameworkActionReqObj(IFrameworkActionReq * frameworkActionReqObj)107     inline void setFrameworkActionReqObj(IFrameworkActionReq* frameworkActionReqObj) {
108         mContext.mFrameworkActionReqObj = frameworkActionReqObj;
109 #ifdef USE_GLIB
110         if (mBackHaulConnectReqCount > 0) {
111             connectBackhaul();
112             mBackHaulConnectReqCount = 0;
113         }
114 #endif
115     }
116 
117     // IDataItemSubscription Overrides
subscribe(const list<DataItemId> & l,IDataItemObserver * client)118     inline virtual void subscribe(const list<DataItemId>& l, IDataItemObserver* client) override {
119         subscribe(l, client, false);
120     }
121     virtual void updateSubscription(const list<DataItemId>& l, IDataItemObserver* client) override;
requestData(const list<DataItemId> & l,IDataItemObserver * client)122     inline virtual void requestData(const list<DataItemId>& l, IDataItemObserver* client) override {
123         subscribe(l, client, true);
124     }
125     virtual void unsubscribe(const list<DataItemId>& l, IDataItemObserver* client) override;
126     virtual void unsubscribeAll(IDataItemObserver* client) override;
127 
128     // IDataItemObserver Overrides
129     virtual void notify(const list<IDataItemCore*>& dlist) override;
getName(string & name)130     inline virtual void getName(string& name) override {
131         name = mAddress;
132     }
133 
134     // IFrameworkActionReq Overrides
135     virtual void turnOn(DataItemId dit, int timeOut = 0) override;
136     virtual void turnOff(DataItemId dit) override;
137 #ifdef USE_GLIB
138     virtual bool connectBackhaul() override;
139     virtual bool disconnectBackhaul();
140 #endif
141 
142 private:
143     SystemStatus*                                    mSystemStatus;
144     ObserverContext                                  mContext;
145     const string                                     mAddress;
146     ClientToDataItems                                mClientToDataItems;
147     DataItemToClients                                mDataItemToClients;
148     DataItemIdToCore                                 mDataItemCache;
149     DataItemIdToInt                                  mActiveRequestCount;
150 
151     // Cache the subscribe and requestData till subscription obj is obtained
152     void cacheObserverRequest(ObserverReqCache& reqCache,
153             const list<DataItemId>& l, IDataItemObserver* client);
154 #ifdef USE_GLIB
155     // Cache the framework action request for connect/disconnect
156     int         mBackHaulConnectReqCount;
157 #endif
158 
159     void subscribe(const list<DataItemId>& l, IDataItemObserver* client, bool toRequestData);
160 
161     // Helpers
162     void sendCachedDataItems(const unordered_set<DataItemId>& s, IDataItemObserver* to);
163     bool updateCache(IDataItemCore* d);
logMe(const unordered_set<DataItemId> & l)164     inline void logMe(const unordered_set<DataItemId>& l) {
165         IF_LOC_LOGD {
166             for (auto id : l) {
167                 LOC_LOGD("DataItem %d", id);
168             }
169         }
170     }
171 };
172 
173 } // namespace loc_core
174 
175 #endif //__SYSTEM_STATUS__
176 
177