1 /* Copyright (c) 2017, 2019, 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_XtraSystemStatusObs"
30 
31 #include <sys/stat.h>
32 #include <sys/un.h>
33 #include <errno.h>
34 #include <ctype.h>
35 #include <cutils/properties.h>
36 #include <math.h>
37 #include <arpa/inet.h>
38 #include <netinet/in.h>
39 #include <netdb.h>
40 #include <string>
41 #include <loc_log.h>
42 #include <loc_nmea.h>
43 #include <SystemStatus.h>
44 #include <vector>
45 #include <sstream>
46 #include <XtraSystemStatusObserver.h>
47 #include <LocAdapterBase.h>
48 #include <DataItemId.h>
49 #include <DataItemsFactoryProxy.h>
50 #include <DataItemConcreteTypesBase.h>
51 
52 using namespace loc_util;
53 using namespace loc_core;
54 
55 #ifdef LOG_TAG
56 #undef LOG_TAG
57 #endif
58 #define LOG_TAG "LocSvc_XSSO"
59 
60 class XtraIpcListener : public ILocIpcListener {
61     IOsObserver*    mSystemStatusObsrvr;
62     const MsgTask* mMsgTask;
63     XtraSystemStatusObserver& mXSSO;
64 public:
XtraIpcListener(IOsObserver * observer,const MsgTask * msgTask,XtraSystemStatusObserver & xsso)65     inline XtraIpcListener(IOsObserver* observer, const MsgTask* msgTask,
66                            XtraSystemStatusObserver& xsso) :
67             mSystemStatusObsrvr(observer), mMsgTask(msgTask), mXSSO(xsso) {}
onReceive(const char * data,uint32_t length,const LocIpcRecver * recver)68     virtual void onReceive(const char* data, uint32_t length,
69                            const LocIpcRecver* recver) override {
70 #define STRNCMP(str, constStr) strncmp(str, constStr, sizeof(constStr)-1)
71         if (!STRNCMP(data, "ping")) {
72             LOC_LOGd("ping received");
73 #ifdef USE_GLIB
74         } else if (!STRNCMP(data, "connectBackhaul")) {
75             mSystemStatusObsrvr->connectBackhaul();
76         } else if (!STRNCMP(data, "disconnectBackhaul")) {
77             mSystemStatusObsrvr->disconnectBackhaul();
78 #endif
79         } else if (!STRNCMP(data, "requestStatus")) {
80             int32_t xtraStatusUpdated = 0;
81             sscanf(data, "%*s %d", &xtraStatusUpdated);
82 
83             struct HandleStatusRequestMsg : public LocMsg {
84                 XtraSystemStatusObserver& mXSSO;
85                 int32_t mXtraStatusUpdated;
86                 inline HandleStatusRequestMsg(XtraSystemStatusObserver& xsso,
87                                               int32_t xtraStatusUpdated) :
88                         mXSSO(xsso), mXtraStatusUpdated(xtraStatusUpdated) {}
89                 inline void proc() const override {
90                     mXSSO.onStatusRequested(mXtraStatusUpdated);
91                 }
92             };
93             mMsgTask->sendMsg(new HandleStatusRequestMsg(mXSSO, xtraStatusUpdated));
94         } else {
95             LOC_LOGw("unknown event: %s", data);
96         }
97     }
98 };
99 
XtraSystemStatusObserver(IOsObserver * sysStatObs,const MsgTask * msgTask)100 XtraSystemStatusObserver::XtraSystemStatusObserver(IOsObserver* sysStatObs,
101                                                    const MsgTask* msgTask) :
102         mSystemStatusObsrvr(sysStatObs), mMsgTask(msgTask),
103         mGpsLock(-1), mConnections(~0), mXtraThrottle(true),
104         mReqStatusReceived(false),
105         mIsConnectivityStatusKnown(false),
106         mSender(LocIpc::getLocIpcLocalSender(LOC_IPC_XTRA)),
107         mDelayLocTimer(*mSender) {
108     subscribe(true);
109     auto recver = LocIpc::getLocIpcLocalRecver(
110             make_shared<XtraIpcListener>(sysStatObs, msgTask, *this),
111             LOC_IPC_HAL);
112     mIpc.startNonBlockingListening(recver);
113     mDelayLocTimer.start(100 /*.1 sec*/,  false);
114 }
115 
updateLockStatus(GnssConfigGpsLock lock)116 bool XtraSystemStatusObserver::updateLockStatus(GnssConfigGpsLock lock) {
117     // mask NI(NFW bit) since from XTRA's standpoint GPS is enabled if
118     // MO(AFW bit) is enabled and disabled when MO is disabled
119     mGpsLock = lock & ~GNSS_CONFIG_GPS_LOCK_NI;
120 
121     if (!mReqStatusReceived) {
122         return true;
123     }
124 
125     stringstream ss;
126     ss <<  "gpslock";
127     ss << " " << mGpsLock;
128     string s = ss.str();
129     return ( LocIpc::send(*mSender, (const uint8_t*)s.data(), s.size()) );
130 }
131 
updateConnections(uint64_t allConnections,NetworkInfoType * networkHandleInfo)132 bool XtraSystemStatusObserver::updateConnections(uint64_t allConnections,
133         NetworkInfoType* networkHandleInfo) {
134     mIsConnectivityStatusKnown = true;
135     mConnections = allConnections;
136 
137     LOC_LOGd("updateConnections mConnections:%" PRIx64, mConnections);
138     for (uint8_t i = 0; i < MAX_NETWORK_HANDLES; ++i) {
139         mNetworkHandle[i] = networkHandleInfo[i];
140         LOC_LOGd("updateConnections [%d] networkHandle:%" PRIx64 " networkType:%u",
141             i, mNetworkHandle[i].networkHandle, mNetworkHandle[i].networkType);
142     }
143 
144     if (!mReqStatusReceived) {
145         return true;
146     }
147 
148     stringstream ss;
149     ss << "connection" << endl << mConnections << endl
150             << mNetworkHandle[0].toString() << endl
151             << mNetworkHandle[1].toString() << endl
152             << mNetworkHandle[2].toString() << endl
153             << mNetworkHandle[3].toString() << endl
154             << mNetworkHandle[4].toString() << endl
155             << mNetworkHandle[5].toString() << endl
156             << mNetworkHandle[6].toString() << endl
157             << mNetworkHandle[7].toString() << endl
158             << mNetworkHandle[8].toString() << endl
159             << mNetworkHandle[MAX_NETWORK_HANDLES-1].toString();
160     string s = ss.str();
161     return ( LocIpc::send(*mSender, (const uint8_t*)s.data(), s.size()) );
162 }
163 
updateTac(const string & tac)164 bool XtraSystemStatusObserver::updateTac(const string& tac) {
165     mTac = tac;
166 
167     if (!mReqStatusReceived) {
168         return true;
169     }
170 
171     stringstream ss;
172     ss <<  "tac";
173     ss << " " << tac.c_str();
174     string s = ss.str();
175     return ( LocIpc::send(*mSender, (const uint8_t*)s.data(), s.size()) );
176 }
177 
updateMccMnc(const string & mccmnc)178 bool XtraSystemStatusObserver::updateMccMnc(const string& mccmnc) {
179     mMccmnc = mccmnc;
180 
181     if (!mReqStatusReceived) {
182         return true;
183     }
184 
185     stringstream ss;
186     ss <<  "mncmcc";
187     ss << " " << mccmnc.c_str();
188     string s = ss.str();
189     return ( LocIpc::send(*mSender, (const uint8_t*)s.data(), s.size()) );
190 }
191 
updateXtraThrottle(const bool enabled)192 bool XtraSystemStatusObserver::updateXtraThrottle(const bool enabled) {
193     mXtraThrottle = enabled;
194 
195     if (!mReqStatusReceived) {
196         return true;
197     }
198 
199     stringstream ss;
200     ss <<  "xtrathrottle";
201     ss << " " << (enabled ? 1 : 0);
202     string s = ss.str();
203     return ( LocIpc::send(*mSender, (const uint8_t*)s.data(), s.size()) );
204 }
205 
onStatusRequested(int32_t xtraStatusUpdated)206 inline bool XtraSystemStatusObserver::onStatusRequested(int32_t xtraStatusUpdated) {
207     mReqStatusReceived = true;
208 
209     if (xtraStatusUpdated) {
210         return true;
211     }
212 
213     stringstream ss;
214 
215     ss << "respondStatus" << endl;
216     (mGpsLock == -1 ? ss : ss << mGpsLock) << endl;
217     (mConnections == (uint64_t)~0 ? ss : ss << mConnections) << endl
218             << mNetworkHandle[0].toString() << endl
219             << mNetworkHandle[1].toString() << endl
220             << mNetworkHandle[2].toString() << endl
221             << mNetworkHandle[3].toString() << endl
222             << mNetworkHandle[4].toString() << endl
223             << mNetworkHandle[5].toString() << endl
224             << mNetworkHandle[6].toString() << endl
225             << mNetworkHandle[7].toString() << endl
226             << mNetworkHandle[8].toString() << endl
227             << mNetworkHandle[MAX_NETWORK_HANDLES-1].toString() << endl
228             << mTac << endl << mMccmnc << endl << mIsConnectivityStatusKnown;
229 
230     string s = ss.str();
231     return ( LocIpc::send(*mSender, (const uint8_t*)s.data(), s.size()) );
232 }
233 
subscribe(bool yes)234 void XtraSystemStatusObserver::subscribe(bool yes)
235 {
236     // Subscription data list
237     list<DataItemId> subItemIdList;
238     subItemIdList.push_back(NETWORKINFO_DATA_ITEM_ID);
239     subItemIdList.push_back(MCCMNC_DATA_ITEM_ID);
240 
241     if (yes) {
242         mSystemStatusObsrvr->subscribe(subItemIdList, this);
243 
244         list<DataItemId> reqItemIdList;
245         reqItemIdList.push_back(TAC_DATA_ITEM_ID);
246 
247         mSystemStatusObsrvr->requestData(reqItemIdList, this);
248 
249     } else {
250         mSystemStatusObsrvr->unsubscribe(subItemIdList, this);
251     }
252 }
253 
254 // IDataItemObserver overrides
getName(string & name)255 void XtraSystemStatusObserver::getName(string& name)
256 {
257     name = "XtraSystemStatusObserver";
258 }
259 
notify(const list<IDataItemCore * > & dlist)260 void XtraSystemStatusObserver::notify(const list<IDataItemCore*>& dlist)
261 {
262     struct HandleOsObserverUpdateMsg : public LocMsg {
263         XtraSystemStatusObserver* mXtraSysStatObj;
264         list <IDataItemCore*> mDataItemList;
265 
266         inline HandleOsObserverUpdateMsg(XtraSystemStatusObserver* xtraSysStatObs,
267                 const list<IDataItemCore*>& dataItemList) :
268                 mXtraSysStatObj(xtraSysStatObs) {
269             for (auto eachItem : dataItemList) {
270                 IDataItemCore* dataitem = DataItemsFactoryProxy::createNewDataItem(
271                         eachItem->getId());
272                 if (NULL == dataitem) {
273                     break;
274                 }
275                 // Copy the contents of the data item
276                 dataitem->copy(eachItem);
277 
278                 mDataItemList.push_back(dataitem);
279             }
280         }
281 
282         inline ~HandleOsObserverUpdateMsg() {
283             for (auto itor = mDataItemList.begin(); itor != mDataItemList.end(); ++itor) {
284                 if (*itor != nullptr) {
285                     delete *itor;
286                     *itor = nullptr;
287                 }
288             }
289         }
290 
291         inline void proc() const {
292             for (auto each : mDataItemList) {
293                 switch (each->getId())
294                 {
295                     case NETWORKINFO_DATA_ITEM_ID:
296                     {
297                         NetworkInfoDataItemBase* networkInfo =
298                                 static_cast<NetworkInfoDataItemBase*>(each);
299                         NetworkInfoType* networkHandleInfo =
300                                 static_cast<NetworkInfoType*>(networkInfo->getNetworkHandle());
301                         mXtraSysStatObj->updateConnections(networkInfo->getAllTypes(),
302                                 networkHandleInfo);
303                     }
304                     break;
305 
306                     case TAC_DATA_ITEM_ID:
307                     {
308                         TacDataItemBase* tac =
309                                  static_cast<TacDataItemBase*>(each);
310                         mXtraSysStatObj->updateTac(tac->mValue);
311                     }
312                     break;
313 
314                     case MCCMNC_DATA_ITEM_ID:
315                     {
316                         MccmncDataItemBase* mccmnc =
317                                 static_cast<MccmncDataItemBase*>(each);
318                         mXtraSysStatObj->updateMccMnc(mccmnc->mValue);
319                     }
320                     break;
321 
322                     default:
323                     break;
324                 }
325             }
326         }
327     };
328     mMsgTask->sendMsg(new (nothrow) HandleOsObserverUpdateMsg(this, dlist));
329 }
330