1 /* Copyright (c) 2017, 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 
51 using namespace loc_core;
52 
53 #define XTRA_HAL_SOCKET_NAME "/data/vendor/location/xtra/socket_hal_xtra"
54 
updateLockStatus(uint32_t lock)55 bool XtraSystemStatusObserver::updateLockStatus(uint32_t lock) {
56     stringstream ss;
57     ss <<  "gpslock";
58     ss << " " << lock;
59     ss << "\n"; // append seperator
60     return ( sendEvent(ss) );
61 }
62 
updateConnectionStatus(bool connected,uint32_t type)63 bool XtraSystemStatusObserver::updateConnectionStatus(bool connected, uint32_t type) {
64     stringstream ss;
65     ss <<  "connection";
66     ss << " " << (connected ? "1" : "0");
67     ss << " " << (int)type;
68     ss << "\n"; // append seperator
69     return ( sendEvent(ss) );
70 }
updateTac(const string & tac)71 bool XtraSystemStatusObserver::updateTac(const string& tac) {
72     stringstream ss;
73     ss <<  "tac";
74     ss << " " << tac.c_str();
75     ss << "\n"; // append seperator
76     return ( sendEvent(ss) );
77 }
78 
updateMccMnc(const string & mccmnc)79 bool XtraSystemStatusObserver::updateMccMnc(const string& mccmnc) {
80     stringstream ss;
81     ss <<  "mncmcc";
82     ss << " " << mccmnc.c_str();
83     ss << "\n"; // append seperator
84     return ( sendEvent(ss) );
85 }
86 
sendEvent(const stringstream & event)87 bool XtraSystemStatusObserver::sendEvent(const stringstream& event) {
88     int socketFd = createSocket();
89     if (socketFd < 0) {
90         LOC_LOGe("XTRA unreachable. sending failed.");
91         return false;
92     }
93 
94     const string& data = event.str();
95     int remain = data.length();
96     ssize_t sent = 0;
97     while (remain > 0 &&
98           (sent = ::send(socketFd, data.c_str() + (data.length() - remain),
99                        remain, MSG_NOSIGNAL)) > 0) {
100         remain -= sent;
101     }
102 
103     if (sent < 0) {
104         LOC_LOGe("sending error. reason:%s", strerror(errno));
105     }
106 
107     closeSocket(socketFd);
108 
109     return (remain == 0);
110 }
111 
112 
createSocket()113 int XtraSystemStatusObserver::createSocket() {
114     int socketFd = -1;
115 
116     if ((socketFd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
117         LOC_LOGe("create socket error. reason:%s", strerror(errno));
118 
119      } else {
120         const char* socketPath = XTRA_HAL_SOCKET_NAME ;
121         struct sockaddr_un addr = { .sun_family = AF_UNIX };
122         snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", socketPath);
123 
124         if (::connect(socketFd, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
125             LOC_LOGe("cannot connect to XTRA. reason:%s", strerror(errno));
126             if (::close(socketFd)) {
127                 LOC_LOGe("close socket error. reason:%s", strerror(errno));
128             }
129             socketFd = -1;
130         }
131     }
132 
133     return socketFd;
134 }
135 
closeSocket(const int socketFd)136 void XtraSystemStatusObserver::closeSocket(const int socketFd) {
137     if (socketFd >= 0) {
138         if(::close(socketFd)) {
139             LOC_LOGe("close socket error. reason:%s", strerror(errno));
140         }
141     }
142 }
143 
subscribe(bool yes)144 void XtraSystemStatusObserver::subscribe(bool yes)
145 {
146     // Subscription data list
147     list<DataItemId> subItemIdList;
148     subItemIdList.push_back(NETWORKINFO_DATA_ITEM_ID);
149     subItemIdList.push_back(MCCMNC_DATA_ITEM_ID);
150 
151     if (yes) {
152         mSystemStatusObsrvr->subscribe(subItemIdList, this);
153 
154         list<DataItemId> reqItemIdList;
155         reqItemIdList.push_back(TAC_DATA_ITEM_ID);
156 
157         mSystemStatusObsrvr->requestData(reqItemIdList, this);
158 
159     } else {
160         mSystemStatusObsrvr->unsubscribe(subItemIdList, this);
161     }
162 }
163 
164 // IDataItemObserver overrides
getName(string & name)165 void XtraSystemStatusObserver::getName(string& name)
166 {
167     name = "XtraSystemStatusObserver";
168 }
169 
notify(const list<IDataItemCore * > & dlist)170 void XtraSystemStatusObserver::notify(const list<IDataItemCore*>& dlist)
171 {
172     struct handleOsObserverUpdateMsg : public LocMsg {
173         XtraSystemStatusObserver* mXtraSysStatObj;
174         list <IDataItemCore*> mDataItemList;
175 
176         inline handleOsObserverUpdateMsg(XtraSystemStatusObserver* xtraSysStatObs,
177                 const list<IDataItemCore*>& dataItemList) :
178                 mXtraSysStatObj(xtraSysStatObs) {
179             for (auto eachItem : dataItemList) {
180                 IDataItemCore* dataitem = DataItemsFactoryProxy::createNewDataItem(
181                         eachItem->getId());
182                 if (NULL == dataitem) {
183                     break;
184                 }
185                 // Copy the contents of the data item
186                 dataitem->copy(eachItem);
187 
188                 mDataItemList.push_back(dataitem);
189             }
190         }
191 
192         inline ~handleOsObserverUpdateMsg() {
193             for (auto each : mDataItemList) {
194                 delete each;
195             }
196         }
197 
198         inline void proc() const {
199             for (auto each : mDataItemList) {
200                 switch (each->getId())
201                 {
202                     case NETWORKINFO_DATA_ITEM_ID:
203                     {
204                         SystemStatusNetworkInfo* networkInfo =
205                                 reinterpret_cast<SystemStatusNetworkInfo*>(each);
206                         mXtraSysStatObj->updateConnectionStatus(networkInfo->mConnected,
207                                 networkInfo->mType);
208                     }
209                     break;
210 
211                     case TAC_DATA_ITEM_ID:
212                     {
213                         SystemStatusTac* tac = reinterpret_cast<SystemStatusTac*>(each);
214                         mXtraSysStatObj->updateTac(tac->mValue);
215                     }
216                     break;
217 
218                     case MCCMNC_DATA_ITEM_ID:
219                     {
220                         SystemStatusMccMnc* mccmnc = reinterpret_cast<SystemStatusMccMnc*>(each);
221                         mXtraSysStatObj->updateMccMnc(mccmnc->mValue);
222                     }
223                     break;
224 
225                     default:
226                     break;
227                 }
228             }
229         }
230     };
231     mMsgTask->sendMsg(new (nothrow) handleOsObserverUpdateMsg(this, dlist));
232 }
233 
234 
235