diff options
Diffstat (limited to 'android/1.0')
32 files changed, 4426 insertions, 0 deletions
diff --git a/android/1.0/AGnss.cpp b/android/1.0/AGnss.cpp new file mode 100644 index 0000000..79f665c --- /dev/null +++ b/android/1.0/AGnss.cpp @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2017-2018, 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_AGnssInterface" + +#include <log_util.h> +#include "Gnss.h" +#include "AGnss.h" + +namespace android { +namespace hardware { +namespace gnss { +namespace V1_0 { +namespace implementation { + +static AGnss* spAGnss = nullptr; + +AGnss::AGnss(Gnss* gnss) : mGnss(gnss) { + spAGnss = this; +} + +AGnss::~AGnss() { + spAGnss = nullptr; +} + +void AGnss::agnssStatusIpV4Cb(AGnssExtStatusIpV4 status){ + if (nullptr != spAGnss) { + spAGnss->statusIpV4Cb(status); + } +} + +void AGnss::statusIpV4Cb(AGnssExtStatusIpV4 status) { + IAGnssCallback::AGnssStatusIpV4 st = {}; + + switch (status.type) { + case LOC_AGPS_TYPE_SUPL: + st.type = IAGnssCallback::AGnssType::TYPE_SUPL; + break; + case LOC_AGPS_TYPE_C2K: + st.type = IAGnssCallback::AGnssType::TYPE_C2K; + break; + default: + LOC_LOGE("invalid type: %d", status.type); + return; + } + + switch (status.status) { + case LOC_GPS_REQUEST_AGPS_DATA_CONN: + st.status = IAGnssCallback::AGnssStatusValue::REQUEST_AGNSS_DATA_CONN; + break; + case LOC_GPS_RELEASE_AGPS_DATA_CONN: + st.status = IAGnssCallback::AGnssStatusValue::RELEASE_AGNSS_DATA_CONN; + break; + case LOC_GPS_AGPS_DATA_CONNECTED: + st.status = IAGnssCallback::AGnssStatusValue::AGNSS_DATA_CONNECTED; + break; + case LOC_GPS_AGPS_DATA_CONN_DONE: + st.status = IAGnssCallback::AGnssStatusValue::AGNSS_DATA_CONN_DONE; + break; + case LOC_GPS_AGPS_DATA_CONN_FAILED: + st.status = IAGnssCallback::AGnssStatusValue::AGNSS_DATA_CONN_FAILED; + break; + default: + LOC_LOGE("invalid status: %d", status.status); + return; + } + st.ipV4Addr = status.ipV4Addr; + + if (mAGnssCbIface != nullptr) { + auto r = mAGnssCbIface->agnssStatusIpV4Cb(st); + if (!r.isOk()) { + LOC_LOGw("Error invoking AGNSS status cb %s", r.description().c_str()); + } + } else { + LOC_LOGw("setCallback has not been called yet"); + } +} + +Return<void> AGnss::setCallback(const sp<IAGnssCallback>& callback) { + + if(mGnss == nullptr || mGnss->getGnssInterface() == nullptr){ + LOC_LOGE("Null GNSS interface"); + return Void(); + } + + // Save the interface + mAGnssCbIface = callback; + + AgpsCbInfo cbInfo = {}; + cbInfo.statusV4Cb = (void*)agnssStatusIpV4Cb; + cbInfo.atlType = AGPS_ATL_TYPE_SUPL | AGPS_ATL_TYPE_SUPL_ES; + + mGnss->getGnssInterface()->agpsInit(cbInfo); + return Void(); +} + +Return<bool> AGnss::dataConnClosed() { + + if(mGnss == nullptr || mGnss->getGnssInterface() == nullptr){ + LOC_LOGE("Null GNSS interface"); + return false; + } + + mGnss->getGnssInterface()->agpsDataConnClosed(LOC_AGPS_TYPE_SUPL); + return true; +} + +Return<bool> AGnss::dataConnFailed() { + + if(mGnss == nullptr || mGnss->getGnssInterface() == nullptr){ + LOC_LOGE("Null GNSS interface"); + return false; + } + + mGnss->getGnssInterface()->agpsDataConnFailed(LOC_AGPS_TYPE_SUPL); + return true; +} + +Return<bool> AGnss::dataConnOpen(const hidl_string& apn, + IAGnss::ApnIpType apnIpType) { + + if(mGnss == nullptr || mGnss->getGnssInterface() == nullptr){ + LOC_LOGE("Null GNSS interface"); + return false; + } + + /* Validate */ + if(apn.empty()){ + LOC_LOGE("Invalid APN"); + return false; + } + + LOC_LOGD("dataConnOpen APN name = [%s]", apn.c_str()); + + AGpsBearerType bearerType; + switch (apnIpType) { + case IAGnss::ApnIpType::IPV4: + bearerType = AGPS_APN_BEARER_IPV4; + break; + case IAGnss::ApnIpType::IPV6: + bearerType = AGPS_APN_BEARER_IPV6; + break; + case IAGnss::ApnIpType::IPV4V6: + bearerType = AGPS_APN_BEARER_IPV4V6; + break; + default: + bearerType = AGPS_APN_BEARER_IPV4; + break; + } + + mGnss->getGnssInterface()->agpsDataConnOpen( + LOC_AGPS_TYPE_SUPL, apn.c_str(), apn.size(), (int)bearerType); + return true; +} + +Return<bool> AGnss::setServer(IAGnssCallback::AGnssType type, + const hidl_string& hostname, + int32_t port) { + if (mGnss == nullptr) { + LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__); + return false; + } + + GnssConfig config; + memset(&config, 0, sizeof(GnssConfig)); + config.size = sizeof(GnssConfig); + config.flags = GNSS_CONFIG_FLAGS_SET_ASSISTANCE_DATA_VALID_BIT; + config.assistanceServer.size = sizeof(GnssConfigSetAssistanceServer); + if (type == IAGnssCallback::AGnssType::TYPE_SUPL) { + config.assistanceServer.type = GNSS_ASSISTANCE_TYPE_SUPL; + } else if (type == IAGnssCallback::AGnssType::TYPE_C2K) { + config.assistanceServer.type = GNSS_ASSISTANCE_TYPE_C2K; + } else { + LOC_LOGE("%s]: invalid AGnssType: %d", __FUNCTION__, static_cast<int>(type)); + return false; + } + config.assistanceServer.hostName = strdup(hostname.c_str()); + config.assistanceServer.port = port; + return mGnss->updateConfiguration(config); +} + +} // namespace implementation +} // namespace V1_0 +} // namespace gnss +} // namespace hardware +} // namespace android diff --git a/android/1.0/AGnss.h b/android/1.0/AGnss.h new file mode 100644 index 0000000..cdd5931 --- /dev/null +++ b/android/1.0/AGnss.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2017-2018, 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. + */ + +#ifndef ANDROID_HARDWARE_GNSS_V1_0_AGNSS_H +#define ANDROID_HARDWARE_GNSS_V1_0_AGNSS_H + +#include <android/hardware/gnss/1.0/IAGnss.h> +#include <hidl/Status.h> +#include <gps_extended_c.h> + +namespace android { +namespace hardware { +namespace gnss { +namespace V1_0 { +namespace implementation { + +using ::android::hardware::gnss::V1_0::IAGnss; +using ::android::hardware::gnss::V1_0::IAGnssCallback; +using ::android::hardware::Return; +using ::android::hardware::Void; +using ::android::hardware::hidl_vec; +using ::android::hardware::hidl_string; +using ::android::sp; + +struct Gnss; +struct AGnss : public IAGnss { + + AGnss(Gnss* gnss); + ~AGnss(); + /* + * Methods from ::android::hardware::gnss::V1_0::IAGnss interface follow. + * These declarations were generated from IAGnss.hal. + */ + Return<void> setCallback(const sp<IAGnssCallback>& callback) override; + + Return<bool> dataConnClosed() override; + + Return<bool> dataConnFailed() override; + + Return<bool> dataConnOpen(const hidl_string& apn, + IAGnss::ApnIpType apnIpType) override; + + Return<bool> setServer(IAGnssCallback::AGnssType type, + const hidl_string& hostname, int32_t port) override; + + void statusIpV4Cb(AGnssExtStatusIpV4 status); + + /* Data call setup callback passed down to GNSS HAL implementation */ + static void agnssStatusIpV4Cb(AGnssExtStatusIpV4 status); + + private: + Gnss* mGnss = nullptr; + sp<IAGnssCallback> mAGnssCbIface = nullptr; +}; + +} // namespace implementation +} // namespace V1_0 +} // namespace gnss +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_GNSS_V1_0_AGNSS_H diff --git a/android/1.0/AGnssRil.cpp b/android/1.0/AGnssRil.cpp new file mode 100644 index 0000000..0437cf1 --- /dev/null +++ b/android/1.0/AGnssRil.cpp @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2017-2018, 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__AGnssRilInterface" + +#include <log_util.h> +#include <dlfcn.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <sstream> +#include <string> +#include "Gnss.h" +#include "AGnssRil.h" +#include <DataItemConcreteTypesBase.h> + +typedef void* (getLocationInterface)(); + +namespace android { +namespace hardware { +namespace gnss { +namespace V1_0 { +namespace implementation { + + +AGnssRil::AGnssRil(Gnss* gnss) : mGnss(gnss) { + ENTRY_LOG_CALLFLOW(); +} + +AGnssRil::~AGnssRil() { + ENTRY_LOG_CALLFLOW(); +} + +Return<bool> AGnssRil::updateNetworkState(bool connected, NetworkType type, bool /*roaming*/) { + ENTRY_LOG_CALLFLOW(); + // Extra NetworkTypes not available in IAgnssRil enums + const int NetworkType_BLUETOOTH = 7; + const int NetworkType_ETHERNET = 9; + const int NetworkType_PROXY = 16; + + // for XTRA + if (nullptr != mGnss && ( nullptr != mGnss->getGnssInterface() )) { + int8_t typeout = loc_core::NetworkInfoDataItemBase::TYPE_UNKNOWN; + switch(type) + { + case IAGnssRil::NetworkType::MOBILE: + typeout = loc_core::NetworkInfoDataItemBase::TYPE_MOBILE; + break; + case IAGnssRil::NetworkType::WIFI: + typeout = loc_core::NetworkInfoDataItemBase::TYPE_WIFI; + break; + case IAGnssRil::NetworkType::MMS: + typeout = loc_core::NetworkInfoDataItemBase::TYPE_MMS; + break; + case IAGnssRil::NetworkType::SUPL: + typeout = loc_core::NetworkInfoDataItemBase::TYPE_SUPL; + break; + case IAGnssRil::NetworkType::DUN: + typeout = loc_core::NetworkInfoDataItemBase::TYPE_DUN; + break; + case IAGnssRil::NetworkType::HIPRI: + typeout = loc_core::NetworkInfoDataItemBase::TYPE_HIPRI; + break; + case IAGnssRil::NetworkType::WIMAX: + typeout = loc_core::NetworkInfoDataItemBase::TYPE_WIMAX; + break; + default: + { + int networkType = (int) type; + // Handling network types not available in IAgnssRil + switch(networkType) + { + case NetworkType_BLUETOOTH: + typeout = loc_core::NetworkInfoDataItemBase::TYPE_BLUETOOTH; + break; + case NetworkType_ETHERNET: + typeout = loc_core::NetworkInfoDataItemBase::TYPE_ETHERNET; + break; + case NetworkType_PROXY: + typeout = loc_core::NetworkInfoDataItemBase::TYPE_PROXY; + break; + default: + typeout = loc_core::NetworkInfoDataItemBase::TYPE_UNKNOWN; + } + } + break; + } + mGnss->getGnssInterface()->updateConnectionStatus(connected, false, typeout, 0); + } + return true; +} + +} // namespace implementation +} // namespace V1_0 +} // namespace gnss +} // namespace hardware +} // namespace android diff --git a/android/1.0/AGnssRil.h b/android/1.0/AGnssRil.h new file mode 100644 index 0000000..7f18c57 --- /dev/null +++ b/android/1.0/AGnssRil.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2017-2018, 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. + */ + +#ifndef ANDROID_HARDWARE_GNSS_V1_0_AGNSSRIL_H_ +#define ANDROID_HARDWARE_GNSS_V1_0_AGNSSRIL_H_ + +#include <android/hardware/gnss/1.0/IAGnssRil.h> +#include <hidl/Status.h> +#include <location_interface.h> + +namespace android { +namespace hardware { +namespace gnss { +namespace V1_0 { +namespace implementation { + +using ::android::hardware::gnss::V1_0::IAGnssRil; +using ::android::hardware::gnss::V1_0::IAGnssRilCallback; +using ::android::hardware::Return; +using ::android::hardware::Void; +using ::android::hardware::hidl_vec; +using ::android::hardware::hidl_string; +using ::android::sp; + +struct Gnss; +/* + * Extended interface for AGNSS RIL support. An Assisted GNSS Radio Interface Layer interface + * allows the GNSS chipset to request radio interface layer information from Android platform. + * Examples of such information are reference location, unique subscriber ID, phone number string + * and network availability changes. Also contains wrapper methods to allow methods from + * IAGnssiRilCallback interface to be passed into the conventional implementation of the GNSS HAL. + */ +struct AGnssRil : public IAGnssRil { + AGnssRil(Gnss* gnss); + ~AGnssRil(); + + /* + * Methods from ::android::hardware::gnss::V1_0::IAGnssRil follow. + * These declarations were generated from IAGnssRil.hal. + */ + Return<void> setCallback(const sp<IAGnssRilCallback>& /*callback*/) override { + return Void(); + } + Return<void> setRefLocation(const IAGnssRil::AGnssRefLocation& /*agnssReflocation*/) override { + return Void(); + } + Return<bool> setSetId(IAGnssRil::SetIDType /*type*/, const hidl_string& /*setid*/) override { + return false; + } + Return<bool> updateNetworkAvailability(bool /*available*/, + const hidl_string& /*apn*/) override { + return false; + } + Return<bool> updateNetworkState(bool connected, NetworkType type, bool roaming) override; + + private: + Gnss* mGnss = nullptr; +}; + +} // namespace implementation +} // namespace V1_0 +} // namespace gnss +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_GNSS_V1_0_AGNSSRIL_H_ diff --git a/android/1.0/Android.mk b/android/1.0/Android.mk new file mode 100644 index 0000000..9337325 --- /dev/null +++ b/android/1.0/Android.mk @@ -0,0 +1,97 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) +LOCAL_MODULE := android.hardware.gnss@1.0-impl-qti +LOCAL_VENDOR_MODULE := true +LOCAL_MODULE_RELATIVE_PATH := hw +LOCAL_SRC_FILES := \ + AGnss.cpp \ + Gnss.cpp \ + GnssBatching.cpp \ + GnssGeofencing.cpp \ + GnssMeasurement.cpp \ + GnssNi.cpp \ + GnssConfiguration.cpp \ + GnssDebug.cpp \ + AGnssRil.cpp + +LOCAL_SRC_FILES += \ + location_api/LocationUtil.cpp \ + location_api/GnssAPIClient.cpp \ + location_api/GeofenceAPIClient.cpp \ + location_api/BatchingAPIClient.cpp \ + location_api/MeasurementAPIClient.cpp \ + +LOCAL_C_INCLUDES:= \ + $(LOCAL_PATH)/location_api +LOCAL_HEADER_LIBRARIES := \ + libgps.utils_headers \ + libloc_core_headers \ + libloc_pla_headers \ + liblocation_api_headers \ + liblocbatterylistener_headers + +LOCAL_SHARED_LIBRARIES := \ + liblog \ + libhidlbase \ + libhidltransport \ + libhwbinder \ + libcutils \ + libutils \ + android.hardware.gnss@1.0 \ + android.hardware.health@1.0 \ + android.hardware.health@2.0 \ + android.hardware.power@1.2 \ + libbase + +LOCAL_SHARED_LIBRARIES += \ + libloc_core \ + libgps.utils \ + libdl \ + liblocation_api \ + +LOCAL_CFLAGS += $(GNSS_CFLAGS) +LOCAL_STATIC_LIBRARIES := liblocbatterylistener +LOCAL_STATIC_LIBRARIES += libhealthhalutils +include $(BUILD_SHARED_LIBRARY) + +include $(CLEAR_VARS) +LOCAL_MODULE := android.hardware.gnss@1.0-service-qti +LOCAL_VINTF_FRAGMENTS := android.hardware.gnss@1.0-service-qti.xml +LOCAL_VENDOR_MODULE := true +LOCAL_MODULE_RELATIVE_PATH := hw +LOCAL_INIT_RC := android.hardware.gnss@1.0-service-qti.rc +LOCAL_SRC_FILES := \ + service.cpp \ + +LOCAL_C_INCLUDES:= \ + $(LOCAL_PATH)/location_api +LOCAL_HEADER_LIBRARIES := \ + libgps.utils_headers \ + libloc_core_headers \ + libloc_pla_headers \ + liblocation_api_headers + + +LOCAL_SHARED_LIBRARIES := \ + liblog \ + libcutils \ + libdl \ + libbase \ + libutils \ + libgps.utils \ + libqti_vndfwk_detect \ + +LOCAL_SHARED_LIBRARIES += \ + libhwbinder \ + libhidlbase \ + libhidltransport \ + android.hardware.gnss@1.0 \ + +LOCAL_CFLAGS += $(GNSS_CFLAGS) + +ifneq ($(LOC_HIDL_VERSION),) +LOCAL_CFLAGS += -DLOC_HIDL_VERSION='"$(LOC_HIDL_VERSION)"' +endif + +include $(BUILD_EXECUTABLE) diff --git a/android/1.0/Gnss.cpp b/android/1.0/Gnss.cpp new file mode 100644 index 0000000..d85e0a4 --- /dev/null +++ b/android/1.0/Gnss.cpp @@ -0,0 +1,360 @@ +/* + * Copyright (c) 2017-2018, 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" +#define LOG_NDEBUG 0 + +#include <fstream> +#include <log_util.h> +#include <dlfcn.h> +#include <cutils/properties.h> +#include "Gnss.h" +#include <LocationUtil.h> +#include "battery_listener.h" + +typedef const GnssInterface* (getLocationInterface)(); + +namespace android { +namespace hardware { +namespace gnss { +namespace V1_0 { +namespace implementation { + +static sp<Gnss> sGnss; +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(); + } +} + +void location_on_battery_status_changed(bool charging) { + LOC_LOGd("battery status changed to %s charging", charging ? "" : "not "); + if (sGnss != nullptr) { + sGnss->getGnssInterface()->updateBatteryStatus(charging); + } +} +Gnss::Gnss() { + ENTRY_LOG_CALLFLOW(); + sGnss = this; + // register health client to listen on battery change + loc_extn_battery_properties_listener_init(location_on_battery_status_changed); + // clear pending GnssConfig + memset(&mPendingConfig, 0, sizeof(GnssConfig)); + + mGnssDeathRecipient = new GnssDeathRecipient(this); +} + +Gnss::~Gnss() { + ENTRY_LOG_CALLFLOW(); + if (mApi != nullptr) { + delete mApi; + mApi = nullptr; + } + sGnss = 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; +} + +const 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 = (const GnssInterface*)(*getter)(); + } + } + return mGnssInterface; +} + +Return<bool> Gnss::setCallback(const sp<V1_0::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->gnssEnable(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->gnssConfigurationUpdate(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; + } + if (gnssConfig.flags & GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT) { + mPendingConfig.flags |= GNSS_CONFIG_FLAGS_BLACKLISTED_SV_IDS_BIT; + mPendingConfig.blacklistedSvIds = gnssConfig.blacklistedSvIds; + } + } + 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->gnssDisable(); + } + + return Void(); +} + +Return<bool> Gnss::injectLocation(double latitudeDegrees, + double longitudeDegrees, + float accuracyMeters) { + ENTRY_LOG_CALLFLOW(); + const 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(); + const GnssInterface* gnssInterface = getGnssInterface(); + if (nullptr != gnssInterface) { + gnssInterface->injectTime(timeMs, timeReferenceMs, uncertaintyMs); + return true; + } else { + return false; + } +} + +Return<void> Gnss::deleteAidingData(V1_0::IGnss::GnssAidingData aidingDataFlags) { + ENTRY_LOG_CALLFLOW(); + GnssAPIClient* api = getApi(); + if (api) { + api->gnssDeleteAidingData(aidingDataFlags); + } + return Void(); +} + +Return<bool> Gnss::setPositionMode(V1_0::IGnss::GnssPositionMode mode, + V1_0::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<V1_0::IAGnss>> Gnss::getExtensionAGnss() { + ENTRY_LOG_CALLFLOW(); + mAGnssIface = new AGnss(this); + return mAGnssIface; +} + +Return<sp<V1_0::IGnssNi>> Gnss::getExtensionGnssNi() { + ENTRY_LOG_CALLFLOW(); + mGnssNi = new GnssNi(this); + return mGnssNi; +} + +Return<sp<V1_0::IGnssMeasurement>> Gnss::getExtensionGnssMeasurement() { + ENTRY_LOG_CALLFLOW(); + if (mGnssMeasurement == nullptr) + mGnssMeasurement = new GnssMeasurement(); + return mGnssMeasurement; +} + +Return<sp<V1_0::IGnssConfiguration>> Gnss::getExtensionGnssConfiguration() { + ENTRY_LOG_CALLFLOW(); + mGnssConfig = new GnssConfiguration(this); + return mGnssConfig; +} + +Return<sp<V1_0::IGnssGeofencing>> Gnss::getExtensionGnssGeofencing() { + ENTRY_LOG_CALLFLOW(); + mGnssGeofencingIface = new GnssGeofencing(); + return mGnssGeofencingIface; +} + +Return<sp<V1_0::IGnssBatching>> Gnss::getExtensionGnssBatching() { + mGnssBatching = new GnssBatching(); + return mGnssBatching; +} + +Return<sp<V1_0::IGnssDebug>> Gnss::getExtensionGnssDebug() { + ENTRY_LOG_CALLFLOW(); + mGnssDebug = new GnssDebug(this); + return mGnssDebug; +} + +Return<sp<V1_0::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 diff --git a/android/1.0/Gnss.h b/android/1.0/Gnss.h new file mode 100644 index 0000000..900a510 --- /dev/null +++ b/android/1.0/Gnss.h @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2017-2018, 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. + */ + +#ifndef ANDROID_HARDWARE_GNSS_V1_0_GNSS_H +#define ANDROID_HARDWARE_GNSS_V1_0_GNSS_H + +#include <AGnss.h> +#include <AGnssRil.h> +#include <GnssBatching.h> +#include <GnssConfiguration.h> +#include <GnssGeofencing.h> +#include <GnssMeasurement.h> +#include <GnssNi.h> +#include <GnssDebug.h> + +#include <android/hardware/gnss/1.0/IGnss.h> +#include <hidl/MQDescriptor.h> +#include <hidl/Status.h> + +#include <GnssAPIClient.h> +#include <location_interface.h> + +namespace android { +namespace hardware { +namespace gnss { +namespace V1_0 { +namespace implementation { + +using ::android::hardware::hidl_array; +using ::android::hardware::hidl_memory; +using ::android::hardware::hidl_string; +using ::android::hardware::hidl_vec; +using ::android::hardware::Return; +using ::android::hardware::Void; +using ::android::sp; +using ::android::hardware::gnss::V1_0::GnssLocation; + +struct Gnss : public IGnss { + Gnss(); + ~Gnss(); + + /* + * Methods from ::android::hardware::gnss::V1_0::IGnss follow. + * These declarations were generated from Gnss.hal. + */ + Return<bool> setCallback(const sp<V1_0::IGnssCallback>& callback) override; + Return<bool> start() override; + Return<bool> stop() override; + Return<void> cleanup() override; + Return<bool> injectLocation(double latitudeDegrees, + double longitudeDegrees, + float accuracyMeters) override; + Return<bool> injectTime(int64_t timeMs, + int64_t timeReferenceMs, + int32_t uncertaintyMs) override; + Return<void> deleteAidingData(V1_0::IGnss::GnssAidingData aidingDataFlags) override; + Return<bool> setPositionMode(V1_0::IGnss::GnssPositionMode mode, + V1_0::IGnss::GnssPositionRecurrence recurrence, + uint32_t minIntervalMs, + uint32_t preferredAccuracyMeters, + uint32_t preferredTimeMs) override; + Return<sp<V1_0::IAGnss>> getExtensionAGnss() override; + Return<sp<V1_0::IGnssNi>> getExtensionGnssNi() override; + Return<sp<V1_0::IGnssMeasurement>> getExtensionGnssMeasurement() override; + Return<sp<V1_0::IGnssConfiguration>> getExtensionGnssConfiguration() override; + Return<sp<V1_0::IGnssGeofencing>> getExtensionGnssGeofencing() override; + Return<sp<V1_0::IGnssBatching>> getExtensionGnssBatching() override; + + Return<sp<V1_0::IAGnssRil>> getExtensionAGnssRil() override; + + inline Return<sp<V1_0::IGnssNavigationMessage>> getExtensionGnssNavigationMessage() override { + return nullptr; + } + + inline Return<sp<V1_0::IGnssXtra>> getExtensionXtra() override { + return nullptr; + } + + Return<sp<V1_0::IGnssDebug>> getExtensionGnssDebug() override; + + // These methods are not part of the IGnss base class. + GnssAPIClient* getApi(); + Return<bool> setGnssNiCb(const sp<IGnssNiCallback>& niCb); + Return<bool> updateConfiguration(GnssConfig& gnssConfig); + const GnssInterface* getGnssInterface(); + + // Callback for ODCPI request + void odcpiRequestCb(const OdcpiRequestInfo& request); + + private: + struct GnssDeathRecipient : hidl_death_recipient { + GnssDeathRecipient(sp<Gnss> gnss) : mGnss(gnss) { + } + ~GnssDeathRecipient() = default; + virtual void serviceDied(uint64_t cookie, const wp<IBase>& who) override; + sp<Gnss> mGnss; + }; + + private: + sp<GnssDeathRecipient> mGnssDeathRecipient = nullptr; + + sp<AGnss> mAGnssIface = nullptr; + sp<GnssNi> mGnssNi = nullptr; + sp<GnssMeasurement> mGnssMeasurement = nullptr; + sp<GnssConfiguration> mGnssConfig = nullptr; + sp<GnssGeofencing> mGnssGeofencingIface = nullptr; + sp<GnssBatching> mGnssBatching = nullptr; + sp<IGnssDebug> mGnssDebug = nullptr; + sp<AGnssRil> mGnssRil = nullptr; + + GnssAPIClient* mApi = nullptr; + sp<V1_0::IGnssCallback> mGnssCbIface = nullptr; + sp<V1_0::IGnssNiCallback> mGnssNiCbIface = nullptr; + GnssConfig mPendingConfig; + const GnssInterface* mGnssInterface = nullptr; +}; + +extern "C" IGnss* HIDL_FETCH_IGnss(const char* name); + +} // namespace implementation +} // namespace V1_0 +} // namespace gnss +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_GNSS_V1_0_GNSS_H diff --git a/android/1.0/GnssBatching.cpp b/android/1.0/GnssBatching.cpp new file mode 100644 index 0000000..3e5a9f4 --- /dev/null +++ b/android/1.0/GnssBatching.cpp @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2017-2018, 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_GnssBatchingInterface" + +#include <log_util.h> +#include <BatchingAPIClient.h> +#include "GnssBatching.h" + +namespace android { +namespace hardware { +namespace gnss { +namespace V1_0 { +namespace implementation { + +void GnssBatching::GnssBatchingDeathRecipient::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 (mGnssBatching != nullptr) { + mGnssBatching->stop(); + mGnssBatching->cleanup(); + } +} + +GnssBatching::GnssBatching() : mApi(nullptr) { + mGnssBatchingDeathRecipient = new GnssBatchingDeathRecipient(this); +} + +GnssBatching::~GnssBatching() { + if (mApi != nullptr) { + delete mApi; + mApi = nullptr; + } +} + + +// Methods from ::android::hardware::gnss::V1_0::IGnssBatching follow. +Return<bool> GnssBatching::init(const sp<IGnssBatchingCallback>& callback) { + if (mApi != nullptr) { + LOC_LOGD("%s]: mApi is NOT nullptr, delete it first", __FUNCTION__); + delete mApi; + mApi = nullptr; + } + + mApi = new BatchingAPIClient(callback); + if (mApi == nullptr) { + LOC_LOGE("%s]: failed to create mApi", __FUNCTION__); + return false; + } + + if (mGnssBatchingCbIface != nullptr) { + mGnssBatchingCbIface->unlinkToDeath(mGnssBatchingDeathRecipient); + } + mGnssBatchingCbIface = callback; + if (mGnssBatchingCbIface != nullptr) { + mGnssBatchingCbIface->linkToDeath(mGnssBatchingDeathRecipient, 0 /*cookie*/); + } + + return true; +} + +Return<uint16_t> GnssBatching::getBatchSize() { + uint16_t ret = 0; + if (mApi == nullptr) { + LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__); + } else { + ret = mApi->getBatchSize(); + } + return ret; +} + +Return<bool> GnssBatching::start(const IGnssBatching::Options& options) { + bool ret = false; + if (mApi == nullptr) { + LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__); + } else { + ret = mApi->startSession(options); + } + return ret; +} + +Return<void> GnssBatching::flush() { + if (mApi == nullptr) { + LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__); + } else { + mApi->flushBatchedLocations(); + } + return Void(); +} + +Return<bool> GnssBatching::stop() { + bool ret = false; + if (mApi == nullptr) { + LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__); + } else { + ret = mApi->stopSession(); + } + return ret; +} + +Return<void> GnssBatching::cleanup() { + if (mGnssBatchingCbIface != nullptr) { + mGnssBatchingCbIface->unlinkToDeath(mGnssBatchingDeathRecipient); + } + return Void(); +} + +} // namespace implementation +} // namespace V1_0 +} // namespace gnss +} // namespace hardware +} // namespace android diff --git a/android/1.0/GnssBatching.h b/android/1.0/GnssBatching.h new file mode 100644 index 0000000..8fab857 --- /dev/null +++ b/android/1.0/GnssBatching.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2017-2018, 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. + */ + +#ifndef ANDROID_HARDWARE_GNSS_V1_0_GNSSBATCHING_H +#define ANDROID_HARDWARE_GNSS_V1_0_GNSSBATCHING_H + +#include <android/hardware/gnss/1.0/IGnssBatching.h> +#include <hidl/Status.h> + + +namespace android { +namespace hardware { +namespace gnss { +namespace V1_0 { +namespace implementation { + +using ::android::hardware::gnss::V1_0::IGnssBatching; +using ::android::hardware::gnss::V1_0::IGnssBatchingCallback; +using ::android::hidl::base::V1_0::IBase; +using ::android::hardware::hidl_array; +using ::android::hardware::hidl_memory; +using ::android::hardware::hidl_string; +using ::android::hardware::hidl_vec; +using ::android::hardware::Return; +using ::android::hardware::Void; +using ::android::sp; + +class BatchingAPIClient; +struct GnssBatching : public IGnssBatching { + GnssBatching(); + ~GnssBatching(); + + // Methods from ::android::hardware::gnss::V1_0::IGnssBatching follow. + Return<bool> init(const sp<IGnssBatchingCallback>& callback) override; + Return<uint16_t> getBatchSize() override; + Return<bool> start(const IGnssBatching::Options& options ) override; + Return<void> flush() override; + Return<bool> stop() override; + Return<void> cleanup() override; + + private: + struct GnssBatchingDeathRecipient : hidl_death_recipient { + GnssBatchingDeathRecipient(sp<GnssBatching> gnssBatching) : + mGnssBatching(gnssBatching) { + } + ~GnssBatchingDeathRecipient() = default; + virtual void serviceDied(uint64_t cookie, const wp<IBase>& who) override; + sp<GnssBatching> mGnssBatching; + }; + + private: + sp<GnssBatchingDeathRecipient> mGnssBatchingDeathRecipient = nullptr; + sp<IGnssBatchingCallback> mGnssBatchingCbIface = nullptr; + BatchingAPIClient* mApi = nullptr; +}; + +} // namespace implementation +} // namespace V1_0 +} // namespace gnss +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_GNSS_V1_0_GNSSBATCHING_H diff --git a/android/1.0/GnssConfiguration.cpp b/android/1.0/GnssConfiguration.cpp new file mode 100644 index 0000000..0b62249 --- /dev/null +++ b/android/1.0/GnssConfiguration.cpp @@ -0,0 +1,230 @@ +/* + * Copyright (c) 2017-2018, 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_GnssConfigurationInterface" + +#include <log_util.h> +#include "Gnss.h" +#include "GnssConfiguration.h" +#include <android/hardware/gnss/1.0/types.h> + +namespace android { +namespace hardware { +namespace gnss { +namespace V1_0 { +namespace implementation { + +using ::android::hardware::gnss::V1_0::GnssConstellationType; + +GnssConfiguration::GnssConfiguration(Gnss* gnss) : mGnss(gnss) { +} + +// Methods from ::android::hardware::gps::V1_0::IGnssConfiguration follow. +Return<bool> GnssConfiguration::setSuplEs(bool enabled) { + if (mGnss == nullptr) { + LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__); + return false; + } + + GnssConfig config; + memset(&config, 0, sizeof(GnssConfig)); + config.size = sizeof(GnssConfig); + config.flags = GNSS_CONFIG_FLAGS_SUPL_EM_SERVICES_BIT; + config.suplEmergencyServices = (enabled ? + GNSS_CONFIG_SUPL_EMERGENCY_SERVICES_YES : + GNSS_CONFIG_SUPL_EMERGENCY_SERVICES_NO); + + return mGnss->updateConfiguration(config); +} + +Return<bool> GnssConfiguration::setSuplVersion(uint32_t version) { + if (mGnss == nullptr) { + LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__); + return false; + } + + GnssConfig config; + memset(&config, 0, sizeof(GnssConfig)); + config.size = sizeof(GnssConfig); + config.flags = GNSS_CONFIG_FLAGS_SUPL_VERSION_VALID_BIT; + switch (version) { + case 0x00020002: + config.suplVersion = GNSS_CONFIG_SUPL_VERSION_2_0_2; + break; + case 0x00020000: + config.suplVersion = GNSS_CONFIG_SUPL_VERSION_2_0_0; + break; + case 0x00010000: + config.suplVersion = GNSS_CONFIG_SUPL_VERSION_1_0_0; + break; + default: + LOC_LOGE("%s]: invalid version: 0x%x.", __FUNCTION__, version); + return false; + break; + } + + return mGnss->updateConfiguration(config); +} + +Return<bool> GnssConfiguration::setSuplMode(uint8_t mode) { + if (mGnss == nullptr) { + LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__); + return false; + } + + GnssConfig config; + memset(&config, 0, sizeof(GnssConfig)); + config.size = sizeof(GnssConfig); + config.flags = GNSS_CONFIG_FLAGS_SUPL_MODE_BIT; + switch (mode) { + case 0: + config.suplModeMask = 0; // STANDALONE ONLY + break; + case 1: + config.suplModeMask = GNSS_CONFIG_SUPL_MODE_MSB_BIT; + break; + case 2: + config.suplModeMask = GNSS_CONFIG_SUPL_MODE_MSA_BIT; + break; + case 3: + config.suplModeMask = GNSS_CONFIG_SUPL_MODE_MSB_BIT | GNSS_CONFIG_SUPL_MODE_MSA_BIT; + break; + default: + LOC_LOGE("%s]: invalid mode: %d.", __FUNCTION__, mode); + return false; + break; + } + + return mGnss->updateConfiguration(config); +} + +Return<bool> GnssConfiguration::setLppProfile(uint8_t lppProfile) { + if (mGnss == nullptr) { + LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__); + return false; + } + + GnssConfig config; + memset(&config, 0, sizeof(GnssConfig)); + config.size = sizeof(GnssConfig); + config.flags = GNSS_CONFIG_FLAGS_LPP_PROFILE_VALID_BIT; + switch (lppProfile) { + case 0: + config.lppProfile = GNSS_CONFIG_LPP_PROFILE_RRLP_ON_LTE; + break; + case 1: + config.lppProfile = GNSS_CONFIG_LPP_PROFILE_USER_PLANE; + break; + case 2: + config.lppProfile = GNSS_CONFIG_LPP_PROFILE_CONTROL_PLANE; + break; + case 3: + config.lppProfile = GNSS_CONFIG_LPP_PROFILE_USER_PLANE_AND_CONTROL_PLANE; + break; + default: + LOC_LOGE("%s]: invalid lppProfile: %d.", __FUNCTION__, lppProfile); + return false; + break; + } + + return mGnss->updateConfiguration(config); +} + +Return<bool> GnssConfiguration::setGlonassPositioningProtocol(uint8_t protocol) { + if (mGnss == nullptr) { + LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__); + return false; + } + + GnssConfig config; + memset(&config, 0, sizeof(GnssConfig)); + config.size = sizeof(GnssConfig); + + config.flags = GNSS_CONFIG_FLAGS_AGLONASS_POSITION_PROTOCOL_VALID_BIT; + if (protocol & (1<<0)) { + config.aGlonassPositionProtocolMask |= GNSS_CONFIG_RRC_CONTROL_PLANE_BIT; + } + if (protocol & (1<<1)) { + config.aGlonassPositionProtocolMask |= GNSS_CONFIG_RRLP_USER_PLANE_BIT; + } + if (protocol & (1<<2)) { + config.aGlonassPositionProtocolMask |= GNSS_CONFIG_LLP_USER_PLANE_BIT; + } + if (protocol & (1<<3)) { + config.aGlonassPositionProtocolMask |= GNSS_CONFIG_LLP_CONTROL_PLANE_BIT; + } + + return mGnss->updateConfiguration(config); +} + +Return<bool> GnssConfiguration::setGpsLock(uint8_t lock) { + if (mGnss == nullptr) { + LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__); + return false; + } + + GnssConfig config; + memset(&config, 0, sizeof(GnssConfig)); + config.size = sizeof(GnssConfig); + config.flags = GNSS_CONFIG_FLAGS_GPS_LOCK_VALID_BIT; + switch (lock) { + case 0: + config.gpsLock = GNSS_CONFIG_GPS_LOCK_NONE; + break; + case 1: + config.gpsLock = GNSS_CONFIG_GPS_LOCK_MO; + break; + case 2: + config.gpsLock = GNSS_CONFIG_GPS_LOCK_NI; + break; + case 3: + config.gpsLock = GNSS_CONFIG_GPS_LOCK_MO_AND_NI; + break; + default: + LOC_LOGE("%s]: invalid lock: %d.", __FUNCTION__, lock); + return false; + break; + } + + return mGnss->updateConfiguration(config); +} + +Return<bool> GnssConfiguration::setEmergencySuplPdn(bool enabled) { + if (mGnss == nullptr) { + LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__); + return false; + } + + GnssConfig config; + memset(&config, 0, sizeof(GnssConfig)); + config.size = sizeof(GnssConfig); + config.flags = GNSS_CONFIG_FLAGS_EM_PDN_FOR_EM_SUPL_VALID_BIT; + config.emergencyPdnForEmergencySupl = (enabled ? + GNSS_CONFIG_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_YES : + GNSS_CONFIG_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_NO); + + return mGnss->updateConfiguration(config); +} + +} // namespace implementation +} // namespace V1_0 +} // namespace gnss +} // namespace hardware +} // namespace android diff --git a/android/1.0/GnssConfiguration.h b/android/1.0/GnssConfiguration.h new file mode 100644 index 0000000..1629e06 --- /dev/null +++ b/android/1.0/GnssConfiguration.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2017-2018, 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. + */ + + +#ifndef ANDROID_HARDWARE_GNSS_V1_0_GNSSCONFIGURATION_H +#define ANDROID_HARDWARE_GNSS_V1_0_GNSSCONFIGURATION_H + +#include <android/hardware/gnss/1.0/IGnssConfiguration.h> +#include <hidl/Status.h> + +namespace android { +namespace hardware { +namespace gnss { +namespace V1_0 { +namespace implementation { + +using ::android::hardware::gnss::V1_0::IGnssConfiguration; +using ::android::hardware::Return; +using ::android::hardware::Void; +using ::android::hardware::hidl_vec; +using ::android::hardware::hidl_string; +using ::android::sp; + +/* + * Interface for passing GNSS configuration info from platform to HAL. + */ +struct Gnss; +struct GnssConfiguration : public IGnssConfiguration { + GnssConfiguration(Gnss* gnss); + ~GnssConfiguration() = default; + + /* + * Methods from ::android::hardware::gnss::V1_0::IGnssConfiguration follow. + * These declarations were generated from IGnssConfiguration.hal. + */ + Return<bool> setSuplVersion(uint32_t version) override; + Return<bool> setSuplMode(uint8_t mode) override; + Return<bool> setSuplEs(bool enabled) override; + Return<bool> setLppProfile(uint8_t lppProfile) override; + Return<bool> setGlonassPositioningProtocol(uint8_t protocol) override; + Return<bool> setEmergencySuplPdn(bool enable) override; + Return<bool> setGpsLock(uint8_t lock) override; + + private: + Gnss* mGnss = nullptr; +}; + +} // namespace implementation +} // namespace V1_0 +} // namespace gnss +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_GNSS_V1_0_GNSSCONFIGURATION_H diff --git a/android/1.0/GnssDebug.cpp b/android/1.0/GnssDebug.cpp new file mode 100644 index 0000000..ead72e1 --- /dev/null +++ b/android/1.0/GnssDebug.cpp @@ -0,0 +1,173 @@ +/* + * 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_GnssDebugInterface" + +#include <log/log.h> +#include <log_util.h> +#include "Gnss.h" +#include "GnssDebug.h" +#include "LocationUtil.h" + +namespace android { +namespace hardware { +namespace gnss { +namespace V1_0 { +namespace implementation { + +using ::android::hardware::hidl_vec; + +#define GNSS_DEBUG_UNKNOWN_HORIZONTAL_ACCURACY_METERS (20000000) +#define GNSS_DEBUG_UNKNOWN_VERTICAL_ACCURACY_METERS (20000) +#define GNSS_DEBUG_UNKNOWN_SPEED_ACCURACY_PER_SEC (500) +#define GNSS_DEBUG_UNKNOWN_BEARING_ACCURACY_DEG (180) + +#define GNSS_DEBUG_UNKNOWN_UTC_TIME (1483228800000LL) // 1/1/2017 00:00 GMT +#define GNSS_DEBUG_UNKNOWN_UTC_TIME_UNC (1.57783680E17) // 5 years in ns +#define GNSS_DEBUG_UNKNOWN_FREQ_UNC_NS_PER_SEC (2.0e5) // ppm + +GnssDebug::GnssDebug(Gnss* gnss) : mGnss(gnss) +{ +} + +/* + * This methods requests position, time and satellite ephemeris debug information + * from the HAL. + * + * @return void +*/ +Return<void> GnssDebug::getDebugData(getDebugData_cb _hidl_cb) +{ + LOC_LOGD("%s]: ", __func__); + + DebugData data = { }; + + if((nullptr == mGnss) || (nullptr == mGnss->getGnssInterface())){ + LOC_LOGE("GnssDebug - Null GNSS interface"); + _hidl_cb(data); + return Void(); + } + + // get debug report snapshot via hal interface + GnssDebugReport reports = { }; + mGnss->getGnssInterface()->getDebugReport(reports); + + // location block + if (reports.mLocation.mValid) { + data.position.valid = true; + data.position.latitudeDegrees = reports.mLocation.mLocation.latitude; + data.position.longitudeDegrees = reports.mLocation.mLocation.longitude; + data.position.altitudeMeters = reports.mLocation.mLocation.altitude; + + data.position.speedMetersPerSec = + (double)(reports.mLocation.mLocation.speed); + data.position.bearingDegrees = + (double)(reports.mLocation.mLocation.bearing); + data.position.horizontalAccuracyMeters = + (double)(reports.mLocation.mLocation.accuracy); + data.position.verticalAccuracyMeters = + reports.mLocation.verticalAccuracyMeters; + data.position.speedAccuracyMetersPerSecond = + reports.mLocation.speedAccuracyMetersPerSecond; + data.position.bearingAccuracyDegrees = + reports.mLocation.bearingAccuracyDegrees; + + timeval tv_now, tv_report; + tv_report.tv_sec = reports.mLocation.mUtcReported.tv_sec; + tv_report.tv_usec = reports.mLocation.mUtcReported.tv_nsec / 1000ULL; + gettimeofday(&tv_now, NULL); + data.position.ageSeconds = + (tv_now.tv_sec - tv_report.tv_sec) + + (float)((tv_now.tv_usec - tv_report.tv_usec)) / 1000000; + } + else { + data.position.valid = false; + } + + if (data.position.horizontalAccuracyMeters <= 0 || + data.position.horizontalAccuracyMeters > GNSS_DEBUG_UNKNOWN_HORIZONTAL_ACCURACY_METERS) { + data.position.horizontalAccuracyMeters = GNSS_DEBUG_UNKNOWN_HORIZONTAL_ACCURACY_METERS; + } + if (data.position.verticalAccuracyMeters <= 0 || + data.position.verticalAccuracyMeters > GNSS_DEBUG_UNKNOWN_VERTICAL_ACCURACY_METERS) { + data.position.verticalAccuracyMeters = GNSS_DEBUG_UNKNOWN_VERTICAL_ACCURACY_METERS; + } + if (data.position.speedAccuracyMetersPerSecond <= 0 || + data.position.speedAccuracyMetersPerSecond > GNSS_DEBUG_UNKNOWN_SPEED_ACCURACY_PER_SEC) { + data.position.speedAccuracyMetersPerSecond = GNSS_DEBUG_UNKNOWN_SPEED_ACCURACY_PER_SEC; + } + if (data.position.bearingAccuracyDegrees <= 0 || + data.position.bearingAccuracyDegrees > GNSS_DEBUG_UNKNOWN_BEARING_ACCURACY_DEG) { + data.position.bearingAccuracyDegrees = GNSS_DEBUG_UNKNOWN_BEARING_ACCURACY_DEG; + } + + // time block + if (reports.mTime.mValid) { + data.time.timeEstimate = reports.mTime.timeEstimate; + data.time.timeUncertaintyNs = reports.mTime.timeUncertaintyNs; + data.time.frequencyUncertaintyNsPerSec = + reports.mTime.frequencyUncertaintyNsPerSec; + } + + if (data.time.timeEstimate < GNSS_DEBUG_UNKNOWN_UTC_TIME) { + data.time.timeEstimate = GNSS_DEBUG_UNKNOWN_UTC_TIME; + } + if (data.time.timeUncertaintyNs <= 0 || + data.time.timeUncertaintyNs > (float)GNSS_DEBUG_UNKNOWN_UTC_TIME_UNC) { + data.time.timeUncertaintyNs = (float)GNSS_DEBUG_UNKNOWN_UTC_TIME_UNC; + } + if (data.time.frequencyUncertaintyNsPerSec <= 0 || + data.time.frequencyUncertaintyNsPerSec > (float)GNSS_DEBUG_UNKNOWN_FREQ_UNC_NS_PER_SEC) { + data.time.frequencyUncertaintyNsPerSec = (float)GNSS_DEBUG_UNKNOWN_FREQ_UNC_NS_PER_SEC; + } + + // satellite data block + SatelliteData s = { }; + std::vector<SatelliteData> s_array = { }; + + for (uint32_t i=0; i<reports.mSatelliteInfo.size(); i++) { + memset(&s, 0, sizeof(s)); + s.svid = reports.mSatelliteInfo[i].svid; + convertGnssConstellationType( + reports.mSatelliteInfo[i].constellation, s.constellation); + convertGnssEphemerisType( + reports.mSatelliteInfo[i].mEphemerisType, s.ephemerisType); + convertGnssEphemerisSource( + reports.mSatelliteInfo[i].mEphemerisSource, s.ephemerisSource); + convertGnssEphemerisHealth( + reports.mSatelliteInfo[i].mEphemerisHealth, s.ephemerisHealth); + + s.ephemerisAgeSeconds = + reports.mSatelliteInfo[i].ephemerisAgeSeconds; + s.serverPredictionIsAvailable = + reports.mSatelliteInfo[i].serverPredictionIsAvailable; + s.serverPredictionAgeSeconds = + reports.mSatelliteInfo[i].serverPredictionAgeSeconds; + + s_array.push_back(s); + } + data.satelliteDataArray = s_array; + + // callback HIDL with collected debug data + _hidl_cb(data); + return Void(); +} + +} // namespace implementation +} // namespace V1_0 +} // namespace gnss +} // namespace hardware +} // namespace android diff --git a/android/1.0/GnssDebug.h b/android/1.0/GnssDebug.h new file mode 100644 index 0000000..a7116cb --- /dev/null +++ b/android/1.0/GnssDebug.h @@ -0,0 +1,59 @@ +/* + * 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. + */ + +#ifndef ANDROID_HARDWARE_GNSS_V1_0_GNSSDEBUG_H +#define ANDROID_HARDWARE_GNSS_V1_0_GNSSDEBUG_H + + +#include <android/hardware/gnss/1.0/IGnssDebug.h> +#include <hidl/Status.h> + +namespace android { +namespace hardware { +namespace gnss { +namespace V1_0 { +namespace implementation { + +using ::android::hardware::gnss::V1_0::IGnssDebug; +using ::android::hardware::Return; +using ::android::hardware::Void; +using ::android::hardware::hidl_vec; +using ::android::hardware::hidl_string; +using ::android::sp; + +/* Interface for GNSS Debug support. */ +struct Gnss; +struct GnssDebug : public IGnssDebug { + GnssDebug(Gnss* gnss); + ~GnssDebug() {}; + + /* + * Methods from ::android::hardware::gnss::V1_0::IGnssDebug follow. + * These declarations were generated from IGnssDebug.hal. + */ + Return<void> getDebugData(getDebugData_cb _hidl_cb) override; + +private: + Gnss* mGnss = nullptr; +}; + +} // namespace implementation +} // namespace V1_0 +} // namespace gnss +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_GNSS_V1_0_GNSSDEBUG_H diff --git a/android/1.0/GnssGeofencing.cpp b/android/1.0/GnssGeofencing.cpp new file mode 100644 index 0000000..2a8ff88 --- /dev/null +++ b/android/1.0/GnssGeofencing.cpp @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2017-2018, 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 "GnssHal_GnssGeofencing" + +#include <log_util.h> +#include <GeofenceAPIClient.h> +#include "GnssGeofencing.h" + +namespace android { +namespace hardware { +namespace gnss { +namespace V1_0 { +namespace implementation { + +void GnssGeofencing::GnssGeofencingDeathRecipient::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 (mGnssGeofencing != nullptr) { + mGnssGeofencing->removeAllGeofences(); + } +} + +GnssGeofencing::GnssGeofencing() : mApi(nullptr) { + mGnssGeofencingDeathRecipient = new GnssGeofencingDeathRecipient(this); +} + +GnssGeofencing::~GnssGeofencing() { + if (mApi != nullptr) { + delete mApi; + mApi = nullptr; + } +} + +// Methods from ::android::hardware::gnss::V1_0::IGnssGeofencing follow. +Return<void> GnssGeofencing::setCallback(const sp<IGnssGeofenceCallback>& callback) { + if (mApi != nullptr) { + LOC_LOGE("%s]: mApi is NOT nullptr", __FUNCTION__); + return Void(); + } + + mApi = new GeofenceAPIClient(callback); + if (mApi == nullptr) { + LOC_LOGE("%s]: failed to create mApi", __FUNCTION__); + } + + if (mGnssGeofencingCbIface != nullptr) { + mGnssGeofencingCbIface->unlinkToDeath(mGnssGeofencingDeathRecipient); + } + mGnssGeofencingCbIface = callback; + if (mGnssGeofencingCbIface != nullptr) { + mGnssGeofencingCbIface->linkToDeath(mGnssGeofencingDeathRecipient, 0 /*cookie*/); + } + + return Void(); +} + +Return<void> GnssGeofencing::addGeofence( + int32_t geofenceId, + double latitudeDegrees, + double longitudeDegrees, + double radiusMeters, + IGnssGeofenceCallback::GeofenceTransition lastTransition, + int32_t monitorTransitions, + uint32_t notificationResponsivenessMs, + uint32_t unknownTimerMs) { + if (mApi == nullptr) { + LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__); + } else { + mApi->geofenceAdd( + geofenceId, + latitudeDegrees, + longitudeDegrees, + radiusMeters, + static_cast<int32_t>(lastTransition), + monitorTransitions, + notificationResponsivenessMs, + unknownTimerMs); + } + return Void(); +} + +Return<void> GnssGeofencing::pauseGeofence(int32_t geofenceId) { + if (mApi == nullptr) { + LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__); + } else { + mApi->geofencePause(geofenceId); + } + return Void(); +} + +Return<void> GnssGeofencing::resumeGeofence(int32_t geofenceId, int32_t monitorTransitions) { + if (mApi == nullptr) { + LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__); + } else { + mApi->geofenceResume(geofenceId, monitorTransitions); + } + return Void(); +} + +Return<void> GnssGeofencing::removeGeofence(int32_t geofenceId) { + if (mApi == nullptr) { + LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__); + } else { + mApi->geofenceRemove(geofenceId); + } + return Void(); +} + +Return<void> GnssGeofencing::removeAllGeofences() { + if (mApi == nullptr) { + LOC_LOGD("%s]: mApi is nullptr, do nothing", __FUNCTION__); + } else { + mApi->geofenceRemoveAll(); + } + return Void(); +} + +} // namespace implementation +} // namespace V1_0 +} // namespace gnss +} // namespace hardware +} // namespace android diff --git a/android/1.0/GnssGeofencing.h b/android/1.0/GnssGeofencing.h new file mode 100644 index 0000000..db5f9d2 --- /dev/null +++ b/android/1.0/GnssGeofencing.h @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2017-2018, 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. + */ + +#ifndef ANDROID_HARDWARE_GNSS_V1_0_GNSSGEOFENCING_H +#define ANDROID_HARDWARE_GNSS_V1_0_GNSSGEOFENCING_H + +#include <android/hardware/gnss/1.0/IGnssGeofencing.h> +#include <hidl/Status.h> + +namespace android { +namespace hardware { +namespace gnss { +namespace V1_0 { +namespace implementation { + +using ::android::hardware::gnss::V1_0::IGnssGeofenceCallback; +using ::android::hardware::gnss::V1_0::IGnssGeofencing; +using ::android::hardware::Return; +using ::android::hardware::Void; +using ::android::hardware::hidl_vec; +using ::android::hardware::hidl_string; +using ::android::sp; + +class GeofenceAPIClient; +struct GnssGeofencing : public IGnssGeofencing { + GnssGeofencing(); + ~GnssGeofencing(); + + /* + * Methods from ::android::hardware::gnss::V1_0::IGnssGeofencing follow. + * These declarations were generated from IGnssGeofencing.hal. + */ + Return<void> setCallback(const sp<IGnssGeofenceCallback>& callback) override; + Return<void> addGeofence(int32_t geofenceId, + double latitudeDegrees, + double longitudeDegrees, + double radiusMeters, + IGnssGeofenceCallback::GeofenceTransition lastTransition, + int32_t monitorTransitions, + uint32_t notificationResponsivenessMs, + uint32_t unknownTimerMs) override; + + Return<void> pauseGeofence(int32_t geofenceId) override; + Return<void> resumeGeofence(int32_t geofenceId, int32_t monitorTransitions) override; + Return<void> removeGeofence(int32_t geofenceId) override; + + private: + // This method is not part of the IGnss base class. + // It is called by GnssGeofencingDeathRecipient to remove all geofences added so far. + Return<void> removeAllGeofences(); + + private: + struct GnssGeofencingDeathRecipient : hidl_death_recipient { + GnssGeofencingDeathRecipient(sp<GnssGeofencing> gnssGeofencing) : + mGnssGeofencing(gnssGeofencing) { + } + ~GnssGeofencingDeathRecipient() = default; + virtual void serviceDied(uint64_t cookie, const wp<IBase>& who) override; + sp<GnssGeofencing> mGnssGeofencing; + }; + + private: + sp<GnssGeofencingDeathRecipient> mGnssGeofencingDeathRecipient = nullptr; + sp<IGnssGeofenceCallback> mGnssGeofencingCbIface = nullptr; + GeofenceAPIClient* mApi = nullptr; +}; + +} // namespace implementation +} // namespace V1_0 +} // namespace gnss +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_GNSS_V1_0_GNSSGEOFENCING_H diff --git a/android/1.0/GnssMeasurement.cpp b/android/1.0/GnssMeasurement.cpp new file mode 100644 index 0000000..1c65bd6 --- /dev/null +++ b/android/1.0/GnssMeasurement.cpp @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2017-2018, 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_GnssMeasurementInterface" + +#include <log_util.h> +#include <MeasurementAPIClient.h> +#include "GnssMeasurement.h" + +namespace android { +namespace hardware { +namespace gnss { +namespace V1_0 { +namespace implementation { + +void GnssMeasurement::GnssMeasurementDeathRecipient::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 (mGnssMeasurement != nullptr) { + mGnssMeasurement->close(); + } +} + +GnssMeasurement::GnssMeasurement() { + mGnssMeasurementDeathRecipient = new GnssMeasurementDeathRecipient(this); + mApi = new MeasurementAPIClient(); +} + +GnssMeasurement::~GnssMeasurement() { + if (mApi) { + delete mApi; + mApi = nullptr; + } +} + +// Methods from ::android::hardware::gnss::V1_0::IGnssMeasurement follow. + +Return<IGnssMeasurement::GnssMeasurementStatus> GnssMeasurement::setCallback( + const sp<V1_0::IGnssMeasurementCallback>& callback) { + + Return<IGnssMeasurement::GnssMeasurementStatus> ret = + IGnssMeasurement::GnssMeasurementStatus::ERROR_GENERIC; + if (mGnssMeasurementCbIface != nullptr) { + LOC_LOGE("%s]: GnssMeasurementCallback is already set", __FUNCTION__); + return IGnssMeasurement::GnssMeasurementStatus::ERROR_ALREADY_INIT; + } + + if (callback == nullptr) { + LOC_LOGE("%s]: callback is nullptr", __FUNCTION__); + return ret; + } + if (mApi == nullptr) { + LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__); + return ret; + } + + mGnssMeasurementCbIface = callback; + mGnssMeasurementCbIface->linkToDeath(mGnssMeasurementDeathRecipient, 0); + + return mApi->measurementSetCallback(callback); + +} + +Return<void> GnssMeasurement::close() { + if (mApi == nullptr) { + LOC_LOGE("%s]: mApi is nullptr", __FUNCTION__); + return Void(); + } + + if (mGnssMeasurementCbIface != nullptr) { + mGnssMeasurementCbIface->unlinkToDeath(mGnssMeasurementDeathRecipient); + mGnssMeasurementCbIface = nullptr; + } + mApi->measurementClose(); + + return Void(); +} + +} // namespace implementation +} // namespace V1_0 +} // namespace gnss +} // namespace hardware +} // namespace android diff --git a/android/1.0/GnssMeasurement.h b/android/1.0/GnssMeasurement.h new file mode 100644 index 0000000..4247dbf --- /dev/null +++ b/android/1.0/GnssMeasurement.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2017-2018, 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. + */ + +#ifndef ANDROID_HARDWARE_GNSS_V1_0_GNSSMEASUREMENT_H +#define ANDROID_HARDWARE_GNSS_V1_0_GNSSMEASUREMENT_H + +#include <android/hardware/gnss/1.0/IGnssMeasurement.h> +#include <hidl/MQDescriptor.h> +#include <hidl/Status.h> + +namespace android { +namespace hardware { +namespace gnss { +namespace V1_0 { +namespace implementation { + +using ::android::hardware::gnss::V1_0::IGnssMeasurement; +using ::android::hardware::gnss::V1_0::IGnssMeasurementCallback; +using ::android::hardware::Return; +using ::android::hardware::Void; +using ::android::hardware::hidl_vec; +using ::android::hardware::hidl_string; +using ::android::sp; + +class MeasurementAPIClient; +struct GnssMeasurement : public IGnssMeasurement { + GnssMeasurement(); + ~GnssMeasurement(); + + /* + * Methods from ::android::hardware::gnss::V1_0::IGnssMeasurement follow. + * These declarations were generated from IGnssMeasurement.hal. + */ + Return<GnssMeasurement::GnssMeasurementStatus> setCallback( + const sp<V1_0::IGnssMeasurementCallback>& callback) override; + Return<void> close() override; + + private: + struct GnssMeasurementDeathRecipient : hidl_death_recipient { + GnssMeasurementDeathRecipient(sp<GnssMeasurement> gnssMeasurement) : + mGnssMeasurement(gnssMeasurement) { + } + ~GnssMeasurementDeathRecipient() = default; + virtual void serviceDied(uint64_t cookie, const wp<IBase>& who) override; + sp<GnssMeasurement> mGnssMeasurement; + }; + + private: + sp<GnssMeasurementDeathRecipient> mGnssMeasurementDeathRecipient = nullptr; + sp<V1_0::IGnssMeasurementCallback> mGnssMeasurementCbIface = nullptr; + MeasurementAPIClient* mApi; +}; + +} // namespace implementation +} // namespace V1_0 +} // namespace gnss +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_GNSS_V1_0_GNSSMEASUREMENT_H diff --git a/android/1.0/GnssNi.cpp b/android/1.0/GnssNi.cpp new file mode 100644 index 0000000..d06cc20 --- /dev/null +++ b/android/1.0/GnssNi.cpp @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2017-2018, 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_GnssNiInterface" + +#include <log_util.h> +#include "Gnss.h" +#include "GnssNi.h" + +namespace android { +namespace hardware { +namespace gnss { +namespace V1_0 { +namespace implementation { + +void GnssNi::GnssNiDeathRecipient::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); + // we do nothing here + // Gnss::GnssDeathRecipient will stop the session +} + +GnssNi::GnssNi(Gnss* gnss) : mGnss(gnss) { + mGnssNiDeathRecipient = new GnssNiDeathRecipient(this); +} + +// Methods from ::android::hardware::gnss::V1_0::IGnssNi follow. +Return<void> GnssNi::setCallback(const sp<IGnssNiCallback>& callback) { + if (mGnss == nullptr) { + LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__); + return Void(); + } + + mGnss->setGnssNiCb(callback); + + if (mGnssNiCbIface != nullptr) { + mGnssNiCbIface->unlinkToDeath(mGnssNiDeathRecipient); + } + mGnssNiCbIface = callback; + if (mGnssNiCbIface != nullptr) { + mGnssNiCbIface->linkToDeath(mGnssNiDeathRecipient, 0 /*cookie*/); + } + + return Void(); +} + +Return<void> GnssNi::respond(int32_t notifId, IGnssNiCallback::GnssUserResponseType userResponse) { + if (mGnss == nullptr) { + LOC_LOGE("%s]: mGnss is nullptr", __FUNCTION__); + return Void(); + } + + GnssAPIClient* api = mGnss->getApi(); + if (api == nullptr) { + LOC_LOGE("%s]: api is nullptr", __FUNCTION__); + return Void(); + } + + api->gnssNiRespond(notifId, userResponse); + + return Void(); +} + +} // namespace implementation +} // namespace V1_0 +} // namespace gnss +} // namespace hardware +} // namespace android diff --git a/android/1.0/GnssNi.h b/android/1.0/GnssNi.h new file mode 100644 index 0000000..90f62d5 --- /dev/null +++ b/android/1.0/GnssNi.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2017-2018, 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. + */ + +#ifndef ANDROID_HARDWARE_GNSS_V1_0_GNSSNI_H +#define ANDROID_HARDWARE_GNSS_V1_0_GNSSNI_H + +#include <android/hardware/gnss/1.0/IGnssNi.h> +#include <hidl/Status.h> + +namespace android { +namespace hardware { +namespace gnss { +namespace V1_0 { +namespace implementation { + +using ::android::hardware::gnss::V1_0::IGnssNi; +using ::android::hardware::gnss::V1_0::IGnssNiCallback; +using ::android::hardware::Return; +using ::android::hardware::Void; +using ::android::hardware::hidl_vec; +using ::android::hardware::hidl_string; +using ::android::sp; + +struct Gnss; +struct GnssNi : public IGnssNi { + GnssNi(Gnss* gnss); + ~GnssNi() = default; + + /* + * Methods from ::android::hardware::gnss::V1_0::IGnssNi follow. + * These declarations were generated from IGnssNi.hal. + */ + Return<void> setCallback(const sp<IGnssNiCallback>& callback) override; + Return<void> respond(int32_t notifId, + IGnssNiCallback::GnssUserResponseType userResponse) override; + + private: + struct GnssNiDeathRecipient : hidl_death_recipient { + GnssNiDeathRecipient(sp<GnssNi> gnssNi) : mGnssNi(gnssNi) { + } + ~GnssNiDeathRecipient() = default; + virtual void serviceDied(uint64_t cookie, const wp<IBase>& who) override; + sp<GnssNi> mGnssNi; + }; + + private: + sp<GnssNiDeathRecipient> mGnssNiDeathRecipient = nullptr; + sp<IGnssNiCallback> mGnssNiCbIface = nullptr; + Gnss* mGnss = nullptr; +}; + +} // namespace implementation +} // namespace V1_0 +} // namespace gnss +} // namespace hardware +} // namespace android + +#endif // ANDROID_HARDWARE_GNSS_V1_0_GNSSNI_H diff --git a/android/1.0/android.hardware.gnss@1.0-service-qti.rc b/android/1.0/android.hardware.gnss@1.0-service-qti.rc new file mode 100644 index 0000000..1fbd893 --- /dev/null +++ b/android/1.0/android.hardware.gnss@1.0-service-qti.rc @@ -0,0 +1,4 @@ +service gnss_service /vendor/bin/hw/android.hardware.gnss@1.0-service-qti + class hal + user gps + group system gps radio vendor_qti_diag diff --git a/android/1.0/android.hardware.gnss@1.0-service-qti.xml b/android/1.0/android.hardware.gnss@1.0-service-qti.xml new file mode 100644 index 0000000..46bcffb --- /dev/null +++ b/android/1.0/android.hardware.gnss@1.0-service-qti.xml @@ -0,0 +1,35 @@ +<!-- Copyright (c) 2019, The Linux Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of The Linux Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--> +<manifest version="1.0" type="device"> + <hal format="hidl"> + <name>android.hardware.gnss</name> + <transport>hwbinder</transport> + <fqname>@1.0::IGnss/default</fqname> + </hal> +</manifest> + diff --git a/android/1.0/location_api/BatchingAPIClient.cpp b/android/1.0/location_api/BatchingAPIClient.cpp new file mode 100644 index 0000000..264ab83 --- /dev/null +++ b/android/1.0/location_api/BatchingAPIClient.cpp @@ -0,0 +1,196 @@ +/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#define LOG_NDEBUG 0 +#define LOG_TAG "LocSvc_BatchingAPIClient" + +#include <log_util.h> +#include <loc_cfg.h> + +#include "LocationUtil.h" +#include "BatchingAPIClient.h" + +#include "limits.h" + + +namespace android { +namespace hardware { +namespace gnss { +namespace V1_0 { +namespace implementation { + +using ::android::hardware::gnss::V1_0::IGnssBatching; +using ::android::hardware::gnss::V1_0::IGnssBatchingCallback; +using ::android::hardware::gnss::V1_0::GnssLocation; + +static void convertBatchOption(const IGnssBatching::Options& in, LocationOptions& out, + LocationCapabilitiesMask mask); + +BatchingAPIClient::BatchingAPIClient(const sp<IGnssBatchingCallback>& callback) : + LocationAPIClientBase(), + mGnssBatchingCbIface(callback), + mDefaultId(UINT_MAX), + mLocationCapabilitiesMask(0) +{ + LOC_LOGD("%s]: (%p)", __FUNCTION__, &callback); + + LocationCallbacks locationCallbacks; + memset(&locationCallbacks, 0, sizeof(LocationCallbacks)); + locationCallbacks.size = sizeof(LocationCallbacks); + + locationCallbacks.trackingCb = nullptr; + locationCallbacks.batchingCb = nullptr; + if (mGnssBatchingCbIface != nullptr) { + locationCallbacks.batchingCb = [this](size_t count, Location* location, + BatchingOptions batchOptions) { + onBatchingCb(count, location, batchOptions); + }; + } + locationCallbacks.geofenceBreachCb = nullptr; + locationCallbacks.geofenceStatusCb = nullptr; + locationCallbacks.gnssLocationInfoCb = nullptr; + locationCallbacks.gnssNiCb = nullptr; + locationCallbacks.gnssSvCb = nullptr; + locationCallbacks.gnssNmeaCb = nullptr; + locationCallbacks.gnssMeasurementsCb = nullptr; + + locAPISetCallbacks(locationCallbacks); +} + +BatchingAPIClient::~BatchingAPIClient() +{ + LOC_LOGD("%s]: ()", __FUNCTION__); +} + +int BatchingAPIClient::getBatchSize() +{ + LOC_LOGD("%s]: ()", __FUNCTION__); + return locAPIGetBatchSize(); +} + +int BatchingAPIClient::startSession(const IGnssBatching::Options& opts) +{ + LOC_LOGD("%s]: (%lld %d)", __FUNCTION__, + static_cast<long long>(opts.periodNanos), static_cast<uint8_t>(opts.flags)); + int retVal = -1; + LocationOptions options; + convertBatchOption(opts, options, mLocationCapabilitiesMask); + uint32_t mode = 0; + if (opts.flags == static_cast<uint8_t>(IGnssBatching::Flag::WAKEUP_ON_FIFO_FULL)) { + mode = SESSION_MODE_ON_FULL; + } + if (locAPIStartSession(mDefaultId, mode, options) == LOCATION_ERROR_SUCCESS) { + retVal = 1; + } + return retVal; +} + +int BatchingAPIClient::updateSessionOptions(const IGnssBatching::Options& opts) +{ + LOC_LOGD("%s]: (%lld %d)", __FUNCTION__, + static_cast<long long>(opts.periodNanos), static_cast<uint8_t>(opts.flags)); + int retVal = -1; + LocationOptions options; + convertBatchOption(opts, options, mLocationCapabilitiesMask); + + uint32_t mode = 0; + if (opts.flags == static_cast<uint8_t>(IGnssBatching::Flag::WAKEUP_ON_FIFO_FULL)) { + mode = SESSION_MODE_ON_FULL; + } + if (locAPIUpdateSessionOptions(mDefaultId, mode, options) == LOCATION_ERROR_SUCCESS) { + retVal = 1; + } + return retVal; +} + +int BatchingAPIClient::stopSession() +{ + LOC_LOGD("%s]: ", __FUNCTION__); + int retVal = -1; + if (locAPIStopSession(mDefaultId) == LOCATION_ERROR_SUCCESS) { + retVal = 1; + } + return retVal; +} + +void BatchingAPIClient::getBatchedLocation(int last_n_locations) +{ + LOC_LOGD("%s]: (%d)", __FUNCTION__, last_n_locations); + locAPIGetBatchedLocations(mDefaultId, last_n_locations); +} + +void BatchingAPIClient::flushBatchedLocations() +{ + LOC_LOGD("%s]: ()", __FUNCTION__); + locAPIGetBatchedLocations(mDefaultId, SIZE_MAX); +} + +void BatchingAPIClient::onCapabilitiesCb(LocationCapabilitiesMask capabilitiesMask) +{ + LOC_LOGD("%s]: (%02x)", __FUNCTION__, capabilitiesMask); + mLocationCapabilitiesMask = capabilitiesMask; +} + +void BatchingAPIClient::onBatchingCb(size_t count, Location* location, + BatchingOptions /*batchOptions*/) +{ + LOC_LOGD("%s]: (count: %zu)", __FUNCTION__, count); + if (mGnssBatchingCbIface != nullptr && count > 0) { + hidl_vec<GnssLocation> locationVec; + locationVec.resize(count); + for (size_t i = 0; i < count; i++) { + convertGnssLocation(location[i], locationVec[i]); + } + auto r = mGnssBatchingCbIface->gnssLocationBatchCb(locationVec); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssLocationBatchCb description=%s", + __func__, r.description().c_str()); + } + } +} + +static void convertBatchOption(const IGnssBatching::Options& in, LocationOptions& out, + LocationCapabilitiesMask mask) +{ + memset(&out, 0, sizeof(LocationOptions)); + out.size = sizeof(LocationOptions); + out.minInterval = (uint32_t)(in.periodNanos / 1000000L); + out.minDistance = 0; + out.mode = GNSS_SUPL_MODE_STANDALONE; + if (mask & LOCATION_CAPABILITIES_GNSS_MSA_BIT) + out.mode = GNSS_SUPL_MODE_MSA; + if (mask & LOCATION_CAPABILITIES_GNSS_MSB_BIT) + out.mode = GNSS_SUPL_MODE_MSB; +} + +} // namespace implementation +} // namespace V1_0 +} // namespace gnss +} // namespace hardware +} // namespace android diff --git a/android/1.0/location_api/BatchingAPIClient.h b/android/1.0/location_api/BatchingAPIClient.h new file mode 100644 index 0000000..5d64df3 --- /dev/null +++ b/android/1.0/location_api/BatchingAPIClient.h @@ -0,0 +1,74 @@ +/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef BATCHING_API_CLINET_H +#define BATCHING_API_CLINET_H + +#include <android/hardware/gnss/1.0/IGnssBatching.h> +#include <android/hardware/gnss/1.0/IGnssBatchingCallback.h> +#include <pthread.h> + +#include <LocationAPIClientBase.h> + +namespace android { +namespace hardware { +namespace gnss { +namespace V1_0 { +namespace implementation { + +class BatchingAPIClient : public LocationAPIClientBase +{ +public: + BatchingAPIClient(const sp<V1_0::IGnssBatchingCallback>& callback); + ~BatchingAPIClient(); + int getBatchSize(); + int startSession(const V1_0::IGnssBatching::Options& options); + int updateSessionOptions(const V1_0::IGnssBatching::Options& options); + int stopSession(); + void getBatchedLocation(int last_n_locations); + void flushBatchedLocations(); + + inline LocationCapabilitiesMask getCapabilities() { return mLocationCapabilitiesMask; } + + // callbacks + void onCapabilitiesCb(LocationCapabilitiesMask capabilitiesMask) final; + void onBatchingCb(size_t count, Location* location, BatchingOptions batchOptions) final; + +private: + sp<V1_0::IGnssBatchingCallback> mGnssBatchingCbIface; + uint32_t mDefaultId; + LocationCapabilitiesMask mLocationCapabilitiesMask; +}; + +} // namespace implementation +} // namespace V1_0 +} // namespace gnss +} // namespace hardware +} // namespace android +#endif // BATCHING_API_CLINET_H diff --git a/android/1.0/location_api/GeofenceAPIClient.cpp b/android/1.0/location_api/GeofenceAPIClient.cpp new file mode 100644 index 0000000..774a049 --- /dev/null +++ b/android/1.0/location_api/GeofenceAPIClient.cpp @@ -0,0 +1,275 @@ +/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#define LOG_NDEBUG 0 +#define LOG_TAG "LocSvc_GeofenceApiClient" + +#include <log_util.h> +#include <loc_cfg.h> + +#include "LocationUtil.h" +#include "GeofenceAPIClient.h" + +namespace android { +namespace hardware { +namespace gnss { +namespace V1_0 { +namespace implementation { + +using ::android::hardware::gnss::V1_0::IGnssGeofenceCallback; +using ::android::hardware::gnss::V1_0::GnssLocation; + +GeofenceAPIClient::GeofenceAPIClient(const sp<IGnssGeofenceCallback>& callback) : + LocationAPIClientBase(), + mGnssGeofencingCbIface(callback) +{ + LOC_LOGD("%s]: (%p)", __FUNCTION__, &callback); + + LocationCallbacks locationCallbacks; + memset(&locationCallbacks, 0, sizeof(LocationCallbacks)); + locationCallbacks.size = sizeof(LocationCallbacks); + + locationCallbacks.trackingCb = nullptr; + locationCallbacks.batchingCb = nullptr; + + locationCallbacks.geofenceBreachCb = nullptr; + if (mGnssGeofencingCbIface != nullptr) { + locationCallbacks.geofenceBreachCb = + [this](GeofenceBreachNotification geofenceBreachNotification) { + onGeofenceBreachCb(geofenceBreachNotification); + }; + + locationCallbacks.geofenceStatusCb = + [this](GeofenceStatusNotification geofenceStatusNotification) { + onGeofenceStatusCb(geofenceStatusNotification); + }; + } + + locationCallbacks.gnssLocationInfoCb = nullptr; + locationCallbacks.gnssNiCb = nullptr; + locationCallbacks.gnssSvCb = nullptr; + locationCallbacks.gnssNmeaCb = nullptr; + locationCallbacks.gnssMeasurementsCb = nullptr; + + locAPISetCallbacks(locationCallbacks); +} + +void GeofenceAPIClient::geofenceAdd(uint32_t geofence_id, double latitude, double longitude, + double radius_meters, int32_t last_transition, int32_t monitor_transitions, + uint32_t notification_responsiveness_ms, uint32_t unknown_timer_ms) +{ + LOC_LOGD("%s]: (%d %f %f %f %d %d %d %d)", __FUNCTION__, + geofence_id, latitude, longitude, radius_meters, + last_transition, monitor_transitions, notification_responsiveness_ms, unknown_timer_ms); + + GeofenceOption options; + memset(&options, 0, sizeof(GeofenceOption)); + options.size = sizeof(GeofenceOption); + if (monitor_transitions & IGnssGeofenceCallback::GeofenceTransition::ENTERED) + options.breachTypeMask |= GEOFENCE_BREACH_ENTER_BIT; + if (monitor_transitions & IGnssGeofenceCallback::GeofenceTransition::EXITED) + options.breachTypeMask |= GEOFENCE_BREACH_EXIT_BIT; + options.responsiveness = notification_responsiveness_ms; + + GeofenceInfo data; + data.size = sizeof(GeofenceInfo); + data.latitude = latitude; + data.longitude = longitude; + data.radius = radius_meters; + + LocationError err = (LocationError)locAPIAddGeofences(1, &geofence_id, &options, &data); + if (LOCATION_ERROR_SUCCESS != err) { + onAddGeofencesCb(1, &err, &geofence_id); + } +} + +void GeofenceAPIClient::geofencePause(uint32_t geofence_id) +{ + LOC_LOGD("%s]: (%d)", __FUNCTION__, geofence_id); + locAPIPauseGeofences(1, &geofence_id); +} + +void GeofenceAPIClient::geofenceResume(uint32_t geofence_id, int32_t monitor_transitions) +{ + LOC_LOGD("%s]: (%d %d)", __FUNCTION__, geofence_id, monitor_transitions); + GeofenceBreachTypeMask mask = 0; + if (monitor_transitions & IGnssGeofenceCallback::GeofenceTransition::ENTERED) + mask |= GEOFENCE_BREACH_ENTER_BIT; + if (monitor_transitions & IGnssGeofenceCallback::GeofenceTransition::EXITED) + mask |= GEOFENCE_BREACH_EXIT_BIT; + locAPIResumeGeofences(1, &geofence_id, &mask); +} + +void GeofenceAPIClient::geofenceRemove(uint32_t geofence_id) +{ + LOC_LOGD("%s]: (%d)", __FUNCTION__, geofence_id); + locAPIRemoveGeofences(1, &geofence_id); +} + +void GeofenceAPIClient::geofenceRemoveAll() +{ + LOC_LOGD("%s]", __FUNCTION__); + // TODO locAPIRemoveAllGeofences(); +} + +// callbacks +void GeofenceAPIClient::onGeofenceBreachCb(GeofenceBreachNotification geofenceBreachNotification) +{ + LOC_LOGD("%s]: (%zu)", __FUNCTION__, geofenceBreachNotification.count); + if (mGnssGeofencingCbIface != nullptr) { + for (size_t i = 0; i < geofenceBreachNotification.count; i++) { + GnssLocation gnssLocation; + convertGnssLocation(geofenceBreachNotification.location, gnssLocation); + + IGnssGeofenceCallback::GeofenceTransition transition; + if (geofenceBreachNotification.type == GEOFENCE_BREACH_ENTER) + transition = IGnssGeofenceCallback::GeofenceTransition::ENTERED; + else if (geofenceBreachNotification.type == GEOFENCE_BREACH_EXIT) + transition = IGnssGeofenceCallback::GeofenceTransition::EXITED; + else { + // continue with other breach if transition is + // nether GPS_GEOFENCE_ENTERED nor GPS_GEOFENCE_EXITED + continue; + } + + auto r = mGnssGeofencingCbIface->gnssGeofenceTransitionCb( + geofenceBreachNotification.ids[i], gnssLocation, transition, + static_cast<V1_0::GnssUtcTime>(geofenceBreachNotification.timestamp)); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssGeofenceTransitionCb description=%s", + __func__, r.description().c_str()); + } + } + } +} + +void GeofenceAPIClient::onGeofenceStatusCb(GeofenceStatusNotification geofenceStatusNotification) +{ + LOC_LOGD("%s]: (%d)", __FUNCTION__, geofenceStatusNotification.available); + if (mGnssGeofencingCbIface != nullptr) { + IGnssGeofenceCallback::GeofenceAvailability status = + IGnssGeofenceCallback::GeofenceAvailability::UNAVAILABLE; + if (geofenceStatusNotification.available == GEOFENCE_STATUS_AVAILABILE_YES) { + status = IGnssGeofenceCallback::GeofenceAvailability::AVAILABLE; + } + GnssLocation gnssLocation; + memset(&gnssLocation, 0, sizeof(GnssLocation)); + auto r = mGnssGeofencingCbIface->gnssGeofenceStatusCb(status, gnssLocation); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssGeofenceStatusCb description=%s", + __func__, r.description().c_str()); + } + } +} + +void GeofenceAPIClient::onAddGeofencesCb(size_t count, LocationError* errors, uint32_t* ids) +{ + LOC_LOGD("%s]: (%zu)", __FUNCTION__, count); + if (mGnssGeofencingCbIface != nullptr) { + for (size_t i = 0; i < count; i++) { + IGnssGeofenceCallback::GeofenceStatus status = + IGnssGeofenceCallback::GeofenceStatus::ERROR_GENERIC; + if (errors[i] == LOCATION_ERROR_SUCCESS) + status = IGnssGeofenceCallback::GeofenceStatus::OPERATION_SUCCESS; + else if (errors[i] == LOCATION_ERROR_ID_EXISTS) + status = IGnssGeofenceCallback::GeofenceStatus::ERROR_ID_EXISTS; + auto r = mGnssGeofencingCbIface->gnssGeofenceAddCb(ids[i], status); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssGeofenceAddCb description=%s", + __func__, r.description().c_str()); + } + } + } +} + +void GeofenceAPIClient::onRemoveGeofencesCb(size_t count, LocationError* errors, uint32_t* ids) +{ + LOC_LOGD("%s]: (%zu)", __FUNCTION__, count); + if (mGnssGeofencingCbIface != nullptr) { + for (size_t i = 0; i < count; i++) { + IGnssGeofenceCallback::GeofenceStatus status = + IGnssGeofenceCallback::GeofenceStatus::ERROR_GENERIC; + if (errors[i] == LOCATION_ERROR_SUCCESS) + status = IGnssGeofenceCallback::GeofenceStatus::OPERATION_SUCCESS; + else if (errors[i] == LOCATION_ERROR_ID_UNKNOWN) + status = IGnssGeofenceCallback::GeofenceStatus::ERROR_ID_UNKNOWN; + auto r = mGnssGeofencingCbIface->gnssGeofenceRemoveCb(ids[i], status); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssGeofenceRemoveCb description=%s", + __func__, r.description().c_str()); + } + } + } +} + +void GeofenceAPIClient::onPauseGeofencesCb(size_t count, LocationError* errors, uint32_t* ids) +{ + LOC_LOGD("%s]: (%zu)", __FUNCTION__, count); + if (mGnssGeofencingCbIface != nullptr) { + for (size_t i = 0; i < count; i++) { + IGnssGeofenceCallback::GeofenceStatus status = + IGnssGeofenceCallback::GeofenceStatus::ERROR_GENERIC; + if (errors[i] == LOCATION_ERROR_SUCCESS) + status = IGnssGeofenceCallback::GeofenceStatus::OPERATION_SUCCESS; + else if (errors[i] == LOCATION_ERROR_ID_UNKNOWN) + status = IGnssGeofenceCallback::GeofenceStatus::ERROR_ID_UNKNOWN; + auto r = mGnssGeofencingCbIface->gnssGeofencePauseCb(ids[i], status); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssGeofencePauseCb description=%s", + __func__, r.description().c_str()); + } + } + } +} + +void GeofenceAPIClient::onResumeGeofencesCb(size_t count, LocationError* errors, uint32_t* ids) +{ + LOC_LOGD("%s]: (%zu)", __FUNCTION__, count); + if (mGnssGeofencingCbIface != nullptr) { + for (size_t i = 0; i < count; i++) { + IGnssGeofenceCallback::GeofenceStatus status = + IGnssGeofenceCallback::GeofenceStatus::ERROR_GENERIC; + if (errors[i] == LOCATION_ERROR_SUCCESS) + status = IGnssGeofenceCallback::GeofenceStatus::OPERATION_SUCCESS; + else if (errors[i] == LOCATION_ERROR_ID_UNKNOWN) + status = IGnssGeofenceCallback::GeofenceStatus::ERROR_ID_UNKNOWN; + auto r = mGnssGeofencingCbIface->gnssGeofenceResumeCb(ids[i], status); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssGeofenceResumeCb description=%s", + __func__, r.description().c_str()); + } + } + } +} + +} // namespace implementation +} // namespace V1_0 +} // namespace gnss +} // namespace hardware +} // namespace android diff --git a/android/1.0/location_api/GeofenceAPIClient.h b/android/1.0/location_api/GeofenceAPIClient.h new file mode 100644 index 0000000..dc99ddd --- /dev/null +++ b/android/1.0/location_api/GeofenceAPIClient.h @@ -0,0 +1,76 @@ +/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef GEOFENCE_API_CLINET_H +#define GEOFENCE_API_CLINET_H + + +#include <android/hardware/gnss/1.0/IGnssGeofenceCallback.h> +#include <LocationAPIClientBase.h> + +namespace android { +namespace hardware { +namespace gnss { +namespace V1_0 { +namespace implementation { + +using ::android::sp; + +class GeofenceAPIClient : public LocationAPIClientBase +{ +public: + GeofenceAPIClient(const sp<V1_0::IGnssGeofenceCallback>& callback); + virtual ~GeofenceAPIClient() = default; + + void geofenceAdd(uint32_t geofence_id, double latitude, double longitude, + double radius_meters, int32_t last_transition, int32_t monitor_transitions, + uint32_t notification_responsiveness_ms, uint32_t unknown_timer_ms); + void geofencePause(uint32_t geofence_id); + void geofenceResume(uint32_t geofence_id, int32_t monitor_transitions); + void geofenceRemove(uint32_t geofence_id); + void geofenceRemoveAll(); + + // callbacks + void onGeofenceBreachCb(GeofenceBreachNotification geofenceBreachNotification) final; + void onGeofenceStatusCb(GeofenceStatusNotification geofenceStatusNotification) final; + void onAddGeofencesCb(size_t count, LocationError* errors, uint32_t* ids) final; + void onRemoveGeofencesCb(size_t count, LocationError* errors, uint32_t* ids) final; + void onPauseGeofencesCb(size_t count, LocationError* errors, uint32_t* ids) final; + void onResumeGeofencesCb(size_t count, LocationError* errors, uint32_t* ids) final; + +private: + sp<V1_0::IGnssGeofenceCallback> mGnssGeofencingCbIface; +}; + +} // namespace implementation +} // namespace V1_0 +} // namespace gnss +} // namespace hardware +} // namespace android +#endif // GEOFENCE_API_CLINET_H diff --git a/android/1.0/location_api/GnssAPIClient.cpp b/android/1.0/location_api/GnssAPIClient.cpp new file mode 100644 index 0000000..b9fe2b2 --- /dev/null +++ b/android/1.0/location_api/GnssAPIClient.cpp @@ -0,0 +1,566 @@ +/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#define LOG_NDEBUG 0 +#define LOG_TAG "LocSvc_GnssAPIClient" +#define SINGLE_SHOT_MIN_TRACKING_INTERVAL_MSEC (590 * 60 * 60 * 1000) // 590 hours + +#include <log_util.h> +#include <loc_cfg.h> + +#include "LocationUtil.h" +#include "GnssAPIClient.h" +#include <LocContext.h> + +namespace android { +namespace hardware { +namespace gnss { +namespace V1_0 { +namespace implementation { + +using ::android::hardware::gnss::V1_0::IGnss; +using ::android::hardware::gnss::V1_0::IGnssCallback; +using ::android::hardware::gnss::V1_0::IGnssNiCallback; +using ::android::hardware::gnss::V1_0::GnssLocation; + +static void convertGnssSvStatus(GnssSvNotification& in, IGnssCallback::GnssSvStatus& out); + +GnssAPIClient::GnssAPIClient(const sp<IGnssCallback>& gpsCb, + const sp<IGnssNiCallback>& niCb) : + LocationAPIClientBase(), + mGnssCbIface(nullptr), + mGnssNiCbIface(nullptr), + mControlClient(new LocationAPIControlClient()), + mLocationCapabilitiesMask(0), + mLocationCapabilitiesCached(false) +{ + LOC_LOGD("%s]: (%p %p)", __FUNCTION__, &gpsCb, &niCb); + + // set default LocationOptions. + memset(&mTrackingOptions, 0, sizeof(TrackingOptions)); + mTrackingOptions.size = sizeof(TrackingOptions); + mTrackingOptions.minInterval = 1000; + mTrackingOptions.minDistance = 0; + mTrackingOptions.mode = GNSS_SUPL_MODE_STANDALONE; + + gnssUpdateCallbacks(gpsCb, niCb); +} + +GnssAPIClient::~GnssAPIClient() +{ + LOC_LOGD("%s]: ()", __FUNCTION__); + if (mControlClient) { + delete mControlClient; + mControlClient = nullptr; + } +} + +// for GpsInterface +void GnssAPIClient::gnssUpdateCallbacks(const sp<IGnssCallback>& gpsCb, + const sp<IGnssNiCallback>& niCb) +{ + LOC_LOGD("%s]: (%p %p)", __FUNCTION__, &gpsCb, &niCb); + + mMutex.lock(); + mGnssCbIface = gpsCb; + mGnssNiCbIface = niCb; + mMutex.unlock(); + + LocationCallbacks locationCallbacks; + memset(&locationCallbacks, 0, sizeof(LocationCallbacks)); + locationCallbacks.size = sizeof(LocationCallbacks); + + locationCallbacks.trackingCb = nullptr; + if (mGnssCbIface != nullptr) { + locationCallbacks.trackingCb = [this](Location location) { + onTrackingCb(location); + }; + } + + locationCallbacks.batchingCb = nullptr; + locationCallbacks.geofenceBreachCb = nullptr; + locationCallbacks.geofenceStatusCb = nullptr; + locationCallbacks.gnssLocationInfoCb = nullptr; + + locationCallbacks.gnssNiCb = nullptr; + loc_core::ContextBase* context = + loc_core::LocContext::getLocContext( + NULL, NULL, + loc_core::LocContext::mLocationHalName, false); + if (mGnssNiCbIface != nullptr && !context->hasAgpsExtendedCapabilities()) { + LOC_LOGD("Registering NI CB"); + locationCallbacks.gnssNiCb = [this](uint32_t id, GnssNiNotification gnssNiNotification) { + onGnssNiCb(id, gnssNiNotification); + }; + } + + locationCallbacks.gnssSvCb = nullptr; + if (mGnssCbIface != nullptr) { + locationCallbacks.gnssSvCb = [this](GnssSvNotification gnssSvNotification) { + onGnssSvCb(gnssSvNotification); + }; + } + + locationCallbacks.gnssNmeaCb = nullptr; + if (mGnssCbIface != nullptr) { + locationCallbacks.gnssNmeaCb = [this](GnssNmeaNotification gnssNmeaNotification) { + onGnssNmeaCb(gnssNmeaNotification); + }; + } + + locationCallbacks.gnssMeasurementsCb = nullptr; + + locAPISetCallbacks(locationCallbacks); +} + +bool GnssAPIClient::gnssStart() +{ + LOC_LOGD("%s]: ()", __FUNCTION__); + bool retVal = true; + locAPIStartTracking(mTrackingOptions); + return retVal; +} + +bool GnssAPIClient::gnssStop() +{ + LOC_LOGD("%s]: ()", __FUNCTION__); + bool retVal = true; + locAPIStopTracking(); + return retVal; +} + +bool GnssAPIClient::gnssSetPositionMode(IGnss::GnssPositionMode mode, + IGnss::GnssPositionRecurrence recurrence, uint32_t minIntervalMs, + uint32_t preferredAccuracyMeters, uint32_t preferredTimeMs, + GnssPowerMode powerMode, uint32_t timeBetweenMeasurement) +{ + LOC_LOGD("%s]: (%d %d %d %d %d %d %d)", __FUNCTION__, + (int)mode, recurrence, minIntervalMs, preferredAccuracyMeters, + preferredTimeMs, (int)powerMode, timeBetweenMeasurement); + bool retVal = true; + memset(&mTrackingOptions, 0, sizeof(TrackingOptions)); + mTrackingOptions.size = sizeof(TrackingOptions); + mTrackingOptions.minInterval = minIntervalMs; + if (IGnss::GnssPositionMode::MS_ASSISTED == mode || + IGnss::GnssPositionRecurrence::RECURRENCE_SINGLE == recurrence) { + // We set a very large interval to simulate SINGLE mode. Once we report a fix, + // the caller should take the responsibility to stop the session. + // For MSA, we always treat it as SINGLE mode. + mTrackingOptions.minInterval = SINGLE_SHOT_MIN_TRACKING_INTERVAL_MSEC; + } + mTrackingOptions.minDistance = preferredAccuracyMeters; + if (mode == IGnss::GnssPositionMode::STANDALONE) + mTrackingOptions.mode = GNSS_SUPL_MODE_STANDALONE; + else if (mode == IGnss::GnssPositionMode::MS_BASED) + mTrackingOptions.mode = GNSS_SUPL_MODE_MSB; + else if (mode == IGnss::GnssPositionMode::MS_ASSISTED) + mTrackingOptions.mode = GNSS_SUPL_MODE_MSA; + else { + LOC_LOGD("%s]: invalid GnssPositionMode: %d", __FUNCTION__, (int)mode); + retVal = false; + } + if (GNSS_POWER_MODE_INVALID != powerMode) { + mTrackingOptions.powerMode = powerMode; + mTrackingOptions.tbm = timeBetweenMeasurement; + } + locAPIUpdateTrackingOptions(mTrackingOptions); + return retVal; +} + +// for GpsNiInterface +void GnssAPIClient::gnssNiRespond(int32_t notifId, + IGnssNiCallback::GnssUserResponseType userResponse) +{ + LOC_LOGD("%s]: (%d %d)", __FUNCTION__, notifId, static_cast<int>(userResponse)); + GnssNiResponse data; + switch (userResponse) { + case IGnssNiCallback::GnssUserResponseType::RESPONSE_ACCEPT: + data = GNSS_NI_RESPONSE_ACCEPT; + break; + case IGnssNiCallback::GnssUserResponseType::RESPONSE_DENY: + data = GNSS_NI_RESPONSE_DENY; + break; + case IGnssNiCallback::GnssUserResponseType::RESPONSE_NORESP: + data = GNSS_NI_RESPONSE_NO_RESPONSE; + break; + default: + data = GNSS_NI_RESPONSE_IGNORE; + break; + } + + locAPIGnssNiResponse(notifId, data); +} + +// these apis using LocationAPIControlClient +void GnssAPIClient::gnssDeleteAidingData(IGnss::GnssAidingData aidingDataFlags) +{ + LOC_LOGD("%s]: (%02hx)", __FUNCTION__, aidingDataFlags); + if (mControlClient == nullptr) { + return; + } + GnssAidingData data; + memset(&data, 0, sizeof (GnssAidingData)); + data.sv.svTypeMask = GNSS_AIDING_DATA_SV_TYPE_GPS_BIT | + GNSS_AIDING_DATA_SV_TYPE_GLONASS_BIT | + GNSS_AIDING_DATA_SV_TYPE_QZSS_BIT | + GNSS_AIDING_DATA_SV_TYPE_BEIDOU_BIT | + GNSS_AIDING_DATA_SV_TYPE_GALILEO_BIT; + data.posEngineMask = STANDARD_POSITIONING_ENGINE; + + if (aidingDataFlags == IGnss::GnssAidingData::DELETE_ALL) + data.deleteAll = true; + else { + if (aidingDataFlags & IGnss::GnssAidingData::DELETE_EPHEMERIS) + data.sv.svMask |= GNSS_AIDING_DATA_SV_EPHEMERIS_BIT; + if (aidingDataFlags & IGnss::GnssAidingData::DELETE_ALMANAC) + data.sv.svMask |= GNSS_AIDING_DATA_SV_ALMANAC_BIT; + if (aidingDataFlags & IGnss::GnssAidingData::DELETE_POSITION) + data.common.mask |= GNSS_AIDING_DATA_COMMON_POSITION_BIT; + if (aidingDataFlags & IGnss::GnssAidingData::DELETE_TIME) + data.common.mask |= GNSS_AIDING_DATA_COMMON_TIME_BIT; + if (aidingDataFlags & IGnss::GnssAidingData::DELETE_IONO) + data.sv.svMask |= GNSS_AIDING_DATA_SV_IONOSPHERE_BIT; + if (aidingDataFlags & IGnss::GnssAidingData::DELETE_UTC) + data.common.mask |= GNSS_AIDING_DATA_COMMON_UTC_BIT; + if (aidingDataFlags & IGnss::GnssAidingData::DELETE_HEALTH) + data.sv.svMask |= GNSS_AIDING_DATA_SV_HEALTH_BIT; + if (aidingDataFlags & IGnss::GnssAidingData::DELETE_SVDIR) + data.sv.svMask |= GNSS_AIDING_DATA_SV_DIRECTION_BIT; + if (aidingDataFlags & IGnss::GnssAidingData::DELETE_SVSTEER) + data.sv.svMask |= GNSS_AIDING_DATA_SV_STEER_BIT; + if (aidingDataFlags & IGnss::GnssAidingData::DELETE_SADATA) + data.sv.svMask |= GNSS_AIDING_DATA_SV_SA_DATA_BIT; + if (aidingDataFlags & IGnss::GnssAidingData::DELETE_RTI) + data.common.mask |= GNSS_AIDING_DATA_COMMON_RTI_BIT; + if (aidingDataFlags & IGnss::GnssAidingData::DELETE_CELLDB_INFO) + data.common.mask |= GNSS_AIDING_DATA_COMMON_CELLDB_BIT; + } + mControlClient->locAPIGnssDeleteAidingData(data); +} + +void GnssAPIClient::gnssEnable(LocationTechnologyType techType) +{ + LOC_LOGD("%s]: (%0d)", __FUNCTION__, techType); + if (mControlClient == nullptr) { + return; + } + mControlClient->locAPIEnable(techType); +} + +void GnssAPIClient::gnssDisable() +{ + LOC_LOGD("%s]: ()", __FUNCTION__); + if (mControlClient == nullptr) { + return; + } + mControlClient->locAPIDisable(); +} + +void GnssAPIClient::gnssConfigurationUpdate(const GnssConfig& gnssConfig) +{ + LOC_LOGD("%s]: (%02x)", __FUNCTION__, gnssConfig.flags); + if (mControlClient == nullptr) { + return; + } + mControlClient->locAPIGnssUpdateConfig(gnssConfig); +} + +void GnssAPIClient::requestCapabilities() { + // only send capablities if it's already cached, otherwise the first time LocationAPI + // is initialized, capabilities will be sent by LocationAPI + if (mLocationCapabilitiesCached) { + onCapabilitiesCb(mLocationCapabilitiesMask); + } +} + +// callbacks +void GnssAPIClient::onCapabilitiesCb(LocationCapabilitiesMask capabilitiesMask) +{ + LOC_LOGD("%s]: (%02x)", __FUNCTION__, capabilitiesMask); + mLocationCapabilitiesMask = capabilitiesMask; + mLocationCapabilitiesCached = true; + + mMutex.lock(); + auto gnssCbIface(mGnssCbIface); + mMutex.unlock(); + + if (gnssCbIface != nullptr) { + uint32_t data = 0; + if ((capabilitiesMask & LOCATION_CAPABILITIES_TIME_BASED_TRACKING_BIT) || + (capabilitiesMask & LOCATION_CAPABILITIES_TIME_BASED_BATCHING_BIT) || + (capabilitiesMask & LOCATION_CAPABILITIES_DISTANCE_BASED_TRACKING_BIT) || + (capabilitiesMask & LOCATION_CAPABILITIES_DISTANCE_BASED_BATCHING_BIT)) + data |= IGnssCallback::Capabilities::SCHEDULING; + if (capabilitiesMask & LOCATION_CAPABILITIES_GEOFENCE_BIT) + data |= IGnssCallback::Capabilities::GEOFENCING; + if (capabilitiesMask & LOCATION_CAPABILITIES_GNSS_MEASUREMENTS_BIT) + data |= IGnssCallback::Capabilities::MEASUREMENTS; + if (capabilitiesMask & LOCATION_CAPABILITIES_GNSS_MSB_BIT) + data |= IGnssCallback::Capabilities::MSB; + if (capabilitiesMask & LOCATION_CAPABILITIES_GNSS_MSA_BIT) + data |= IGnssCallback::Capabilities::MSA; + auto r = gnssCbIface->gnssSetCapabilitesCb(data); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssSetCapabilitesCb description=%s", + __func__, r.description().c_str()); + } + } + if (gnssCbIface != nullptr) { + IGnssCallback::GnssSystemInfo gnssInfo; + if (capabilitiesMask & LOCATION_CAPABILITIES_CONSTELLATION_ENABLEMENT_BIT || + capabilitiesMask & LOCATION_CAPABILITIES_AGPM_BIT) { + gnssInfo.yearOfHw = 2018; + } else if (capabilitiesMask & LOCATION_CAPABILITIES_DEBUG_NMEA_BIT) { + gnssInfo.yearOfHw = 2017; + } else if (capabilitiesMask & LOCATION_CAPABILITIES_GNSS_MEASUREMENTS_BIT) { + gnssInfo.yearOfHw = 2016; + } else { + gnssInfo.yearOfHw = 2015; + } + LOC_LOGV("%s:%d] set_system_info_cb (%d)", __FUNCTION__, __LINE__, gnssInfo.yearOfHw); + auto r = gnssCbIface->gnssSetSystemInfoCb(gnssInfo); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssSetSystemInfoCb description=%s", + __func__, r.description().c_str()); + } + } +} + +void GnssAPIClient::onTrackingCb(Location location) +{ + LOC_LOGD("%s]: (flags: %02x)", __FUNCTION__, location.flags); + mMutex.lock(); + auto gnssCbIface(mGnssCbIface); + mMutex.unlock(); + + if (gnssCbIface != nullptr) { + GnssLocation gnssLocation; + convertGnssLocation(location, gnssLocation); + auto r = gnssCbIface->gnssLocationCb(gnssLocation); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssLocationCb description=%s", + __func__, r.description().c_str()); + } + } +} + +void GnssAPIClient::onGnssNiCb(uint32_t id, GnssNiNotification gnssNiNotification) +{ + LOC_LOGD("%s]: (id: %d)", __FUNCTION__, id); + mMutex.lock(); + auto gnssNiCbIface(mGnssNiCbIface); + mMutex.unlock(); + + if (gnssNiCbIface == nullptr) { + LOC_LOGE("%s]: mGnssNiCbIface is nullptr", __FUNCTION__); + return; + } + + IGnssNiCallback::GnssNiNotification notificationGnss = {}; + + notificationGnss.notificationId = id; + + if (gnssNiNotification.type == GNSS_NI_TYPE_VOICE) + notificationGnss.niType = IGnssNiCallback::GnssNiType::VOICE; + else if (gnssNiNotification.type == GNSS_NI_TYPE_SUPL) + notificationGnss.niType = IGnssNiCallback::GnssNiType::UMTS_SUPL; + else if (gnssNiNotification.type == GNSS_NI_TYPE_CONTROL_PLANE) + notificationGnss.niType = IGnssNiCallback::GnssNiType::UMTS_CTRL_PLANE; + else if (gnssNiNotification.type == GNSS_NI_TYPE_EMERGENCY_SUPL) + notificationGnss.niType = IGnssNiCallback::GnssNiType::EMERGENCY_SUPL; + + if (gnssNiNotification.options & GNSS_NI_OPTIONS_NOTIFICATION_BIT) + notificationGnss.notifyFlags |= IGnssNiCallback::GnssNiNotifyFlags::NEED_NOTIFY; + if (gnssNiNotification.options & GNSS_NI_OPTIONS_VERIFICATION_BIT) + notificationGnss.notifyFlags |= IGnssNiCallback::GnssNiNotifyFlags::NEED_VERIFY; + if (gnssNiNotification.options & GNSS_NI_OPTIONS_PRIVACY_OVERRIDE_BIT) + notificationGnss.notifyFlags |= IGnssNiCallback::GnssNiNotifyFlags::PRIVACY_OVERRIDE; + + notificationGnss.timeoutSec = gnssNiNotification.timeout; + + if (gnssNiNotification.timeoutResponse == GNSS_NI_RESPONSE_ACCEPT) + notificationGnss.defaultResponse = IGnssNiCallback::GnssUserResponseType::RESPONSE_ACCEPT; + else if (gnssNiNotification.timeoutResponse == GNSS_NI_RESPONSE_DENY) + notificationGnss.defaultResponse = IGnssNiCallback::GnssUserResponseType::RESPONSE_DENY; + else if (gnssNiNotification.timeoutResponse == GNSS_NI_RESPONSE_NO_RESPONSE || + gnssNiNotification.timeoutResponse == GNSS_NI_RESPONSE_IGNORE) + notificationGnss.defaultResponse = IGnssNiCallback::GnssUserResponseType::RESPONSE_NORESP; + + notificationGnss.requestorId = gnssNiNotification.requestor; + + notificationGnss.notificationMessage = gnssNiNotification.message; + + if (gnssNiNotification.requestorEncoding == GNSS_NI_ENCODING_TYPE_NONE) + notificationGnss.requestorIdEncoding = + IGnssNiCallback::GnssNiEncodingType::ENC_NONE; + else if (gnssNiNotification.requestorEncoding == GNSS_NI_ENCODING_TYPE_GSM_DEFAULT) + notificationGnss.requestorIdEncoding = + IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_GSM_DEFAULT; + else if (gnssNiNotification.requestorEncoding == GNSS_NI_ENCODING_TYPE_UTF8) + notificationGnss.requestorIdEncoding = + IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_UTF8; + else if (gnssNiNotification.requestorEncoding == GNSS_NI_ENCODING_TYPE_UCS2) + notificationGnss.requestorIdEncoding = + IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_UCS2; + + if (gnssNiNotification.messageEncoding == GNSS_NI_ENCODING_TYPE_NONE) + notificationGnss.notificationIdEncoding = + IGnssNiCallback::GnssNiEncodingType::ENC_NONE; + else if (gnssNiNotification.messageEncoding == GNSS_NI_ENCODING_TYPE_GSM_DEFAULT) + notificationGnss.notificationIdEncoding = + IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_GSM_DEFAULT; + else if (gnssNiNotification.messageEncoding == GNSS_NI_ENCODING_TYPE_UTF8) + notificationGnss.notificationIdEncoding = + IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_UTF8; + else if (gnssNiNotification.messageEncoding == GNSS_NI_ENCODING_TYPE_UCS2) + notificationGnss.notificationIdEncoding = + IGnssNiCallback::GnssNiEncodingType::ENC_SUPL_UCS2; + + gnssNiCbIface->niNotifyCb(notificationGnss); +} + +void GnssAPIClient::onGnssSvCb(GnssSvNotification gnssSvNotification) +{ + LOC_LOGD("%s]: (count: %zu)", __FUNCTION__, gnssSvNotification.count); + mMutex.lock(); + auto gnssCbIface(mGnssCbIface); + mMutex.unlock(); + + if (gnssCbIface != nullptr) { + IGnssCallback::GnssSvStatus svStatus; + convertGnssSvStatus(gnssSvNotification, svStatus); + auto r = gnssCbIface->gnssSvStatusCb(svStatus); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssSvStatusCb description=%s", + __func__, r.description().c_str()); + } + } +} + +void GnssAPIClient::onGnssNmeaCb(GnssNmeaNotification gnssNmeaNotification) +{ + mMutex.lock(); + auto gnssCbIface(mGnssCbIface); + mMutex.unlock(); + + if (gnssCbIface != nullptr) { + const std::string s(gnssNmeaNotification.nmea); + std::stringstream ss(s); + std::string each; + while(std::getline(ss, each, '\n')) { + each += '\n'; + android::hardware::hidl_string nmeaString; + nmeaString.setToExternal(each.c_str(), each.length()); + auto r = gnssCbIface->gnssNmeaCb( + static_cast<V1_0::GnssUtcTime>(gnssNmeaNotification.timestamp), nmeaString); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssNmeaCb nmea=%s length=%zu description=%s", __func__, + gnssNmeaNotification.nmea, gnssNmeaNotification.length, + r.description().c_str()); + } + } + } +} + +void GnssAPIClient::onStartTrackingCb(LocationError error) +{ + LOC_LOGD("%s]: (%d)", __FUNCTION__, error); + mMutex.lock(); + auto gnssCbIface(mGnssCbIface); + mMutex.unlock(); + + if (error == LOCATION_ERROR_SUCCESS && gnssCbIface != nullptr) { + auto r = gnssCbIface->gnssStatusCb(IGnssCallback::GnssStatusValue::ENGINE_ON); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssStatusCb ENGINE_ON description=%s", + __func__, r.description().c_str()); + } + r = gnssCbIface->gnssStatusCb(IGnssCallback::GnssStatusValue::SESSION_BEGIN); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssStatusCb SESSION_BEGIN description=%s", + __func__, r.description().c_str()); + } + } +} + +void GnssAPIClient::onStopTrackingCb(LocationError error) +{ + LOC_LOGD("%s]: (%d)", __FUNCTION__, error); + mMutex.lock(); + auto gnssCbIface(mGnssCbIface); + mMutex.unlock(); + + if (error == LOCATION_ERROR_SUCCESS && gnssCbIface != nullptr) { + auto r = gnssCbIface->gnssStatusCb(IGnssCallback::GnssStatusValue::SESSION_END); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssStatusCb SESSION_END description=%s", + __func__, r.description().c_str()); + } + r = gnssCbIface->gnssStatusCb(IGnssCallback::GnssStatusValue::ENGINE_OFF); + if (!r.isOk()) { + LOC_LOGE("%s] Error from gnssStatusCb ENGINE_OFF description=%s", + __func__, r.description().c_str()); + } + } +} + +static void convertGnssSvStatus(GnssSvNotification& in, IGnssCallback::GnssSvStatus& out) +{ + memset(&out, 0, sizeof(IGnssCallback::GnssSvStatus)); + out.numSvs = in.count; + if (out.numSvs > static_cast<uint32_t>(V1_0::GnssMax::SVS_COUNT)) { + LOC_LOGW("%s]: Too many satellites %u. Clamps to %d.", + __FUNCTION__, out.numSvs, V1_0::GnssMax::SVS_COUNT); + out.numSvs = static_cast<uint32_t>(V1_0::GnssMax::SVS_COUNT); + } + for (size_t i = 0; i < out.numSvs; i++) { + IGnssCallback::GnssSvInfo& info = out.gnssSvList[i]; + info.svid = in.gnssSvs[i].svId; + convertGnssConstellationType(in.gnssSvs[i].type, info.constellation); + info.cN0Dbhz = in.gnssSvs[i].cN0Dbhz; + info.elevationDegrees = in.gnssSvs[i].elevation; + info.azimuthDegrees = in.gnssSvs[i].azimuth; + info.carrierFrequencyHz = in.gnssSvs[i].carrierFrequencyHz; + info.svFlag = static_cast<uint8_t>(IGnssCallback::GnssSvFlags::NONE); + if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_EPHEMER_BIT) + info.svFlag |= IGnssCallback::GnssSvFlags::HAS_EPHEMERIS_DATA; + if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_ALMANAC_BIT) + info.svFlag |= IGnssCallback::GnssSvFlags::HAS_ALMANAC_DATA; + if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_USED_IN_FIX_BIT) + info.svFlag |= IGnssCallback::GnssSvFlags::USED_IN_FIX; + if (in.gnssSvs[i].gnssSvOptionsMask & GNSS_SV_OPTIONS_HAS_CARRIER_FREQUENCY_BIT) + info.svFlag |= IGnssCallback::GnssSvFlags::HAS_CARRIER_FREQUENCY; + } +} + +} // namespace implementation +} // namespace V1_0 +} // namespace gnss +} // namespace hardware +} // namespace android diff --git a/android/1.0/location_api/GnssAPIClient.h b/android/1.0/location_api/GnssAPIClient.h new file mode 100644 index 0000000..4e4b4a9 --- /dev/null +++ b/android/1.0/location_api/GnssAPIClient.h @@ -0,0 +1,109 @@ +/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef GNSS_API_CLINET_H +#define GNSS_API_CLINET_H + + +#include <mutex> +#include <android/hardware/gnss/1.0/IGnss.h> +#include <android/hardware/gnss/1.0/IGnssCallback.h> +#include <android/hardware/gnss/1.0/IGnssNiCallback.h> +#include <LocationAPIClientBase.h> + +namespace android { +namespace hardware { +namespace gnss { +namespace V1_0 { +namespace implementation { + +using ::android::sp; + +class GnssAPIClient : public LocationAPIClientBase +{ +public: + GnssAPIClient(const sp<V1_0::IGnssCallback>& gpsCb, + const sp<V1_0::IGnssNiCallback>& niCb); + virtual ~GnssAPIClient(); + GnssAPIClient(const GnssAPIClient&) = delete; + GnssAPIClient& operator=(const GnssAPIClient&) = delete; + + // for GpsInterface + void gnssUpdateCallbacks(const sp<V1_0::IGnssCallback>& gpsCb, + const sp<V1_0::IGnssNiCallback>& niCb); + bool gnssStart(); + bool gnssStop(); + bool gnssSetPositionMode(V1_0::IGnss::GnssPositionMode mode, + V1_0::IGnss::GnssPositionRecurrence recurrence, + uint32_t minIntervalMs, + uint32_t preferredAccuracyMeters, + uint32_t preferredTimeMs, + GnssPowerMode powerMode = GNSS_POWER_MODE_INVALID, + uint32_t timeBetweenMeasurement = 0); + + // for GpsNiInterface + void gnssNiRespond(int32_t notifId, V1_0::IGnssNiCallback::GnssUserResponseType userResponse); + + // these apis using LocationAPIControlClient + void gnssDeleteAidingData(V1_0::IGnss::GnssAidingData aidingDataFlags); + void gnssEnable(LocationTechnologyType techType); + void gnssDisable(); + void gnssConfigurationUpdate(const GnssConfig& gnssConfig); + + inline LocationCapabilitiesMask gnssGetCapabilities() const { + return mLocationCapabilitiesMask; + } + void requestCapabilities(); + + // callbacks we are interested in + void onCapabilitiesCb(LocationCapabilitiesMask capabilitiesMask) final; + void onTrackingCb(Location location) final; + void onGnssNiCb(uint32_t id, GnssNiNotification gnssNiNotification) final; + void onGnssSvCb(GnssSvNotification gnssSvNotification) final; + void onGnssNmeaCb(GnssNmeaNotification gnssNmeaNotification) final; + + void onStartTrackingCb(LocationError error) final; + void onStopTrackingCb(LocationError error) final; + +private: + sp<V1_0::IGnssCallback> mGnssCbIface; + sp<V1_0::IGnssNiCallback> mGnssNiCbIface; + std::mutex mMutex; + LocationAPIControlClient* mControlClient; + LocationCapabilitiesMask mLocationCapabilitiesMask; + bool mLocationCapabilitiesCached; + TrackingOptions mTrackingOptions; +}; + +} // namespace implementation +} // namespace V1_0 +} // namespace gnss +} // namespace hardware +} // namespace android +#endif // GNSS_API_CLINET_H diff --git a/android/1.0/location_api/LocationUtil.cpp b/android/1.0/location_api/LocationUtil.cpp new file mode 100644 index 0000000..102593b --- /dev/null +++ b/android/1.0/location_api/LocationUtil.cpp @@ -0,0 +1,206 @@ +/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include <LocationUtil.h> + +namespace android { +namespace hardware { +namespace gnss { +namespace V1_0 { +namespace implementation { + +using ::android::hardware::gnss::V1_0::GnssLocation; +using ::android::hardware::gnss::V1_0::GnssConstellationType; +using ::android::hardware::gnss::V1_0::GnssLocationFlags; + +void convertGnssLocation(Location& in, GnssLocation& out) +{ + memset(&out, 0, sizeof(GnssLocation)); + if (in.flags & LOCATION_HAS_LAT_LONG_BIT) { + out.gnssLocationFlags |= GnssLocationFlags::HAS_LAT_LONG; + out.latitudeDegrees = in.latitude; + out.longitudeDegrees = in.longitude; + } + if (in.flags & LOCATION_HAS_ALTITUDE_BIT) { + out.gnssLocationFlags |= GnssLocationFlags::HAS_ALTITUDE; + out.altitudeMeters = in.altitude; + } + if (in.flags & LOCATION_HAS_SPEED_BIT) { + out.gnssLocationFlags |= GnssLocationFlags::HAS_SPEED; + out.speedMetersPerSec = in.speed; + } + if (in.flags & LOCATION_HAS_BEARING_BIT) { + out.gnssLocationFlags |= GnssLocationFlags::HAS_BEARING; + out.bearingDegrees = in.bearing; + } + if (in.flags & LOCATION_HAS_ACCURACY_BIT) { + out.gnssLocationFlags |= GnssLocationFlags::HAS_HORIZONTAL_ACCURACY; + out.horizontalAccuracyMeters = in.accuracy; + } + if (in.flags & LOCATION_HAS_VERTICAL_ACCURACY_BIT) { + out.gnssLocationFlags |= GnssLocationFlags::HAS_VERTICAL_ACCURACY; + out.verticalAccuracyMeters = in.verticalAccuracy; + } + if (in.flags & LOCATION_HAS_SPEED_ACCURACY_BIT) { + out.gnssLocationFlags |= GnssLocationFlags::HAS_SPEED_ACCURACY; + out.speedAccuracyMetersPerSecond = in.speedAccuracy; + } + if (in.flags & LOCATION_HAS_BEARING_ACCURACY_BIT) { + out.gnssLocationFlags |= GnssLocationFlags::HAS_BEARING_ACCURACY; + out.bearingAccuracyDegrees = in.bearingAccuracy; + } + + out.timestamp = static_cast<V1_0::GnssUtcTime>(in.timestamp); +} + +void convertGnssLocation(const GnssLocation& in, Location& out) +{ + memset(&out, 0, sizeof(out)); + if (in.gnssLocationFlags & GnssLocationFlags::HAS_LAT_LONG) { + out.flags |= LOCATION_HAS_LAT_LONG_BIT; + out.latitude = in.latitudeDegrees; + out.longitude = in.longitudeDegrees; + } + if (in.gnssLocationFlags & GnssLocationFlags::HAS_ALTITUDE) { + out.flags |= LOCATION_HAS_ALTITUDE_BIT; + out.altitude = in.altitudeMeters; + } + if (in.gnssLocationFlags & GnssLocationFlags::HAS_SPEED) { + out.flags |= LOCATION_HAS_SPEED_BIT; + out.speed = in.speedMetersPerSec; + } + if (in.gnssLocationFlags & GnssLocationFlags::HAS_BEARING) { + out.flags |= LOCATION_HAS_BEARING_BIT; + out.bearing = in.bearingDegrees; + } + if (in.gnssLocationFlags & GnssLocationFlags::HAS_HORIZONTAL_ACCURACY) { + out.flags |= LOCATION_HAS_ACCURACY_BIT; + out.accuracy = in.horizontalAccuracyMeters; + } + if (in.gnssLocationFlags & GnssLocationFlags::HAS_VERTICAL_ACCURACY) { + out.flags |= LOCATION_HAS_VERTICAL_ACCURACY_BIT; + out.verticalAccuracy = in.verticalAccuracyMeters; + } + if (in.gnssLocationFlags & GnssLocationFlags::HAS_SPEED_ACCURACY) { + out.flags |= LOCATION_HAS_SPEED_ACCURACY_BIT; + out.speedAccuracy = in.speedAccuracyMetersPerSecond; + } + if (in.gnssLocationFlags & GnssLocationFlags::HAS_BEARING_ACCURACY) { + out.flags |= LOCATION_HAS_BEARING_ACCURACY_BIT; + out.bearingAccuracy = in.bearingAccuracyDegrees; + } + + out.timestamp = static_cast<uint64_t>(in.timestamp); +} + +void convertGnssConstellationType(GnssSvType& in, GnssConstellationType& out) +{ + switch(in) { + case GNSS_SV_TYPE_GPS: + out = GnssConstellationType::GPS; + break; + case GNSS_SV_TYPE_SBAS: + out = GnssConstellationType::SBAS; + break; + case GNSS_SV_TYPE_GLONASS: + out = GnssConstellationType::GLONASS; + break; + case GNSS_SV_TYPE_QZSS: + out = GnssConstellationType::QZSS; + break; + case GNSS_SV_TYPE_BEIDOU: + out = GnssConstellationType::BEIDOU; + break; + case GNSS_SV_TYPE_GALILEO: + out = GnssConstellationType::GALILEO; + break; + case GNSS_SV_TYPE_UNKNOWN: + default: + out = GnssConstellationType::UNKNOWN; + break; + } +} + +void convertGnssEphemerisType(GnssEphemerisType& in, GnssDebug::SatelliteEphemerisType& out) +{ + switch(in) { + case GNSS_EPH_TYPE_EPHEMERIS: + out = GnssDebug::SatelliteEphemerisType::EPHEMERIS; + break; + case GNSS_EPH_TYPE_ALMANAC: + out = GnssDebug::SatelliteEphemerisType::ALMANAC_ONLY; + break; + case GNSS_EPH_TYPE_UNKNOWN: + default: + out = GnssDebug::SatelliteEphemerisType::NOT_AVAILABLE; + break; + } +} + +void convertGnssEphemerisSource(GnssEphemerisSource& in, GnssDebug::SatelliteEphemerisSource& out) +{ + switch(in) { + case GNSS_EPH_SOURCE_DEMODULATED: + out = GnssDebug::SatelliteEphemerisSource::DEMODULATED; + break; + case GNSS_EPH_SOURCE_SUPL_PROVIDED: + out = GnssDebug::SatelliteEphemerisSource::SUPL_PROVIDED; + break; + case GNSS_EPH_SOURCE_OTHER_SERVER_PROVIDED: + out = GnssDebug::SatelliteEphemerisSource::OTHER_SERVER_PROVIDED; + break; + case GNSS_EPH_SOURCE_LOCAL: + case GNSS_EPH_SOURCE_UNKNOWN: + default: + out = GnssDebug::SatelliteEphemerisSource::OTHER; + break; + } +} + +void convertGnssEphemerisHealth(GnssEphemerisHealth& in, GnssDebug::SatelliteEphemerisHealth& out) +{ + switch(in) { + case GNSS_EPH_HEALTH_GOOD: + out = GnssDebug::SatelliteEphemerisHealth::GOOD; + break; + case GNSS_EPH_HEALTH_BAD: + out = GnssDebug::SatelliteEphemerisHealth::BAD; + break; + case GNSS_EPH_HEALTH_UNKNOWN: + default: + out = GnssDebug::SatelliteEphemerisHealth::UNKNOWN; + break; + } +} + +} // namespace implementation +} // namespace V1_0 +} // namespace gnss +} // namespace hardware +} // namespace android diff --git a/android/1.0/location_api/LocationUtil.h b/android/1.0/location_api/LocationUtil.h new file mode 100644 index 0000000..9e0cd36 --- /dev/null +++ b/android/1.0/location_api/LocationUtil.h @@ -0,0 +1,55 @@ +/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef LOCATION_UTIL_H +#define LOCATION_UTIL_H + +#include <android/hardware/gnss/1.0/types.h> +#include <LocationAPI.h> +#include <GnssDebug.h> + +namespace android { +namespace hardware { +namespace gnss { +namespace V1_0 { +namespace implementation { + +void convertGnssLocation(Location& in, V1_0::GnssLocation& out); +void convertGnssLocation(const V1_0::GnssLocation& in, Location& out); +void convertGnssConstellationType(GnssSvType& in, V1_0::GnssConstellationType& out); +void convertGnssEphemerisType(GnssEphemerisType& in, GnssDebug::SatelliteEphemerisType& out); +void convertGnssEphemerisSource(GnssEphemerisSource& in, GnssDebug::SatelliteEphemerisSource& out); +void convertGnssEphemerisHealth(GnssEphemerisHealth& in, GnssDebug::SatelliteEphemerisHealth& out); + +} // namespace implementation +} // namespace V1_0 +} // namespace gnss +} // namespace hardware +} // namespace android +#endif // LOCATION_UTIL_H diff --git a/android/1.0/location_api/MeasurementAPIClient.cpp b/android/1.0/location_api/MeasurementAPIClient.cpp new file mode 100644 index 0000000..73709e3 --- /dev/null +++ b/android/1.0/location_api/MeasurementAPIClient.cpp @@ -0,0 +1,276 @@ +/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#define LOG_NDEBUG 0 +#define LOG_TAG "LocSvc_MeasurementAPIClient" + +#include <log_util.h> +#include <loc_cfg.h> + +#include "LocationUtil.h" +#include "MeasurementAPIClient.h" + +namespace android { +namespace hardware { +namespace gnss { +namespace V1_0 { +namespace implementation { + +using ::android::hardware::gnss::V1_0::IGnssMeasurement; +using ::android::hardware::gnss::V1_0::IGnssMeasurementCallback; + +static void convertGnssData(GnssMeasurementsNotification& in, + V1_0::IGnssMeasurementCallback::GnssData& out); +static void convertGnssMeasurement(GnssMeasurementsData& in, + V1_0::IGnssMeasurementCallback::GnssMeasurement& out); +static void convertGnssClock(GnssMeasurementsClock& in, IGnssMeasurementCallback::GnssClock& out); + +MeasurementAPIClient::MeasurementAPIClient() : + mGnssMeasurementCbIface(nullptr), + mTracking(false) +{ + LOC_LOGD("%s]: ()", __FUNCTION__); +} + +MeasurementAPIClient::~MeasurementAPIClient() +{ + LOC_LOGD("%s]: ()", __FUNCTION__); +} + +// for GpsInterface +Return<IGnssMeasurement::GnssMeasurementStatus> +MeasurementAPIClient::measurementSetCallback(const sp<V1_0::IGnssMeasurementCallback>& callback) +{ + LOC_LOGD("%s]: (%p)", __FUNCTION__, &callback); + + mMutex.lock(); + mGnssMeasurementCbIface = callback; + mMutex.unlock(); + + return startTracking(); +} + +Return<IGnssMeasurement::GnssMeasurementStatus> +MeasurementAPIClient::startTracking() +{ + LocationCallbacks locationCallbacks; + memset(&locationCallbacks, 0, sizeof(LocationCallbacks)); + locationCallbacks.size = sizeof(LocationCallbacks); + + locationCallbacks.trackingCb = nullptr; + locationCallbacks.batchingCb = nullptr; + locationCallbacks.geofenceBreachCb = nullptr; + locationCallbacks.geofenceStatusCb = nullptr; + locationCallbacks.gnssLocationInfoCb = nullptr; + locationCallbacks.gnssNiCb = nullptr; + locationCallbacks.gnssSvCb = nullptr; + locationCallbacks.gnssNmeaCb = nullptr; + + locationCallbacks.gnssMeasurementsCb = nullptr; + if (mGnssMeasurementCbIface != nullptr) { + locationCallbacks.gnssMeasurementsCb = + [this](GnssMeasurementsNotification gnssMeasurementsNotification) { + onGnssMeasurementsCb(gnssMeasurementsNotification); + }; + } + + locAPISetCallbacks(locationCallbacks); + + TrackingOptions options = {}; + memset(&options, 0, sizeof(TrackingOptions)); + options.size = sizeof(TrackingOptions); + options.minInterval = 1000; + options.mode = GNSS_SUPL_MODE_STANDALONE; + + mTracking = true; + LOC_LOGD("%s]: start tracking session", __FUNCTION__); + locAPIStartTracking(options); + return IGnssMeasurement::GnssMeasurementStatus::SUCCESS; +} + +// for GpsMeasurementInterface +void MeasurementAPIClient::measurementClose() { + LOC_LOGD("%s]: ()", __FUNCTION__); + mTracking = false; + locAPIStopTracking(); +} + +// callbacks +void MeasurementAPIClient::onGnssMeasurementsCb( + GnssMeasurementsNotification gnssMeasurementsNotification) +{ + LOC_LOGD("%s]: (count: %zu active: %d)", + __FUNCTION__, gnssMeasurementsNotification.count, mTracking); + if (mTracking) { + mMutex.lock(); + sp<V1_0::IGnssMeasurementCallback> gnssMeasurementCbIface = nullptr; + if (mGnssMeasurementCbIface != nullptr) { + gnssMeasurementCbIface = mGnssMeasurementCbIface; + } + mMutex.unlock(); + + if (gnssMeasurementCbIface != nullptr) { + V1_0::IGnssMeasurementCallback::GnssData gnssData; + convertGnssData(gnssMeasurementsNotification, gnssData); + auto r = gnssMeasurementCbIface->GnssMeasurementCb(gnssData); + if (!r.isOk()) { + LOC_LOGE("%s] Error from GnssMeasurementCb description=%s", + __func__, r.description().c_str()); + } + } + } +} + +static void convertGnssMeasurement(GnssMeasurementsData& in, + V1_0::IGnssMeasurementCallback::GnssMeasurement& out) +{ + memset(&out, 0, sizeof(IGnssMeasurementCallback::GnssMeasurement)); + if (in.flags & GNSS_MEASUREMENTS_DATA_SIGNAL_TO_NOISE_RATIO_BIT) + out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_SNR; + if (in.flags & GNSS_MEASUREMENTS_DATA_CARRIER_FREQUENCY_BIT) + out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_CARRIER_FREQUENCY; + if (in.flags & GNSS_MEASUREMENTS_DATA_CARRIER_CYCLES_BIT) + out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_CARRIER_CYCLES; + if (in.flags & GNSS_MEASUREMENTS_DATA_CARRIER_PHASE_BIT) + out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_CARRIER_PHASE; + if (in.flags & GNSS_MEASUREMENTS_DATA_CARRIER_PHASE_UNCERTAINTY_BIT) + out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_CARRIER_PHASE_UNCERTAINTY; + if (in.flags & GNSS_MEASUREMENTS_DATA_AUTOMATIC_GAIN_CONTROL_BIT) + out.flags |= IGnssMeasurementCallback::GnssMeasurementFlags::HAS_AUTOMATIC_GAIN_CONTROL; + out.svid = in.svId; + convertGnssConstellationType(in.svType, out.constellation); + out.timeOffsetNs = in.timeOffsetNs; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_CODE_LOCK_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_CODE_LOCK; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_BIT_SYNC_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_BIT_SYNC; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_SUBFRAME_SYNC_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_SUBFRAME_SYNC; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_TOW_DECODED_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_TOW_DECODED; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_MSEC_AMBIGUOUS_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_MSEC_AMBIGUOUS; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_SYMBOL_SYNC_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_SYMBOL_SYNC; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_GLO_STRING_SYNC_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GLO_STRING_SYNC; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_GLO_TOD_DECODED_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GLO_TOD_DECODED; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_BDS_D2_BIT_SYNC_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_BDS_D2_BIT_SYNC; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_BDS_D2_SUBFRAME_SYNC_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_BDS_D2_SUBFRAME_SYNC; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_GAL_E1BC_CODE_LOCK_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GAL_E1BC_CODE_LOCK; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_GAL_E1C_2ND_CODE_LOCK_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GAL_E1C_2ND_CODE_LOCK; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_GAL_E1B_PAGE_SYNC_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GAL_E1B_PAGE_SYNC; + if (in.stateMask & GNSS_MEASUREMENTS_STATE_SBAS_SYNC_BIT) + out.state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_SBAS_SYNC; + out.receivedSvTimeInNs = in.receivedSvTimeNs; + out.receivedSvTimeUncertaintyInNs = in.receivedSvTimeUncertaintyNs; + out.cN0DbHz = in.carrierToNoiseDbHz; + out.pseudorangeRateMps = in.pseudorangeRateMps; + out.pseudorangeRateUncertaintyMps = in.pseudorangeRateUncertaintyMps; + if (in.adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_VALID_BIT) + out.accumulatedDeltaRangeState |= + IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_VALID; + if (in.adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_RESET_BIT) + out.accumulatedDeltaRangeState |= + IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_RESET; + if (in.adrStateMask & GNSS_MEASUREMENTS_ACCUMULATED_DELTA_RANGE_STATE_CYCLE_SLIP_BIT) + out.accumulatedDeltaRangeState |= + IGnssMeasurementCallback::GnssAccumulatedDeltaRangeState::ADR_STATE_CYCLE_SLIP; + out.accumulatedDeltaRangeM = in.adrMeters; + out.accumulatedDeltaRangeUncertaintyM = in.adrUncertaintyMeters; + out.carrierFrequencyHz = in.carrierFrequencyHz; + out.carrierCycles = in.carrierCycles; + out.carrierPhase = in.carrierPhase; + out.carrierPhaseUncertainty = in.carrierPhaseUncertainty; + uint8_t indicator = + static_cast<uint8_t>(IGnssMeasurementCallback::GnssMultipathIndicator::INDICATOR_UNKNOWN); + if (in.multipathIndicator & GNSS_MEASUREMENTS_MULTIPATH_INDICATOR_PRESENT) + indicator |= IGnssMeasurementCallback::GnssMultipathIndicator::INDICATOR_PRESENT; + if (in.multipathIndicator & GNSS_MEASUREMENTS_MULTIPATH_INDICATOR_NOT_PRESENT) + indicator |= IGnssMeasurementCallback::GnssMultipathIndicator::INDICATIOR_NOT_PRESENT; + out.multipathIndicator = + static_cast<IGnssMeasurementCallback::GnssMultipathIndicator>(indicator); + out.snrDb = in.signalToNoiseRatioDb; + out.agcLevelDb = in.agcLevelDb; +} + +static void convertGnssClock(GnssMeasurementsClock& in, IGnssMeasurementCallback::GnssClock& out) +{ + memset(&out, 0, sizeof(IGnssMeasurementCallback::GnssClock)); + if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_LEAP_SECOND_BIT) + out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_LEAP_SECOND; + if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_TIME_UNCERTAINTY_BIT) + out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_TIME_UNCERTAINTY; + if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_FULL_BIAS_BIT) + out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_FULL_BIAS; + if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_BIAS_BIT) + out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_BIAS; + if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_BIAS_UNCERTAINTY_BIT) + out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_BIAS_UNCERTAINTY; + if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_DRIFT_BIT) + out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_DRIFT; + if (in.flags & GNSS_MEASUREMENTS_CLOCK_FLAGS_DRIFT_UNCERTAINTY_BIT) + out.gnssClockFlags |= IGnssMeasurementCallback::GnssClockFlags::HAS_DRIFT_UNCERTAINTY; + out.leapSecond = in.leapSecond; + out.timeNs = in.timeNs; + out.timeUncertaintyNs = in.timeUncertaintyNs; + out.fullBiasNs = in.fullBiasNs; + out.biasNs = in.biasNs; + out.biasUncertaintyNs = in.biasUncertaintyNs; + out.driftNsps = in.driftNsps; + out.driftUncertaintyNsps = in.driftUncertaintyNsps; + out.hwClockDiscontinuityCount = in.hwClockDiscontinuityCount; +} + +static void convertGnssData(GnssMeasurementsNotification& in, + V1_0::IGnssMeasurementCallback::GnssData& out) +{ + out.measurementCount = in.count; + if (out.measurementCount > static_cast<uint32_t>(V1_0::GnssMax::SVS_COUNT)) { + LOC_LOGW("%s]: Too many measurement %u. Clamps to %d.", + __FUNCTION__, out.measurementCount, V1_0::GnssMax::SVS_COUNT); + out.measurementCount = static_cast<uint32_t>(V1_0::GnssMax::SVS_COUNT); + } + for (size_t i = 0; i < out.measurementCount; i++) { + convertGnssMeasurement(in.measurements[i], out.measurements[i]); + } + convertGnssClock(in.clock, out.clock); +} + +} // namespace implementation +} // namespace V1_0 +} // namespace gnss +} // namespace hardware +} // namespace android diff --git a/android/1.0/location_api/MeasurementAPIClient.h b/android/1.0/location_api/MeasurementAPIClient.h new file mode 100644 index 0000000..c357313 --- /dev/null +++ b/android/1.0/location_api/MeasurementAPIClient.h @@ -0,0 +1,77 @@ +/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of The Linux Foundation, nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef MEASUREMENT_API_CLINET_H +#define MEASUREMENT_API_CLINET_H + +#include <mutex> +#include <android/hardware/gnss/1.0/IGnssMeasurement.h> +#include <android/hardware/gnss/1.0/IGnssMeasurementCallback.h> +#include <LocationAPIClientBase.h> +#include <hidl/Status.h> +#include <gps_extended_c.h> + +namespace android { +namespace hardware { +namespace gnss { +namespace V1_0 { +namespace implementation { + +using ::android::sp; + +class MeasurementAPIClient : public LocationAPIClientBase +{ +public: + MeasurementAPIClient(); + virtual ~MeasurementAPIClient(); + MeasurementAPIClient(const MeasurementAPIClient&) = delete; + MeasurementAPIClient& operator=(const MeasurementAPIClient&) = delete; + + // for GpsMeasurementInterface + Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> measurementSetCallback( + const sp<V1_0::IGnssMeasurementCallback>& callback); + void measurementClose(); + Return<IGnssMeasurement::GnssMeasurementStatus> startTracking(); + + // callbacks we are interested in + void onGnssMeasurementsCb(GnssMeasurementsNotification gnssMeasurementsNotification) final; + +private: + std::mutex mMutex; + sp<V1_0::IGnssMeasurementCallback> mGnssMeasurementCbIface; + + bool mTracking; +}; + +} // namespace implementation +} // namespace V1_0 +} // namespace gnss +} // namespace hardware +} // namespace android +#endif // MEASUREMENT_API_CLINET_H diff --git a/android/1.0/service.cpp b/android/1.0/service.cpp new file mode 100644 index 0000000..2a6f60f --- /dev/null +++ b/android/1.0/service.cpp @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2017-2018, 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 "android.hardware.gnss@1.0-service-qti" + +#include <android/hardware/gnss/1.0/IGnss.h> +#include <hidl/LegacySupport.h> +#include "loc_cfg.h" +#include "loc_misc_utils.h" + +extern "C" { +#include "vndfwk-detect.h" +} + +#ifdef ARCH_ARM_32 +#define DEFAULT_HW_BINDER_MEM_SIZE 65536 +#endif + +using android::hardware::gnss::V1_0::IGnss; + +using android::hardware::configureRpcThreadpool; +using android::hardware::registerPassthroughServiceImplementation; +using android::hardware::joinRpcThreadpool; + +using android::status_t; +using android::OK; + +typedef int vendorEnhancedServiceMain(int /* argc */, char* /* argv */ []); + +int main() { + + ALOGI("%s", __FUNCTION__); + + int vendorInfo = getVendorEnhancedInfo(); + bool vendorEnhanced = ( 1 == vendorInfo || 3 == vendorInfo ); + setVendorEnhanced(vendorEnhanced); + +#ifdef ARCH_ARM_32 + android::hardware::ProcessState::initWithMmapSize((size_t)(DEFAULT_HW_BINDER_MEM_SIZE)); +#endif + configureRpcThreadpool(1, true); + status_t status; + + status = registerPassthroughServiceImplementation<IGnss>(); + if (status == OK) { + if (vendorEnhanced) { + #ifdef LOC_HIDL_VERSION + #define VENDOR_ENHANCED_LIB "vendor.qti.gnss@" LOC_HIDL_VERSION "-service.so" + + void* libHandle = NULL; + vendorEnhancedServiceMain* vendorEnhancedMainMethod = (vendorEnhancedServiceMain*) + dlGetSymFromLib(libHandle, VENDOR_ENHANCED_LIB, "main"); + if (NULL != vendorEnhancedMainMethod) { + (*vendorEnhancedMainMethod)(0, NULL); + } + #else + ALOGE("LOC_HIDL_VERSION not defined."); + #endif + } + + joinRpcThreadpool(); + + } else { + ALOGE("Error while registering IGnss 1.0 service: %d", status); + } + + return 0; +} |