1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define LOG_TAG "GnssHAL_AGnssInterface"
18 
19 #include "AGnss.h"
20 
21 namespace android {
22 namespace hardware {
23 namespace gnss {
24 namespace V1_0 {
25 namespace implementation {
26 
27 std::vector<std::unique_ptr<ThreadFuncArgs>> AGnss::sThreadFuncArgsList;
28 sp<IAGnssCallback> AGnss::sAGnssCbIface = nullptr;
29 bool AGnss::sInterfaceExists = false;
30 
31 AGpsCallbacks AGnss::sAGnssCb = {
32     .status_cb = statusCb,
33     .create_thread_cb = createThreadCb
34 };
35 
AGnss(const AGpsInterface * aGpsIface)36 AGnss::AGnss(const AGpsInterface* aGpsIface) : mAGnssIface(aGpsIface) {
37     /* Error out if an instance of the interface already exists. */
38     LOG_ALWAYS_FATAL_IF(sInterfaceExists);
39     sInterfaceExists = true;
40 }
41 
~AGnss()42 AGnss::~AGnss() {
43     sThreadFuncArgsList.clear();
44     sInterfaceExists = false;
45 }
46 
statusCb(AGpsStatus * status)47 void AGnss::statusCb(AGpsStatus* status) {
48     if (sAGnssCbIface == nullptr) {
49         ALOGE("%s: AGNSS Callback Interface configured incorrectly", __func__);
50         return;
51     }
52 
53     if (status == nullptr) {
54         ALOGE("AGNSS status is invalid");
55         return;
56     }
57 
58     /*
59      * Logic based on AGnssStatus processing by GnssLocationProvider. Size of
60      * AGpsStatus is checked for backward compatibility since some devices may
61      * be sending out an older version of AGpsStatus that only supports IPv4.
62      */
63     size_t statusSize = status->size;
64     if (status->size == sizeof(AGpsStatus)) {
65         switch (status->addr.ss_family)
66         {
67             case AF_INET:
68                 {
69                     /*
70                      * ss_family indicates IPv4.
71                      */
72                     struct sockaddr_in* in = reinterpret_cast<struct sockaddr_in*>(&(status->addr));
73                     IAGnssCallback::AGnssStatusIpV4 aGnssStatusIpV4 = {
74                         .type = static_cast<IAGnssCallback::AGnssType>(status->type),
75                         .status = static_cast<IAGnssCallback::AGnssStatusValue>(status->status),
76                         .ipV4Addr = in->sin_addr.s_addr,
77                     };
78 
79                     /*
80                      * Callback to client with agnssStatusIpV4Cb.
81                      */
82                     auto ret = sAGnssCbIface->agnssStatusIpV4Cb(aGnssStatusIpV4);
83                     if (!ret.isOk()) {
84                         ALOGE("%s: Unable to invoke callback", __func__);
85                     }
86                     break;
87                 }
88             case AF_INET6:
89                 {
90                     /*
91                      * ss_family indicates IPv6. Callback to client with agnssStatusIpV6Cb.
92                      */
93                     IAGnssCallback::AGnssStatusIpV6 aGnssStatusIpV6;
94 
95                     aGnssStatusIpV6.type = static_cast<IAGnssCallback::AGnssType>(status->type);
96                     aGnssStatusIpV6.status = static_cast<IAGnssCallback::AGnssStatusValue>(
97                             status->status);
98 
99                     struct sockaddr_in6* in6 = reinterpret_cast<struct sockaddr_in6 *>(
100                             &(status->addr));
101                     memcpy(&(aGnssStatusIpV6.ipV6Addr[0]), in6->sin6_addr.s6_addr,
102                            aGnssStatusIpV6.ipV6Addr.size());
103                     auto ret = sAGnssCbIface->agnssStatusIpV6Cb(aGnssStatusIpV6);
104                     if (!ret.isOk()) {
105                         ALOGE("%s: Unable to invoke callback", __func__);
106                     }
107                     break;
108                 }
109              default:
110                     ALOGE("Invalid ss_family found: %d", status->addr.ss_family);
111         }
112     } else if (statusSize >= sizeof(AGpsStatus_v2)) {
113         AGpsStatus_v2* statusV2 = reinterpret_cast<AGpsStatus_v2*>(status);
114         uint32_t ipV4Addr = statusV2->ipaddr;
115         IAGnssCallback::AGnssStatusIpV4 aGnssStatusIpV4 = {
116             .type = static_cast<IAGnssCallback::AGnssType>(AF_INET),
117             .status = static_cast<IAGnssCallback::AGnssStatusValue>(status->status),
118             /*
119              * For older versions of AGpsStatus, change IP addr to net order. This
120              * was earlier being done in GnssLocationProvider.
121              */
122             .ipV4Addr = htonl(ipV4Addr)
123         };
124         /*
125          * Callback to client with agnssStatusIpV4Cb.
126          */
127         auto ret = sAGnssCbIface->agnssStatusIpV4Cb(aGnssStatusIpV4);
128         if (!ret.isOk()) {
129             ALOGE("%s: Unable to invoke callback", __func__);
130         }
131     } else {
132         ALOGE("%s: Invalid size for AGPS Status", __func__);
133     }
134 }
135 
createThreadCb(const char * name,void (* start)(void *),void * arg)136 pthread_t AGnss::createThreadCb(const char* name, void (*start)(void*), void* arg) {
137     return createPthread(name, start, arg, &sThreadFuncArgsList);
138 }
139 
140 /*
141  * Implementation of methods from ::android::hardware::gnss::V1_0::IAGnss follow.
142  */
setCallback(const sp<IAGnssCallback> & callback)143 Return<void> AGnss::setCallback(const sp<IAGnssCallback>& callback) {
144     if (mAGnssIface == nullptr) {
145         ALOGE("%s: AGnss interface is unavailable", __func__);
146         return Void();
147     }
148 
149     sAGnssCbIface = callback;
150 
151     mAGnssIface->init(&sAGnssCb);
152     return Void();
153 }
154 
dataConnClosed()155 Return<bool> AGnss::dataConnClosed()  {
156     if (mAGnssIface == nullptr) {
157         ALOGE("%s: AGnss interface is unavailable", __func__);
158         return false;
159     }
160 
161     return (mAGnssIface->data_conn_closed() == 0);
162 }
163 
dataConnFailed()164 Return<bool> AGnss::dataConnFailed()  {
165     if (mAGnssIface == nullptr) {
166         ALOGE("%s: AGnss interface is unavailable", __func__);
167         return false;
168     }
169 
170     return (mAGnssIface->data_conn_failed() == 0);
171 }
172 
setServer(IAGnssCallback::AGnssType type,const hidl_string & hostname,int32_t port)173 Return<bool> AGnss::setServer(IAGnssCallback::AGnssType type,
174                               const hidl_string& hostname,
175                               int32_t port) {
176     if (mAGnssIface == nullptr) {
177         ALOGE("%s: AGnss interface is unavailable", __func__);
178         return false;
179     }
180 
181     return (mAGnssIface->set_server(static_cast<AGpsType>(type), hostname.c_str(), port) == 0);
182 }
183 
dataConnOpen(const hidl_string & apn,IAGnss::ApnIpType apnIpType)184 Return<bool> AGnss::dataConnOpen(const hidl_string& apn, IAGnss::ApnIpType apnIpType) {
185     if (mAGnssIface == nullptr) {
186         ALOGE("%s: AGnss interface is unavailable", __func__);
187         return false;
188     }
189 
190     return (mAGnssIface->data_conn_open_with_apn_ip_type(apn.c_str(),
191                                                      static_cast<uint16_t>(apnIpType)) == 0);
192 }
193 
194 }  // namespace implementation
195 }  // namespace V1_0
196 }  // namespace gnss
197 }  // namespace hardware
198 }  // namespace android
199