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