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