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