| /* |
| * 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 |