1 /* Copyright (c) 2017-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_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             char clientName[30] = {0};
76             sscanf(data, "%*s %29s", clientName);
77             mSystemStatusObsrvr->connectBackhaul(string(clientName));
78         } else if (!STRNCMP(data, "disconnectBackhaul")) {
79             char clientName[30] = {0};
80             sscanf(data, "%*s %29s", clientName);
81             mSystemStatusObsrvr->disconnectBackhaul(string(clientName));
82 #endif
83         } else if (!STRNCMP(data, "requestStatus")) {
84             int32_t xtraStatusUpdated = 0;
85             sscanf(data, "%*s %d", &xtraStatusUpdated);
86 
87             struct HandleStatusRequestMsg : public LocMsg {
88                 XtraSystemStatusObserver& mXSSO;
89                 int32_t mXtraStatusUpdated;
90                 inline HandleStatusRequestMsg(XtraSystemStatusObserver& xsso,
91                                               int32_t xtraStatusUpdated) :
92                         mXSSO(xsso), mXtraStatusUpdated(xtraStatusUpdated) {}
93                 inline void proc() const override {
94                     mXSSO.onStatusRequested(mXtraStatusUpdated);
95                     /* SSR for DGnss Ntrip Source*/
96                     mXSSO.restartDgnssSource();
97                 }
98             };
99             mMsgTask->sendMsg(new HandleStatusRequestMsg(mXSSO, xtraStatusUpdated));
100         } else {
101             LOC_LOGw("unknown event: %s", data);
102         }
103     }
104 };
105 
XtraSystemStatusObserver(IOsObserver * sysStatObs,const MsgTask * msgTask)106 XtraSystemStatusObserver::XtraSystemStatusObserver(IOsObserver* sysStatObs,
107                                                    const MsgTask* msgTask) :
108         mSystemStatusObsrvr(sysStatObs), mMsgTask(msgTask),
109         mGpsLock(-1), mConnections(~0), mXtraThrottle(true),
110         mReqStatusReceived(false),
111         mIsConnectivityStatusKnown(false),
112         mSender(LocIpc::getLocIpcLocalSender(LOC_IPC_XTRA)),
113         mDelayLocTimer(*mSender) {
114     subscribe(true);
115     auto recver = LocIpc::getLocIpcLocalRecver(
116             make_shared<XtraIpcListener>(sysStatObs, msgTask, *this),
117             LOC_IPC_HAL);
118     mIpc.startNonBlockingListening(recver);
119     mDelayLocTimer.start(100 /*.1 sec*/,  false);
120 }
121 
updateLockStatus(GnssConfigGpsLock lock)122 bool XtraSystemStatusObserver::updateLockStatus(GnssConfigGpsLock lock) {
123     // mask NI(NFW bit) since from XTRA's standpoint GPS is enabled if
124     // MO(AFW bit) is enabled and disabled when MO is disabled
125     mGpsLock = lock & ~GNSS_CONFIG_GPS_LOCK_NI;
126 
127     if (!mReqStatusReceived) {
128         return true;
129     }
130 
131     stringstream ss;
132     ss <<  "gpslock";
133     ss << " " << mGpsLock;
134     string s = ss.str();
135     return ( LocIpc::send(*mSender, (const uint8_t*)s.data(), s.size()) );
136 }
137 
updateConnections(uint64_t allConnections,NetworkInfoType * networkHandleInfo)138 bool XtraSystemStatusObserver::updateConnections(uint64_t allConnections,
139         NetworkInfoType* networkHandleInfo) {
140     mIsConnectivityStatusKnown = true;
141     mConnections = allConnections;
142 
143     LOC_LOGd("updateConnections mConnections:%" PRIx64, mConnections);
144     for (uint8_t i = 0; i < MAX_NETWORK_HANDLES; ++i) {
145         mNetworkHandle[i] = networkHandleInfo[i];
146         LOC_LOGd("updateConnections [%d] networkHandle:%" PRIx64 " networkType:%u",
147             i, mNetworkHandle[i].networkHandle, mNetworkHandle[i].networkType);
148     }
149 
150     if (!mReqStatusReceived) {
151         return true;
152     }
153 
154     stringstream ss;
155     ss << "connection" << endl << mConnections << endl
156             << mNetworkHandle[0].toString() << endl
157             << mNetworkHandle[1].toString() << endl
158             << mNetworkHandle[2].toString() << endl
159             << mNetworkHandle[3].toString() << endl
160             << mNetworkHandle[4].toString() << endl
161             << mNetworkHandle[5].toString() << endl
162             << mNetworkHandle[6].toString() << endl
163             << mNetworkHandle[7].toString() << endl
164             << mNetworkHandle[8].toString() << endl
165             << mNetworkHandle[MAX_NETWORK_HANDLES-1].toString();
166     string s = ss.str();
167     return ( LocIpc::send(*mSender, (const uint8_t*)s.data(), s.size()) );
168 }
169 
updateTac(const string & tac)170 bool XtraSystemStatusObserver::updateTac(const string& tac) {
171     mTac = tac;
172 
173     if (!mReqStatusReceived) {
174         return true;
175     }
176 
177     stringstream ss;
178     ss <<  "tac";
179     ss << " " << tac.c_str();
180     string s = ss.str();
181     return ( LocIpc::send(*mSender, (const uint8_t*)s.data(), s.size()) );
182 }
183 
updateMccMnc(const string & mccmnc)184 bool XtraSystemStatusObserver::updateMccMnc(const string& mccmnc) {
185     mMccmnc = mccmnc;
186 
187     if (!mReqStatusReceived) {
188         return true;
189     }
190 
191     stringstream ss;
192     ss <<  "mncmcc";
193     ss << " " << mccmnc.c_str();
194     string s = ss.str();
195     return ( LocIpc::send(*mSender, (const uint8_t*)s.data(), s.size()) );
196 }
197 
updateXtraThrottle(const bool enabled)198 bool XtraSystemStatusObserver::updateXtraThrottle(const bool enabled) {
199     mXtraThrottle = enabled;
200 
201     if (!mReqStatusReceived) {
202         return true;
203     }
204 
205     stringstream ss;
206     ss <<  "xtrathrottle";
207     ss << " " << (enabled ? 1 : 0);
208     string s = ss.str();
209     return ( LocIpc::send(*mSender, (const uint8_t*)s.data(), s.size()) );
210 }
211 
onStatusRequested(int32_t xtraStatusUpdated)212 inline bool XtraSystemStatusObserver::onStatusRequested(int32_t xtraStatusUpdated) {
213     mReqStatusReceived = true;
214 
215     if (xtraStatusUpdated) {
216         return true;
217     }
218 
219     stringstream ss;
220 
221     ss << "respondStatus" << endl;
222     (mGpsLock == -1 ? ss : ss << mGpsLock) << endl;
223     (mConnections == (uint64_t)~0 ? ss : ss << mConnections) << endl
224             << mNetworkHandle[0].toString() << endl
225             << mNetworkHandle[1].toString() << endl
226             << mNetworkHandle[2].toString() << endl
227             << mNetworkHandle[3].toString() << endl
228             << mNetworkHandle[4].toString() << endl
229             << mNetworkHandle[5].toString() << endl
230             << mNetworkHandle[6].toString() << endl
231             << mNetworkHandle[7].toString() << endl
232             << mNetworkHandle[8].toString() << endl
233             << mNetworkHandle[MAX_NETWORK_HANDLES-1].toString() << endl
234             << mTac << endl << mMccmnc << endl << mIsConnectivityStatusKnown;
235 
236     string s = ss.str();
237     return ( LocIpc::send(*mSender, (const uint8_t*)s.data(), s.size()) );
238 }
239 
startDgnssSource(const StartDgnssNtripParams & params)240 void XtraSystemStatusObserver::startDgnssSource(const StartDgnssNtripParams& params) {
241     stringstream ss;
242     const GnssNtripConnectionParams* ntripParams = &(params.ntripParams);
243 
244     ss <<  "startDgnssSource" << endl;
245     ss << ntripParams->useSSL << endl;
246     ss << ntripParams->hostNameOrIp.data() << endl;
247     ss << ntripParams->port << endl;
248     ss << ntripParams->mountPoint.data() << endl;
249     ss << ntripParams->username.data() << endl;
250     ss << ntripParams->password.data() << endl;
251     if (ntripParams->requiresNmeaLocation && !params.nmea.empty()) {
252         ss << params.nmea.data() << endl;
253     }
254     string s = ss.str();
255 
256     LOC_LOGd("%s", s.data());
257     LocIpc::send(*mSender, (const uint8_t*)s.data(), s.size());
258     // make a local copy of the string for SSR
259     mNtripParamsString.assign(std::move(s));
260 }
261 
restartDgnssSource()262 void XtraSystemStatusObserver::restartDgnssSource() {
263     if (!mNtripParamsString.empty()) {
264         LocIpc::send(*mSender,
265             (const uint8_t*)mNtripParamsString.data(), mNtripParamsString.size());
266         LOC_LOGv("Xtra SSR %s", mNtripParamsString.data());
267     }
268 }
269 
stopDgnssSource()270 void XtraSystemStatusObserver::stopDgnssSource() {
271     LOC_LOGv();
272     mNtripParamsString.clear();
273 
274     const char s[] = "stopDgnssSource";
275     LocIpc::send(*mSender, (const uint8_t*)s, strlen(s));
276 }
277 
updateNmeaToDgnssServer(const string & nmea)278 void XtraSystemStatusObserver::updateNmeaToDgnssServer(const string& nmea)
279 {
280     stringstream ss;
281     ss <<  "updateDgnssServerNmea" << endl;
282     ss << nmea.data() << endl;
283 
284     string s = ss.str();
285     LOC_LOGd("%s", s.data());
286     LocIpc::send(*mSender, (const uint8_t*)s.data(), s.size());
287 }
288 
subscribe(bool yes)289 void XtraSystemStatusObserver::subscribe(bool yes)
290 {
291     // Subscription data list
292     list<DataItemId> subItemIdList;
293     subItemIdList.push_back(NETWORKINFO_DATA_ITEM_ID);
294     subItemIdList.push_back(MCCMNC_DATA_ITEM_ID);
295 
296     if (yes) {
297         mSystemStatusObsrvr->subscribe(subItemIdList, this);
298 
299         list<DataItemId> reqItemIdList;
300         reqItemIdList.push_back(TAC_DATA_ITEM_ID);
301 
302         mSystemStatusObsrvr->requestData(reqItemIdList, this);
303 
304     } else {
305         mSystemStatusObsrvr->unsubscribe(subItemIdList, this);
306     }
307 }
308 
309 // IDataItemObserver overrides
getName(string & name)310 void XtraSystemStatusObserver::getName(string& name)
311 {
312     name = "XtraSystemStatusObserver";
313 }
314 
notify(const list<IDataItemCore * > & dlist)315 void XtraSystemStatusObserver::notify(const list<IDataItemCore*>& dlist)
316 {
317     struct HandleOsObserverUpdateMsg : public LocMsg {
318         XtraSystemStatusObserver* mXtraSysStatObj;
319         list <IDataItemCore*> mDataItemList;
320 
321         inline HandleOsObserverUpdateMsg(XtraSystemStatusObserver* xtraSysStatObs,
322                 const list<IDataItemCore*>& dataItemList) :
323                 mXtraSysStatObj(xtraSysStatObs) {
324             for (auto eachItem : dataItemList) {
325                 IDataItemCore* dataitem = DataItemsFactoryProxy::createNewDataItem(
326                         eachItem->getId());
327                 if (NULL == dataitem) {
328                     break;
329                 }
330                 // Copy the contents of the data item
331                 dataitem->copy(eachItem);
332 
333                 mDataItemList.push_back(dataitem);
334             }
335         }
336 
337         inline ~HandleOsObserverUpdateMsg() {
338             for (auto itor = mDataItemList.begin(); itor != mDataItemList.end(); ++itor) {
339                 if (*itor != nullptr) {
340                     delete *itor;
341                     *itor = nullptr;
342                 }
343             }
344         }
345 
346         inline void proc() const {
347             for (auto each : mDataItemList) {
348                 switch (each->getId())
349                 {
350                     case NETWORKINFO_DATA_ITEM_ID:
351                     {
352                         NetworkInfoDataItemBase* networkInfo =
353                                 static_cast<NetworkInfoDataItemBase*>(each);
354                         NetworkInfoType* networkHandleInfo =
355                                 static_cast<NetworkInfoType*>(networkInfo->getNetworkHandle());
356                         mXtraSysStatObj->updateConnections(networkInfo->getAllTypes(),
357                                 networkHandleInfo);
358                     }
359                     break;
360 
361                     case TAC_DATA_ITEM_ID:
362                     {
363                         TacDataItemBase* tac =
364                                  static_cast<TacDataItemBase*>(each);
365                         mXtraSysStatObj->updateTac(tac->mValue);
366                     }
367                     break;
368 
369                     case MCCMNC_DATA_ITEM_ID:
370                     {
371                         MccmncDataItemBase* mccmnc =
372                                 static_cast<MccmncDataItemBase*>(each);
373                         mXtraSysStatObj->updateMccMnc(mccmnc->mValue);
374                     }
375                     break;
376 
377                     default:
378                     break;
379                 }
380             }
381         }
382     };
383     mMsgTask->sendMsg(new (nothrow) HandleOsObserverUpdateMsg(this, dlist));
384 }
385