blob: 29c6ddd13b600f31855fddf74c2edd43c7164ba3 [file] [log] [blame]
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -07001/*
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
21namespace android {
22namespace hardware {
23namespace gnss {
24namespace V1_0 {
25namespace implementation {
26
27std::vector<std::unique_ptr<ThreadFuncArgs>> AGnss::sThreadFuncArgsList;
28sp<IAGnssCallback> AGnss::sAGnssCbIface = nullptr;
29bool AGnss::sInterfaceExists = false;
30
31AGpsCallbacks AGnss::sAGnssCb = {
32 .status_cb = statusCb,
33 .create_thread_cb = createThreadCb
34};
35
36AGnss::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
42AGnss::~AGnss() {
43 sThreadFuncArgsList.clear();
Hridya Valsarajue020ce22017-02-15 20:31:18 -080044 sInterfaceExists = false;
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -070045}
46
47void 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 */
Hridya Valsarajue020ce22017-02-15 20:31:18 -080082 auto ret = sAGnssCbIface->agnssStatusIpV4Cb(aGnssStatusIpV4);
83 if (!ret.isOk()) {
84 ALOGE("%s: Unable to invoke callback", __func__);
85 }
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -070086 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());
Hridya Valsarajue020ce22017-02-15 20:31:18 -0800103 auto ret = sAGnssCbIface->agnssStatusIpV6Cb(aGnssStatusIpV6);
104 if (!ret.isOk()) {
105 ALOGE("%s: Unable to invoke callback", __func__);
106 }
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700107 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 */
Hridya Valsarajue020ce22017-02-15 20:31:18 -0800127 auto ret = sAGnssCbIface->agnssStatusIpV4Cb(aGnssStatusIpV4);
128 if (!ret.isOk()) {
129 ALOGE("%s: Unable to invoke callback", __func__);
130 }
Hridya Valsaraju29dc1e02016-10-21 14:41:12 -0700131 } else {
132 ALOGE("%s: Invalid size for AGPS Status", __func__);
133 }
134}
135
136pthread_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 */
143Return<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
155Return<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
164Return<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
173Return<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
184Return<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