blob: 52fdc26338e9da15fc562483866184a0d4c9609d [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();
44}
45
46void AGnss::statusCb(AGpsStatus* status) {
47 if (sAGnssCbIface == nullptr) {
48 ALOGE("%s: AGNSS Callback Interface configured incorrectly", __func__);
49 return;
50 }
51
52 if (status == nullptr) {
53 ALOGE("AGNSS status is invalid");
54 return;
55 }
56
57 /*
58 * Logic based on AGnssStatus processing by GnssLocationProvider. Size of
59 * AGpsStatus is checked for backward compatibility since some devices may
60 * be sending out an older version of AGpsStatus that only supports IPv4.
61 */
62 size_t statusSize = status->size;
63 if (status->size == sizeof(AGpsStatus)) {
64 switch (status->addr.ss_family)
65 {
66 case AF_INET:
67 {
68 /*
69 * ss_family indicates IPv4.
70 */
71 struct sockaddr_in* in = reinterpret_cast<struct sockaddr_in*>(&(status->addr));
72 IAGnssCallback::AGnssStatusIpV4 aGnssStatusIpV4 = {
73 .type = static_cast<IAGnssCallback::AGnssType>(status->type),
74 .status = static_cast<IAGnssCallback::AGnssStatusValue>(status->status),
75 .ipV4Addr = in->sin_addr.s_addr,
76 };
77
78 /*
79 * Callback to client with agnssStatusIpV4Cb.
80 */
81 sAGnssCbIface->agnssStatusIpV4Cb(aGnssStatusIpV4);
82 break;
83 }
84 case AF_INET6:
85 {
86 /*
87 * ss_family indicates IPv6. Callback to client with agnssStatusIpV6Cb.
88 */
89 IAGnssCallback::AGnssStatusIpV6 aGnssStatusIpV6;
90
91 aGnssStatusIpV6.type = static_cast<IAGnssCallback::AGnssType>(status->type);
92 aGnssStatusIpV6.status = static_cast<IAGnssCallback::AGnssStatusValue>(
93 status->status);
94
95 struct sockaddr_in6* in6 = reinterpret_cast<struct sockaddr_in6 *>(
96 &(status->addr));
97 memcpy(&(aGnssStatusIpV6.ipV6Addr[0]), in6->sin6_addr.s6_addr,
98 aGnssStatusIpV6.ipV6Addr.size());
99 sAGnssCbIface->agnssStatusIpV6Cb(aGnssStatusIpV6);
100 break;
101 }
102 default:
103 ALOGE("Invalid ss_family found: %d", status->addr.ss_family);
104 }
105 } else if (statusSize >= sizeof(AGpsStatus_v2)) {
106 AGpsStatus_v2* statusV2 = reinterpret_cast<AGpsStatus_v2*>(status);
107 uint32_t ipV4Addr = statusV2->ipaddr;
108 IAGnssCallback::AGnssStatusIpV4 aGnssStatusIpV4 = {
109 .type = static_cast<IAGnssCallback::AGnssType>(AF_INET),
110 .status = static_cast<IAGnssCallback::AGnssStatusValue>(status->status),
111 /*
112 * For older versions of AGpsStatus, change IP addr to net order. This
113 * was earlier being done in GnssLocationProvider.
114 */
115 .ipV4Addr = htonl(ipV4Addr)
116 };
117 /*
118 * Callback to client with agnssStatusIpV4Cb.
119 */
120 sAGnssCbIface->agnssStatusIpV4Cb(aGnssStatusIpV4);
121 } else {
122 ALOGE("%s: Invalid size for AGPS Status", __func__);
123 }
124}
125
126pthread_t AGnss::createThreadCb(const char* name, void (*start)(void*), void* arg) {
127 return createPthread(name, start, arg, &sThreadFuncArgsList);
128}
129
130/*
131 * Implementation of methods from ::android::hardware::gnss::V1_0::IAGnss follow.
132 */
133Return<void> AGnss::setCallback(const sp<IAGnssCallback>& callback) {
134 if (mAGnssIface == nullptr) {
135 ALOGE("%s: AGnss interface is unavailable", __func__);
136 return Void();
137 }
138
139 sAGnssCbIface = callback;
140
141 mAGnssIface->init(&sAGnssCb);
142 return Void();
143}
144
145Return<bool> AGnss::dataConnClosed() {
146 if (mAGnssIface == nullptr) {
147 ALOGE("%s: AGnss interface is unavailable", __func__);
148 return false;
149 }
150
151 return (mAGnssIface->data_conn_closed() == 0);
152}
153
154Return<bool> AGnss::dataConnFailed() {
155 if (mAGnssIface == nullptr) {
156 ALOGE("%s: AGnss interface is unavailable", __func__);
157 return false;
158 }
159
160 return (mAGnssIface->data_conn_failed() == 0);
161}
162
163Return<bool> AGnss::setServer(IAGnssCallback::AGnssType type,
164 const hidl_string& hostname,
165 int32_t port) {
166 if (mAGnssIface == nullptr) {
167 ALOGE("%s: AGnss interface is unavailable", __func__);
168 return false;
169 }
170
171 return (mAGnssIface->set_server(static_cast<AGpsType>(type), hostname.c_str(), port) == 0);
172}
173
174Return<bool> AGnss::dataConnOpen(const hidl_string& apn, IAGnss::ApnIpType apnIpType) {
175 if (mAGnssIface == nullptr) {
176 ALOGE("%s: AGnss interface is unavailable", __func__);
177 return false;
178 }
179
180 return (mAGnssIface->data_conn_open_with_apn_ip_type(apn.c_str(),
181 static_cast<uint16_t>(apnIpType)) == 0);
182}
183
184} // namespace implementation
185} // namespace V1_0
186} // namespace gnss
187} // namespace hardware
188} // namespace android