diff --git a/BoardConfig.mk b/BoardConfig.mk new file mode 100644 index 0000000..e69de29 diff --git a/battery/init.redroid.battery.sh b/battery/init.redroid.battery.sh new file mode 100644 index 0000000..e08a9e1 --- /dev/null +++ b/battery/init.redroid.battery.sh @@ -0,0 +1,22 @@ +#!/vendor/bin/sh + +SRC_PATH=/vendor/etc/init/hw/battery/power_supply +DEST_PATH=/data/vendor/battery/power_supply + +copy_files() { + if [ -f $DEST_PATH/battery/v ]; then + ret=$(cmp -s $SRC_PATH/battery/v $DEST_PATH/battery/v || echo -n 1) + if [ "$ret" != "1" ]; then + return + fi + fi + rm -rf $DEST_PATH + cp -r $SRC_PATH $DEST_PATH + echo `expr 80 + $RANDOM % 20` > $DEST_PATH/battery/capacity + chmod -R 777 $DEST_PATH +} + +copy_files + +mount --bind $DEST_PATH /sys/class/power_supply +chmod 755 /sys/class/power_supply diff --git a/battery/power_supply/battery/capacity b/battery/power_supply/battery/capacity new file mode 100644 index 0000000..900731f --- /dev/null +++ b/battery/power_supply/battery/capacity @@ -0,0 +1 @@ +64 diff --git a/battery/power_supply/battery/capacity_level b/battery/power_supply/battery/capacity_level new file mode 100644 index 0000000..b09e2da --- /dev/null +++ b/battery/power_supply/battery/capacity_level @@ -0,0 +1 @@ +Normal diff --git a/battery/power_supply/battery/charge_counter b/battery/power_supply/battery/charge_counter new file mode 100644 index 0000000..2cac83e --- /dev/null +++ b/battery/power_supply/battery/charge_counter @@ -0,0 +1 @@ +2926000 diff --git a/battery/power_supply/battery/charge_full b/battery/power_supply/battery/charge_full new file mode 100644 index 0000000..dc48e35 --- /dev/null +++ b/battery/power_supply/battery/charge_full @@ -0,0 +1 @@ +4524000 diff --git a/battery/power_supply/battery/charge_full_design b/battery/power_supply/battery/charge_full_design new file mode 100644 index 0000000..dc48e35 --- /dev/null +++ b/battery/power_supply/battery/charge_full_design @@ -0,0 +1 @@ +4524000 diff --git a/battery/power_supply/battery/current_avg b/battery/power_supply/battery/current_avg new file mode 100644 index 0000000..743d839 --- /dev/null +++ b/battery/power_supply/battery/current_avg @@ -0,0 +1 @@ +-68125 diff --git a/battery/power_supply/battery/current_max b/battery/power_supply/battery/current_max new file mode 100644 index 0000000..1628ffb --- /dev/null +++ b/battery/power_supply/battery/current_max @@ -0,0 +1 @@ +3250000 diff --git a/battery/power_supply/battery/current_now b/battery/power_supply/battery/current_now new file mode 100644 index 0000000..3feda45 --- /dev/null +++ b/battery/power_supply/battery/current_now @@ -0,0 +1 @@ +3240000 diff --git a/battery/power_supply/battery/cycle_count b/battery/power_supply/battery/cycle_count new file mode 100644 index 0000000..68aaff4 --- /dev/null +++ b/battery/power_supply/battery/cycle_count @@ -0,0 +1 @@ +13213213 diff --git a/battery/power_supply/battery/health b/battery/power_supply/battery/health new file mode 100644 index 0000000..cd9dd73 --- /dev/null +++ b/battery/power_supply/battery/health @@ -0,0 +1 @@ +Good diff --git a/battery/power_supply/battery/online b/battery/power_supply/battery/online new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/battery/power_supply/battery/online @@ -0,0 +1 @@ +1 diff --git a/battery/power_supply/battery/present b/battery/power_supply/battery/present new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/battery/power_supply/battery/present @@ -0,0 +1 @@ +1 diff --git a/battery/power_supply/battery/status b/battery/power_supply/battery/status new file mode 100644 index 0000000..a71a143 --- /dev/null +++ b/battery/power_supply/battery/status @@ -0,0 +1 @@ +Charging diff --git a/battery/power_supply/battery/technology b/battery/power_supply/battery/technology new file mode 100644 index 0000000..2c679ca --- /dev/null +++ b/battery/power_supply/battery/technology @@ -0,0 +1 @@ +Li-ion diff --git a/battery/power_supply/battery/temp b/battery/power_supply/battery/temp new file mode 100644 index 0000000..29d6383 --- /dev/null +++ b/battery/power_supply/battery/temp @@ -0,0 +1 @@ +100 diff --git a/battery/power_supply/battery/time_to_full_now b/battery/power_supply/battery/time_to_full_now new file mode 100644 index 0000000..3a2e3f4 --- /dev/null +++ b/battery/power_supply/battery/time_to_full_now @@ -0,0 +1 @@ +-1 diff --git a/battery/power_supply/battery/type b/battery/power_supply/battery/type new file mode 100644 index 0000000..6784dd3 --- /dev/null +++ b/battery/power_supply/battery/type @@ -0,0 +1 @@ +Battery diff --git a/battery/power_supply/battery/v b/battery/power_supply/battery/v new file mode 100644 index 0000000..56a6051 --- /dev/null +++ b/battery/power_supply/battery/v @@ -0,0 +1 @@ +1 \ No newline at end of file diff --git a/battery/power_supply/battery/voltage_max b/battery/power_supply/battery/voltage_max new file mode 100644 index 0000000..98d39c5 --- /dev/null +++ b/battery/power_supply/battery/voltage_max @@ -0,0 +1 @@ +20000000 diff --git a/battery/power_supply/battery/voltage_min b/battery/power_supply/battery/voltage_min new file mode 100644 index 0000000..98d39c5 --- /dev/null +++ b/battery/power_supply/battery/voltage_min @@ -0,0 +1 @@ +20000000 diff --git a/battery/power_supply/battery/voltage_now b/battery/power_supply/battery/voltage_now new file mode 100644 index 0000000..98d39c5 --- /dev/null +++ b/battery/power_supply/battery/voltage_now @@ -0,0 +1 @@ +20000000 diff --git a/battery/power_supply/dc/current_max b/battery/power_supply/dc/current_max new file mode 100644 index 0000000..a98e572 --- /dev/null +++ b/battery/power_supply/dc/current_max @@ -0,0 +1 @@ +687500 diff --git a/battery/power_supply/dc/current_now b/battery/power_supply/dc/current_now new file mode 100644 index 0000000..f7393e8 --- /dev/null +++ b/battery/power_supply/dc/current_now @@ -0,0 +1 @@ +100000 diff --git a/battery/power_supply/dc/online b/battery/power_supply/dc/online new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/battery/power_supply/dc/online @@ -0,0 +1 @@ +1 diff --git a/battery/power_supply/dc/type b/battery/power_supply/dc/type new file mode 100644 index 0000000..1ee1f7b --- /dev/null +++ b/battery/power_supply/dc/type @@ -0,0 +1 @@ +Unknown diff --git a/battery/power_supply/dc/voltage_max b/battery/power_supply/dc/voltage_max new file mode 100644 index 0000000..573541a --- /dev/null +++ b/battery/power_supply/dc/voltage_max @@ -0,0 +1 @@ +0 diff --git a/battery/power_supply/dc/voltage_now b/battery/power_supply/dc/voltage_now new file mode 100644 index 0000000..573541a --- /dev/null +++ b/battery/power_supply/dc/voltage_now @@ -0,0 +1 @@ +0 diff --git a/battery/power_supply/usb/current_max b/battery/power_supply/usb/current_max new file mode 100644 index 0000000..a98e572 --- /dev/null +++ b/battery/power_supply/usb/current_max @@ -0,0 +1 @@ +687500 diff --git a/battery/power_supply/usb/current_now b/battery/power_supply/usb/current_now new file mode 100644 index 0000000..f7393e8 --- /dev/null +++ b/battery/power_supply/usb/current_now @@ -0,0 +1 @@ +100000 diff --git a/battery/power_supply/usb/online b/battery/power_supply/usb/online new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/battery/power_supply/usb/online @@ -0,0 +1 @@ +1 diff --git a/battery/power_supply/usb/type b/battery/power_supply/usb/type new file mode 100644 index 0000000..3bb28d9 --- /dev/null +++ b/battery/power_supply/usb/type @@ -0,0 +1 @@ +USB diff --git a/battery/power_supply/usb/voltage_max b/battery/power_supply/usb/voltage_max new file mode 100644 index 0000000..447a331 --- /dev/null +++ b/battery/power_supply/usb/voltage_max @@ -0,0 +1 @@ +5000000 diff --git a/battery/power_supply/usb/voltage_now b/battery/power_supply/usb/voltage_now new file mode 100644 index 0000000..b801575 --- /dev/null +++ b/battery/power_supply/usb/voltage_now @@ -0,0 +1 @@ +4600000 diff --git a/gps/gnss/aidl/default/Android.bp b/gps/gnss/aidl/default/Android.bp new file mode 100644 index 0000000..aaf64e2 --- /dev/null +++ b/gps/gnss/aidl/default/Android.bp @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2020 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. + */ + +// package { +// // See: http://go/android-license-faq +// // A large-scale-change added 'default_applicable_licenses' to import +// // all of the 'license_kinds' from "hardware_interfaces_license" +// // to get the below license kinds: +// // SPDX-license-identifier-Apache-2.0 +// default_applicable_licenses: ["hardware_interfaces_license"], +// } + +cc_binary { + name: "android.hardware.gnss-service", + relative_install_path: "hw", +// init_rc: [ +// "gnss-xxx-service.rc", +// ], + vintf_fragments: [ + "gnss-xxx.xml", + "gnss-xxx@2.1-service.xml", + ], + vendor: true, + cflags: [ + "-Wall", + "-Wextra", + ], + shared_libs: [ + "libbase", + "libcutils", + "libbinder_ndk", + "libhidlbase", + "libutils", + "liblog", + "android.hardware.gnss@2.1", + "android.hardware.gnss@2.0", + "android.hardware.gnss@1.1", + "android.hardware.gnss@1.0", + "android.hardware.gnss.measurement_corrections@1.1", + "android.hardware.gnss.measurement_corrections@1.0", + "android.hardware.gnss.visibility_control@1.0", + "android.hardware.gnss-V1-ndk_platform", + ], + srcs: [ + "Gnss.cpp", + "GnssHidlHal.cpp", + "GnssPowerIndication.cpp", + "GnssPsds.cpp", + "GnssConfiguration.cpp", + "GnssMeasurementInterface.cpp", + "service.cpp", + ], + static_libs: [ + "android.hardware.gnss@common-default-lib2", + ], +} diff --git a/gps/gnss/aidl/default/Gnss.cpp b/gps/gnss/aidl/default/Gnss.cpp new file mode 100644 index 0000000..6061eec --- /dev/null +++ b/gps/gnss/aidl/default/Gnss.cpp @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2020 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 "GnssAidl" + +#include "Gnss.h" +#include +#include "GnssConfiguration.h" +#include "GnssMeasurementInterface.h" +#include "GnssPsds.h" + +namespace aidl::android::hardware::gnss { + +std::shared_ptr Gnss::sGnssCallback = nullptr; + +ndk::ScopedAStatus Gnss::setCallback(const std::shared_ptr& callback) { + ALOGD("Gnss::setCallback"); + if (callback == nullptr) { + ALOGE("%s: Null callback ignored", __func__); + return ndk::ScopedAStatus::fromExceptionCode(STATUS_INVALID_OPERATION); + } + + sGnssCallback = callback; + + int capabilities = (int)(IGnssCallback::CAPABILITY_SATELLITE_BLOCKLIST | + IGnssCallback::CAPABILITY_SATELLITE_PVT | + IGnssCallback::CAPABILITY_CORRELATION_VECTOR); + + auto status = sGnssCallback->gnssSetCapabilitiesCb(capabilities); + if (!status.isOk()) { + ALOGE("%s: Unable to invoke callback.gnssSetCapabilities", __func__); + } + + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus Gnss::close() { + ALOGD("Gnss::close"); + sGnssCallback = nullptr; + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus Gnss::getExtensionPsds(std::shared_ptr* iGnssPsds) { + ALOGD("Gnss::getExtensionPsds"); + *iGnssPsds = SharedRefBase::make(); + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus Gnss::getExtensionGnssConfiguration( + std::shared_ptr* iGnssConfiguration) { + ALOGD("Gnss::getExtensionGnssConfiguration"); + if (mGnssConfiguration == nullptr) { + mGnssConfiguration = SharedRefBase::make(); + } + *iGnssConfiguration = mGnssConfiguration; + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus Gnss::getExtensionGnssPowerIndication( + std::shared_ptr* iGnssPowerIndication) { + ALOGD("Gnss::getExtensionGnssPowerIndication"); + if (mGnssPowerIndication == nullptr) { + mGnssPowerIndication = SharedRefBase::make(); + } + + *iGnssPowerIndication = mGnssPowerIndication; + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus Gnss::getExtensionGnssMeasurement( + std::shared_ptr* iGnssMeasurement) { + ALOGD("Gnss::getExtensionGnssMeasurement"); + + *iGnssMeasurement = SharedRefBase::make(); + return ndk::ScopedAStatus::ok(); +} + +} // namespace aidl::android::hardware::gnss diff --git a/gps/gnss/aidl/default/Gnss.h b/gps/gnss/aidl/default/Gnss.h new file mode 100644 index 0000000..76ebe4d --- /dev/null +++ b/gps/gnss/aidl/default/Gnss.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2020 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. + */ + +#pragma once + +#include +#include +#include +#include +#include +#include "GnssConfiguration.h" +#include "GnssPowerIndication.h" + +namespace aidl::android::hardware::gnss { + +class Gnss : public BnGnss { + public: + ndk::ScopedAStatus setCallback(const std::shared_ptr& callback) override; + ndk::ScopedAStatus close() override; + ndk::ScopedAStatus getExtensionPsds(std::shared_ptr* iGnssPsds) override; + ndk::ScopedAStatus getExtensionGnssConfiguration( + std::shared_ptr* iGnssConfiguration) override; + ndk::ScopedAStatus getExtensionGnssPowerIndication( + std::shared_ptr* iGnssPowerIndication) override; + ndk::ScopedAStatus getExtensionGnssMeasurement( + std::shared_ptr* iGnssMeasurement) override; + + std::shared_ptr mGnssConfiguration; + std::shared_ptr mGnssPowerIndication; + + private: + static std::shared_ptr sGnssCallback; +}; + +} // namespace aidl::android::hardware::gnss diff --git a/gps/gnss/aidl/default/GnssConfiguration.cpp b/gps/gnss/aidl/default/GnssConfiguration.cpp new file mode 100644 index 0000000..30e0d8c --- /dev/null +++ b/gps/gnss/aidl/default/GnssConfiguration.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2020 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 "GnssConfigurationAidl" + +#include "GnssConfiguration.h" +#include + +namespace aidl::android::hardware::gnss { + +ndk::ScopedAStatus GnssConfiguration::setBlocklist(const vector& sourceList) { + ALOGD("GnssConfiguration::setBlocklist"); + std::unique_lock lock(mMutex); + mBlocklistedConstellationSet.clear(); + mBlocklistedSourceSet.clear(); + for (const auto& source : sourceList) { + if (source.svid == 0) { + // Wildcard blocklist, i.e., blocklist entire constellation. + mBlocklistedConstellationSet.insert(source.constellation); + } else { + mBlocklistedSourceSet.insert(source); + } + } + return ndk::ScopedAStatus::ok(); +} + +bool GnssConfiguration::isBlocklistedV2_1(const GnssSvInfoV2_1& gnssSvInfo) const { + std::unique_lock lock(mMutex); + if (mBlocklistedConstellationSet.find(static_cast( + gnssSvInfo.v2_0.constellation)) != mBlocklistedConstellationSet.end()) { + return true; + } + BlocklistedSource source = { + .constellation = static_cast(gnssSvInfo.v2_0.constellation), + .svid = gnssSvInfo.v2_0.v1_0.svid}; + return (mBlocklistedSourceSet.find(source) != mBlocklistedSourceSet.end()); +} + +} // namespace aidl::android::hardware::gnss diff --git a/gps/gnss/aidl/default/GnssConfiguration.h b/gps/gnss/aidl/default/GnssConfiguration.h new file mode 100644 index 0000000..491733c --- /dev/null +++ b/gps/gnss/aidl/default/GnssConfiguration.h @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2020 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. + */ + +#pragma once + +#include +#include +#include +#include +#include + +namespace aidl::android::hardware::gnss { + +struct BlocklistedSourceHash { + inline int operator()(const BlocklistedSource& source) const { + return int(source.constellation) * 1000 + int(source.svid); + } +}; + +struct BlocklistedSourceEqual { + inline bool operator()(const BlocklistedSource& s1, const BlocklistedSource& s2) const { + return (s1.constellation == s2.constellation) && (s1.svid == s2.svid); + } +}; + +using GnssSvInfoV2_1 = ::android::hardware::gnss::V2_1::IGnssCallback::GnssSvInfo; +using std::vector; +using BlocklistedSourceSet = + std::unordered_set; +using BlocklistedConstellationSet = + std::unordered_set; + +struct GnssConfiguration : public BnGnssConfiguration { + public: + ndk::ScopedAStatus setSuplVersion(int) override { return ndk::ScopedAStatus::ok(); } + + ndk::ScopedAStatus setSuplMode(int) override { return ndk::ScopedAStatus::ok(); } + + ndk::ScopedAStatus setLppProfile(int) override { return ndk::ScopedAStatus::ok(); } + + ndk::ScopedAStatus setGlonassPositioningProtocol(int) override { + return ndk::ScopedAStatus::ok(); + } + + ndk::ScopedAStatus setEmergencySuplPdn(bool) override { return ndk::ScopedAStatus::ok(); } + + ndk::ScopedAStatus setEsExtensionSec(int) override { return ndk::ScopedAStatus::ok(); } + + ndk::ScopedAStatus setBlocklist(const vector& blocklist) override; + + bool isBlocklistedV2_1(const GnssSvInfoV2_1& gnssSvInfo) const; + + private: + BlocklistedSourceSet mBlocklistedSourceSet; + BlocklistedConstellationSet mBlocklistedConstellationSet; + mutable std::recursive_mutex mMutex; +}; + +} // namespace aidl::android::hardware::gnss diff --git a/gps/gnss/aidl/default/GnssHidlHal.cpp b/gps/gnss/aidl/default/GnssHidlHal.cpp new file mode 100644 index 0000000..10b0106 --- /dev/null +++ b/gps/gnss/aidl/default/GnssHidlHal.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2020 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 "GnssHidlHal" + +#include "GnssHidlHal.h" + +namespace aidl::android::hardware::gnss { + +using GnssSvInfo = ::android::hardware::gnss::V2_1::IGnssCallback::GnssSvInfo; + +GnssHidlHal::GnssHidlHal(const std::shared_ptr& gnssAidl) : mGnssAidl(gnssAidl) { + Gnss* iGnss = mGnssAidl.get(); + std::shared_ptr iGnssConfiguration; + auto status = iGnss->getExtensionGnssConfiguration(&iGnssConfiguration); + if (!status.isOk()) { + ALOGE("Failed to getExtensionGnssConfiguration."); + } else { + mGnssConfigurationAidl = iGnss->mGnssConfiguration; + } + + std::shared_ptr iGnssPowerIndication; + status = iGnss->getExtensionGnssPowerIndication(&iGnssPowerIndication); + if (!status.isOk()) { + ALOGE("Failed to getExtensionGnssPowerIndication."); + } else { + mGnssPowerIndicationAidl = iGnss->mGnssPowerIndication; + } +}; + +hidl_vec GnssHidlHal::filterBlocklistedSatellitesV2_1( + hidl_vec gnssSvInfoList) { + if (mGnssConfigurationAidl == nullptr) { + ALOGE("Handle to AIDL GnssConfiguration is not available."); + return gnssSvInfoList; + } + for (uint32_t i = 0; i < gnssSvInfoList.size(); i++) { + if (mGnssConfigurationAidl->isBlocklistedV2_1(gnssSvInfoList[i])) { + ALOGD("Blocklisted constellation: %d, svid: %d", + (int)gnssSvInfoList[i].v2_0.constellation, gnssSvInfoList[i].v2_0.v1_0.svid); + gnssSvInfoList[i].v2_0.v1_0.svFlag &= ~static_cast( + ::android::hardware::gnss::V1_0::IGnssCallback::GnssSvFlags::USED_IN_FIX); + } + } + return gnssSvInfoList; +} + +void GnssHidlHal::notePowerConsumption() { + mGnssPowerIndicationAidl->notePowerConsumption(); +} + +} // namespace aidl::android::hardware::gnss diff --git a/gps/gnss/aidl/default/GnssHidlHal.h b/gps/gnss/aidl/default/GnssHidlHal.h new file mode 100644 index 0000000..5fb4f97 --- /dev/null +++ b/gps/gnss/aidl/default/GnssHidlHal.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2020 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. + */ + +#pragma once + +#include "Gnss.h" +#include "GnssConfiguration.h" +#include "v2_1/GnssTemplate.h" + +namespace aidl::android::hardware::gnss { + +class GnssHidlHal : public ::android::hardware::gnss::common::implementation::GnssTemplate< + ::android::hardware::gnss::V2_1::IGnss> { + public: + GnssHidlHal(const std::shared_ptr& gnssAidl); + + private: + hidl_vec<::android::hardware::gnss::V2_1::IGnssCallback::GnssSvInfo> + filterBlocklistedSatellitesV2_1( + hidl_vec<::android::hardware::gnss::V2_1::IGnssCallback::GnssSvInfo> gnssSvInfoList) + override; + void notePowerConsumption() override; + + std::shared_ptr mGnssAidl; + std::shared_ptr mGnssConfigurationAidl; + std::shared_ptr mGnssPowerIndicationAidl; +}; + +} // namespace aidl::android::hardware::gnss diff --git a/gps/gnss/aidl/default/GnssMeasurementInterface.cpp b/gps/gnss/aidl/default/GnssMeasurementInterface.cpp new file mode 100644 index 0000000..fcc1f98 --- /dev/null +++ b/gps/gnss/aidl/default/GnssMeasurementInterface.cpp @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2020 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 "GnssMeasIfaceAidl" + +#include "GnssMeasurementInterface.h" +#include +#include +#include "Utils.h" + +namespace aidl::android::hardware::gnss { + +using Utils = ::android::hardware::gnss::common::Utils; + +std::shared_ptr GnssMeasurementInterface::sCallback = nullptr; + +GnssMeasurementInterface::GnssMeasurementInterface() : mMinIntervalMillis(1000) {} + +GnssMeasurementInterface::~GnssMeasurementInterface() { + stop(); +} + +ndk::ScopedAStatus GnssMeasurementInterface::setCallback( + const std::shared_ptr& callback, const bool enableFullTracking, + const bool enableCorrVecOutputs) { + ALOGD("setCallback: enableFullTracking: %d enableCorrVecOutputs: %d", (int)enableFullTracking, + (int)enableCorrVecOutputs); + std::unique_lock lock(mMutex); + sCallback = callback; + + if (mIsActive) { + ALOGW("GnssMeasurement callback already set. Resetting the callback..."); + stop(); + } + start(enableCorrVecOutputs); + + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus GnssMeasurementInterface::close() { + ALOGD("close"); + stop(); + std::unique_lock lock(mMutex); + sCallback = nullptr; + return ndk::ScopedAStatus::ok(); +} + +void GnssMeasurementInterface::start(const bool enableCorrVecOutputs) { + ALOGD("start"); + mIsActive = true; + mThread = std::thread([this, enableCorrVecOutputs]() { + while (mIsActive == true) { + auto measurement = Utils::getMockMeasurement(enableCorrVecOutputs); + this->reportMeasurement(measurement); + + std::this_thread::sleep_for(std::chrono::milliseconds(mMinIntervalMillis)); + } + }); + mThread.detach(); +} + +void GnssMeasurementInterface::stop() { + ALOGD("stop"); + mIsActive = false; +} + +void GnssMeasurementInterface::reportMeasurement(const GnssData& data) { + ALOGD("reportMeasurement()"); + std::shared_ptr callbackCopy; + { + std::unique_lock lock(mMutex); + if (sCallback == nullptr) { + ALOGE("%s: GnssMeasurement::sCallback is null.", __func__); + return; + } + callbackCopy = sCallback; + } + callbackCopy->gnssMeasurementCb(data); +} + +} // namespace aidl::android::hardware::gnss diff --git a/gps/gnss/aidl/default/GnssMeasurementInterface.h b/gps/gnss/aidl/default/GnssMeasurementInterface.h new file mode 100644 index 0000000..db63515 --- /dev/null +++ b/gps/gnss/aidl/default/GnssMeasurementInterface.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2020 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. + */ + +#pragma once + +#include +#include +#include +#include +#include + +namespace aidl::android::hardware::gnss { + +struct GnssMeasurementInterface : public BnGnssMeasurementInterface { + public: + GnssMeasurementInterface(); + ~GnssMeasurementInterface(); + ndk::ScopedAStatus setCallback(const std::shared_ptr& callback, + const bool enableFullTracking, + const bool enableCorrVecOutputs) override; + ndk::ScopedAStatus close() override; + + private: + void start(const bool enableCorrVecOutputs); + void stop(); + void reportMeasurement(const GnssData&); + + std::atomic mMinIntervalMillis; + std::atomic mIsActive; + std::thread mThread; + + // Guarded by mMutex + static std::shared_ptr sCallback; + + // Synchronization lock for sCallback + mutable std::mutex mMutex; +}; + +} // namespace aidl::android::hardware::gnss diff --git a/gps/gnss/aidl/default/GnssPowerIndication.cpp b/gps/gnss/aidl/default/GnssPowerIndication.cpp new file mode 100644 index 0000000..4dec1c6 --- /dev/null +++ b/gps/gnss/aidl/default/GnssPowerIndication.cpp @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2020 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 "GnssPowerIndicationAidl" + +#include "GnssPowerIndication.h" +#include +#include +#include + +namespace aidl::android::hardware::gnss { + +std::shared_ptr GnssPowerIndication::sCallback = nullptr; + +ndk::ScopedAStatus GnssPowerIndication::setCallback( + const std::shared_ptr& callback) { + ALOGD("setCallback"); + std::unique_lock lock(mMutex); + sCallback = callback; + sCallback->setCapabilitiesCb(IGnssPowerIndicationCallback::CAPABILITY_TOTAL | + IGnssPowerIndicationCallback::CAPABILITY_SINGLEBAND_TRACKING | + IGnssPowerIndicationCallback::CAPABILITY_MULTIBAND_TRACKING | + IGnssPowerIndicationCallback::CAPABILITY_SINGLEBAND_ACQUISITION | + IGnssPowerIndicationCallback::CAPABILITY_MULTIBAND_ACQUISITION | + IGnssPowerIndicationCallback::CAPABILITY_OTHER_MODES); + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus GnssPowerIndication::requestGnssPowerStats() { + ALOGD("requestGnssPowerStats"); + std::unique_lock lock(mMutex); + + ElapsedRealtime elapsedRealtime = { + .flags = ElapsedRealtime::HAS_TIMESTAMP_NS | ElapsedRealtime::HAS_TIME_UNCERTAINTY_NS, + .timestampNs = ::android::elapsedRealtimeNano(), + .timeUncertaintyNs = 1000, + }; + GnssPowerStats gnssPowerStats = { + .elapsedRealtime = elapsedRealtime, + .totalEnergyMilliJoule = 1.500e+3 + numLocationReported * 22.0, + .singlebandTrackingModeEnergyMilliJoule = 0.0, + .multibandTrackingModeEnergyMilliJoule = 1.28e+2 + numLocationReported * 4.0, + .singlebandAcquisitionModeEnergyMilliJoule = 0.0, + .multibandAcquisitionModeEnergyMilliJoule = 3.65e+2 + numLocationReported * 15.0, + .otherModesEnergyMilliJoule = {1.232e+2, 3.234e+3}, + }; + sCallback->gnssPowerStatsCb(gnssPowerStats); + return ndk::ScopedAStatus::ok(); +} + +void GnssPowerIndication::notePowerConsumption() { + numLocationReported++; +} + +} // namespace aidl::android::hardware::gnss diff --git a/gps/gnss/aidl/default/GnssPowerIndication.h b/gps/gnss/aidl/default/GnssPowerIndication.h new file mode 100644 index 0000000..93ca0b7 --- /dev/null +++ b/gps/gnss/aidl/default/GnssPowerIndication.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2020 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. + */ + +#pragma once + +#include + +namespace aidl::android::hardware::gnss { + +struct GnssPowerIndication : public BnGnssPowerIndication { + public: + ndk::ScopedAStatus setCallback( + const std::shared_ptr& callback) override; + ndk::ScopedAStatus requestGnssPowerStats() override; + + void notePowerConsumption(); + + private: + // Guarded by mMutex + static std::shared_ptr sCallback; + + // Synchronization lock for sCallback + mutable std::mutex mMutex; + + int numLocationReported; +}; + +} // namespace aidl::android::hardware::gnss diff --git a/gps/gnss/aidl/default/GnssPsds.cpp b/gps/gnss/aidl/default/GnssPsds.cpp new file mode 100644 index 0000000..6512af6 --- /dev/null +++ b/gps/gnss/aidl/default/GnssPsds.cpp @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2020 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 "GnssPsdsAidl" + +#include "GnssPsds.h" +#include +#include + +namespace aidl::android::hardware::gnss { + +std::shared_ptr GnssPsds::sCallback = nullptr; + +ndk::ScopedAStatus GnssPsds::setCallback(const std::shared_ptr& callback) { + ALOGD("setCallback"); + std::unique_lock lock(mMutex); + sCallback = callback; + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus GnssPsds::injectPsdsData(PsdsType psdsType, + const std::vector& psdsData) { + ALOGD("injectPsdsData. psdsType: %d, psdsData: %d bytes", static_cast(psdsType), + static_cast(psdsData.size())); + if (psdsData.size() > 0) { + return ndk::ScopedAStatus::ok(); + } else { + return ndk::ScopedAStatus::fromServiceSpecificError(IGnss::ERROR_INVALID_ARGUMENT); + } +} +} // namespace aidl::android::hardware::gnss diff --git a/gps/gnss/aidl/default/GnssPsds.h b/gps/gnss/aidl/default/GnssPsds.h new file mode 100644 index 0000000..de9e68f --- /dev/null +++ b/gps/gnss/aidl/default/GnssPsds.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2020 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. + */ + +#pragma once + +#include + +namespace aidl::android::hardware::gnss { + +struct GnssPsds : public BnGnssPsds { + public: + ndk::ScopedAStatus setCallback(const std::shared_ptr& callback) override; + ndk::ScopedAStatus injectPsdsData(PsdsType psdsType, + const std::vector& psdsData) override; + + private: + // Guarded by mMutex + static std::shared_ptr sCallback; + + // Synchronization lock for sCallback + mutable std::mutex mMutex; +}; + +} // namespace aidl::android::hardware::gnss diff --git a/gps/gnss/aidl/default/gnss-xxx-service.rc b/gps/gnss/aidl/default/gnss-xxx-service.rc new file mode 100644 index 0000000..15cddd1 --- /dev/null +++ b/gps/gnss/aidl/default/gnss-xxx-service.rc @@ -0,0 +1,4 @@ +service gnss /vendor/bin/hw/android.hardware.gnss-service + class hal + user nobody + group nobody \ No newline at end of file diff --git a/gps/gnss/aidl/default/gnss-xxx.xml b/gps/gnss/aidl/default/gnss-xxx.xml new file mode 100644 index 0000000..2b06cd2 --- /dev/null +++ b/gps/gnss/aidl/default/gnss-xxx.xml @@ -0,0 +1,9 @@ + + + android.hardware.gnss + + IGnss + default + + + diff --git a/gps/gnss/aidl/default/gnss-xxx@2.1-service.xml b/gps/gnss/aidl/default/gnss-xxx@2.1-service.xml new file mode 100644 index 0000000..12a1fdf --- /dev/null +++ b/gps/gnss/aidl/default/gnss-xxx@2.1-service.xml @@ -0,0 +1,12 @@ + + + android.hardware.gnss + hwbinder + 2.1 + 1.1 + + IGnss + default + + + diff --git a/gps/gnss/aidl/default/service.cpp b/gps/gnss/aidl/default/service.cpp new file mode 100644 index 0000000..09f1ad2 --- /dev/null +++ b/gps/gnss/aidl/default/service.cpp @@ -0,0 +1,58 @@ +/* + * Copyright 2020, 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 "Gnss-main" + +#include +#include +#include +#include +#include +#include +#include +#include "Gnss.h" +#include "GnssHidlHal.h" + +using aidl::android::hardware::gnss::Gnss; +using aidl::android::hardware::gnss::GnssHidlHal; +using ::android::OK; +using ::android::sp; +using ::android::hardware::configureRpcThreadpool; +using ::android::hardware::joinRpcThreadpool; +using ::android::hardware::gnss::V2_1::IGnss; + +int main() { + ABinderProcess_setThreadPoolMaxThreadCount(1); + ABinderProcess_startThreadPool(); + + std::shared_ptr gnssAidl = ndk::SharedRefBase::make(); + const std::string instance = std::string() + Gnss::descriptor + "/default"; + binder_status_t status = + AServiceManager_addService(gnssAidl->asBinder().get(), instance.c_str()); + CHECK(status == STATUS_OK); + + sp gnss = new GnssHidlHal(gnssAidl); + configureRpcThreadpool(1, true /* will join */); + if (gnss->registerAsService() != OK) { + ALOGE("Could not register gnss 2.1 service."); + return 0; + } + + joinRpcThreadpool(); + ABinderProcess_joinThreadPool(); + + return EXIT_FAILURE; // should not reach +} diff --git a/gps/gnss/common/OWNERS b/gps/gnss/common/OWNERS new file mode 100644 index 0000000..3ed36da --- /dev/null +++ b/gps/gnss/common/OWNERS @@ -0,0 +1,7 @@ +wyattriley@google.com +gomo@google.com +smalkos@google.com +yuhany@google.com + +# VTS team +yim@google.com diff --git a/gps/gnss/common/utils/default/Android.bp b/gps/gnss/common/utils/default/Android.bp new file mode 100644 index 0000000..63abff9 --- /dev/null +++ b/gps/gnss/common/utils/default/Android.bp @@ -0,0 +1,57 @@ +// +// Copyright (C) 2019 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. +// + +// package { +// // See: http://go/android-license-faq +// // A large-scale-change added 'default_applicable_licenses' to import +// // all of the 'license_kinds' from "hardware_interfaces_license" +// // to get the below license kinds: +// // SPDX-license-identifier-Apache-2.0 +// default_applicable_licenses: ["hardware_interfaces_license"], +// } + +cc_library_static { + name: "android.hardware.gnss@common-default-lib2", + vendor_available: true, + relative_install_path: "hw", + cflags: [ + "-Wall", + "-Wextra", + "-Werror", + ], + srcs: [ + "v2_1/GnssAntennaInfo.cpp", + "v2_1/GnssConfiguration.cpp", + "v2_1/GnssDebug.cpp", + "v2_1/GnssMeasurement.cpp", + "v2_1/GnssMeasurementCorrections.cpp", + "MockLocation.cpp", + "Utils.cpp", + "NmeaFixInfo.cpp", + ], + export_include_dirs: ["include"], + shared_libs: [ + "libcutils", + "libhidlbase", + "libutils", + "android.hardware.gnss@1.0", + "android.hardware.gnss@2.0", + "android.hardware.gnss@2.1", + "android.hardware.gnss.measurement_corrections@1.1", + "android.hardware.gnss.measurement_corrections@1.0", + "android.hardware.gnss-V1-ndk_platform", + ], +} diff --git a/gps/gnss/common/utils/default/MockLocation.cpp b/gps/gnss/common/utils/default/MockLocation.cpp new file mode 100644 index 0000000..c90075f --- /dev/null +++ b/gps/gnss/common/utils/default/MockLocation.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2020 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. + */ + +#include "MockLocation.h" + +namespace android::hardware::gnss::common { + +float gMockLatitudeDegrees{37.4219999}; +float gMockLongitudeDegrees{-122.0840575}; +float gMockAltitudeMeters{1.60062531}; +float gMockBearingDegrees{0}; +float gMockSpeedMetersPerSec{0}; + +} // namespace android::hardware::gnss::common diff --git a/gps/gnss/common/utils/default/NmeaFixInfo.cpp b/gps/gnss/common/utils/default/NmeaFixInfo.cpp new file mode 100644 index 0000000..c7ee134 --- /dev/null +++ b/gps/gnss/common/utils/default/NmeaFixInfo.cpp @@ -0,0 +1,273 @@ +/* + * Copyright (C) 2020 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 "NmeaFixInfo" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace android { +namespace hardware { +namespace gnss { +namespace common { + +NmeaFixInfo::NmeaFixInfo() : hasGMCRecord(false), hasGGARecord(false) {} + +float NmeaFixInfo::getAltitudeMeters() const { + return altitudeMeters; +} + +float NmeaFixInfo::checkAndConvertToFloat(const std::string& sentence) { + if (sentence.empty()) { + return std::numeric_limits::quiet_NaN(); + } + return std::stof(sentence); +} + +float NmeaFixInfo::getBearingAccuracyDegrees() const { + // Current NMEA doesn't contains beaing accuracy inforamtion + return kMockBearingAccuracyDegrees; +} +float NmeaFixInfo::getBearingDegrees() const { + return bearingDegrees; +} + +float NmeaFixInfo::getHorizontalAccuracyMeters() const { + // Current NMEA doesn't contains horizontal accuracy inforamtion + return kMockHorizontalAccuracyMeters; +} + +float NmeaFixInfo::getLatDeg() const { + return latDeg; +} + +float NmeaFixInfo::getLngDeg() const { + return lngDeg; +} + +float NmeaFixInfo::getSpeedAccuracyMetersPerSecond() const { + // Current NMEA doesn't contains speed accuracy inforamtion + return kMockSpeedAccuracyMetersPerSecond; +} + +float NmeaFixInfo::getSpeedMetersPerSec() const { + return speedMetersPerSec; +} + +int64_t NmeaFixInfo::getTimestamp() const { + return timestamp; +} + +float NmeaFixInfo::getVerticalAccuracyMeters() const { + // Current NMEA doesn't contains vertical accuracy inforamtion + return kMockVerticalAccuracyMeters; +} + +int64_t NmeaFixInfo::nmeaPartsToTimestamp(const std::string& timeStr, const std::string& dateStr) { + /** + * In NMEA format, the full time can only get from the $GPRMC record, see + * the following example: + * $GPRMC,213204.00,A,3725.371240,N,12205.589239,W,000.0,000.0,290819,,,A*49 + * the datetime is stored in two parts, 213204 and 290819, which means + * 2019/08/29 21:32:04, however for in unix the year starts from 1900, we + * need to add the offset. + */ + struct tm tm; + const int32_t unixYearOffset = 100; + tm.tm_mday = std::stoi(dateStr.substr(0, 2).c_str()); + tm.tm_mon = std::stoi(dateStr.substr(2, 2).c_str()) - 1; + tm.tm_year = std::stoi(dateStr.substr(4, 2).c_str()) + unixYearOffset; + tm.tm_hour = std::stoi(timeStr.substr(0, 2).c_str()); + tm.tm_min = std::stoi(timeStr.substr(2, 2).c_str()); + tm.tm_sec = std::stoi(timeStr.substr(4, 2).c_str()); + return static_cast(mktime(&tm) - timezone); +} + +bool NmeaFixInfo::isValidFix() const { + return hasGMCRecord && hasGGARecord; +} + +void NmeaFixInfo::parseGGALine(const std::vector& sentenceValues) { + if (sentenceValues.size() == 0 || sentenceValues[0].compare(GPGA_RECORD_TAG) != 0) { + return; + } + // LatDeg, need covert to degree, if it is 'N', should be negative value + this->latDeg = std::stof(sentenceValues[2].substr(0, 2)) + + (std::stof(sentenceValues[2].substr(2)) / 60.0); + if (sentenceValues[3].compare("N") != 0) { + this->latDeg *= -1; + } + + // LngDeg, need covert to degree, if it is 'E', should be negative value + this->lngDeg = std::stof(sentenceValues[4].substr(0, 3)) + + std::stof(sentenceValues[4].substr(3)) / 60.0; + if (sentenceValues[5].compare("E") != 0) { + this->lngDeg *= -1; + } + + this->altitudeMeters = std::stof(sentenceValues[9]); + + this->hDop = sentenceValues[8].empty() ? std::numeric_limits::quiet_NaN() + : std::stof(sentenceValues[8]); + this->hasGGARecord = true; +} + +void NmeaFixInfo::parseRMCLine(const std::vector& sentenceValues) { + if (sentenceValues.size() == 0 || sentenceValues[0].compare(GPRMC_RECORD_TAG) != 0) { + return; + } + this->speedMetersPerSec = checkAndConvertToFloat(sentenceValues[7]); + this->bearingDegrees = checkAndConvertToFloat(sentenceValues[8]); + this->timestamp = nmeaPartsToTimestamp(sentenceValues[1], sentenceValues[9]); + this->hasGMCRecord = true; +} + +/** invalid the current NmeaFixInfo */ +void NmeaFixInfo::reset() { + this->altitudeMeters = 0; + this->bearingDegrees = 0; + this->fixId = 0; + this->hasGMCRecord = false; + this->hasGGARecord = false; + this->latDeg = 0; + this->lngDeg = 0; + this->hDop = 0; + this->vDop = 0; + this->satelliteCount = 0; + this->speedMetersPerSec = 0; + this->timestamp = 0; +} + +void NmeaFixInfo::splitStr(const std::string& line, const char& delimiter, + std::vector& out) { + std::istringstream iss(line); + std::string item; + while (std::getline(iss, item, delimiter)) { + out.push_back(item); + } +} + +NmeaFixInfo& NmeaFixInfo::operator=(const NmeaFixInfo& rhs) { + if (this == &rhs) return *this; + this->altitudeMeters = rhs.altitudeMeters; + this->bearingDegrees = rhs.bearingDegrees; + this->fixId = rhs.fixId; + this->hasGMCRecord = rhs.hasGMCRecord; + this->hasGGARecord = rhs.hasGGARecord; + this->hDop = rhs.hDop; + this->vDop = rhs.vDop; + this->latDeg = rhs.latDeg; + this->lngDeg = rhs.lngDeg; + this->satelliteCount = rhs.satelliteCount; + this->speedMetersPerSec = rhs.speedMetersPerSec; + this->timestamp = rhs.timestamp; + + return *this; +} + +/** + * Parses the input string in NMEA format and convert to GnssLocation. + * Currently version only cares about $GPGGA and $GPRMC records. but we + * can easily extend to other types supported by NMEA if needed. + */ +std::unique_ptr NmeaFixInfo::getLocationFromInputStr( + const std::string& inputStr) { + std::vector nmeaRecords; + splitStr(inputStr, LINE_SEPARATOR, nmeaRecords); + NmeaFixInfo nmeaFixInfo; + NmeaFixInfo candidateFixInfo; + uint32_t fixId = 0; + double lastTimeStamp = 0; + for (const auto& line : nmeaRecords) { + if (line.compare(0, strlen(GPGA_RECORD_TAG), GPGA_RECORD_TAG) != 0 && + line.compare(0, strlen(GPRMC_RECORD_TAG), GPRMC_RECORD_TAG) != 0) { + continue; + } + std::vector sentenceValues; + splitStr(line, COMMA_SEPARATOR, sentenceValues); + if (sentenceValues.size() < MIN_COL_NUM) { + continue; + } + double currentTimeStamp = std::stof(sentenceValues[1]); + // If see a new timestamp, report correct location. + if ((currentTimeStamp - lastTimeStamp) > TIMESTAMP_EPSILON && + candidateFixInfo.isValidFix()) { + nmeaFixInfo = candidateFixInfo; + candidateFixInfo.reset(); + fixId++; + } + if (line.compare(0, strlen(GPGA_RECORD_TAG), GPGA_RECORD_TAG) == 0) { + candidateFixInfo.fixId = fixId; + candidateFixInfo.parseGGALine(sentenceValues); + } else if (line.compare(0, strlen(GPRMC_RECORD_TAG), GPRMC_RECORD_TAG) == 0) { + candidateFixInfo.parseRMCLine(sentenceValues); + } + } + if (candidateFixInfo.isValidFix()) { + nmeaFixInfo = candidateFixInfo; + candidateFixInfo.reset(); + } + if (!nmeaFixInfo.isValidFix()) { + return nullptr; + } + return nmeaFixInfo.toGnssLocation(); +} + +/** + * Parses the input string in NMEA format and convert to GnssLocation. + */ +std::unique_ptr NmeaFixInfo::toGnssLocation() const { + const V2_0::ElapsedRealtime currentOsTimestamp = { + .flags = V2_0::ElapsedRealtimeFlags::HAS_TIMESTAMP_NS | + V2_0::ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS, + .timestampNs = static_cast(::android::elapsedRealtimeNano()), + // This is an hardcoded value indicating a 1ms of uncertainty between the two clocks. + // In an actual implementation provide an estimate of the synchronization uncertainty + // or don't set the field. + .timeUncertaintyNs = 1000000}; + + V1_0::GnssLocation locationV1 = { + .gnssLocationFlags = 0xFF, + .latitudeDegrees = this->getLatDeg(), + .longitudeDegrees = this->getLngDeg(), + .altitudeMeters = this->getAltitudeMeters(), + .speedMetersPerSec = this->getSpeedMetersPerSec(), + .bearingDegrees = this->getBearingDegrees(), + .horizontalAccuracyMeters = this->getHorizontalAccuracyMeters(), + .verticalAccuracyMeters = this->getVerticalAccuracyMeters(), + .speedAccuracyMetersPerSecond = this->getSpeedAccuracyMetersPerSecond(), + .bearingAccuracyDegrees = this->getBearingAccuracyDegrees(), + .timestamp = this->getTimestamp()}; + + V2_0::GnssLocation locationV2 = {.v1_0 = locationV1, .elapsedRealtime = currentOsTimestamp}; + + return std::make_unique(locationV2); +} + +} // namespace common +} // namespace gnss +} // namespace hardware +} // namespace android \ No newline at end of file diff --git a/gps/gnss/common/utils/default/Utils.cpp b/gps/gnss/common/utils/default/Utils.cpp new file mode 100644 index 0000000..23e39b2 --- /dev/null +++ b/gps/gnss/common/utils/default/Utils.cpp @@ -0,0 +1,405 @@ +/* + * Copyright (C) 2019 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. + */ + +#include +#include +#include +#include +#include + +namespace android { +namespace hardware { +namespace gnss { +namespace common { + +using aidl::android::hardware::gnss::ElapsedRealtime; +using aidl::android::hardware::gnss::GnssClock; +using aidl::android::hardware::gnss::GnssData; +using aidl::android::hardware::gnss::GnssMeasurement; +using aidl::android::hardware::gnss::IGnss; +using aidl::android::hardware::gnss::IGnssMeasurementCallback; +using aidl::android::hardware::gnss::SatellitePvt; + +using GnssSvFlags = V1_0::IGnssCallback::GnssSvFlags; +using GnssMeasurementFlagsV1_0 = V1_0::IGnssMeasurementCallback::GnssMeasurementFlags; +using GnssMeasurementFlagsV2_1 = V2_1::IGnssMeasurementCallback::GnssMeasurementFlags; +using GnssMeasurementStateV2_0 = V2_0::IGnssMeasurementCallback::GnssMeasurementState; +using ElapsedRealtimeFlags = V2_0::ElapsedRealtimeFlags; +using GnssConstellationTypeV2_0 = V2_0::GnssConstellationType; +using IGnssMeasurementCallbackV2_0 = V2_0::IGnssMeasurementCallback; +using GnssSignalType = V2_1::GnssSignalType; + +using GnssDataV2_0 = V2_0::IGnssMeasurementCallback::GnssData; +using GnssDataV2_1 = V2_1::IGnssMeasurementCallback::GnssData; +using GnssSvInfoV1_0 = V1_0::IGnssCallback::GnssSvInfo; +using GnssSvInfoV2_0 = V2_0::IGnssCallback::GnssSvInfo; +using GnssSvInfoV2_1 = V2_1::IGnssCallback::GnssSvInfo; +using GnssAntennaInfo = ::android::hardware::gnss::V2_1::IGnssAntennaInfoCallback::GnssAntennaInfo; +using Row = V2_1::IGnssAntennaInfoCallback::Row; +using Coord = V2_1::IGnssAntennaInfoCallback::Coord; + +GnssDataV2_1 Utils::getMockMeasurementV2_1() { + GnssDataV2_0 gnssDataV2_0 = Utils::getMockMeasurementV2_0(); + V2_1::IGnssMeasurementCallback::GnssMeasurement gnssMeasurementV2_1 = { + .v2_0 = gnssDataV2_0.measurements[0], + .flags = (uint32_t)(GnssMeasurementFlagsV2_1::HAS_CARRIER_FREQUENCY | + GnssMeasurementFlagsV2_1::HAS_CARRIER_PHASE | + GnssMeasurementFlagsV2_1::HAS_FULL_ISB | + GnssMeasurementFlagsV2_1::HAS_FULL_ISB_UNCERTAINTY | + GnssMeasurementFlagsV2_1::HAS_SATELLITE_ISB | + GnssMeasurementFlagsV2_1::HAS_SATELLITE_ISB_UNCERTAINTY), + .fullInterSignalBiasNs = 30.0, + .fullInterSignalBiasUncertaintyNs = 250.0, + .satelliteInterSignalBiasNs = 20.0, + .satelliteInterSignalBiasUncertaintyNs = 150.0, + .basebandCN0DbHz = 25.0, + }; + GnssSignalType referenceSignalTypeForIsb = { + .constellation = GnssConstellationTypeV2_0::GPS, + .carrierFrequencyHz = 1.59975e+09, + .codeType = "C", + }; + V2_1::IGnssMeasurementCallback::GnssClock gnssClockV2_1 = { + .v1_0 = gnssDataV2_0.clock, + .referenceSignalTypeForIsb = referenceSignalTypeForIsb, + }; + hidl_vec measurements(1); + measurements[0] = gnssMeasurementV2_1; + GnssDataV2_1 gnssDataV2_1 = { + .measurements = measurements, + .clock = gnssClockV2_1, + .elapsedRealtime = gnssDataV2_0.elapsedRealtime, + }; + return gnssDataV2_1; +} + +GnssDataV2_0 Utils::getMockMeasurementV2_0() { + V1_0::IGnssMeasurementCallback::GnssMeasurement measurement_1_0 = { + .flags = (uint32_t)GnssMeasurementFlagsV1_0::HAS_CARRIER_FREQUENCY, + .svid = (int16_t)6, + .constellation = V1_0::GnssConstellationType::UNKNOWN, + .timeOffsetNs = 0.0, + .receivedSvTimeInNs = 8195997131077, + .receivedSvTimeUncertaintyInNs = 15, + .cN0DbHz = 30.0, + .pseudorangeRateMps = -484.13739013671875, + .pseudorangeRateUncertaintyMps = 1.0379999876022339, + .accumulatedDeltaRangeState = (uint32_t)V1_0::IGnssMeasurementCallback:: + GnssAccumulatedDeltaRangeState::ADR_STATE_UNKNOWN, + .accumulatedDeltaRangeM = 0.0, + .accumulatedDeltaRangeUncertaintyM = 0.0, + .carrierFrequencyHz = 1.59975e+09, + .multipathIndicator = + V1_0::IGnssMeasurementCallback::GnssMultipathIndicator::INDICATOR_UNKNOWN}; + V1_1::IGnssMeasurementCallback::GnssMeasurement measurement_1_1 = {.v1_0 = measurement_1_0}; + V2_0::IGnssMeasurementCallback::GnssMeasurement measurement_2_0 = { + .v1_1 = measurement_1_1, + .codeType = "C", + .state = GnssMeasurementStateV2_0::STATE_CODE_LOCK | + GnssMeasurementStateV2_0::STATE_BIT_SYNC | + GnssMeasurementStateV2_0::STATE_SUBFRAME_SYNC | + GnssMeasurementStateV2_0::STATE_TOW_DECODED | + GnssMeasurementStateV2_0::STATE_GLO_STRING_SYNC | + GnssMeasurementStateV2_0::STATE_GLO_TOD_DECODED, + .constellation = GnssConstellationTypeV2_0::GLONASS, + }; + + hidl_vec measurements(1); + measurements[0] = measurement_2_0; + V1_0::IGnssMeasurementCallback::GnssClock clock = {.timeNs = 2713545000000, + .fullBiasNs = -1226701900521857520, + .biasNs = 0.59689998626708984, + .biasUncertaintyNs = 47514.989972114563, + .driftNsps = -51.757811607455452, + .driftUncertaintyNsps = 310.64968328491528, + .hwClockDiscontinuityCount = 1}; + + V2_0::ElapsedRealtime timestamp = { + .flags = ElapsedRealtimeFlags::HAS_TIMESTAMP_NS | + ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS, + .timestampNs = static_cast(::android::elapsedRealtimeNano()), + // This is an hardcoded value indicating a 1ms of uncertainty between the two clocks. + // In an actual implementation provide an estimate of the synchronization uncertainty + // or don't set the field. + .timeUncertaintyNs = 1000000}; + + GnssDataV2_0 gnssData = { + .measurements = measurements, .clock = clock, .elapsedRealtime = timestamp}; + return gnssData; +} + +GnssData Utils::getMockMeasurement(const bool enableCorrVecOutputs) { + aidl::android::hardware::gnss::GnssSignalType signalType = { + .constellation = aidl::android::hardware::gnss::GnssConstellationType::GLONASS, + .carrierFrequencyHz = 1.59975e+09, + .codeType = aidl::android::hardware::gnss::GnssSignalType::CODE_TYPE_C, + }; + GnssMeasurement measurement = { + .flags = GnssMeasurement::HAS_AUTOMATIC_GAIN_CONTROL | + GnssMeasurement::HAS_CARRIER_FREQUENCY | GnssMeasurement::HAS_CARRIER_PHASE | + GnssMeasurement::HAS_CARRIER_PHASE_UNCERTAINTY | + GnssMeasurement::HAS_FULL_ISB | GnssMeasurement::HAS_FULL_ISB_UNCERTAINTY | + GnssMeasurement::HAS_SATELLITE_ISB | + GnssMeasurement::HAS_SATELLITE_ISB_UNCERTAINTY | + GnssMeasurement::HAS_SATELLITE_PVT, + .svid = 13, + .signalType = signalType, + .receivedSvTimeInNs = 8195997131077, + .receivedSvTimeUncertaintyInNs = 15, + .antennaCN0DbHz = 30.0, + .basebandCN0DbHz = 26.5, + .agcLevelDb = 2.3, + .pseudorangeRateMps = -484.13739013671875, + .pseudorangeRateUncertaintyMps = 1.0379999876022339, + .accumulatedDeltaRangeState = GnssMeasurement::ADR_STATE_UNKNOWN, + .accumulatedDeltaRangeM = 1.52, + .accumulatedDeltaRangeUncertaintyM = 2.43, + .multipathIndicator = aidl::android::hardware::gnss::GnssMultipathIndicator::UNKNOWN, + .state = GnssMeasurement::STATE_CODE_LOCK | GnssMeasurement::STATE_BIT_SYNC | + GnssMeasurement::STATE_SUBFRAME_SYNC | GnssMeasurement::STATE_TOW_DECODED | + GnssMeasurement::STATE_GLO_STRING_SYNC | + GnssMeasurement::STATE_GLO_TOD_DECODED, + .fullInterSignalBiasNs = 21.5, + .fullInterSignalBiasUncertaintyNs = 792.0, + .satelliteInterSignalBiasNs = 233.9, + .satelliteInterSignalBiasUncertaintyNs = 921.2, + .satellitePvt = {.flags = SatellitePvt::HAS_POSITION_VELOCITY_CLOCK_INFO | + SatellitePvt::HAS_IONO | SatellitePvt::HAS_TROPO, + .satPosEcef = {.posXMeters = 10442993.1153328, + .posYMeters = -19926932.8051666, + .posZMeters = -12034295.0216203, + .ureMeters = 1000.2345678}, + .satVelEcef = {.velXMps = -478.667183715732, + .velYMps = 1580.68371984114, + .velZMps = -3030.52994449997, + .ureRateMps = 10.2345678}, + .satClockInfo = {.satHardwareCodeBiasMeters = 1.396983861923e-09, + .satTimeCorrectionMeters = -7113.08964331, + .satClkDriftMps = 0}, + .ionoDelayMeters = 3.069949602639317e-08, + .tropoDelayMeters = 3.882265204404031}, + .correlationVectors = {}}; + + GnssClock clock = {.gnssClockFlags = GnssClock::HAS_FULL_BIAS | GnssClock::HAS_BIAS | + GnssClock::HAS_BIAS_UNCERTAINTY | GnssClock::HAS_DRIFT | + GnssClock::HAS_DRIFT_UNCERTAINTY, + .timeNs = 35854545000000, + .fullBiasNs = -234621900521857520, + .biasNs = 0.2352389998626708984, + .biasUncertaintyNs = 274.989972114563, + .driftNsps = -124.3742360, + .driftUncertaintyNsps = 239.6234285828, + .hwClockDiscontinuityCount = 999}; + + ElapsedRealtime timestamp = { + .flags = ElapsedRealtime::HAS_TIMESTAMP_NS | ElapsedRealtime::HAS_TIME_UNCERTAINTY_NS, + .timestampNs = ::android::elapsedRealtimeNano(), + // This is an hardcoded value indicating a 1ms of uncertainty between the two clocks. + // In an actual implementation provide an estimate of the synchronization uncertainty + // or don't set the field. + .timeUncertaintyNs = 1020400}; + + if (enableCorrVecOutputs) { + aidl::android::hardware::gnss::CorrelationVector correlationVector1 = { + .frequencyOffsetMps = 10, + .samplingWidthM = 30, + .samplingStartM = 0, + .magnitude = {0, 5000, 10000, 5000, 0, 0, 3000, 0}}; + aidl::android::hardware::gnss::CorrelationVector correlationVector2 = { + .frequencyOffsetMps = 20, + .samplingWidthM = 30, + .samplingStartM = -10, + .magnitude = {0, 3000, 5000, 3000, 0, 0, 1000, 0}}; + measurement.correlationVectors = {correlationVector1, correlationVector2}; + measurement.flags |= GnssMeasurement::HAS_CORRELATION_VECTOR; + } + + GnssData gnssData = { + .measurements = {measurement}, .clock = clock, .elapsedRealtime = timestamp}; + return gnssData; +} + +V2_0::GnssLocation Utils::getMockLocationV2_0() { + const V2_0::ElapsedRealtime timestamp = { + .flags = V2_0::ElapsedRealtimeFlags::HAS_TIMESTAMP_NS | + V2_0::ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS, + .timestampNs = static_cast(::android::elapsedRealtimeNano()), + // This is an hardcoded value indicating a 1ms of uncertainty between the two clocks. + // In an actual implementation provide an estimate of the synchronization uncertainty + // or don't set the field. + .timeUncertaintyNs = 1000000}; + + V2_0::GnssLocation location = {.v1_0 = Utils::getMockLocationV1_0(), + .elapsedRealtime = timestamp}; + return location; +} + +V1_0::GnssLocation Utils::getMockLocationV1_0() { + V1_0::GnssLocation location = { + .gnssLocationFlags = 0xFF, + .latitudeDegrees = gMockLatitudeDegrees, + .longitudeDegrees = gMockLongitudeDegrees, + .altitudeMeters = gMockAltitudeMeters, + .speedMetersPerSec = gMockSpeedMetersPerSec, + .bearingDegrees = gMockBearingDegrees, + .horizontalAccuracyMeters = kMockHorizontalAccuracyMeters, + .verticalAccuracyMeters = kMockVerticalAccuracyMeters, + .speedAccuracyMetersPerSecond = kMockSpeedAccuracyMetersPerSecond, + .bearingAccuracyDegrees = kMockBearingAccuracyDegrees, + .timestamp = + static_cast(kMockTimestamp + ::android::elapsedRealtimeNano() / 1e6)}; + return location; +} + +hidl_vec Utils::getMockSvInfoListV2_1() { + GnssSvInfoV1_0 gnssSvInfoV1_0 = Utils::getMockSvInfoV1_0(3, V1_0::GnssConstellationType::GPS, + 32.5, 59.1, 166.5, kGpsL1FreqHz); + GnssSvInfoV2_0 gnssSvInfoV2_0 = + Utils::getMockSvInfoV2_0(gnssSvInfoV1_0, V2_0::GnssConstellationType::GPS); + hidl_vec gnssSvInfoList = { + Utils::getMockSvInfoV2_1(gnssSvInfoV2_0, 27.5), + getMockSvInfoV2_1( + getMockSvInfoV2_0(getMockSvInfoV1_0(5, V1_0::GnssConstellationType::GPS, 27.0, + 29.0, 56.5, kGpsL1FreqHz), + V2_0::GnssConstellationType::GPS), + 22.0), + getMockSvInfoV2_1( + getMockSvInfoV2_0(getMockSvInfoV1_0(17, V1_0::GnssConstellationType::GPS, 30.5, + 71.0, 77.0, kGpsL5FreqHz), + V2_0::GnssConstellationType::GPS), + 25.5), + getMockSvInfoV2_1( + getMockSvInfoV2_0(getMockSvInfoV1_0(26, V1_0::GnssConstellationType::GPS, 24.1, + 28.0, 253.0, kGpsL5FreqHz), + V2_0::GnssConstellationType::GPS), + 19.1), + getMockSvInfoV2_1( + getMockSvInfoV2_0(getMockSvInfoV1_0(5, V1_0::GnssConstellationType::GLONASS, + 20.5, 11.5, 116.0, kGloG1FreqHz), + V2_0::GnssConstellationType::GLONASS), + 15.5), + getMockSvInfoV2_1( + getMockSvInfoV2_0(getMockSvInfoV1_0(17, V1_0::GnssConstellationType::GLONASS, + 21.5, 28.5, 186.0, kGloG1FreqHz), + V2_0::GnssConstellationType::GLONASS), + 16.5), + getMockSvInfoV2_1( + getMockSvInfoV2_0(getMockSvInfoV1_0(18, V1_0::GnssConstellationType::GLONASS, + 28.3, 38.8, 69.0, kGloG1FreqHz), + V2_0::GnssConstellationType::GLONASS), + 25.3), + getMockSvInfoV2_1( + getMockSvInfoV2_0(getMockSvInfoV1_0(10, V1_0::GnssConstellationType::GLONASS, + 25.0, 66.0, 247.0, kGloG1FreqHz), + V2_0::GnssConstellationType::GLONASS), + 20.0), + getMockSvInfoV2_1( + getMockSvInfoV2_0(getMockSvInfoV1_0(3, V1_0::GnssConstellationType::UNKNOWN, + 22.0, 35.0, 112.0, kIrnssL5FreqHz), + V2_0::GnssConstellationType::IRNSS), + 19.7), + }; + return gnssSvInfoList; +} + +GnssSvInfoV2_1 Utils::getMockSvInfoV2_1(GnssSvInfoV2_0 gnssSvInfoV2_0, float basebandCN0DbHz) { + GnssSvInfoV2_1 gnssSvInfoV2_1 = { + .v2_0 = gnssSvInfoV2_0, + .basebandCN0DbHz = basebandCN0DbHz, + }; + return gnssSvInfoV2_1; +} + +GnssSvInfoV2_0 Utils::getMockSvInfoV2_0(GnssSvInfoV1_0 gnssSvInfoV1_0, + V2_0::GnssConstellationType type) { + GnssSvInfoV2_0 gnssSvInfoV2_0 = { + .v1_0 = gnssSvInfoV1_0, + .constellation = type, + }; + return gnssSvInfoV2_0; +} + +GnssSvInfoV1_0 Utils::getMockSvInfoV1_0(int16_t svid, V1_0::GnssConstellationType type, + float cN0DbHz, float elevationDegrees, float azimuthDegrees, + float carrierFrequencyHz) { + GnssSvInfoV1_0 svInfo = {.svid = svid, + .constellation = type, + .cN0Dbhz = cN0DbHz, + .elevationDegrees = elevationDegrees, + .azimuthDegrees = azimuthDegrees, + .carrierFrequencyHz = carrierFrequencyHz, + .svFlag = GnssSvFlags::USED_IN_FIX | GnssSvFlags::HAS_EPHEMERIS_DATA | + GnssSvFlags::HAS_ALMANAC_DATA | + GnssSvFlags::HAS_CARRIER_FREQUENCY}; + return svInfo; +} + +hidl_vec Utils::getMockAntennaInfos() { + GnssAntennaInfo mockAntennaInfo_1 = { + .carrierFrequencyMHz = kGpsL1FreqHz * 1e-6, + .phaseCenterOffsetCoordinateMillimeters = Coord{.x = 1, + .xUncertainty = 0.1, + .y = 2, + .yUncertainty = 0.1, + .z = 3, + .zUncertainty = 0.1}, + .phaseCenterVariationCorrectionMillimeters = + { + Row{hidl_vec{1, -1, 5, -2, 3, -1}}, + Row{hidl_vec{-2, 3, 2, 0, 1, 2}}, + Row{hidl_vec{1, 3, 2, -1, -3, 5}}, + }, + .phaseCenterVariationCorrectionUncertaintyMillimeters = + { + Row{hidl_vec{0.1, 0.2, 0.4, 0.1, 0.2, 0.3}}, + Row{hidl_vec{0.3, 0.2, 0.3, 0.6, 0.1, 0.1}}, + Row{hidl_vec{0.1, 0.1, 0.4, 0.2, 0.5, 0.3}}, + }, + .signalGainCorrectionDbi = + { + Row{hidl_vec{2, -3, 1, -3, 0, -4}}, + Row{hidl_vec{1, 0, -4, 1, 3, -2}}, + Row{hidl_vec{3, -2, 0, -2, 3, 0}}, + }, + .signalGainCorrectionUncertaintyDbi = + { + Row{hidl_vec{0.3, 0.1, 0.2, 0.6, 0.1, 0.3}}, + Row{hidl_vec{0.1, 0.1, 0.5, 0.2, 0.3, 0.1}}, + Row{hidl_vec{0.2, 0.4, 0.2, 0.1, 0.1, 0.2}}, + }, + }; + + GnssAntennaInfo mockAntennaInfo_2 = { + .carrierFrequencyMHz = kGpsL5FreqHz * 1e-6, + .phaseCenterOffsetCoordinateMillimeters = Coord{.x = 5, + .xUncertainty = 0.1, + .y = 6, + .yUncertainty = 0.1, + .z = 7, + .zUncertainty = 0.1}, + }; + + hidl_vec mockAntennaInfos = { + mockAntennaInfo_1, + mockAntennaInfo_2, + }; + return mockAntennaInfos; +} + +} // namespace common +} // namespace gnss +} // namespace hardware +} // namespace android diff --git a/gps/gnss/common/utils/default/include/Constants.h b/gps/gnss/common/utils/default/include/Constants.h new file mode 100644 index 0000000..22afee1 --- /dev/null +++ b/gps/gnss/common/utils/default/include/Constants.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2019 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_common_Constants_H_ +#define android_hardware_gnss_common_Constants_H_ + +#include + +namespace android { +namespace hardware { +namespace gnss { +namespace common { + +const float kMockHorizontalAccuracyMeters = 5; +const float kMockVerticalAccuracyMeters = 5; +const float kMockSpeedAccuracyMetersPerSecond = 1; +const float kMockBearingAccuracyDegrees = 90; +const int64_t kMockTimestamp = 1519930775453L; +const float kGpsL1FreqHz = 1575.42 * 1e6; +const float kGpsL5FreqHz = 1176.45 * 1e6; +const float kGloG1FreqHz = 1602.0 * 1e6; +const float kIrnssL5FreqHz = 1176.45 * 1e6; + +} // namespace common +} // namespace gnss +} // namespace hardware +} // namespace android + +#endif // android_hardware_gnss_common_Constants_H_ diff --git a/gps/gnss/common/utils/default/include/MockLocation.h b/gps/gnss/common/utils/default/include/MockLocation.h new file mode 100644 index 0000000..0bfdd1a --- /dev/null +++ b/gps/gnss/common/utils/default/include/MockLocation.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2020 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_common_MockLocation_H_ +#define android_hardware_gnss_common_MockLocation_H_ + +#include + +namespace android { +namespace hardware { +namespace gnss { +namespace common { + +extern float gMockLatitudeDegrees; +extern float gMockLongitudeDegrees; +extern float gMockAltitudeMeters; +extern float gMockBearingDegrees; +extern float gMockSpeedMetersPerSec; + +} // namespace common +} // namespace gnss +} // namespace hardware +} // namespace android + +#endif // android_hardware_gnss_common_MockLocation_H_ diff --git a/gps/gnss/common/utils/default/include/NmeaFixInfo.h b/gps/gnss/common/utils/default/include/NmeaFixInfo.h new file mode 100644 index 0000000..c96eece --- /dev/null +++ b/gps/gnss/common/utils/default/include/NmeaFixInfo.h @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2020 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. + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +namespace android { +namespace hardware { +namespace gnss { +namespace common { + +constexpr char GPGA_RECORD_TAG[] = "$GPGGA"; +constexpr char GPRMC_RECORD_TAG[] = "$GPRMC"; +constexpr char LINE_SEPARATOR = '\n'; +constexpr char COMMA_SEPARATOR = ','; +constexpr double TIMESTAMP_EPSILON = 0.001; +constexpr int MIN_COL_NUM = 13; + +/** Helper class to parse and store the GNSS fix details information. */ +class NmeaFixInfo { + private: + float altitudeMeters; + float bearingDegrees; + uint32_t fixId; + bool hasGMCRecord; + bool hasGGARecord; + float hDop; + float vDop; + float latDeg; + float lngDeg; + uint32_t satelliteCount; + float speedMetersPerSec; + int64_t timestamp; + + public: + static std::unique_ptr getLocationFromInputStr(const std::string& inputStr); + + private: + static void splitStr(const std::string& line, const char& delimiter, + std::vector& out); + static float checkAndConvertToFloat(const std::string& sentence); + static int64_t nmeaPartsToTimestamp(const std::string& timeStr, const std::string& dateStr); + + NmeaFixInfo(); + void parseGGALine(const std::vector& sentenceValues); + void parseRMCLine(const std::vector& sentenceValues); + std::unique_ptr toGnssLocation() const; + + // Getters + float getAltitudeMeters() const; + float getBearingAccuracyDegrees() const; + float getBearingDegrees() const; + uint32_t getFixId() const; + float getHorizontalAccuracyMeters() const; + float getLatDeg() const; + float getLngDeg() const; + float getSpeedAccuracyMetersPerSecond() const; + float getSpeedMetersPerSec() const; + int64_t getTimestamp() const; + float getVerticalAccuracyMeters() const; + + bool isValidFix() const; + void reset(); + NmeaFixInfo& operator=(const NmeaFixInfo& rhs); +}; + +} // namespace common +} // namespace gnss +} // namespace hardware +} // namespace android \ No newline at end of file diff --git a/gps/gnss/common/utils/default/include/Utils.h b/gps/gnss/common/utils/default/include/Utils.h new file mode 100644 index 0000000..43772ce --- /dev/null +++ b/gps/gnss/common/utils/default/include/Utils.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2019 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_common_default_Utils_H_ +#define android_hardware_gnss_common_default_Utils_H_ + +#include +#include +#include +#include + +using ::android::hardware::hidl_vec; + +namespace android { +namespace hardware { +namespace gnss { +namespace common { + +struct Utils { + static aidl::android::hardware::gnss::GnssData getMockMeasurement( + const bool enableCorrVecOutputs); + static V2_0::IGnssMeasurementCallback::GnssData getMockMeasurementV2_0(); + static V2_1::IGnssMeasurementCallback::GnssData getMockMeasurementV2_1(); + static V2_0::GnssLocation getMockLocationV2_0(); + static V1_0::GnssLocation getMockLocationV1_0(); + static hidl_vec getMockSvInfoListV2_1(); + static V2_1::IGnssCallback::GnssSvInfo getMockSvInfoV2_1( + V2_0::IGnssCallback::GnssSvInfo gnssSvInfoV2_0, float basebandCN0DbHz); + static V2_0::IGnssCallback::GnssSvInfo getMockSvInfoV2_0( + V1_0::IGnssCallback::GnssSvInfo gnssSvInfoV1_0, V2_0::GnssConstellationType type); + static V1_0::IGnssCallback::GnssSvInfo getMockSvInfoV1_0(int16_t svid, + V1_0::GnssConstellationType type, + float cN0DbHz, float elevationDegrees, + float azimuthDegrees, + float carrierFrequencyHz); + static hidl_vec getMockAntennaInfos(); +}; + +} // namespace common +} // namespace gnss +} // namespace hardware +} // namespace android + +#endif // android_hardware_gnss_common_default_Utils_H_ diff --git a/gps/gnss/common/utils/default/include/v2_1/GnssAntennaInfo.h b/gps/gnss/common/utils/default/include/v2_1/GnssAntennaInfo.h new file mode 100644 index 0000000..a232499 --- /dev/null +++ b/gps/gnss/common/utils/default/include/v2_1/GnssAntennaInfo.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2020 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. + */ + +#pragma once + +#include + +#include +#include + +namespace android::hardware::gnss::V2_1::implementation { + +struct GnssAntennaInfo : public ::android::hardware::gnss::V2_1::IGnssAntennaInfo { + GnssAntennaInfo(); + ~GnssAntennaInfo(); + + // Methods from ::android::hardware::gnss::V2_1::IGnssAntennaInfo follow. + Return setCallback( + const sp<::android::hardware::gnss::V2_1::IGnssAntennaInfoCallback>& callback) override; + Return close() override; + + private: + void start(); + void stop(); + void reportAntennaInfo( + const hidl_vec< + ::android::hardware::gnss::V2_1::IGnssAntennaInfoCallback::GnssAntennaInfo>& + antennaInfo) const; + + // Guarded by mMutex + static sp<::android::hardware::gnss::V2_1::IGnssAntennaInfoCallback> sCallback; + + std::atomic mMinIntervalMillis; + std::atomic mIsActive; + std::thread mThread; + + // Synchronization lock for sCallback + mutable std::mutex mMutex; +}; + +} // namespace android::hardware::gnss::V2_1::implementation diff --git a/gps/gnss/common/utils/default/include/v2_1/GnssConfiguration.h b/gps/gnss/common/utils/default/include/v2_1/GnssConfiguration.h new file mode 100644 index 0000000..2cfb38f --- /dev/null +++ b/gps/gnss/common/utils/default/include/v2_1/GnssConfiguration.h @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2019 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. + */ + +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace android::hardware::gnss::V2_1::implementation { + +struct BlacklistedSourceHashV2_1 { + inline int operator()( + const ::android::hardware::gnss::V2_1::IGnssConfiguration::BlacklistedSource& source) + const { + return int(source.constellation) * 1000 + int(source.svid); + } +}; + +struct BlacklistedSourceEqualV2_1 { + inline bool operator()( + const ::android::hardware::gnss::V2_1::IGnssConfiguration::BlacklistedSource& s1, + const ::android::hardware::gnss::V2_1::IGnssConfiguration::BlacklistedSource& s2) + const { + return (s1.constellation == s2.constellation) && (s1.svid == s2.svid); + } +}; + +using BlacklistedSourceSetV2_1 = + std::unordered_set<::android::hardware::gnss::V2_1::IGnssConfiguration::BlacklistedSource, + BlacklistedSourceHashV2_1, BlacklistedSourceEqualV2_1>; +using BlacklistedConstellationSetV2_1 = std::unordered_set; + +struct GnssConfiguration : public IGnssConfiguration { + // Methods from ::android::hardware::gnss::V1_0::IGnssConfiguration follow. + Return setSuplEs(bool enabled) override; + Return setSuplVersion(uint32_t version) override; + Return setSuplMode(hidl_bitfield mode) override; + Return setGpsLock(hidl_bitfield lock) override; + Return setLppProfile(hidl_bitfield lppProfile) override; + Return setGlonassPositioningProtocol(hidl_bitfield protocol) override; + Return setEmergencySuplPdn(bool enable) override; + + // Methods from ::android::hardware::gnss::V1_1::IGnssConfiguration follow. + Return setBlacklist( + const hidl_vec& blacklist) override; + + std::recursive_mutex& getMutex() const; + + // Methods from ::android::hardware::gnss::V2_0::IGnssConfiguration follow. + Return setEsExtensionSec(uint32_t emergencyExtensionSeconds) override; + + // Methods from ::android::hardware::gnss::V2_1::IGnssConfiguration follow. + Return setBlacklist_2_1( + const hidl_vec& blacklist) override; + + Return isBlacklistedV2_1(const V2_1::IGnssCallback::GnssSvInfo& gnssSvInfo) const; + + private: + mutable std::recursive_mutex mMutex; + + BlacklistedSourceSetV2_1 mBlacklistedSourceSet; + BlacklistedConstellationSetV2_1 mBlacklistedConstellationSet; +}; + +} // namespace android::hardware::gnss::V2_1::implementation diff --git a/gps/gnss/common/utils/default/include/v2_1/GnssDebug.h b/gps/gnss/common/utils/default/include/v2_1/GnssDebug.h new file mode 100644 index 0000000..481de59 --- /dev/null +++ b/gps/gnss/common/utils/default/include/v2_1/GnssDebug.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2018 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. + */ + +#pragma once + +#include +#include + +namespace android::hardware::gnss::V1_1::implementation { + +/* Interface for GNSS Debug support. */ +struct GnssDebug : public V1_0::IGnssDebug { + /* + * Methods from ::android::hardware::gnss::V1_0::IGnssDebug follow. + * These declarations were generated from IGnssDebug.hal. + */ + Return getDebugData(V1_0::IGnssDebug::getDebugData_cb _hidl_cb) override; +}; + +} // namespace android::hardware::gnss::V1_1::implementation diff --git a/gps/gnss/common/utils/default/include/v2_1/GnssMeasurement.h b/gps/gnss/common/utils/default/include/v2_1/GnssMeasurement.h new file mode 100644 index 0000000..db8407b --- /dev/null +++ b/gps/gnss/common/utils/default/include/v2_1/GnssMeasurement.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2019 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. + */ + +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace android::hardware::gnss::V2_1::implementation { + +struct GnssMeasurement : public IGnssMeasurement { + GnssMeasurement(); + ~GnssMeasurement(); + // Methods from V1_0::IGnssMeasurement follow. + Return setCallback( + const sp& callback) override; + Return close() override; + + // Methods from V1_1::IGnssMeasurement follow. + Return setCallback_1_1( + const sp& callback, bool enableFullTracking) override; + + // Methods from V2_0::IGnssMeasurement follow. + Return setCallback_2_0( + const sp& callback, bool enableFullTracking) override; + + // Methods from V2_1::IGnssMeasurement follow. + Return setCallback_2_1( + const sp& callback, bool enableFullTracking) override; + + private: + void start(); + void stop(); + void reportMeasurement(const V2_0::IGnssMeasurementCallback::GnssData&); + void reportMeasurement(const V2_1::IGnssMeasurementCallback::GnssData&); + + // Guarded by mMutex + static sp sCallback_2_1; + + // Guarded by mMutex + static sp sCallback_2_0; + + std::atomic mMinIntervalMillis; + std::atomic mIsActive; + std::thread mThread; + + // Synchronization lock for sCallback_2_1 and sCallback_2_0 + mutable std::mutex mMutex; +}; + +} // namespace android::hardware::gnss::V2_1::implementation diff --git a/gps/gnss/common/utils/default/include/v2_1/GnssMeasurementCorrections.h b/gps/gnss/common/utils/default/include/v2_1/GnssMeasurementCorrections.h new file mode 100644 index 0000000..54045ad --- /dev/null +++ b/gps/gnss/common/utils/default/include/v2_1/GnssMeasurementCorrections.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2019 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. + */ + +#pragma once + +#include +#include +#include + +namespace android::hardware::gnss::measurement_corrections::V1_1::implementation { + +struct GnssMeasurementCorrections : public IMeasurementCorrections { + GnssMeasurementCorrections(); + ~GnssMeasurementCorrections(); + + // Methods from V1_0::IMeasurementCorrections follow. + Return setCorrections(const V1_0::MeasurementCorrections& corrections) override; + Return setCallback(const sp& callback) override; + + // Methods from V1_1::IMeasurementCorrections follow. + Return setCorrections_1_1(const V1_1::MeasurementCorrections& corrections) override; +}; + +} // namespace android::hardware::gnss::measurement_corrections::V1_1::implementation diff --git a/gps/gnss/common/utils/default/include/v2_1/GnssTemplate.h b/gps/gnss/common/utils/default/include/v2_1/GnssTemplate.h new file mode 100644 index 0000000..2ff1ec7 --- /dev/null +++ b/gps/gnss/common/utils/default/include/v2_1/GnssTemplate.h @@ -0,0 +1,779 @@ +/* + * Copyright (C) 2019 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. + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "GnssAntennaInfo.h" +#include "GnssConfiguration.h" +#include "GnssDebug.h" +#include "GnssMeasurement.h" +#include "GnssMeasurementCorrections.h" +#include "MockLocation.h" +#include "NmeaFixInfo.h" +#include "Utils.h" + +namespace android::hardware::gnss::common::implementation { + +constexpr int INPUT_BUFFER_SIZE = 128; +constexpr char CMD_GET_LOCATION[] = "CMD_GET_LOCATION"; +constexpr char GNSS_PATH[] = "/data/vendor/gps/gnss"; + +template +struct GnssTemplate : public T_IGnss { + GnssTemplate(); + ~GnssTemplate(); + // Methods from V1_0::IGnss follow. + Return setCallback(const sp& callback) override; + Return start() override; + Return stop() override; + Return cleanup() override; + Return injectTime(int64_t timeMs, int64_t timeReferenceMs, + int32_t uncertaintyMs) override; + Return injectLocation(double latitudeDegrees, double longitudeDegrees, + float accuracyMeters) override; + Return deleteAidingData(V1_0::IGnss::GnssAidingData aidingDataFlags) override; + Return setPositionMode(V1_0::IGnss::GnssPositionMode mode, + V1_0::IGnss::GnssPositionRecurrence recurrence, + uint32_t minIntervalMs, uint32_t preferredAccuracyMeters, + uint32_t preferredTimeMs) override; + Return> getExtensionAGnssRil() override; + Return> getExtensionGnssGeofencing() override; + Return> getExtensionAGnss() override; + Return> getExtensionGnssNi() override; + Return> getExtensionGnssMeasurement() override; + Return> getExtensionGnssNavigationMessage() override; + Return> getExtensionXtra() override; + Return> getExtensionGnssConfiguration() override; + Return> getExtensionGnssDebug() override; + Return> getExtensionGnssBatching() override; + + // Methods from V1_1::IGnss follow. + Return setCallback_1_1(const sp& callback) override; + Return setPositionMode_1_1(V1_0::IGnss::GnssPositionMode mode, + V1_0::IGnss::GnssPositionRecurrence recurrence, + uint32_t minIntervalMs, uint32_t preferredAccuracyMeters, + uint32_t preferredTimeMs, bool lowPowerMode) override; + Return> getExtensionGnssConfiguration_1_1() override; + Return> getExtensionGnssMeasurement_1_1() override; + Return injectBestLocation(const V1_0::GnssLocation& location) override; + + // Methods from V2_0::IGnss follow. + Return setCallback_2_0(const sp& callback) override; + Return> getExtensionGnssConfiguration_2_0() override; + Return> getExtensionGnssDebug_2_0() override; + Return> getExtensionAGnss_2_0() override; + Return> getExtensionAGnssRil_2_0() override; + Return> getExtensionGnssMeasurement_2_0() override; + Return> + getExtensionMeasurementCorrections() override; + Return> getExtensionVisibilityControl() + override; + Return> getExtensionGnssBatching_2_0() override; + Return injectBestLocation_2_0(const V2_0::GnssLocation& location) override; + + // Methods from V2_1::IGnss follow. + Return setCallback_2_1(const sp& callback) override; + Return> getExtensionGnssMeasurement_2_1() override; + Return> getExtensionGnssConfiguration_2_1() override; + Return> + getExtensionMeasurementCorrections_1_1() override; + Return> getExtensionGnssAntennaInfo() override; + + Return debug(const hidl_handle& fd, const hidl_vec& options) override; + + private: + std::unique_ptr getLocationFromHW(); + void reportLocation(const V2_0::GnssLocation&) const; + void reportLocation(const V1_0::GnssLocation&) const; + void reportSvStatus(const hidl_vec&) const; + void reportGnssStatusValue(const V1_0::IGnssCallback::GnssStatusValue) const; + + Return help(const hidl_handle& fd); + Return setLocation(const hidl_handle& fd, const hidl_vec& options); + + static sp sGnssCallback_2_1; + static sp sGnssCallback_2_0; + static sp sGnssCallback_1_1; + static sp sGnssCallback_1_0; + + std::atomic mMinIntervalMs; + sp mGnssConfiguration; + std::atomic mIsActive; + std::atomic mHardwareModeChecked; + std::atomic mGnssFd; + std::thread mThread; + + mutable std::mutex mMutex; + virtual hidl_vec filterBlocklistedSatellitesV2_1( + hidl_vec gnssSvInfoList); + virtual void notePowerConsumption(); +}; + +template +sp GnssTemplate::sGnssCallback_2_1 = nullptr; +template +sp GnssTemplate::sGnssCallback_2_0 = nullptr; +template +sp GnssTemplate::sGnssCallback_1_1 = nullptr; +template +sp GnssTemplate::sGnssCallback_1_0 = nullptr; + +template +GnssTemplate::GnssTemplate() + : mMinIntervalMs(1000), + mGnssConfiguration{new V2_1::implementation::GnssConfiguration()}, + mHardwareModeChecked(false), + mGnssFd(-1) {} + +template +GnssTemplate::~GnssTemplate() { + stop(); +} + +template +std::unique_ptr GnssTemplate::getLocationFromHW() { + float latitudeDegrees = gMockLatitudeDegrees; + float longitudeDegrees = gMockLongitudeDegrees; + float altitudeMeters = gMockAltitudeMeters; + float speedMetersPerSec = gMockSpeedMetersPerSec; + float bearingDegrees = gMockBearingDegrees; + float horizontalAccuracyMeters = kMockHorizontalAccuracyMeters; + float verticalAccuracyMeters = kMockVerticalAccuracyMeters; + float speedAccuracyMetersPerSecond = kMockSpeedAccuracyMetersPerSecond; + float bearingAccuracyDegrees = kMockBearingAccuracyDegrees; + int64_t timestamp = static_cast(time(NULL)) - 1; + + const char * gnss_dev_path = GNSS_PATH; + int gnss_fd = open(gnss_dev_path, O_RDONLY); + if (gnss_fd != -1) { + int bytes_read = -1; + std::string inputStr = ""; + char inputBuffer[INPUT_BUFFER_SIZE]; + while (true) { + memset(inputBuffer, 0, INPUT_BUFFER_SIZE); + bytes_read = read(gnss_fd, &inputBuffer, INPUT_BUFFER_SIZE); + if (bytes_read <= 0) { + break; + } + inputStr += std::string(inputBuffer, bytes_read); + } + + std::istringstream iss(inputStr); + std::string item; + while (std::getline(iss, item, LINE_SEPARATOR)) { + if (item.compare(0, strlen("LatitudeDegrees="), "LatitudeDegrees=") == 0) { + latitudeDegrees = std::stof(item.substr(strlen("LatitudeDegrees="))); + } else if (item.compare(0, strlen("LongitudeDegrees="), "LongitudeDegrees=") == 0) { + longitudeDegrees = std::stof(item.substr(strlen("LongitudeDegrees="))); + } else if (item.compare(0, strlen("AltitudeMeters="), "AltitudeMeters=") == 0) { + altitudeMeters = std::stof(item.substr(strlen("AltitudeMeters="))); + } else if (item.compare(0, strlen("SpeedMetersPerSec="), "SpeedMetersPerSec=") == 0) { + speedMetersPerSec = std::stof(item.substr(strlen("SpeedMetersPerSec="))); + } else if (item.compare(0, strlen("BearingDegrees="), "BearingDegrees=") == 0) { + bearingDegrees = std::stof(item.substr(strlen("BearingDegrees="))); + } else if (item.compare(0, strlen("HorizontalAccuracyMeters="), "HorizontalAccuracyMeters=") == 0) { + horizontalAccuracyMeters = std::stof(item.substr(strlen("HorizontalAccuracyMeters="))); + } else if (item.compare(0, strlen("VerticalAccuracyMeters="), "VerticalAccuracyMeters=") == 0) { + verticalAccuracyMeters = std::stof(item.substr(strlen("VerticalAccuracyMeters="))); + } else if (item.compare(0, strlen("SpeedAccuracyMetersPerSecond="), "SpeedAccuracyMetersPerSecond=") == 0) { + speedAccuracyMetersPerSecond = std::stof(item.substr(strlen("SpeedAccuracyMetersPerSecond="))); + } else if (item.compare(0, strlen("BearingAccuracyDegrees="), "BearingAccuracyDegrees=") == 0) { + bearingAccuracyDegrees = std::stof(item.substr(strlen("BearingAccuracyDegrees="))); + } else if (item.compare(0, strlen("Timestamp="), "Timestamp=") == 0) { + timestamp = std::stol(item.substr(strlen("Timestamp="))); + } + } + close(gnss_fd); + } else { + ALOGW("Failed to open %s errno: %d", gnss_dev_path, errno); + } + + const V2_0::ElapsedRealtime currentOsTimestamp = { + .flags = V2_0::ElapsedRealtimeFlags::HAS_TIMESTAMP_NS | + V2_0::ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS, + .timestampNs = static_cast(::android::elapsedRealtimeNano()), + // This is an hardcoded value indicating a 1ms of uncertainty between the two clocks. + // In an actual implementation provide an estimate of the synchronization uncertainty + // or don't set the field. + .timeUncertaintyNs = 1000000}; + + V1_0::GnssLocation locationV1 = { + .gnssLocationFlags = 0xFF, + .latitudeDegrees = latitudeDegrees, + .longitudeDegrees = longitudeDegrees, + .altitudeMeters = altitudeMeters, + .speedMetersPerSec = speedMetersPerSec, + .bearingDegrees = bearingDegrees, + .horizontalAccuracyMeters = horizontalAccuracyMeters, + .verticalAccuracyMeters = verticalAccuracyMeters, + .speedAccuracyMetersPerSecond = speedAccuracyMetersPerSecond, + .bearingAccuracyDegrees = bearingAccuracyDegrees, + .timestamp = timestamp}; + + V2_0::GnssLocation locationV2 = {.v1_0 = locationV1, .elapsedRealtime = currentOsTimestamp}; + + return std::make_unique(locationV2); +} + +template +Return GnssTemplate::start() { + if (mIsActive) { + ALOGW("Gnss has started. Restarting..."); + stop(); + } + + mIsActive = true; + this->reportGnssStatusValue(V1_0::IGnssCallback::GnssStatusValue::SESSION_BEGIN); + mThread = std::thread([this]() { + while (mIsActive == true) { + auto svStatus = filterBlocklistedSatellitesV2_1(Utils::getMockSvInfoListV2_1()); + this->reportSvStatus(svStatus); + auto currentLocation = getLocationFromHW(); + notePowerConsumption(); + if (currentLocation != nullptr) { + this->reportLocation(*currentLocation); + } else { + if (sGnssCallback_2_1 != nullptr || sGnssCallback_2_0 != nullptr) { + const auto location = Utils::getMockLocationV2_0(); + this->reportLocation(location); + } else { + const auto location = Utils::getMockLocationV1_0(); + this->reportLocation(location); + } + } + std::this_thread::sleep_for(std::chrono::milliseconds(mMinIntervalMs)); + } + }); + return true; +} + +template +hidl_vec GnssTemplate::filterBlocklistedSatellitesV2_1( + hidl_vec gnssSvInfoList) { + ALOGD("GnssTemplate::filterBlocklistedSatellitesV2_1"); + for (uint32_t i = 0; i < gnssSvInfoList.size(); i++) { + if (mGnssConfiguration->isBlacklistedV2_1(gnssSvInfoList[i])) { + gnssSvInfoList[i].v2_0.v1_0.svFlag &= + ~static_cast(V1_0::IGnssCallback::GnssSvFlags::USED_IN_FIX); + } + } + return gnssSvInfoList; +} + +template +void GnssTemplate::notePowerConsumption() { + ALOGD("GnssTemplate::notePowerConsumption"); +} + +template +Return GnssTemplate::stop() { + ALOGD("stop"); + mIsActive = false; + this->reportGnssStatusValue(V1_0::IGnssCallback::GnssStatusValue::SESSION_END); + if (mThread.joinable()) { + mThread.join(); + } + if (mGnssFd != -1) { + close(mGnssFd); + mGnssFd = -1; + mHardwareModeChecked = false; + } + return true; +} + +// Methods from V1_0::IGnss follow. +template +Return GnssTemplate::setCallback(const sp& callback) { + if (callback == nullptr) { + ALOGE("%s: Null callback ignored", __func__); + return false; + } + + sGnssCallback_1_0 = callback; + + uint32_t capabilities = 0x0 | V1_0::IGnssCallback::Capabilities::MEASUREMENTS | + V1_0::IGnssCallback::Capabilities::SCHEDULING; + auto ret = sGnssCallback_1_0->gnssSetCapabilitesCb(capabilities); + if (!ret.isOk()) { + ALOGE("%s: Unable to invoke callback", __func__); + } + + V2_1::IGnssCallback::GnssSystemInfo gnssInfo = {.yearOfHw = 2018}; + + ret = sGnssCallback_1_0->gnssSetSystemInfoCb(gnssInfo); + if (!ret.isOk()) { + ALOGE("%s: Unable to invoke callback", __func__); + } + + return true; +} + +template +Return GnssTemplate::cleanup() { + sGnssCallback_2_1 = nullptr; + sGnssCallback_2_0 = nullptr; + return Void(); +} + +template +Return GnssTemplate::injectTime(int64_t, int64_t, int32_t) { + return true; +} + +template +Return GnssTemplate::injectLocation(double, double, float) { + return true; +} + +template +Return GnssTemplate::deleteAidingData(V1_0::IGnss::GnssAidingData) { + // TODO implement + return Void(); +} + +template +Return GnssTemplate::setPositionMode(V1_0::IGnss::GnssPositionMode, + V1_0::IGnss::GnssPositionRecurrence, + uint32_t minIntervalMs, uint32_t, uint32_t) { + mMinIntervalMs = minIntervalMs; + return true; +} + +template +Return> GnssTemplate::getExtensionAGnssRil() { + // TODO implement + return ::android::sp{}; +} + +template +Return> GnssTemplate::getExtensionGnssGeofencing() { + // TODO implement + return ::android::sp{}; +} + +template +Return> GnssTemplate::getExtensionAGnss() { + // TODO implement + return ::android::sp{}; +} + +template +Return> GnssTemplate::getExtensionGnssNi() { + // TODO implement + return ::android::sp{}; +} + +template +Return> GnssTemplate::getExtensionGnssMeasurement() { + ALOGD("Gnss::getExtensionGnssMeasurement"); + return new V2_1::implementation::GnssMeasurement(); +} + +template +Return> +GnssTemplate::getExtensionGnssNavigationMessage() { + // TODO implement + return ::android::sp{}; +} + +template +Return> GnssTemplate::getExtensionXtra() { + // TODO implement + return ::android::sp{}; +} + +template +Return> GnssTemplate::getExtensionGnssConfiguration() { + // TODO implement + return ::android::sp{}; +} + +template +Return> GnssTemplate::getExtensionGnssDebug() { + return new V1_1::implementation::GnssDebug(); +} + +template +Return> GnssTemplate::getExtensionGnssBatching() { + // TODO implement + return ::android::sp{}; +} + +// Methods from V1_1::IGnss follow. +template +Return GnssTemplate::setCallback_1_1(const sp& callback) { + if (callback == nullptr) { + ALOGE("%s: Null callback ignored", __func__); + return false; + } + + sGnssCallback_1_1 = callback; + + uint32_t capabilities = 0x0; + auto ret = sGnssCallback_1_1->gnssSetCapabilitesCb(capabilities); + if (!ret.isOk()) { + ALOGE("%s: Unable to invoke callback", __func__); + } + + V2_1::IGnssCallback::GnssSystemInfo gnssInfo = {.yearOfHw = 2018}; + + ret = sGnssCallback_1_1->gnssSetSystemInfoCb(gnssInfo); + if (!ret.isOk()) { + ALOGE("%s: Unable to invoke callback", __func__); + } + + auto gnssName = "Google Mock GNSS Implementation v2.1"; + ret = sGnssCallback_1_1->gnssNameCb(gnssName); + if (!ret.isOk()) { + ALOGE("%s: Unable to invoke callback", __func__); + } + + return true; +} + +template +Return GnssTemplate::setPositionMode_1_1(V1_0::IGnss::GnssPositionMode, + V1_0::IGnss::GnssPositionRecurrence, + uint32_t minIntervalMs, uint32_t, uint32_t, + bool) { + mMinIntervalMs = minIntervalMs; + return true; +} + +template +Return> GnssTemplate::getExtensionGnssConfiguration_1_1() { + // TODO implement + return ::android::sp{}; +} + +template +Return> GnssTemplate::getExtensionGnssMeasurement_1_1() { + // TODO implement + return ::android::sp{}; +} + +template +Return GnssTemplate::injectBestLocation(const V1_0::GnssLocation&) { + return true; +} + +// Methods from V2_0::IGnss follow. +template +Return GnssTemplate::setCallback_2_0(const sp& callback) { + ALOGD("Gnss::setCallback_2_0"); + if (callback == nullptr) { + ALOGE("%s: Null callback ignored", __func__); + return false; + } + + sGnssCallback_2_0 = callback; + + using Capabilities = V2_0::IGnssCallback::Capabilities; + const auto capabilities = Capabilities::MEASUREMENTS | Capabilities::MEASUREMENT_CORRECTIONS | + Capabilities::LOW_POWER_MODE | Capabilities::SATELLITE_BLACKLIST; + auto ret = sGnssCallback_2_0->gnssSetCapabilitiesCb_2_0(capabilities); + if (!ret.isOk()) { + ALOGE("%s: Unable to invoke callback", __func__); + } + + V1_1::IGnssCallback::GnssSystemInfo gnssInfo = {.yearOfHw = 2019}; + + ret = sGnssCallback_2_0->gnssSetSystemInfoCb(gnssInfo); + if (!ret.isOk()) { + ALOGE("%s: Unable to invoke callback", __func__); + } + + auto gnssName = "Google Mock GNSS Implementation v2.1"; + ret = sGnssCallback_2_0->gnssNameCb(gnssName); + if (!ret.isOk()) { + ALOGE("%s: Unable to invoke callback", __func__); + } + + return true; +} + +template +Return> GnssTemplate::getExtensionGnssConfiguration_2_0() { + ALOGD("Gnss::getExtensionGnssConfiguration_2_0"); + return mGnssConfiguration; +} + +template +Return> GnssTemplate::getExtensionGnssDebug_2_0() { + // TODO implement + return ::android::sp{}; +} + +template +Return> GnssTemplate::getExtensionAGnss_2_0() { + // TODO implement + return ::android::sp{}; +} + +template +Return> GnssTemplate::getExtensionAGnssRil_2_0() { + // TODO implement + return ::android::sp{}; +} + +template +Return> GnssTemplate::getExtensionGnssMeasurement_2_0() { + ALOGD("Gnss::getExtensionGnssMeasurement_2_0"); + return new V2_1::implementation::GnssMeasurement(); +} + +template +Return> +GnssTemplate::getExtensionMeasurementCorrections() { + ALOGD("Gnss::getExtensionMeasurementCorrections()"); + return new measurement_corrections::V1_1::implementation::GnssMeasurementCorrections(); +} + +template +Return> +GnssTemplate::getExtensionVisibilityControl() { + // TODO implement + return ::android::sp{}; +} + +template +Return> GnssTemplate::getExtensionGnssBatching_2_0() { + // TODO implement + return ::android::sp{}; +} + +template +Return GnssTemplate::injectBestLocation_2_0(const V2_0::GnssLocation&) { + // TODO(b/124012850): Implement function. + return bool{}; +} + +// Methods from V2_1::IGnss follow. +template +Return GnssTemplate::setCallback_2_1(const sp& callback) { + ALOGD("Gnss::setCallback_2_1"); + if (callback == nullptr) { + ALOGE("%s: Null callback ignored", __func__); + return false; + } + + sGnssCallback_2_1 = callback; + + using Capabilities = V2_1::IGnssCallback::Capabilities; + const auto capabilities = Capabilities::MEASUREMENTS | Capabilities::MEASUREMENT_CORRECTIONS | + Capabilities::LOW_POWER_MODE | Capabilities::SATELLITE_BLACKLIST | + Capabilities::ANTENNA_INFO; + auto ret = sGnssCallback_2_1->gnssSetCapabilitiesCb_2_1(capabilities); + if (!ret.isOk()) { + ALOGE("%s: Unable to invoke callback", __func__); + } + + V1_1::IGnssCallback::GnssSystemInfo gnssInfo = {.yearOfHw = 2020}; + + ret = sGnssCallback_2_1->gnssSetSystemInfoCb(gnssInfo); + if (!ret.isOk()) { + ALOGE("%s: Unable to invoke callback", __func__); + } + + auto gnssName = "Android Mock GNSS Implementation v2.1"; + ret = sGnssCallback_2_1->gnssNameCb(gnssName); + if (!ret.isOk()) { + ALOGE("%s: Unable to invoke callback", __func__); + } + + return true; +} + +template +Return> GnssTemplate::getExtensionGnssMeasurement_2_1() { + ALOGD("Gnss::getExtensionGnssMeasurement_2_1"); + return new V2_1::implementation::GnssMeasurement(); +} + +template +Return> GnssTemplate::getExtensionGnssConfiguration_2_1() { + ALOGD("Gnss::getExtensionGnssConfiguration_2_1"); + return mGnssConfiguration; +} + +template +Return> +GnssTemplate::getExtensionMeasurementCorrections_1_1() { + ALOGD("Gnss::getExtensionMeasurementCorrections_1_1()"); + return new measurement_corrections::V1_1::implementation::GnssMeasurementCorrections(); +} + +template +Return> GnssTemplate::getExtensionGnssAntennaInfo() { + ALOGD("Gnss::getExtensionGnssAntennaInfo"); + return new V2_1::implementation::GnssAntennaInfo(); +} + +template +void GnssTemplate::reportGnssStatusValue( + const V1_0::IGnssCallback::GnssStatusValue gnssStatusValue) const { + std::unique_lock lock(mMutex); + if (sGnssCallback_2_1 == nullptr) { + ALOGE("%s: sGnssCallback v2.1 is null.", __func__); + return; + } + auto ret = sGnssCallback_2_1->gnssStatusCb(gnssStatusValue); + if (!ret.isOk()) { + ALOGE("%s: Unable to invoke callback", __func__); + } +} + +template +void GnssTemplate::reportSvStatus( + const hidl_vec& svInfoList) const { + std::unique_lock lock(mMutex); + // TODO(skz): update this to call 2_0 callback if non-null + if (sGnssCallback_2_1 == nullptr) { + ALOGE("%s: sGnssCallback v2.1 is null.", __func__); + return; + } + auto ret = sGnssCallback_2_1->gnssSvStatusCb_2_1(svInfoList); + if (!ret.isOk()) { + ALOGE("%s: Unable to invoke callback", __func__); + } +} + +template +void GnssTemplate::reportLocation(const V1_0::GnssLocation& location) const { + std::unique_lock lock(mMutex); + if (sGnssCallback_1_1 != nullptr) { + auto ret = sGnssCallback_1_1->gnssLocationCb(location); + if (!ret.isOk()) { + ALOGE("%s: Unable to invoke callback v1.1", __func__); + } + return; + } + if (sGnssCallback_1_0 == nullptr) { + ALOGE("%s: No non-null callback", __func__); + return; + } + auto ret = sGnssCallback_1_0->gnssLocationCb(location); + if (!ret.isOk()) { + ALOGE("%s: Unable to invoke callback v1.0", __func__); + } +} + +template +void GnssTemplate::reportLocation(const V2_0::GnssLocation& location) const { + std::unique_lock lock(mMutex); + if (sGnssCallback_2_1 != nullptr) { + auto ret = sGnssCallback_2_1->gnssLocationCb_2_0(location); + if (!ret.isOk()) { + ALOGE("%s: Unable to invoke callback v2.1", __func__); + } + return; + } + if (sGnssCallback_2_0 == nullptr) { + ALOGE("%s: No non-null callback", __func__); + return; + } + auto ret = sGnssCallback_2_0->gnssLocationCb_2_0(location); + if (!ret.isOk()) { + ALOGE("%s: Unable to invoke callback v2.0", __func__); + } +} + +template +Return GnssTemplate::setLocation(const hidl_handle& fd, + const hidl_vec& options) { + auto lat = gMockLatitudeDegrees; + auto lon = gMockLongitudeDegrees; + auto ele = gMockAltitudeMeters; + auto bea = gMockBearingDegrees; + auto spd = gMockSpeedMetersPerSec; + + for (size_t i = 1; i < options.size(); ++i) { + std::string option = options[i]; + if (option.rfind("lat=", 0) == 0) { + option = option.substr(4); + lat = stof(option); + } else if (option.rfind("lon=", 0) == 0) { + option = option.substr(4); + lon = stof(option); + } else if (option.rfind("ele=", 0) == 0) { + option = option.substr(4); + ele = stof(option); + } else if (option.rfind("bea=", 0) == 0) { + option = option.substr(4); + bea = stof(option); + } else if (option.rfind("spd=", 0) == 0) { + option = option.substr(4); + spd = stof(option); + } else { + dprintf(fd->data[0], "unsupported location argument: %s\n", option.c_str()); + } + } + + gMockLatitudeDegrees = lat; + gMockLongitudeDegrees = lon; + gMockAltitudeMeters = ele; + gMockBearingDegrees = bea; + gMockSpeedMetersPerSec = spd; + + dprintf(fd->data[0], "mock location updated to lat=%f lon=%f ele=%f bea=%f spd=%f\n", + gMockLatitudeDegrees, gMockLongitudeDegrees, gMockAltitudeMeters, gMockBearingDegrees, + gMockSpeedMetersPerSec); + + return Void(); +} + +template +Return GnssTemplate::help(const hidl_handle& fd) { + dprintf(fd->data[0], + "invalid option for Gnss HAL; valid options are:\n" + "location [lat=..] [lon=..] [ele=..] [bea=..] [spd=..]\n"); + return Void(); +} + +template +Return GnssTemplate::debug(const hidl_handle& fd, + const hidl_vec& options) { + if (fd == nullptr || fd->numFds == 0) { + return Void(); + } + + if (options.size() == 0) { + return help(fd); + } else if (options[0] == "location") { + return setLocation(fd, options); + } else { + return help(fd); + } + + return Void(); +} + +} // namespace android::hardware::gnss::common::implementation diff --git a/gps/gnss/common/utils/default/v2_1/GnssAntennaInfo.cpp b/gps/gnss/common/utils/default/v2_1/GnssAntennaInfo.cpp new file mode 100644 index 0000000..962451c --- /dev/null +++ b/gps/gnss/common/utils/default/v2_1/GnssAntennaInfo.cpp @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2020 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 "GnssAntennaInfo" + +#include "v2_1/GnssAntennaInfo.h" +#include "Utils.h" + +#include + +using ::android::hardware::gnss::common::Utils; + +namespace android::hardware::gnss::V2_1::implementation { + +sp GnssAntennaInfo::sCallback = nullptr; + +GnssAntennaInfo::GnssAntennaInfo() : mMinIntervalMillis(1000) {} + +GnssAntennaInfo::~GnssAntennaInfo() { + stop(); +} + +// Methods from ::android::hardware::gnss::V2_1::IGnssAntennaInfo follow. +Return GnssAntennaInfo::setCallback( + const sp& callback) { + ALOGD("setCallback"); + std::unique_lock lock(mMutex); + sCallback = callback; + + if (mIsActive) { + ALOGW("GnssAntennaInfo callback already set. Resetting the callback..."); + stop(); + } + start(); + + return GnssAntennaInfoStatus::SUCCESS; +} + +Return GnssAntennaInfo::close() { + ALOGD("close"); + stop(); + std::unique_lock lock(mMutex); + sCallback = nullptr; + return Void(); +} + +// Private methods +void GnssAntennaInfo::start() { + ALOGD("start"); + mIsActive = true; + mThread = std::thread([this]() { + while (mIsActive == true) { + if (sCallback != nullptr) { + auto antennaInfos = Utils::getMockAntennaInfos(); + this->reportAntennaInfo(antennaInfos); + } + + /** For mock implementation this is good. On real device, we should only report + antennaInfo at start and when there is a configuration change. **/ + std::this_thread::sleep_for(std::chrono::milliseconds(mMinIntervalMillis)); + } + }); +} + +void GnssAntennaInfo::stop() { + ALOGD("stop"); + mIsActive = false; + if (mThread.joinable()) { + mThread.join(); + } +} + +void GnssAntennaInfo::reportAntennaInfo( + const hidl_vec& antennaInfo) const { + std::unique_lock lock(mMutex); + + if (sCallback == nullptr) { + ALOGE("%s: No non-null callback", __func__); + return; + } + + auto ret = sCallback->gnssAntennaInfoCb(antennaInfo); + if (!ret.isOk()) { + ALOGE("%s: Unable to invoke callback", __func__); + } +} + +} // namespace android::hardware::gnss::V2_1::implementation diff --git a/gps/gnss/common/utils/default/v2_1/GnssConfiguration.cpp b/gps/gnss/common/utils/default/v2_1/GnssConfiguration.cpp new file mode 100644 index 0000000..be974bc --- /dev/null +++ b/gps/gnss/common/utils/default/v2_1/GnssConfiguration.cpp @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2019 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 "GnssConfiguration" + +#include "v2_1/GnssConfiguration.h" +#include + +namespace android::hardware::gnss::V2_1::implementation { + +using GnssSvInfoV2_1 = V2_1::IGnssCallback::GnssSvInfo; +using BlacklistedSourceV2_1 = V2_1::IGnssConfiguration::BlacklistedSource; + +// Methods from ::android::hardware::gnss::V1_0::IGnssConfiguration follow. +Return GnssConfiguration::setSuplEs(bool enable) { + ALOGD("setSuplEs enable: %d", enable); + // Method deprecated in 2.0 and not expected to be called by the framework. + return false; +} + +Return GnssConfiguration::setSuplVersion(uint32_t) { + return true; +} + +Return GnssConfiguration::setSuplMode(hidl_bitfield) { + return true; +} + +Return GnssConfiguration::setGpsLock(hidl_bitfield gpsLock) { + ALOGD("setGpsLock gpsLock: %hhu", static_cast(gpsLock)); + // Method deprecated in 2.0 and not expected to be called by the framework. + return false; +} + +Return GnssConfiguration::setLppProfile(hidl_bitfield) { + return true; +} + +Return GnssConfiguration::setGlonassPositioningProtocol(hidl_bitfield) { + return true; +} + +Return GnssConfiguration::setEmergencySuplPdn(bool) { + return true; +} + +// Methods from ::android::hardware::gnss::V1_1::IGnssConfiguration follow. +Return GnssConfiguration::setBlacklist( + const hidl_vec&) { + // TODO (b/122463906): Reuse 1.1 implementation. + return bool{}; +} + +// Methods from ::android::hardware::gnss::V2_0::IGnssConfiguration follow. +Return GnssConfiguration::setEsExtensionSec(uint32_t emergencyExtensionSeconds) { + ALOGD("setEsExtensionSec emergencyExtensionSeconds: %d", emergencyExtensionSeconds); + return true; +} + +// Methods from ::android::hardware::gnss::V2_1::IGnssConfiguration follow. +Return GnssConfiguration::setBlacklist_2_1( + const hidl_vec& sourceList) { + std::unique_lock lock(mMutex); + mBlacklistedConstellationSet.clear(); + mBlacklistedSourceSet.clear(); + for (auto source : sourceList) { + if (source.svid == 0) { + // Wildcard blacklist, i.e., blacklist entire constellation. + mBlacklistedConstellationSet.insert(source.constellation); + } else { + mBlacklistedSourceSet.insert(source); + } + } + return true; +} + +Return GnssConfiguration::isBlacklistedV2_1(const GnssSvInfoV2_1& gnssSvInfo) const { + std::unique_lock lock(mMutex); + if (mBlacklistedConstellationSet.find(gnssSvInfo.v2_0.constellation) != + mBlacklistedConstellationSet.end()) { + return true; + } + BlacklistedSourceV2_1 source = {.constellation = gnssSvInfo.v2_0.constellation, + .svid = gnssSvInfo.v2_0.v1_0.svid}; + return (mBlacklistedSourceSet.find(source) != mBlacklistedSourceSet.end()); +} + +} // namespace android::hardware::gnss::V2_1::implementation diff --git a/gps/gnss/common/utils/default/v2_1/GnssDebug.cpp b/gps/gnss/common/utils/default/v2_1/GnssDebug.cpp new file mode 100644 index 0000000..537a90c --- /dev/null +++ b/gps/gnss/common/utils/default/v2_1/GnssDebug.cpp @@ -0,0 +1,55 @@ +/* + * 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 "GnssDebug" + +#include + +#include "Constants.h" +#include "MockLocation.h" +#include "v2_1/GnssDebug.h" + +using namespace ::android::hardware::gnss::common; + +namespace android::hardware::gnss::V1_1::implementation { + +// Methods from ::android::hardware::gnss::V1_0::IGnssDebug follow. +Return GnssDebug::getDebugData(V1_0::IGnssDebug::getDebugData_cb _hidl_cb) { + PositionDebug positionDebug = { + .valid = true, + .latitudeDegrees = gMockLatitudeDegrees, + .longitudeDegrees = gMockLongitudeDegrees, + .altitudeMeters = gMockAltitudeMeters, + .speedMetersPerSec = gMockSpeedMetersPerSec, + .bearingDegrees = gMockBearingDegrees, + .horizontalAccuracyMeters = kMockHorizontalAccuracyMeters, + .verticalAccuracyMeters = kMockVerticalAccuracyMeters, + .speedAccuracyMetersPerSecond = kMockSpeedAccuracyMetersPerSecond, + .bearingAccuracyDegrees = kMockBearingAccuracyDegrees, + .ageSeconds = 0.99}; + + TimeDebug timeDebug = {.timeEstimate = kMockTimestamp, + .timeUncertaintyNs = 1000, + .frequencyUncertaintyNsPerSec = 5.0e4}; + + DebugData data = {.position = positionDebug, .time = timeDebug}; + + _hidl_cb(data); + + return Void(); +} + +} // namespace android::hardware::gnss::V1_1::implementation diff --git a/gps/gnss/common/utils/default/v2_1/GnssMeasurement.cpp b/gps/gnss/common/utils/default/v2_1/GnssMeasurement.cpp new file mode 100644 index 0000000..887cb5a --- /dev/null +++ b/gps/gnss/common/utils/default/v2_1/GnssMeasurement.cpp @@ -0,0 +1,143 @@ +/* + * Copyright (C) 2019 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 "GnssMeasurement" + +#include "v2_1/GnssMeasurement.h" +#include +#include "Utils.h" + +namespace android::hardware::gnss::V2_1::implementation { + +using common::Utils; + +sp GnssMeasurement::sCallback_2_1 = nullptr; +sp GnssMeasurement::sCallback_2_0 = nullptr; + +GnssMeasurement::GnssMeasurement() : mMinIntervalMillis(1000) {} + +GnssMeasurement::~GnssMeasurement() { + stop(); +} + +// Methods from V1_0::IGnssMeasurement follow. +Return GnssMeasurement::setCallback( + const sp&) { + // TODO implement + return V1_0::IGnssMeasurement::GnssMeasurementStatus{}; +} + +Return GnssMeasurement::close() { + ALOGD("close"); + stop(); + std::unique_lock lock(mMutex); + sCallback_2_1 = nullptr; + sCallback_2_0 = nullptr; + return Void(); +} + +// Methods from V1_1::IGnssMeasurement follow. +Return GnssMeasurement::setCallback_1_1( + const sp&, bool) { + // TODO implement + return V1_0::IGnssMeasurement::GnssMeasurementStatus{}; +} + +// Methods from V2_0::IGnssMeasurement follow. +Return GnssMeasurement::setCallback_2_0( + const sp& callback, bool) { + ALOGD("setCallback_2_0"); + std::unique_lock lock(mMutex); + sCallback_2_0 = callback; + + if (mIsActive) { + ALOGW("GnssMeasurement callback already set. Resetting the callback..."); + stop(); + } + start(); + + return V1_0::IGnssMeasurement::GnssMeasurementStatus::SUCCESS; +} + +// Methods from V2_1::IGnssMeasurement follow. +Return GnssMeasurement::setCallback_2_1( + const sp& callback, bool) { + ALOGD("setCallback_2_1"); + std::unique_lock lock(mMutex); + sCallback_2_1 = callback; + + if (mIsActive) { + ALOGW("GnssMeasurement callback already set. Resetting the callback..."); + stop(); + } + start(); + + return V1_0::IGnssMeasurement::GnssMeasurementStatus::SUCCESS; +} + +void GnssMeasurement::start() { + ALOGD("start"); + mIsActive = true; + mThread = std::thread([this]() { + while (mIsActive == true) { + if (sCallback_2_1 != nullptr) { + auto measurement = Utils::getMockMeasurementV2_1(); + this->reportMeasurement(measurement); + } else { + auto measurement = Utils::getMockMeasurementV2_0(); + this->reportMeasurement(measurement); + } + + std::this_thread::sleep_for(std::chrono::milliseconds(mMinIntervalMillis)); + } + }); +} + +void GnssMeasurement::stop() { + ALOGD("stop"); + mIsActive = false; + if (mThread.joinable()) { + mThread.join(); + } +} + +void GnssMeasurement::reportMeasurement(const V2_0::IGnssMeasurementCallback::GnssData& data) { + ALOGD("reportMeasurement()"); + std::unique_lock lock(mMutex); + if (sCallback_2_0 == nullptr) { + ALOGE("%s: GnssMeasurement::sCallback_2_0 is null.", __func__); + return; + } + auto ret = sCallback_2_0->gnssMeasurementCb_2_0(data); + if (!ret.isOk()) { + ALOGE("%s: Unable to invoke callback", __func__); + } +} + +void GnssMeasurement::reportMeasurement(const V2_1::IGnssMeasurementCallback::GnssData& data) { + ALOGD("reportMeasurement()"); + std::unique_lock lock(mMutex); + if (sCallback_2_1 == nullptr) { + ALOGE("%s: GnssMeasurement::sCallback_2_1 is null.", __func__); + return; + } + auto ret = sCallback_2_1->gnssMeasurementCb_2_1(data); + if (!ret.isOk()) { + ALOGE("%s: Unable to invoke callback", __func__); + } +} + +} // namespace android::hardware::gnss::V2_1::implementation diff --git a/gps/gnss/common/utils/default/v2_1/GnssMeasurementCorrections.cpp b/gps/gnss/common/utils/default/v2_1/GnssMeasurementCorrections.cpp new file mode 100644 index 0000000..9be7e23 --- /dev/null +++ b/gps/gnss/common/utils/default/v2_1/GnssMeasurementCorrections.cpp @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2019 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 "GnssMeasurementCorrections" + +#include "v2_1/GnssMeasurementCorrections.h" +#include + +namespace android::hardware::gnss::measurement_corrections::V1_1::implementation { + +GnssMeasurementCorrections::GnssMeasurementCorrections() {} + +GnssMeasurementCorrections::~GnssMeasurementCorrections() {} + +// Methods from V1_0::IMeasurementCorrections follow. +Return GnssMeasurementCorrections::setCorrections( + const V1_0::MeasurementCorrections& corrections) { + ALOGD("setCorrections"); + ALOGD("corrections = lat: %f, lng: %f, alt: %f, hUnc: %f, vUnc: %f, toa: %llu, " + "satCorrections.size: %d", + corrections.latitudeDegrees, corrections.longitudeDegrees, corrections.altitudeMeters, + corrections.horizontalPositionUncertaintyMeters, + corrections.verticalPositionUncertaintyMeters, + static_cast(corrections.toaGpsNanosecondsOfWeek), + static_cast(corrections.satCorrections.size())); + for (auto singleSatCorrection : corrections.satCorrections) { + ALOGD("singleSatCorrection = flags: %d, constellation: %d, svid: %d, cfHz: %f, probLos: %f," + " epl: %f, eplUnc: %f", + static_cast(singleSatCorrection.singleSatCorrectionFlags), + static_cast(singleSatCorrection.constellation), + static_cast(singleSatCorrection.svid), singleSatCorrection.carrierFrequencyHz, + singleSatCorrection.probSatIsLos, singleSatCorrection.excessPathLengthMeters, + singleSatCorrection.excessPathLengthUncertaintyMeters); + ALOGD("reflecting plane = lat: %f, lng: %f, alt: %f, azm: %f", + singleSatCorrection.reflectingPlane.latitudeDegrees, + singleSatCorrection.reflectingPlane.longitudeDegrees, + singleSatCorrection.reflectingPlane.altitudeMeters, + singleSatCorrection.reflectingPlane.azimuthDegrees); + } + + return true; +} + +Return GnssMeasurementCorrections::setCallback( + const sp& callback) { + using Capabilities = V1_0::IMeasurementCorrectionsCallback::Capabilities; + auto ret = + callback->setCapabilitiesCb(Capabilities::LOS_SATS | Capabilities::EXCESS_PATH_LENGTH | + Capabilities::REFLECTING_PLANE); + if (!ret.isOk()) { + ALOGE("%s: Unable to invoke callback", __func__); + return false; + } + return true; +} + +// Methods from V1_1::IMeasurementCorrections follow. +Return GnssMeasurementCorrections::setCorrections_1_1( + const V1_1::MeasurementCorrections& corrections) { + ALOGD("setCorrections_1_1"); + ALOGD("corrections = lat: %f, lng: %f, alt: %f, hUnc: %f, vUnc: %f, toa: %llu," + "satCorrections.size: %d, hasEnvironmentBearing: %d, environmentBearingDeg: %f," + "environmentBearingUncDeg: %f", + corrections.v1_0.latitudeDegrees, corrections.v1_0.longitudeDegrees, + corrections.v1_0.altitudeMeters, corrections.v1_0.horizontalPositionUncertaintyMeters, + corrections.v1_0.verticalPositionUncertaintyMeters, + static_cast(corrections.v1_0.toaGpsNanosecondsOfWeek), + static_cast(corrections.v1_0.satCorrections.size()), + corrections.hasEnvironmentBearing, corrections.environmentBearingDegrees, + corrections.environmentBearingUncertaintyDegrees); + for (auto singleSatCorrection : corrections.satCorrections) { + ALOGD("singleSatCorrection = flags: %d, constellation: %d, svid: %d, cfHz: %f, probLos: %f," + " epl: %f, eplUnc: %f", + static_cast(singleSatCorrection.v1_0.singleSatCorrectionFlags), + static_cast(singleSatCorrection.constellation), + static_cast(singleSatCorrection.v1_0.svid), + singleSatCorrection.v1_0.carrierFrequencyHz, singleSatCorrection.v1_0.probSatIsLos, + singleSatCorrection.v1_0.excessPathLengthMeters, + singleSatCorrection.v1_0.excessPathLengthUncertaintyMeters); + ALOGD("reflecting plane = lat: %f, lng: %f, alt: %f, azm: %f", + singleSatCorrection.v1_0.reflectingPlane.latitudeDegrees, + singleSatCorrection.v1_0.reflectingPlane.longitudeDegrees, + singleSatCorrection.v1_0.reflectingPlane.altitudeMeters, + singleSatCorrection.v1_0.reflectingPlane.azimuthDegrees); + } + + return true; +} + +} // namespace android::hardware::gnss::measurement_corrections::V1_1::implementation diff --git a/gps/init.redroid.gps.sh b/gps/init.redroid.gps.sh new file mode 100644 index 0000000..b5d0819 --- /dev/null +++ b/gps/init.redroid.gps.sh @@ -0,0 +1,10 @@ +#!/vendor/bin/sh + +if [ ! -f /data/vendor/gps/gnss ]; then + echo "LatitudeDegrees=30.281026818001678" > /data/vendor/gps/gnss + echo "LongitudeDegrees=120.01934876982831" >> /data/vendor/gps/gnss + echo "AltitudeMeters=1.60062531" >> /data/vendor/gps/gnss + echo "BearingDegrees=0" >> /data/vendor/gps/gnss + echo "SpeedMetersPerSec=0" >> /data/vendor/gps/gnss + chmod 777 /data/vendor/gps/gnss +fi diff --git a/redroid.legacy.rc b/redroid.legacy.rc index a6d641f..eab6936 100644 --- a/redroid.legacy.rc +++ b/redroid.legacy.rc @@ -1,4 +1,6 @@ # convert legacy props +on late-init + umount /sys/fs/fuse/connections # overlay data on early-init && property:ro.kernel.redroid.overlay=1 @@ -45,3 +47,20 @@ on early-init && property:ro.kernel.redroid.gpu.mode=* on early-init && property:ro.kernel.redroid.gpu.node=* setprop ro.boot.redroid_gpu_node ${ro.kernel.redroid.gpu.node} + + +# Battery +on post-fs-data + mkdir /data/vendor/battery 0751 root root + exec -- /system/bin/sh /vendor/bin/hw/init.redroid.battery.sh + + +# GPS +on post-fs-data + mkdir /data/vendor/gps 0751 root root + exec -- /system/bin/sh /vendor/bin/hw/init.redroid.gps.sh + +service gnss /vendor/bin/hw/android.hardware.gnss-service + class hal + user nobody + group nobody \ No newline at end of file diff --git a/vendor.mk b/vendor.mk index 3b38e0c..9b40c8f 100644 --- a/vendor.mk +++ b/vendor.mk @@ -1,3 +1,6 @@ +include vendor/redroid/BoardConfig.mk + + # skip androidx.window.extensions check PRODUCT_BROKEN_VERIFY_USES_LIBRARIES := true @@ -16,3 +19,49 @@ PRODUCT_COPY_FILES += \ PRODUCT_COPY_FILES += \ frameworks/native/data/etc/android.hardware.touchscreen.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.touchscreen.xml \ + + +###################### +# battery config +###################### +# +# Power HAL +# +PRODUCT_PACKAGES += \ + android.hardware.power-service.example + +# +# PowerStats HAL +# +PRODUCT_PACKAGES += \ + android.hardware.power.stats-service.example + +PRODUCT_COPY_FILES += \ + vendor/redroid/battery/init.redroid.battery.sh:$(TARGET_COPY_OUT_VENDOR)/bin/hw/init.redroid.battery.sh \ + $(call find-copy-subdir-files,*,vendor/redroid/battery/power_supply,$(TARGET_COPY_OUT_VENDOR)/etc/init/hw/battery/power_supply) \ + + +###################### +# gps config +###################### +PRODUCT_PACKAGES += \ + android.hardware.gnss-service + +PRODUCT_COPY_FILES += \ + vendor/redroid/gps/init.redroid.gps.sh:$(TARGET_COPY_OUT_VENDOR)/bin/hw/init.redroid.gps.sh \ + + +###################### +# gms config +###################### +$(call inherit-product-if-exists, vendor/redroid/gapps/arm64/arm64-vendor.mk) + +# disable setupwizard +PRODUCT_SYSTEM_EXT_PROPERTIES += \ + ro.setupwizard.mode=DISABLED + + +###################### +# zygisk config +###################### +$(call inherit-product-if-exists, vendor/magisk/device.mk)