You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
338 lines
11 KiB
338 lines
11 KiB
/* |
|
* Copyright (c) 2017, The Linux Foundation. All rights reserved. |
|
* Not a Contribution |
|
*/ |
|
/* |
|
* 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 "LocSvc_GnssInterface" |
|
|
|
#include <log_util.h> |
|
#include <dlfcn.h> |
|
#include "Gnss.h" |
|
typedef void* (getLocationInterface)(); |
|
|
|
namespace android { |
|
namespace hardware { |
|
namespace gnss { |
|
namespace V1_0 { |
|
namespace implementation { |
|
|
|
void Gnss::GnssDeathRecipient::serviceDied(uint64_t cookie, const wp<IBase>& who) { |
|
LOC_LOGE("%s] service died. cookie: %llu, who: %p", |
|
__FUNCTION__, static_cast<unsigned long long>(cookie), &who); |
|
if (mGnss != nullptr) { |
|
mGnss->stop(); |
|
mGnss->cleanup(); |
|
} |
|
} |
|
|
|
Gnss::Gnss() { |
|
ENTRY_LOG_CALLFLOW(); |
|
// clear pending GnssConfig |
|
memset(&mPendingConfig, 0, sizeof(GnssConfig)); |
|
|
|
mGnssDeathRecipient = new GnssDeathRecipient(this); |
|
} |
|
|
|
Gnss::~Gnss() { |
|
ENTRY_LOG_CALLFLOW(); |
|
if (mApi != nullptr) { |
|
delete mApi; |
|
mApi = nullptr; |
|
} |
|
} |
|
|
|
GnssAPIClient* Gnss::getApi() { |
|
if (mApi == nullptr && (mGnssCbIface != nullptr || mGnssNiCbIface != nullptr)) { |
|
mApi = new GnssAPIClient(mGnssCbIface, mGnssNiCbIface); |
|
if (mApi == nullptr) { |
|
LOC_LOGE("%s] faild to create GnssAPIClient", __FUNCTION__); |
|
return mApi; |
|
} |
|
|
|
if (mPendingConfig.size == sizeof(GnssConfig)) { |
|
// we have pending GnssConfig |
|
mApi->gnssConfigurationUpdate(mPendingConfig); |
|
// clear size to invalid mPendingConfig |
|
mPendingConfig.size = 0; |
|
if (mPendingConfig.assistanceServer.hostName != nullptr) { |
|
free((void*)mPendingConfig.assistanceServer.hostName); |
|
} |
|
} |
|
} |
|
if (mApi == nullptr) { |
|
LOC_LOGW("%s] GnssAPIClient is not ready", __FUNCTION__); |
|
} |
|
return mApi; |
|
} |
|
|
|
GnssInterface* Gnss::getGnssInterface() { |
|
static bool getGnssInterfaceFailed = false; |
|
if (nullptr == mGnssInterface && !getGnssInterfaceFailed) { |
|
LOC_LOGD("%s]: loading libgnss.so::getGnssInterface ...", __func__); |
|
getLocationInterface* getter = NULL; |
|
const char *error = NULL; |
|
dlerror(); |
|
void *handle = dlopen("libgnss.so", RTLD_NOW); |
|
if (NULL == handle || (error = dlerror()) != NULL) { |
|
LOC_LOGW("dlopen for libgnss.so failed, error = %s", error); |
|
} else { |
|
getter = (getLocationInterface*)dlsym(handle, "getGnssInterface"); |
|
if ((error = dlerror()) != NULL) { |
|
LOC_LOGW("dlsym for libgnss.so::getGnssInterface failed, error = %s", error); |
|
getter = NULL; |
|
} |
|
} |
|
|
|
if (NULL == getter) { |
|
getGnssInterfaceFailed = true; |
|
} else { |
|
mGnssInterface = (GnssInterface*)(*getter)(); |
|
} |
|
} |
|
return mGnssInterface; |
|
} |
|
|
|
Return<bool> Gnss::setCallback(const sp<IGnssCallback>& callback) { |
|
ENTRY_LOG_CALLFLOW(); |
|
if (mGnssCbIface != nullptr) { |
|
mGnssCbIface->unlinkToDeath(mGnssDeathRecipient); |
|
} |
|
mGnssCbIface = callback; |
|
if (mGnssCbIface != nullptr) { |
|
mGnssCbIface->linkToDeath(mGnssDeathRecipient, 0 /*cookie*/); |
|
} |
|
|
|
GnssAPIClient* api = getApi(); |
|
if (api != nullptr) { |
|
api->gnssUpdateCallbacks(mGnssCbIface, mGnssNiCbIface); |
|
api->locAPIEnable(LOCATION_TECHNOLOGY_TYPE_GNSS); |
|
api->requestCapabilities(); |
|
} |
|
return true; |
|
} |
|
|
|
Return<bool> Gnss::setGnssNiCb(const sp<IGnssNiCallback>& callback) { |
|
ENTRY_LOG_CALLFLOW(); |
|
mGnssNiCbIface = callback; |
|
GnssAPIClient* api = getApi(); |
|
if (api != nullptr) { |
|
api->gnssUpdateCallbacks(mGnssCbIface, mGnssNiCbIface); |
|
} |
|
return true; |
|
} |
|
|
|
Return<bool> Gnss::updateConfiguration(GnssConfig& gnssConfig) { |
|
ENTRY_LOG_CALLFLOW(); |
|
GnssAPIClient* api = getApi(); |
|
if (api) { |
|
api->locAPIGnssUpdateConfig(gnssConfig); |
|
} else if (gnssConfig.flags != 0) { |
|
// api is not ready yet, update mPendingConfig with gnssConfig |
|
mPendingConfig.size = sizeof(GnssConfig); |
|
|
|
if (gnssConfig.flags & GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT) { |
|
mPendingConfig.flags |= GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT; |
|
mPendingConfig.gpsLock = gnssConfig.gpsLock; |
|
} |
|
if (gnssConfig.flags & GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT) { |
|
mPendingConfig.flags |= GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT; |
|
mPendingConfig.suplVersion = gnssConfig.suplVersion; |
|
} |
|
if (gnssConfig.flags & GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT) { |
|
mPendingConfig.flags |= GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT; |
|
mPendingConfig.assistanceServer.size = sizeof(GnssConfigSetAssistanceServer); |
|
mPendingConfig.assistanceServer.type = gnssConfig.assistanceServer.type; |
|
if (mPendingConfig.assistanceServer.hostName != nullptr) { |
|
free((void*)mPendingConfig.assistanceServer.hostName); |
|
mPendingConfig.assistanceServer.hostName = |
|
strdup(gnssConfig.assistanceServer.hostName); |
|
} |
|
mPendingConfig.assistanceServer.port = gnssConfig.assistanceServer.port; |
|
} |
|
if (gnssConfig.flags & GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT) { |
|
mPendingConfig.flags |= GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT; |
|
mPendingConfig.lppProfile = gnssConfig.lppProfile; |
|
} |
|
if (gnssConfig.flags & GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT) { |
|
mPendingConfig.flags |= GNSS_CONFIG_FLAGS_LPPE_CONTROL_PLANE_VALID_BIT; |
|
mPendingConfig.lppeControlPlaneMask = gnssConfig.lppeControlPlaneMask; |
|
} |
|
if (gnssConfig.flags & GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT) { |
|
mPendingConfig.flags |= GNSS_CONFIG_FLAGS_LPPE_USER_PLANE_VALID_BIT; |
|
mPendingConfig.lppeUserPlaneMask = gnssConfig.lppeUserPlaneMask; |
|
} |
|
if (gnssConfig.flags & GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT) { |
|
mPendingConfig.flags |= GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT; |
|
mPendingConfig.aGlonassPositionProtocolMask = gnssConfig.aGlonassPositionProtocolMask; |
|
} |
|
if (gnssConfig.flags & GNSS_CONFIG_FLAGS_EM_PDN_FOR_EM_SUPL_VALID_BIT) { |
|
mPendingConfig.flags |= GNSS_CONFIG_FLAGS_EM_PDN_FOR_EM_SUPL_VALID_BIT; |
|
mPendingConfig.emergencyPdnForEmergencySupl = gnssConfig.emergencyPdnForEmergencySupl; |
|
} |
|
if (gnssConfig.flags & GNSS_CONFIG_FLAGS_SUPL_EM_SERVICES_BIT) { |
|
mPendingConfig.flags |= GNSS_CONFIG_FLAGS_SUPL_EM_SERVICES_BIT; |
|
mPendingConfig.suplEmergencyServices = gnssConfig.suplEmergencyServices; |
|
} |
|
if (gnssConfig.flags & GNSS_CONFIG_FLAGS_SUPL_MODE_BIT) { |
|
mPendingConfig.flags |= GNSS_CONFIG_FLAGS_SUPL_MODE_BIT; |
|
mPendingConfig.suplModeMask = gnssConfig.suplModeMask; |
|
} |
|
} |
|
return true; |
|
} |
|
|
|
Return<bool> Gnss::start() { |
|
ENTRY_LOG_CALLFLOW(); |
|
bool retVal = false; |
|
GnssAPIClient* api = getApi(); |
|
if (api) { |
|
retVal = api->gnssStart(); |
|
} |
|
return retVal; |
|
} |
|
|
|
Return<bool> Gnss::stop() { |
|
ENTRY_LOG_CALLFLOW(); |
|
bool retVal = false; |
|
GnssAPIClient* api = getApi(); |
|
if (api) { |
|
retVal = api->gnssStop(); |
|
} |
|
return retVal; |
|
} |
|
|
|
Return<void> Gnss::cleanup() { |
|
ENTRY_LOG_CALLFLOW(); |
|
|
|
if (mApi != nullptr) { |
|
mApi->locAPIDisable(); |
|
} |
|
|
|
return Void(); |
|
} |
|
|
|
Return<bool> Gnss::injectLocation(double latitudeDegrees, |
|
double longitudeDegrees, |
|
float accuracyMeters) { |
|
ENTRY_LOG_CALLFLOW(); |
|
GnssInterface* gnssInterface = getGnssInterface(); |
|
if (nullptr != gnssInterface) { |
|
gnssInterface->injectLocation(latitudeDegrees, longitudeDegrees, accuracyMeters); |
|
return true; |
|
} else { |
|
return false; |
|
} |
|
} |
|
|
|
Return<bool> Gnss::injectTime(int64_t timeMs, int64_t timeReferenceMs, |
|
int32_t uncertaintyMs) { |
|
ENTRY_LOG_CALLFLOW(); |
|
GnssInterface* gnssInterface = getGnssInterface(); |
|
if (nullptr != gnssInterface) { |
|
gnssInterface->injectTime(timeMs, timeReferenceMs, uncertaintyMs); |
|
return true; |
|
} else { |
|
return false; |
|
} |
|
} |
|
|
|
Return<void> Gnss::deleteAidingData(IGnss::GnssAidingData aidingDataFlags) { |
|
ENTRY_LOG_CALLFLOW(); |
|
GnssAPIClient* api = getApi(); |
|
if (api) { |
|
api->gnssDeleteAidingData(aidingDataFlags); |
|
} |
|
return Void(); |
|
} |
|
|
|
Return<bool> Gnss::setPositionMode(IGnss::GnssPositionMode mode, |
|
IGnss::GnssPositionRecurrence recurrence, |
|
uint32_t minIntervalMs, |
|
uint32_t preferredAccuracyMeters, |
|
uint32_t preferredTimeMs) { |
|
ENTRY_LOG_CALLFLOW(); |
|
bool retVal = false; |
|
GnssAPIClient* api = getApi(); |
|
if (api) { |
|
retVal = api->gnssSetPositionMode(mode, recurrence, minIntervalMs, |
|
preferredAccuracyMeters, preferredTimeMs); |
|
} |
|
return retVal; |
|
} |
|
|
|
Return<sp<IAGnss>> Gnss::getExtensionAGnss() { |
|
ENTRY_LOG_CALLFLOW(); |
|
mAGnssIface = new AGnss(this); |
|
return mAGnssIface; |
|
} |
|
|
|
Return<sp<IGnssNi>> Gnss::getExtensionGnssNi() { |
|
ENTRY_LOG_CALLFLOW(); |
|
mGnssNi = new GnssNi(this); |
|
return mGnssNi; |
|
} |
|
|
|
Return<sp<IGnssMeasurement>> Gnss::getExtensionGnssMeasurement() { |
|
ENTRY_LOG_CALLFLOW(); |
|
mGnssMeasurement = new GnssMeasurement(); |
|
return mGnssMeasurement; |
|
} |
|
|
|
Return<sp<IGnssConfiguration>> Gnss::getExtensionGnssConfiguration() { |
|
ENTRY_LOG_CALLFLOW(); |
|
mGnssConfig = new GnssConfiguration(this); |
|
return mGnssConfig; |
|
} |
|
|
|
Return<sp<IGnssGeofencing>> Gnss::getExtensionGnssGeofencing() { |
|
ENTRY_LOG_CALLFLOW(); |
|
mGnssGeofencingIface = new GnssGeofencing(); |
|
return mGnssGeofencingIface; |
|
} |
|
|
|
Return<sp<IGnssBatching>> Gnss::getExtensionGnssBatching() { |
|
mGnssBatching = new GnssBatching(); |
|
return mGnssBatching; |
|
} |
|
|
|
Return<sp<IGnssDebug>> Gnss::getExtensionGnssDebug() { |
|
ENTRY_LOG_CALLFLOW(); |
|
mGnssDebug = new GnssDebug(this); |
|
return mGnssDebug; |
|
} |
|
|
|
Return<sp<IAGnssRil>> Gnss::getExtensionAGnssRil() { |
|
mGnssRil = new AGnssRil(this); |
|
return mGnssRil; |
|
} |
|
|
|
IGnss* HIDL_FETCH_IGnss(const char* hal) { |
|
ENTRY_LOG_CALLFLOW(); |
|
IGnss* iface = nullptr; |
|
iface = new Gnss(); |
|
if (iface == nullptr) { |
|
LOC_LOGE("%s]: failed to get %s", __FUNCTION__, hal); |
|
} |
|
return iface; |
|
} |
|
|
|
} // namespace implementation |
|
} // namespace V1_0 |
|
} // namespace gnss |
|
} // namespace hardware |
|
} // namespace android
|
|
|