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