199 lines
6.8 KiB
199 lines
6.8 KiB
/*
|
|
* Copyright (C) 2016 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#define LOG_TAG "GnssHAL_AGnssInterface"
|
|
|
|
#include "AGnss.h"
|
|
|
|
namespace android {
|
|
namespace hardware {
|
|
namespace gnss {
|
|
namespace V1_0 {
|
|
namespace implementation {
|
|
|
|
std::vector<std::unique_ptr<ThreadFuncArgs>> AGnss::sThreadFuncArgsList;
|
|
sp<IAGnssCallback> AGnss::sAGnssCbIface = nullptr;
|
|
bool AGnss::sInterfaceExists = false;
|
|
|
|
AGpsCallbacks AGnss::sAGnssCb = {
|
|
.status_cb = statusCb,
|
|
.create_thread_cb = createThreadCb
|
|
};
|
|
|
|
AGnss::AGnss(const AGpsInterface* aGpsIface) : mAGnssIface(aGpsIface) {
|
|
/* Error out if an instance of the interface already exists. */
|
|
LOG_ALWAYS_FATAL_IF(sInterfaceExists);
|
|
sInterfaceExists = true;
|
|
}
|
|
|
|
AGnss::~AGnss() {
|
|
sThreadFuncArgsList.clear();
|
|
sInterfaceExists = false;
|
|
}
|
|
|
|
void AGnss::statusCb(AGpsStatus* status) {
|
|
if (sAGnssCbIface == nullptr) {
|
|
ALOGE("%s: AGNSS Callback Interface configured incorrectly", __func__);
|
|
return;
|
|
}
|
|
|
|
if (status == nullptr) {
|
|
ALOGE("AGNSS status is invalid");
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* Logic based on AGnssStatus processing by GnssLocationProvider. Size of
|
|
* AGpsStatus is checked for backward compatibility since some devices may
|
|
* be sending out an older version of AGpsStatus that only supports IPv4.
|
|
*/
|
|
size_t statusSize = status->size;
|
|
if (status->size == sizeof(AGpsStatus)) {
|
|
switch (status->addr.ss_family)
|
|
{
|
|
case AF_INET:
|
|
{
|
|
/*
|
|
* ss_family indicates IPv4.
|
|
*/
|
|
struct sockaddr_in* in = reinterpret_cast<struct sockaddr_in*>(&(status->addr));
|
|
IAGnssCallback::AGnssStatusIpV4 aGnssStatusIpV4 = {
|
|
.type = static_cast<IAGnssCallback::AGnssType>(status->type),
|
|
.status = static_cast<IAGnssCallback::AGnssStatusValue>(status->status),
|
|
.ipV4Addr = in->sin_addr.s_addr,
|
|
};
|
|
|
|
/*
|
|
* Callback to client with agnssStatusIpV4Cb.
|
|
*/
|
|
auto ret = sAGnssCbIface->agnssStatusIpV4Cb(aGnssStatusIpV4);
|
|
if (!ret.isOk()) {
|
|
ALOGE("%s: Unable to invoke callback", __func__);
|
|
}
|
|
break;
|
|
}
|
|
case AF_INET6:
|
|
{
|
|
/*
|
|
* ss_family indicates IPv6. Callback to client with agnssStatusIpV6Cb.
|
|
*/
|
|
IAGnssCallback::AGnssStatusIpV6 aGnssStatusIpV6;
|
|
|
|
aGnssStatusIpV6.type = static_cast<IAGnssCallback::AGnssType>(status->type);
|
|
aGnssStatusIpV6.status = static_cast<IAGnssCallback::AGnssStatusValue>(
|
|
status->status);
|
|
|
|
struct sockaddr_in6* in6 = reinterpret_cast<struct sockaddr_in6 *>(
|
|
&(status->addr));
|
|
memcpy(&(aGnssStatusIpV6.ipV6Addr[0]), in6->sin6_addr.s6_addr,
|
|
aGnssStatusIpV6.ipV6Addr.size());
|
|
auto ret = sAGnssCbIface->agnssStatusIpV6Cb(aGnssStatusIpV6);
|
|
if (!ret.isOk()) {
|
|
ALOGE("%s: Unable to invoke callback", __func__);
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
ALOGE("Invalid ss_family found: %d", status->addr.ss_family);
|
|
}
|
|
} else if (statusSize >= sizeof(AGpsStatus_v2)) {
|
|
AGpsStatus_v2* statusV2 = reinterpret_cast<AGpsStatus_v2*>(status);
|
|
uint32_t ipV4Addr = statusV2->ipaddr;
|
|
IAGnssCallback::AGnssStatusIpV4 aGnssStatusIpV4 = {
|
|
.type = static_cast<IAGnssCallback::AGnssType>(AF_INET),
|
|
.status = static_cast<IAGnssCallback::AGnssStatusValue>(status->status),
|
|
/*
|
|
* For older versions of AGpsStatus, change IP addr to net order. This
|
|
* was earlier being done in GnssLocationProvider.
|
|
*/
|
|
.ipV4Addr = htonl(ipV4Addr)
|
|
};
|
|
/*
|
|
* Callback to client with agnssStatusIpV4Cb.
|
|
*/
|
|
auto ret = sAGnssCbIface->agnssStatusIpV4Cb(aGnssStatusIpV4);
|
|
if (!ret.isOk()) {
|
|
ALOGE("%s: Unable to invoke callback", __func__);
|
|
}
|
|
} else {
|
|
ALOGE("%s: Invalid size for AGPS Status", __func__);
|
|
}
|
|
}
|
|
|
|
pthread_t AGnss::createThreadCb(const char* name, void (*start)(void*), void* arg) {
|
|
return createPthread(name, start, arg, &sThreadFuncArgsList);
|
|
}
|
|
|
|
/*
|
|
* Implementation of methods from ::android::hardware::gnss::V1_0::IAGnss follow.
|
|
*/
|
|
Return<void> AGnss::setCallback(const sp<IAGnssCallback>& callback) {
|
|
if (mAGnssIface == nullptr) {
|
|
ALOGE("%s: AGnss interface is unavailable", __func__);
|
|
return Void();
|
|
}
|
|
|
|
sAGnssCbIface = callback;
|
|
|
|
mAGnssIface->init(&sAGnssCb);
|
|
return Void();
|
|
}
|
|
|
|
Return<bool> AGnss::dataConnClosed() {
|
|
if (mAGnssIface == nullptr) {
|
|
ALOGE("%s: AGnss interface is unavailable", __func__);
|
|
return false;
|
|
}
|
|
|
|
return (mAGnssIface->data_conn_closed() == 0);
|
|
}
|
|
|
|
Return<bool> AGnss::dataConnFailed() {
|
|
if (mAGnssIface == nullptr) {
|
|
ALOGE("%s: AGnss interface is unavailable", __func__);
|
|
return false;
|
|
}
|
|
|
|
return (mAGnssIface->data_conn_failed() == 0);
|
|
}
|
|
|
|
Return<bool> AGnss::setServer(IAGnssCallback::AGnssType type,
|
|
const hidl_string& hostname,
|
|
int32_t port) {
|
|
if (mAGnssIface == nullptr) {
|
|
ALOGE("%s: AGnss interface is unavailable", __func__);
|
|
return false;
|
|
}
|
|
|
|
return (mAGnssIface->set_server(static_cast<AGpsType>(type), hostname.c_str(), port) == 0);
|
|
}
|
|
|
|
Return<bool> AGnss::dataConnOpen(const hidl_string& apn, IAGnss::ApnIpType apnIpType) {
|
|
if (mAGnssIface == nullptr) {
|
|
ALOGE("%s: AGnss interface is unavailable", __func__);
|
|
return false;
|
|
}
|
|
|
|
return (mAGnssIface->data_conn_open_with_apn_ip_type(apn.c_str(),
|
|
static_cast<uint16_t>(apnIpType)) == 0);
|
|
}
|
|
|
|
} // namespace implementation
|
|
} // namespace V1_0
|
|
} // namespace gnss
|
|
} // namespace hardware
|
|
} // namespace android
|