feat: 更新GPS功能,添加自定义位置支持,调整权限和配置,移除旧服务

This commit is contained in:
2025-09-17 00:07:25 +08:00
parent 15936404b6
commit f67e673321
44 changed files with 1603 additions and 3415 deletions

66
gps/Android.bp Normal file
View File

@@ -0,0 +1,66 @@
// Copyright (C) 2023 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.
cc_library_shared {
name: "libredroid_gps_jni",
srcs: [
"com_android_server_location_GnssLocationProvider.cpp",
],
cflags: [
"-Wall",
"-Werror",
"-Wextra",
"-std=c++17",
],
shared_libs: [
"libandroid_runtime",
"libbinder",
"libcutils",
"liblog",
"libnativehelper",
"libutils",
"libhardware",
"libhardware_legacy",
"libhidlbase",
"libhidltransport",
"android.hardware.gnss@1.0",
"android.hardware.gnss@1.1",
"android.hardware.gnss@2.0",
"android.hardware.gnss@2.1",
"android.hardware.gnss-V1-ndk",
],
static_libs: [
"libc++fs",
],
header_libs: [
"jni_headers",
"libandroid_runtime_headers",
],
include_dirs: [
"frameworks/base/services/core/jni",
"frameworks/base/core/jni",
],
vendor: true,
compile_multilib: "both",
relative_install_path: "hw",
}

196
gps/BUILD_GUIDE.md Normal file
View File

@@ -0,0 +1,196 @@
# Redroid 自定义GPS位置构建指南
本指南详细说明如何构建和使用Redroid的自定义GPS位置功能。
## 📋 修改的文件列表
### 1. 核心实现文件
- `gps/com_android_server_location_GnssLocationProvider.cpp` - 主要的JNI实现
- `gps/Android.bp` - 编译配置文件(新增)
- `gps/init.redroid.gps.sh` - GPS初始化脚本
### 2. 集成配置文件
- `vendor.mk` - 添加GPS JNI库到产品包
- `redroid.legacy.rc` - 调整GPS目录权限
## 🔧 构建步骤
### 1. 准备源码
确保所有修改的文件都在正确的位置:
```bash
vendor/redroid/
├── gps/
│ ├── com_android_server_location_GnssLocationProvider.cpp
│ ├── Android.bp
│ └── init.redroid.gps.sh
├── vendor.mk
└── redroid.legacy.rc
```
### 2. 编译系统
在Android源码根目录执行
```bash
# 设置环境
source build/envsetup.sh
# 选择目标(根据你的设备调整)
lunch aosp_arm64-eng
# 编译GPS JNI库
m libredroid_gps_jni
# 或者编译整个vendor模块
m vendor-redroid
```
### 3. 验证编译结果
检查编译输出:
```bash
# 检查生成的库文件
ls -la out/target/product/*/vendor/lib*/hw/libredroid_gps_jni.so
```
## 🚀 部署和使用
### 1. 系统启动
当Android系统启动时`redroid.legacy.rc`会自动:
- 创建`/data/vendor/gps`目录
- 执行`init.redroid.gps.sh`脚本
- 设置正确的权限
### 2. 默认位置
系统会创建默认的GPS位置文件
```bash
/data/vendor/gps/custom_location.txt
```
默认坐标(杭州):`30.281026,120.019348`
### 3. 自定义位置
修改GPS位置只需编辑文件
```bash
# 使用adb连接设备
adb shell
# 修改GPS位置例如北京天安门
echo "39.904989,116.405285" > /data/vendor/gps/custom_location.txt
# 或者使用adb push
echo "39.904989,116.405285" > custom_location.txt
adb push custom_location.txt /data/vendor/gps/
```
### 4. 实时生效
- 修改文件后新的GPS位置会在下次位置请求时自动生效
- 无需重启系统或GPS服务
- 系统会检测文件修改时间并自动加载新坐标
## 📍 支持的坐标格式
### 逗号分隔格式
```
纬度,经度
39.904989,116.405285
```
### 空格分隔格式
```
纬度 经度
39.904989 116.405285
```
### 坐标范围
- 纬度:-90° 到 +90°
- 经度:-180° 到 +180°
## 🧪 测试验证
### 1. 查看日志
```bash
# 查看GPS相关日志
adb logcat | grep -i gnss
adb logcat | grep -i "custom.*gps"
# 期望看到的日志:
# I/GnssLocationProviderJni: Custom GPS location loaded: lat=39.904989, lon=116.405285
# I/GnssLocationProviderJni: Using custom GPS location: lat=39.904989, lon=116.405285
```
### 2. 使用GPS应用
- 打开地图应用如Google Maps
- 启用位置服务
- 应该显示自定义的GPS位置
### 3. 验证位置变更
```bash
# 修改位置
echo "31.239666,121.499809" > /data/vendor/gps/custom_location.txt
# 在地图应用中观察位置变化
```
## 🔍 故障排除
### 编译错误
1. 确保Android编译环境正确设置
2. 检查依赖库是否存在
3. 验证Android.bp语法
### 运行时错误
1. 检查文件权限:
```bash
ls -la /data/vendor/gps/
```
2. 验证文件格式:
```bash
cat /data/vendor/gps/custom_location.txt
```
3. 查看详细日志:
```bash
adb logcat -v threadtime | grep -E "(Gnss|GPS)"
```
### 权限问题
如果遇到权限错误:
```bash
# 重新设置权限
adb shell
chown system:system /data/vendor/gps/custom_location.txt
chmod 644 /data/vendor/gps/custom_location.txt
```
## 📱 兼容性
### Android版本
- 支持Android 8.0+API 26+
- 测试过的版本Android 11、12、13
### 架构支持
- ARM64
- ARM32
- x86_64通过Android.bp的compile_multilib配置
## 🔄 回退到默认GPS
如果要禁用自定义GPS功能
```bash
# 删除自定义位置文件
rm /data/vendor/gps/custom_location.txt
# 系统会自动回退到默认GPS行为
```
## 📞 技术支持
如果遇到问题,请提供:
1. Android版本和设备信息
2. 完整的logcat日志
3. 文件权限和内容截图
4. 具体的错误现象描述

File diff suppressed because it is too large Load Diff

View File

@@ -1,69 +0,0 @@
/*
* 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",
],
}

View File

@@ -1,91 +0,0 @@
/*
* 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 <log/log.h>
#include "GnssConfiguration.h"
#include "GnssMeasurementInterface.h"
#include "GnssPsds.h"
namespace aidl::android::hardware::gnss {
std::shared_ptr<IGnssCallback> Gnss::sGnssCallback = nullptr;
ndk::ScopedAStatus Gnss::setCallback(const std::shared_ptr<IGnssCallback>& 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>* iGnssPsds) {
ALOGD("Gnss::getExtensionPsds");
*iGnssPsds = SharedRefBase::make<GnssPsds>();
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus Gnss::getExtensionGnssConfiguration(
std::shared_ptr<IGnssConfiguration>* iGnssConfiguration) {
ALOGD("Gnss::getExtensionGnssConfiguration");
if (mGnssConfiguration == nullptr) {
mGnssConfiguration = SharedRefBase::make<GnssConfiguration>();
}
*iGnssConfiguration = mGnssConfiguration;
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus Gnss::getExtensionGnssPowerIndication(
std::shared_ptr<IGnssPowerIndication>* iGnssPowerIndication) {
ALOGD("Gnss::getExtensionGnssPowerIndication");
if (mGnssPowerIndication == nullptr) {
mGnssPowerIndication = SharedRefBase::make<GnssPowerIndication>();
}
*iGnssPowerIndication = mGnssPowerIndication;
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus Gnss::getExtensionGnssMeasurement(
std::shared_ptr<IGnssMeasurementInterface>* iGnssMeasurement) {
ALOGD("Gnss::getExtensionGnssMeasurement");
*iGnssMeasurement = SharedRefBase::make<GnssMeasurementInterface>();
return ndk::ScopedAStatus::ok();
}
} // namespace aidl::android::hardware::gnss

View File

@@ -1,48 +0,0 @@
/*
* 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 <aidl/android/hardware/gnss/BnGnss.h>
#include <aidl/android/hardware/gnss/BnGnssConfiguration.h>
#include <aidl/android/hardware/gnss/BnGnssMeasurementInterface.h>
#include <aidl/android/hardware/gnss/BnGnssPowerIndication.h>
#include <aidl/android/hardware/gnss/BnGnssPsds.h>
#include "GnssConfiguration.h"
#include "GnssPowerIndication.h"
namespace aidl::android::hardware::gnss {
class Gnss : public BnGnss {
public:
ndk::ScopedAStatus setCallback(const std::shared_ptr<IGnssCallback>& callback) override;
ndk::ScopedAStatus close() override;
ndk::ScopedAStatus getExtensionPsds(std::shared_ptr<IGnssPsds>* iGnssPsds) override;
ndk::ScopedAStatus getExtensionGnssConfiguration(
std::shared_ptr<IGnssConfiguration>* iGnssConfiguration) override;
ndk::ScopedAStatus getExtensionGnssPowerIndication(
std::shared_ptr<IGnssPowerIndication>* iGnssPowerIndication) override;
ndk::ScopedAStatus getExtensionGnssMeasurement(
std::shared_ptr<IGnssMeasurementInterface>* iGnssMeasurement) override;
std::shared_ptr<GnssConfiguration> mGnssConfiguration;
std::shared_ptr<GnssPowerIndication> mGnssPowerIndication;
private:
static std::shared_ptr<IGnssCallback> sGnssCallback;
};
} // namespace aidl::android::hardware::gnss

View File

@@ -1,52 +0,0 @@
/*
* 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 <log/log.h>
namespace aidl::android::hardware::gnss {
ndk::ScopedAStatus GnssConfiguration::setBlocklist(const vector<BlocklistedSource>& sourceList) {
ALOGD("GnssConfiguration::setBlocklist");
std::unique_lock<std::recursive_mutex> 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<std::recursive_mutex> lock(mMutex);
if (mBlocklistedConstellationSet.find(static_cast<GnssConstellationType>(
gnssSvInfo.v2_0.constellation)) != mBlocklistedConstellationSet.end()) {
return true;
}
BlocklistedSource source = {
.constellation = static_cast<GnssConstellationType>(gnssSvInfo.v2_0.constellation),
.svid = gnssSvInfo.v2_0.v1_0.svid};
return (mBlocklistedSourceSet.find(source) != mBlocklistedSourceSet.end());
}
} // namespace aidl::android::hardware::gnss

View File

@@ -1,72 +0,0 @@
/*
* 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 <aidl/android/hardware/gnss/BnGnssConfiguration.h>
#include <android/hardware/gnss/2.1/IGnssCallback.h>
#include <mutex>
#include <unordered_set>
#include <vector>
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<BlocklistedSource, BlocklistedSourceHash, BlocklistedSourceEqual>;
using BlocklistedConstellationSet =
std::unordered_set<android::hardware::gnss::GnssConstellationType>;
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<BlocklistedSource>& 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

View File

@@ -1,65 +0,0 @@
/*
* 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<Gnss>& gnssAidl) : mGnssAidl(gnssAidl) {
Gnss* iGnss = mGnssAidl.get();
std::shared_ptr<IGnssConfiguration> iGnssConfiguration;
auto status = iGnss->getExtensionGnssConfiguration(&iGnssConfiguration);
if (!status.isOk()) {
ALOGE("Failed to getExtensionGnssConfiguration.");
} else {
mGnssConfigurationAidl = iGnss->mGnssConfiguration;
}
std::shared_ptr<IGnssPowerIndication> iGnssPowerIndication;
status = iGnss->getExtensionGnssPowerIndication(&iGnssPowerIndication);
if (!status.isOk()) {
ALOGE("Failed to getExtensionGnssPowerIndication.");
} else {
mGnssPowerIndicationAidl = iGnss->mGnssPowerIndication;
}
};
hidl_vec<GnssSvInfo> GnssHidlHal::filterBlocklistedSatellitesV2_1(
hidl_vec<GnssSvInfo> 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<uint8_t>(
::android::hardware::gnss::V1_0::IGnssCallback::GnssSvFlags::USED_IN_FIX);
}
}
return gnssSvInfoList;
}
void GnssHidlHal::notePowerConsumption() {
mGnssPowerIndicationAidl->notePowerConsumption();
}
} // namespace aidl::android::hardware::gnss

View File

@@ -1,42 +0,0 @@
/*
* 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<Gnss>& 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<Gnss> mGnssAidl;
std::shared_ptr<GnssConfiguration> mGnssConfigurationAidl;
std::shared_ptr<GnssPowerIndication> mGnssPowerIndicationAidl;
};
} // namespace aidl::android::hardware::gnss

View File

@@ -1,94 +0,0 @@
/*
* 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 <aidl/android/hardware/gnss/BnGnss.h>
#include <log/log.h>
#include "Utils.h"
namespace aidl::android::hardware::gnss {
using Utils = ::android::hardware::gnss::common::Utils;
std::shared_ptr<IGnssMeasurementCallback> GnssMeasurementInterface::sCallback = nullptr;
GnssMeasurementInterface::GnssMeasurementInterface() : mMinIntervalMillis(1000) {}
GnssMeasurementInterface::~GnssMeasurementInterface() {
stop();
}
ndk::ScopedAStatus GnssMeasurementInterface::setCallback(
const std::shared_ptr<IGnssMeasurementCallback>& callback, const bool enableFullTracking,
const bool enableCorrVecOutputs) {
ALOGD("setCallback: enableFullTracking: %d enableCorrVecOutputs: %d", (int)enableFullTracking,
(int)enableCorrVecOutputs);
std::unique_lock<std::mutex> 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<std::mutex> 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<IGnssMeasurementCallback> callbackCopy;
{
std::unique_lock<std::mutex> lock(mMutex);
if (sCallback == nullptr) {
ALOGE("%s: GnssMeasurement::sCallback is null.", __func__);
return;
}
callbackCopy = sCallback;
}
callbackCopy->gnssMeasurementCb(data);
}
} // namespace aidl::android::hardware::gnss

View File

@@ -1,52 +0,0 @@
/*
* 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 <aidl/android/hardware/gnss/BnGnssMeasurementCallback.h>
#include <aidl/android/hardware/gnss/BnGnssMeasurementInterface.h>
#include <atomic>
#include <mutex>
#include <thread>
namespace aidl::android::hardware::gnss {
struct GnssMeasurementInterface : public BnGnssMeasurementInterface {
public:
GnssMeasurementInterface();
~GnssMeasurementInterface();
ndk::ScopedAStatus setCallback(const std::shared_ptr<IGnssMeasurementCallback>& 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<long> mMinIntervalMillis;
std::atomic<bool> mIsActive;
std::thread mThread;
// Guarded by mMutex
static std::shared_ptr<IGnssMeasurementCallback> sCallback;
// Synchronization lock for sCallback
mutable std::mutex mMutex;
};
} // namespace aidl::android::hardware::gnss

View File

@@ -1,68 +0,0 @@
/*
* 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 <aidl/android/hardware/gnss/BnGnss.h>
#include <log/log.h>
#include <utils/SystemClock.h>
namespace aidl::android::hardware::gnss {
std::shared_ptr<IGnssPowerIndicationCallback> GnssPowerIndication::sCallback = nullptr;
ndk::ScopedAStatus GnssPowerIndication::setCallback(
const std::shared_ptr<IGnssPowerIndicationCallback>& callback) {
ALOGD("setCallback");
std::unique_lock<std::mutex> 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<std::mutex> 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

View File

@@ -1,41 +0,0 @@
/*
* 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 <aidl/android/hardware/gnss/BnGnssPowerIndication.h>
namespace aidl::android::hardware::gnss {
struct GnssPowerIndication : public BnGnssPowerIndication {
public:
ndk::ScopedAStatus setCallback(
const std::shared_ptr<IGnssPowerIndicationCallback>& callback) override;
ndk::ScopedAStatus requestGnssPowerStats() override;
void notePowerConsumption();
private:
// Guarded by mMutex
static std::shared_ptr<IGnssPowerIndicationCallback> sCallback;
// Synchronization lock for sCallback
mutable std::mutex mMutex;
int numLocationReported;
};
} // namespace aidl::android::hardware::gnss

View File

@@ -1,44 +0,0 @@
/*
* 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 <aidl/android/hardware/gnss/BnGnss.h>
#include <log/log.h>
namespace aidl::android::hardware::gnss {
std::shared_ptr<IGnssPsdsCallback> GnssPsds::sCallback = nullptr;
ndk::ScopedAStatus GnssPsds::setCallback(const std::shared_ptr<IGnssPsdsCallback>& callback) {
ALOGD("setCallback");
std::unique_lock<std::mutex> lock(mMutex);
sCallback = callback;
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus GnssPsds::injectPsdsData(PsdsType psdsType,
const std::vector<uint8_t>& psdsData) {
ALOGD("injectPsdsData. psdsType: %d, psdsData: %d bytes", static_cast<int>(psdsType),
static_cast<int>(psdsData.size()));
if (psdsData.size() > 0) {
return ndk::ScopedAStatus::ok();
} else {
return ndk::ScopedAStatus::fromServiceSpecificError(IGnss::ERROR_INVALID_ARGUMENT);
}
}
} // namespace aidl::android::hardware::gnss

View File

@@ -1,37 +0,0 @@
/*
* 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 <aidl/android/hardware/gnss/BnGnssPsds.h>
namespace aidl::android::hardware::gnss {
struct GnssPsds : public BnGnssPsds {
public:
ndk::ScopedAStatus setCallback(const std::shared_ptr<IGnssPsdsCallback>& callback) override;
ndk::ScopedAStatus injectPsdsData(PsdsType psdsType,
const std::vector<uint8_t>& psdsData) override;
private:
// Guarded by mMutex
static std::shared_ptr<IGnssPsdsCallback> sCallback;
// Synchronization lock for sCallback
mutable std::mutex mMutex;
};
} // namespace aidl::android::hardware::gnss

View File

@@ -1,4 +0,0 @@
service gnss /vendor/bin/hw/android.hardware.gnss-service
class hal
user nobody
group nobody

View File

@@ -1,9 +0,0 @@
<manifest version="1.0" type="device">
<hal format="aidl">
<name>android.hardware.gnss</name>
<interface>
<name>IGnss</name>
<instance>default</instance>
</interface>
</hal>
</manifest>

View File

@@ -1,12 +0,0 @@
<manifest version="1.0" type="device">
<hal format="hidl">
<name>android.hardware.gnss</name>
<transport>hwbinder</transport>
<version>2.1</version>
<version>1.1</version>
<interface>
<name>IGnss</name>
<instance>default</instance>
</interface>
</hal>
</manifest>

View File

@@ -1,58 +0,0 @@
/*
* 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 <android-base/logging.h>
#include <android/binder_manager.h>
#include <android/binder_process.h>
#include <hidl/HidlSupport.h>
#include <hidl/HidlTransportSupport.h>
#include <log/log.h>
#include <pthread.h>
#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<Gnss> gnssAidl = ndk::SharedRefBase::make<Gnss>();
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<IGnss> 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
}

View File

@@ -1,7 +0,0 @@
wyattriley@google.com
gomo@google.com
smalkos@google.com
yuhany@google.com
# VTS team
yim@google.com

View File

@@ -1,57 +0,0 @@
//
// 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",
],
}

View File

@@ -1,27 +0,0 @@
/*
* 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

View File

@@ -1,273 +0,0 @@
/*
* 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 <Constants.h>
#include <NmeaFixInfo.h>
#include <Utils.h>
#include <log/log.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <utils/SystemClock.h>
#include <limits>
#include <sstream>
#include <string>
#include <vector>
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<float>::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<int64_t>(mktime(&tm) - timezone);
}
bool NmeaFixInfo::isValidFix() const {
return hasGMCRecord && hasGGARecord;
}
void NmeaFixInfo::parseGGALine(const std::vector<std::string>& 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<float>::quiet_NaN()
: std::stof(sentenceValues[8]);
this->hasGGARecord = true;
}
void NmeaFixInfo::parseRMCLine(const std::vector<std::string>& 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<std::string>& 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<V2_0::GnssLocation> NmeaFixInfo::getLocationFromInputStr(
const std::string& inputStr) {
std::vector<std::string> 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<std::string> 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<V2_0::GnssLocation> 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<uint64_t>(::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<V2_0::GnssLocation>(locationV2);
}
} // namespace common
} // namespace gnss
} // namespace hardware
} // namespace android

View File

@@ -1,405 +0,0 @@
/*
* 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 <Constants.h>
#include <MockLocation.h>
#include <Utils.h>
#include <aidl/android/hardware/gnss/BnGnss.h>
#include <utils/SystemClock.h>
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<V2_1::IGnssMeasurementCallback::GnssMeasurement> 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<IGnssMeasurementCallbackV2_0::GnssMeasurement> 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<uint64_t>(::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<uint64_t>(::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<int64_t>(kMockTimestamp + ::android::elapsedRealtimeNano() / 1e6)};
return location;
}
hidl_vec<GnssSvInfoV2_1> 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<GnssSvInfoV2_1> 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<GnssAntennaInfo> 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<double>{1, -1, 5, -2, 3, -1}},
Row{hidl_vec<double>{-2, 3, 2, 0, 1, 2}},
Row{hidl_vec<double>{1, 3, 2, -1, -3, 5}},
},
.phaseCenterVariationCorrectionUncertaintyMillimeters =
{
Row{hidl_vec<double>{0.1, 0.2, 0.4, 0.1, 0.2, 0.3}},
Row{hidl_vec<double>{0.3, 0.2, 0.3, 0.6, 0.1, 0.1}},
Row{hidl_vec<double>{0.1, 0.1, 0.4, 0.2, 0.5, 0.3}},
},
.signalGainCorrectionDbi =
{
Row{hidl_vec<double>{2, -3, 1, -3, 0, -4}},
Row{hidl_vec<double>{1, 0, -4, 1, 3, -2}},
Row{hidl_vec<double>{3, -2, 0, -2, 3, 0}},
},
.signalGainCorrectionUncertaintyDbi =
{
Row{hidl_vec<double>{0.3, 0.1, 0.2, 0.6, 0.1, 0.3}},
Row{hidl_vec<double>{0.1, 0.1, 0.5, 0.2, 0.3, 0.1}},
Row{hidl_vec<double>{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<GnssAntennaInfo> mockAntennaInfos = {
mockAntennaInfo_1,
mockAntennaInfo_2,
};
return mockAntennaInfos;
}
} // namespace common
} // namespace gnss
} // namespace hardware
} // namespace android

View File

@@ -1,42 +0,0 @@
/*
* 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 <cstdint>
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_

View File

@@ -1,38 +0,0 @@
/*
* 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 <cstdint>
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_

View File

@@ -1,88 +0,0 @@
/*
* 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 <Constants.h>
#include <android/hardware/gnss/1.0/IGnss.h>
#include <android/hardware/gnss/2.0/IGnss.h>
#include <hidl/Status.h>
#include <ctime>
#include <string>
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<V2_0::GnssLocation> getLocationFromInputStr(const std::string& inputStr);
private:
static void splitStr(const std::string& line, const char& delimiter,
std::vector<std::string>& 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<std::string>& sentenceValues);
void parseRMCLine(const std::vector<std::string>& sentenceValues);
std::unique_ptr<V2_0::GnssLocation> 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

View File

@@ -1,57 +0,0 @@
/*
* 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 <aidl/android/hardware/gnss/BnGnssMeasurementInterface.h>
#include <android/hardware/gnss/1.0/IGnss.h>
#include <android/hardware/gnss/2.0/IGnss.h>
#include <android/hardware/gnss/2.1/IGnss.h>
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<V2_1::IGnssCallback::GnssSvInfo> 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<V2_1::IGnssAntennaInfoCallback::GnssAntennaInfo> getMockAntennaInfos();
};
} // namespace common
} // namespace gnss
} // namespace hardware
} // namespace android
#endif // android_hardware_gnss_common_default_Utils_H_

View File

@@ -1,54 +0,0 @@
/*
* 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 <android/hardware/gnss/2.1/IGnssAntennaInfo.h>
#include <mutex>
#include <thread>
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<GnssAntennaInfoStatus> setCallback(
const sp<::android::hardware::gnss::V2_1::IGnssAntennaInfoCallback>& callback) override;
Return<void> 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<long> mMinIntervalMillis;
std::atomic<bool> mIsActive;
std::thread mThread;
// Synchronization lock for sCallback
mutable std::mutex mMutex;
};
} // namespace android::hardware::gnss::V2_1::implementation

View File

@@ -1,82 +0,0 @@
/*
* 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 <android/hardware/gnss/2.1/IGnssCallback.h>
#include <android/hardware/gnss/2.1/IGnssConfiguration.h>
#include <hidl/MQDescriptor.h>
#include <hidl/Status.h>
#include <mutex>
#include <unordered_set>
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<V2_0::GnssConstellationType>;
struct GnssConfiguration : public IGnssConfiguration {
// Methods from ::android::hardware::gnss::V1_0::IGnssConfiguration follow.
Return<bool> setSuplEs(bool enabled) override;
Return<bool> setSuplVersion(uint32_t version) override;
Return<bool> setSuplMode(hidl_bitfield<SuplMode> mode) override;
Return<bool> setGpsLock(hidl_bitfield<GpsLock> lock) override;
Return<bool> setLppProfile(hidl_bitfield<LppProfile> lppProfile) override;
Return<bool> setGlonassPositioningProtocol(hidl_bitfield<GlonassPosProtocol> protocol) override;
Return<bool> setEmergencySuplPdn(bool enable) override;
// Methods from ::android::hardware::gnss::V1_1::IGnssConfiguration follow.
Return<bool> setBlacklist(
const hidl_vec<V1_1::IGnssConfiguration::BlacklistedSource>& blacklist) override;
std::recursive_mutex& getMutex() const;
// Methods from ::android::hardware::gnss::V2_0::IGnssConfiguration follow.
Return<bool> setEsExtensionSec(uint32_t emergencyExtensionSeconds) override;
// Methods from ::android::hardware::gnss::V2_1::IGnssConfiguration follow.
Return<bool> setBlacklist_2_1(
const hidl_vec<V2_1::IGnssConfiguration::BlacklistedSource>& blacklist) override;
Return<bool> 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

View File

@@ -1,33 +0,0 @@
/*
* 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 <android/hardware/gnss/1.0/IGnssDebug.h>
#include <hidl/Status.h>
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<void> getDebugData(V1_0::IGnssDebug::getDebugData_cb _hidl_cb) override;
};
} // namespace android::hardware::gnss::V1_1::implementation

View File

@@ -1,68 +0,0 @@
/*
* 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 <android/hardware/gnss/2.1/IGnssMeasurement.h>
#include <hidl/MQDescriptor.h>
#include <hidl/Status.h>
#include <atomic>
#include <mutex>
#include <thread>
namespace android::hardware::gnss::V2_1::implementation {
struct GnssMeasurement : public IGnssMeasurement {
GnssMeasurement();
~GnssMeasurement();
// Methods from V1_0::IGnssMeasurement follow.
Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> setCallback(
const sp<V1_0::IGnssMeasurementCallback>& callback) override;
Return<void> close() override;
// Methods from V1_1::IGnssMeasurement follow.
Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> setCallback_1_1(
const sp<V1_1::IGnssMeasurementCallback>& callback, bool enableFullTracking) override;
// Methods from V2_0::IGnssMeasurement follow.
Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> setCallback_2_0(
const sp<V2_0::IGnssMeasurementCallback>& callback, bool enableFullTracking) override;
// Methods from V2_1::IGnssMeasurement follow.
Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> setCallback_2_1(
const sp<V2_1::IGnssMeasurementCallback>& 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<V2_1::IGnssMeasurementCallback> sCallback_2_1;
// Guarded by mMutex
static sp<V2_0::IGnssMeasurementCallback> sCallback_2_0;
std::atomic<long> mMinIntervalMillis;
std::atomic<bool> 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

View File

@@ -1,37 +0,0 @@
/*
* 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 <android/hardware/gnss/measurement_corrections/1.1/IMeasurementCorrections.h>
#include <hidl/MQDescriptor.h>
#include <hidl/Status.h>
namespace android::hardware::gnss::measurement_corrections::V1_1::implementation {
struct GnssMeasurementCorrections : public IMeasurementCorrections {
GnssMeasurementCorrections();
~GnssMeasurementCorrections();
// Methods from V1_0::IMeasurementCorrections follow.
Return<bool> setCorrections(const V1_0::MeasurementCorrections& corrections) override;
Return<bool> setCallback(const sp<V1_0::IMeasurementCorrectionsCallback>& callback) override;
// Methods from V1_1::IMeasurementCorrections follow.
Return<bool> setCorrections_1_1(const V1_1::MeasurementCorrections& corrections) override;
};
} // namespace android::hardware::gnss::measurement_corrections::V1_1::implementation

View File

@@ -1,779 +0,0 @@
/*
* 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 <android/hardware/gnss/2.1/IGnss.h>
#include <errno.h>
#include <fcntl.h>
#include <hidl/MQDescriptor.h>
#include <hidl/Status.h>
#include <log/log.h>
#include <sys/epoll.h>
#include <atomic>
#include <mutex>
#include <string>
#include <thread>
#include <utils/SystemClock.h>
#include <cutils/properties.h>
#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 <class T_IGnss>
struct GnssTemplate : public T_IGnss {
GnssTemplate();
~GnssTemplate();
// Methods from V1_0::IGnss follow.
Return<bool> setCallback(const sp<V1_0::IGnssCallback>& callback) override;
Return<bool> start() override;
Return<bool> stop() override;
Return<void> cleanup() override;
Return<bool> injectTime(int64_t timeMs, int64_t timeReferenceMs,
int32_t uncertaintyMs) override;
Return<bool> injectLocation(double latitudeDegrees, double longitudeDegrees,
float accuracyMeters) override;
Return<void> deleteAidingData(V1_0::IGnss::GnssAidingData aidingDataFlags) override;
Return<bool> setPositionMode(V1_0::IGnss::GnssPositionMode mode,
V1_0::IGnss::GnssPositionRecurrence recurrence,
uint32_t minIntervalMs, uint32_t preferredAccuracyMeters,
uint32_t preferredTimeMs) override;
Return<sp<V1_0::IAGnssRil>> getExtensionAGnssRil() override;
Return<sp<V1_0::IGnssGeofencing>> getExtensionGnssGeofencing() override;
Return<sp<V1_0::IAGnss>> getExtensionAGnss() override;
Return<sp<V1_0::IGnssNi>> getExtensionGnssNi() override;
Return<sp<V1_0::IGnssMeasurement>> getExtensionGnssMeasurement() override;
Return<sp<V1_0::IGnssNavigationMessage>> getExtensionGnssNavigationMessage() override;
Return<sp<V1_0::IGnssXtra>> getExtensionXtra() override;
Return<sp<V1_0::IGnssConfiguration>> getExtensionGnssConfiguration() override;
Return<sp<V1_0::IGnssDebug>> getExtensionGnssDebug() override;
Return<sp<V1_0::IGnssBatching>> getExtensionGnssBatching() override;
// Methods from V1_1::IGnss follow.
Return<bool> setCallback_1_1(const sp<V1_1::IGnssCallback>& callback) override;
Return<bool> 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<sp<V1_1::IGnssConfiguration>> getExtensionGnssConfiguration_1_1() override;
Return<sp<V1_1::IGnssMeasurement>> getExtensionGnssMeasurement_1_1() override;
Return<bool> injectBestLocation(const V1_0::GnssLocation& location) override;
// Methods from V2_0::IGnss follow.
Return<bool> setCallback_2_0(const sp<V2_0::IGnssCallback>& callback) override;
Return<sp<V2_0::IGnssConfiguration>> getExtensionGnssConfiguration_2_0() override;
Return<sp<V2_0::IGnssDebug>> getExtensionGnssDebug_2_0() override;
Return<sp<V2_0::IAGnss>> getExtensionAGnss_2_0() override;
Return<sp<V2_0::IAGnssRil>> getExtensionAGnssRil_2_0() override;
Return<sp<V2_0::IGnssMeasurement>> getExtensionGnssMeasurement_2_0() override;
Return<sp<measurement_corrections::V1_0::IMeasurementCorrections>>
getExtensionMeasurementCorrections() override;
Return<sp<visibility_control::V1_0::IGnssVisibilityControl>> getExtensionVisibilityControl()
override;
Return<sp<V2_0::IGnssBatching>> getExtensionGnssBatching_2_0() override;
Return<bool> injectBestLocation_2_0(const V2_0::GnssLocation& location) override;
// Methods from V2_1::IGnss follow.
Return<bool> setCallback_2_1(const sp<V2_1::IGnssCallback>& callback) override;
Return<sp<V2_1::IGnssMeasurement>> getExtensionGnssMeasurement_2_1() override;
Return<sp<V2_1::IGnssConfiguration>> getExtensionGnssConfiguration_2_1() override;
Return<sp<measurement_corrections::V1_1::IMeasurementCorrections>>
getExtensionMeasurementCorrections_1_1() override;
Return<sp<V2_1::IGnssAntennaInfo>> getExtensionGnssAntennaInfo() override;
Return<void> debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) override;
private:
std::unique_ptr<V2_0::GnssLocation> getLocationFromHW();
void reportLocation(const V2_0::GnssLocation&) const;
void reportLocation(const V1_0::GnssLocation&) const;
void reportSvStatus(const hidl_vec<V2_1::IGnssCallback::GnssSvInfo>&) const;
void reportGnssStatusValue(const V1_0::IGnssCallback::GnssStatusValue) const;
Return<void> help(const hidl_handle& fd);
Return<void> setLocation(const hidl_handle& fd, const hidl_vec<hidl_string>& options);
static sp<V2_1::IGnssCallback> sGnssCallback_2_1;
static sp<V2_0::IGnssCallback> sGnssCallback_2_0;
static sp<V1_1::IGnssCallback> sGnssCallback_1_1;
static sp<V1_0::IGnssCallback> sGnssCallback_1_0;
std::atomic<long> mMinIntervalMs;
sp<V2_1::implementation::GnssConfiguration> mGnssConfiguration;
std::atomic<bool> mIsActive;
std::atomic<bool> mHardwareModeChecked;
std::atomic<int> mGnssFd;
std::thread mThread;
mutable std::mutex mMutex;
virtual hidl_vec<V2_1::IGnssCallback::GnssSvInfo> filterBlocklistedSatellitesV2_1(
hidl_vec<V2_1::IGnssCallback::GnssSvInfo> gnssSvInfoList);
virtual void notePowerConsumption();
};
template <class T_IGnss>
sp<V2_1::IGnssCallback> GnssTemplate<T_IGnss>::sGnssCallback_2_1 = nullptr;
template <class T_IGnss>
sp<V2_0::IGnssCallback> GnssTemplate<T_IGnss>::sGnssCallback_2_0 = nullptr;
template <class T_IGnss>
sp<V1_1::IGnssCallback> GnssTemplate<T_IGnss>::sGnssCallback_1_1 = nullptr;
template <class T_IGnss>
sp<V1_0::IGnssCallback> GnssTemplate<T_IGnss>::sGnssCallback_1_0 = nullptr;
template <class T_IGnss>
GnssTemplate<T_IGnss>::GnssTemplate()
: mMinIntervalMs(1000),
mGnssConfiguration{new V2_1::implementation::GnssConfiguration()},
mHardwareModeChecked(false),
mGnssFd(-1) {}
template <class T_IGnss>
GnssTemplate<T_IGnss>::~GnssTemplate() {
stop();
}
template <class T_IGnss>
std::unique_ptr<V2_0::GnssLocation> GnssTemplate<T_IGnss>::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<int64_t>(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<uint64_t>(::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<V2_0::GnssLocation>(locationV2);
}
template <class T_IGnss>
Return<bool> GnssTemplate<T_IGnss>::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 <class T_IGnss>
hidl_vec<V2_1::IGnssCallback::GnssSvInfo> GnssTemplate<T_IGnss>::filterBlocklistedSatellitesV2_1(
hidl_vec<V2_1::IGnssCallback::GnssSvInfo> 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<uint8_t>(V1_0::IGnssCallback::GnssSvFlags::USED_IN_FIX);
}
}
return gnssSvInfoList;
}
template <class T_IGnss>
void GnssTemplate<T_IGnss>::notePowerConsumption() {
ALOGD("GnssTemplate::notePowerConsumption");
}
template <class T_IGnss>
Return<bool> GnssTemplate<T_IGnss>::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 <class T_IGnss>
Return<bool> GnssTemplate<T_IGnss>::setCallback(const sp<V1_0::IGnssCallback>& 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 <class T_IGnss>
Return<void> GnssTemplate<T_IGnss>::cleanup() {
sGnssCallback_2_1 = nullptr;
sGnssCallback_2_0 = nullptr;
return Void();
}
template <class T_IGnss>
Return<bool> GnssTemplate<T_IGnss>::injectTime(int64_t, int64_t, int32_t) {
return true;
}
template <class T_IGnss>
Return<bool> GnssTemplate<T_IGnss>::injectLocation(double, double, float) {
return true;
}
template <class T_IGnss>
Return<void> GnssTemplate<T_IGnss>::deleteAidingData(V1_0::IGnss::GnssAidingData) {
// TODO implement
return Void();
}
template <class T_IGnss>
Return<bool> GnssTemplate<T_IGnss>::setPositionMode(V1_0::IGnss::GnssPositionMode,
V1_0::IGnss::GnssPositionRecurrence,
uint32_t minIntervalMs, uint32_t, uint32_t) {
mMinIntervalMs = minIntervalMs;
return true;
}
template <class T_IGnss>
Return<sp<V1_0::IAGnssRil>> GnssTemplate<T_IGnss>::getExtensionAGnssRil() {
// TODO implement
return ::android::sp<V1_0::IAGnssRil>{};
}
template <class T_IGnss>
Return<sp<V1_0::IGnssGeofencing>> GnssTemplate<T_IGnss>::getExtensionGnssGeofencing() {
// TODO implement
return ::android::sp<V1_0::IGnssGeofencing>{};
}
template <class T_IGnss>
Return<sp<V1_0::IAGnss>> GnssTemplate<T_IGnss>::getExtensionAGnss() {
// TODO implement
return ::android::sp<V1_0::IAGnss>{};
}
template <class T_IGnss>
Return<sp<V1_0::IGnssNi>> GnssTemplate<T_IGnss>::getExtensionGnssNi() {
// TODO implement
return ::android::sp<V1_0::IGnssNi>{};
}
template <class T_IGnss>
Return<sp<V1_0::IGnssMeasurement>> GnssTemplate<T_IGnss>::getExtensionGnssMeasurement() {
ALOGD("Gnss::getExtensionGnssMeasurement");
return new V2_1::implementation::GnssMeasurement();
}
template <class T_IGnss>
Return<sp<V1_0::IGnssNavigationMessage>>
GnssTemplate<T_IGnss>::getExtensionGnssNavigationMessage() {
// TODO implement
return ::android::sp<V1_0::IGnssNavigationMessage>{};
}
template <class T_IGnss>
Return<sp<V1_0::IGnssXtra>> GnssTemplate<T_IGnss>::getExtensionXtra() {
// TODO implement
return ::android::sp<V1_0::IGnssXtra>{};
}
template <class T_IGnss>
Return<sp<V1_0::IGnssConfiguration>> GnssTemplate<T_IGnss>::getExtensionGnssConfiguration() {
// TODO implement
return ::android::sp<V1_0::IGnssConfiguration>{};
}
template <class T_IGnss>
Return<sp<V1_0::IGnssDebug>> GnssTemplate<T_IGnss>::getExtensionGnssDebug() {
return new V1_1::implementation::GnssDebug();
}
template <class T_IGnss>
Return<sp<V1_0::IGnssBatching>> GnssTemplate<T_IGnss>::getExtensionGnssBatching() {
// TODO implement
return ::android::sp<V1_0::IGnssBatching>{};
}
// Methods from V1_1::IGnss follow.
template <class T_IGnss>
Return<bool> GnssTemplate<T_IGnss>::setCallback_1_1(const sp<V1_1::IGnssCallback>& 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 <class T_IGnss>
Return<bool> GnssTemplate<T_IGnss>::setPositionMode_1_1(V1_0::IGnss::GnssPositionMode,
V1_0::IGnss::GnssPositionRecurrence,
uint32_t minIntervalMs, uint32_t, uint32_t,
bool) {
mMinIntervalMs = minIntervalMs;
return true;
}
template <class T_IGnss>
Return<sp<V1_1::IGnssConfiguration>> GnssTemplate<T_IGnss>::getExtensionGnssConfiguration_1_1() {
// TODO implement
return ::android::sp<V1_1::IGnssConfiguration>{};
}
template <class T_IGnss>
Return<sp<V1_1::IGnssMeasurement>> GnssTemplate<T_IGnss>::getExtensionGnssMeasurement_1_1() {
// TODO implement
return ::android::sp<V1_1::IGnssMeasurement>{};
}
template <class T_IGnss>
Return<bool> GnssTemplate<T_IGnss>::injectBestLocation(const V1_0::GnssLocation&) {
return true;
}
// Methods from V2_0::IGnss follow.
template <class T_IGnss>
Return<bool> GnssTemplate<T_IGnss>::setCallback_2_0(const sp<V2_0::IGnssCallback>& 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 <class T_IGnss>
Return<sp<V2_0::IGnssConfiguration>> GnssTemplate<T_IGnss>::getExtensionGnssConfiguration_2_0() {
ALOGD("Gnss::getExtensionGnssConfiguration_2_0");
return mGnssConfiguration;
}
template <class T_IGnss>
Return<sp<V2_0::IGnssDebug>> GnssTemplate<T_IGnss>::getExtensionGnssDebug_2_0() {
// TODO implement
return ::android::sp<V2_0::IGnssDebug>{};
}
template <class T_IGnss>
Return<sp<V2_0::IAGnss>> GnssTemplate<T_IGnss>::getExtensionAGnss_2_0() {
// TODO implement
return ::android::sp<V2_0::IAGnss>{};
}
template <class T_IGnss>
Return<sp<V2_0::IAGnssRil>> GnssTemplate<T_IGnss>::getExtensionAGnssRil_2_0() {
// TODO implement
return ::android::sp<V2_0::IAGnssRil>{};
}
template <class T_IGnss>
Return<sp<V2_0::IGnssMeasurement>> GnssTemplate<T_IGnss>::getExtensionGnssMeasurement_2_0() {
ALOGD("Gnss::getExtensionGnssMeasurement_2_0");
return new V2_1::implementation::GnssMeasurement();
}
template <class T_IGnss>
Return<sp<measurement_corrections::V1_0::IMeasurementCorrections>>
GnssTemplate<T_IGnss>::getExtensionMeasurementCorrections() {
ALOGD("Gnss::getExtensionMeasurementCorrections()");
return new measurement_corrections::V1_1::implementation::GnssMeasurementCorrections();
}
template <class T_IGnss>
Return<sp<visibility_control::V1_0::IGnssVisibilityControl>>
GnssTemplate<T_IGnss>::getExtensionVisibilityControl() {
// TODO implement
return ::android::sp<visibility_control::V1_0::IGnssVisibilityControl>{};
}
template <class T_IGnss>
Return<sp<V2_0::IGnssBatching>> GnssTemplate<T_IGnss>::getExtensionGnssBatching_2_0() {
// TODO implement
return ::android::sp<V2_0::IGnssBatching>{};
}
template <class T_IGnss>
Return<bool> GnssTemplate<T_IGnss>::injectBestLocation_2_0(const V2_0::GnssLocation&) {
// TODO(b/124012850): Implement function.
return bool{};
}
// Methods from V2_1::IGnss follow.
template <class T_IGnss>
Return<bool> GnssTemplate<T_IGnss>::setCallback_2_1(const sp<V2_1::IGnssCallback>& 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 <class T_IGnss>
Return<sp<V2_1::IGnssMeasurement>> GnssTemplate<T_IGnss>::getExtensionGnssMeasurement_2_1() {
ALOGD("Gnss::getExtensionGnssMeasurement_2_1");
return new V2_1::implementation::GnssMeasurement();
}
template <class T_IGnss>
Return<sp<V2_1::IGnssConfiguration>> GnssTemplate<T_IGnss>::getExtensionGnssConfiguration_2_1() {
ALOGD("Gnss::getExtensionGnssConfiguration_2_1");
return mGnssConfiguration;
}
template <class T_IGnss>
Return<sp<measurement_corrections::V1_1::IMeasurementCorrections>>
GnssTemplate<T_IGnss>::getExtensionMeasurementCorrections_1_1() {
ALOGD("Gnss::getExtensionMeasurementCorrections_1_1()");
return new measurement_corrections::V1_1::implementation::GnssMeasurementCorrections();
}
template <class T_IGnss>
Return<sp<V2_1::IGnssAntennaInfo>> GnssTemplate<T_IGnss>::getExtensionGnssAntennaInfo() {
ALOGD("Gnss::getExtensionGnssAntennaInfo");
return new V2_1::implementation::GnssAntennaInfo();
}
template <class T_IGnss>
void GnssTemplate<T_IGnss>::reportGnssStatusValue(
const V1_0::IGnssCallback::GnssStatusValue gnssStatusValue) const {
std::unique_lock<std::mutex> 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 <class T_IGnss>
void GnssTemplate<T_IGnss>::reportSvStatus(
const hidl_vec<V2_1::IGnssCallback::GnssSvInfo>& svInfoList) const {
std::unique_lock<std::mutex> 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 <class T_IGnss>
void GnssTemplate<T_IGnss>::reportLocation(const V1_0::GnssLocation& location) const {
std::unique_lock<std::mutex> 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 <class T_IGnss>
void GnssTemplate<T_IGnss>::reportLocation(const V2_0::GnssLocation& location) const {
std::unique_lock<std::mutex> 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 <class T_IGnss>
Return<void> GnssTemplate<T_IGnss>::setLocation(const hidl_handle& fd,
const hidl_vec<hidl_string>& 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 <class T_IGnss>
Return<void> GnssTemplate<T_IGnss>::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 <class T_IGnss>
Return<void> GnssTemplate<T_IGnss>::debug(const hidl_handle& fd,
const hidl_vec<hidl_string>& 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

View File

@@ -1,101 +0,0 @@
/*
* 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 <log/log.h>
using ::android::hardware::gnss::common::Utils;
namespace android::hardware::gnss::V2_1::implementation {
sp<IGnssAntennaInfoCallback> GnssAntennaInfo::sCallback = nullptr;
GnssAntennaInfo::GnssAntennaInfo() : mMinIntervalMillis(1000) {}
GnssAntennaInfo::~GnssAntennaInfo() {
stop();
}
// Methods from ::android::hardware::gnss::V2_1::IGnssAntennaInfo follow.
Return<GnssAntennaInfo::GnssAntennaInfoStatus> GnssAntennaInfo::setCallback(
const sp<IGnssAntennaInfoCallback>& callback) {
ALOGD("setCallback");
std::unique_lock<std::mutex> lock(mMutex);
sCallback = callback;
if (mIsActive) {
ALOGW("GnssAntennaInfo callback already set. Resetting the callback...");
stop();
}
start();
return GnssAntennaInfoStatus::SUCCESS;
}
Return<void> GnssAntennaInfo::close() {
ALOGD("close");
stop();
std::unique_lock<std::mutex> 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<IGnssAntennaInfoCallback::GnssAntennaInfo>& antennaInfo) const {
std::unique_lock<std::mutex> 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

View File

@@ -1,101 +0,0 @@
/*
* 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 <log/log.h>
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<bool> 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<bool> GnssConfiguration::setSuplVersion(uint32_t) {
return true;
}
Return<bool> GnssConfiguration::setSuplMode(hidl_bitfield<SuplMode>) {
return true;
}
Return<bool> GnssConfiguration::setGpsLock(hidl_bitfield<GpsLock> gpsLock) {
ALOGD("setGpsLock gpsLock: %hhu", static_cast<GpsLock>(gpsLock));
// Method deprecated in 2.0 and not expected to be called by the framework.
return false;
}
Return<bool> GnssConfiguration::setLppProfile(hidl_bitfield<LppProfile>) {
return true;
}
Return<bool> GnssConfiguration::setGlonassPositioningProtocol(hidl_bitfield<GlonassPosProtocol>) {
return true;
}
Return<bool> GnssConfiguration::setEmergencySuplPdn(bool) {
return true;
}
// Methods from ::android::hardware::gnss::V1_1::IGnssConfiguration follow.
Return<bool> GnssConfiguration::setBlacklist(
const hidl_vec<V1_1::IGnssConfiguration::BlacklistedSource>&) {
// TODO (b/122463906): Reuse 1.1 implementation.
return bool{};
}
// Methods from ::android::hardware::gnss::V2_0::IGnssConfiguration follow.
Return<bool> GnssConfiguration::setEsExtensionSec(uint32_t emergencyExtensionSeconds) {
ALOGD("setEsExtensionSec emergencyExtensionSeconds: %d", emergencyExtensionSeconds);
return true;
}
// Methods from ::android::hardware::gnss::V2_1::IGnssConfiguration follow.
Return<bool> GnssConfiguration::setBlacklist_2_1(
const hidl_vec<BlacklistedSourceV2_1>& sourceList) {
std::unique_lock<std::recursive_mutex> 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<bool> GnssConfiguration::isBlacklistedV2_1(const GnssSvInfoV2_1& gnssSvInfo) const {
std::unique_lock<std::recursive_mutex> 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

View File

@@ -1,55 +0,0 @@
/*
* 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 <log/log.h>
#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<void> 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

View File

@@ -1,143 +0,0 @@
/*
* 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 <log/log.h>
#include "Utils.h"
namespace android::hardware::gnss::V2_1::implementation {
using common::Utils;
sp<V2_1::IGnssMeasurementCallback> GnssMeasurement::sCallback_2_1 = nullptr;
sp<V2_0::IGnssMeasurementCallback> GnssMeasurement::sCallback_2_0 = nullptr;
GnssMeasurement::GnssMeasurement() : mMinIntervalMillis(1000) {}
GnssMeasurement::~GnssMeasurement() {
stop();
}
// Methods from V1_0::IGnssMeasurement follow.
Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> GnssMeasurement::setCallback(
const sp<V1_0::IGnssMeasurementCallback>&) {
// TODO implement
return V1_0::IGnssMeasurement::GnssMeasurementStatus{};
}
Return<void> GnssMeasurement::close() {
ALOGD("close");
stop();
std::unique_lock<std::mutex> lock(mMutex);
sCallback_2_1 = nullptr;
sCallback_2_0 = nullptr;
return Void();
}
// Methods from V1_1::IGnssMeasurement follow.
Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> GnssMeasurement::setCallback_1_1(
const sp<V1_1::IGnssMeasurementCallback>&, bool) {
// TODO implement
return V1_0::IGnssMeasurement::GnssMeasurementStatus{};
}
// Methods from V2_0::IGnssMeasurement follow.
Return<V1_0::IGnssMeasurement::GnssMeasurementStatus> GnssMeasurement::setCallback_2_0(
const sp<V2_0::IGnssMeasurementCallback>& callback, bool) {
ALOGD("setCallback_2_0");
std::unique_lock<std::mutex> 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<V1_0::IGnssMeasurement::GnssMeasurementStatus> GnssMeasurement::setCallback_2_1(
const sp<V2_1::IGnssMeasurementCallback>& callback, bool) {
ALOGD("setCallback_2_1");
std::unique_lock<std::mutex> 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<std::mutex> 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<std::mutex> 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

View File

@@ -1,103 +0,0 @@
/*
* 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 <log/log.h>
namespace android::hardware::gnss::measurement_corrections::V1_1::implementation {
GnssMeasurementCorrections::GnssMeasurementCorrections() {}
GnssMeasurementCorrections::~GnssMeasurementCorrections() {}
// Methods from V1_0::IMeasurementCorrections follow.
Return<bool> 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<unsigned long long>(corrections.toaGpsNanosecondsOfWeek),
static_cast<int>(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<int>(singleSatCorrection.singleSatCorrectionFlags),
static_cast<int>(singleSatCorrection.constellation),
static_cast<int>(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<bool> GnssMeasurementCorrections::setCallback(
const sp<V1_0::IMeasurementCorrectionsCallback>& 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<bool> 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<unsigned long long>(corrections.v1_0.toaGpsNanosecondsOfWeek),
static_cast<int>(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<int>(singleSatCorrection.v1_0.singleSatCorrectionFlags),
static_cast<int>(singleSatCorrection.constellation),
static_cast<int>(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

View File

@@ -1,10 +1,28 @@
#!/vendor/bin/sh #!/vendor/bin/sh
# Create GPS data directory if it doesn't exist
if [ ! -d /data/vendor/gps ]; then
mkdir -p /data/vendor/gps
chmod 755 /data/vendor/gps
fi
# Create legacy gnss file for compatibility
if [ ! -f /data/vendor/gps/gnss ]; then if [ ! -f /data/vendor/gps/gnss ]; then
echo "LatitudeDegrees=30.281026818001678" > /data/vendor/gps/gnss echo "LatitudeDegrees=30.281026818001678" > /data/vendor/gps/gnss
echo "LongitudeDegrees=120.01934876982831" >> /data/vendor/gps/gnss echo "LongitudeDegrees=120.01934876982831" >> /data/vendor/gps/gnss
echo "AltitudeMeters=1.60062531" >> /data/vendor/gps/gnss echo "AltitudeMeters=1.60062531" >> /data/vendor/gps/gnss
echo "BearingDegrees=0" >> /data/vendor/gps/gnss echo "BearingDegrees=0" >> /data/vendor/gps/gnss
echo "SpeedMetersPerSec=0" >> /data/vendor/gps/gnss echo "SpeedMetersPerSec=0" >> /data/vendor/gps/gnss
chmod 777 /data/vendor/gps/gnss chmod 644 /data/vendor/gps/gnss
fi fi
# Create custom location file for new JNI implementation
# This file uses simple "latitude,longitude" format
if [ ! -f /data/vendor/gps/custom_location.txt ]; then
echo "30.281026,120.019348" > /data/vendor/gps/custom_location.txt
chmod 644 /data/vendor/gps/custom_location.txt
fi
# Set proper ownership and permissions
chown -R system:system /data/vendor/gps/
chmod 644 /data/vendor/gps/*

82
gps/set_gps_location.sh Normal file
View File

@@ -0,0 +1,82 @@
#!/bin/bash
# Redroid GPS位置设置脚本
# 用法: ./set_gps_location.sh <纬度> <经度>
# 示例: ./set_gps_location.sh 39.904989 116.405285
if [ $# -ne 2 ]; then
echo "用法: $0 <纬度> <经度>"
echo ""
echo "示例位置:"
echo " 北京天安门: $0 39.904989 116.405285"
echo " 上海外滩: $0 31.239666 121.499809"
echo " 广州塔: $0 23.109831 113.324504"
echo " 深圳地王: $0 22.544249 114.095298"
echo " 杭州西湖: $0 30.281026 120.019348"
echo ""
echo "坐标范围:"
echo " 纬度: -90 到 90"
echo " 经度: -180 到 180"
exit 1
fi
LATITUDE=$1
LONGITUDE=$2
# 验证纬度范围
if (( $(echo "$LATITUDE < -90.0 || $LATITUDE > 90.0" | bc -l) )); then
echo "错误: 纬度必须在 -90 到 90 之间"
exit 1
fi
# 验证经度范围
if (( $(echo "$LONGITUDE < -180.0 || $LONGITUDE > 180.0" | bc -l) )); then
echo "错误: 经度必须在 -180 到 180 之间"
exit 1
fi
GPS_FILE="/data/vendor/gps/custom_location.txt"
echo "设置GPS位置为: 纬度 $LATITUDE, 经度 $LONGITUDE"
# 检查设备连接
if ! adb devices | grep -q "device$"; then
echo "错误: 未找到连接的Android设备"
echo "请确保:"
echo "1. 设备已连接并启用USB调试"
echo "2. 已授权计算机的USB调试请求"
exit 1
fi
# 创建临时文件
TEMP_FILE=$(mktemp)
echo "$LATITUDE,$LONGITUDE" > "$TEMP_FILE"
# 推送到设备
echo "正在更新GPS位置文件..."
adb push "$TEMP_FILE" "$GPS_FILE"
if [ $? -eq 0 ]; then
echo "✅ GPS位置更新成功"
# 设置正确权限
adb shell "chown system:system $GPS_FILE"
adb shell "chmod 644 $GPS_FILE"
# 验证文件内容
echo "📍 当前GPS位置"
adb shell "cat $GPS_FILE"
echo ""
echo "💡 提示:"
echo "- 新位置将在下次GPS请求时生效"
echo "- 打开地图应用验证位置是否正确"
echo "- 查看日志: adb logcat | grep -i 'custom.*gps'"
else
echo "❌ GPS位置更新失败"
echo "请检查设备权限和连接状态"
fi
# 清理临时文件
rm -f "$TEMP_FILE"

View File

@@ -57,10 +57,10 @@ on post-fs-data
# GPS # GPS
on post-fs-data on post-fs-data
mkdir /data/vendor/gps 0751 root root mkdir /data/vendor/gps 0755 system system
exec -- /system/bin/sh /vendor/bin/hw/init.redroid.gps.sh exec -- /system/bin/sh /vendor/bin/hw/init.redroid.gps.sh
service gnss /vendor/bin/hw/android.hardware.gnss-service # service gnss /vendor/bin/hw/android.hardware.gnss-service
class hal # class hal
user nobody # user nobody
group nobody # group nobody

View File

@@ -45,7 +45,10 @@ PRODUCT_COPY_FILES += \
# gps config # gps config
###################### ######################
PRODUCT_PACKAGES += \ PRODUCT_PACKAGES += \
android.hardware.gnss-service libredroid_gps_jni
# PRODUCT_PACKAGES += \
# android.hardware.gnss-service
PRODUCT_COPY_FILES += \ PRODUCT_COPY_FILES += \
vendor/redroid/gps/init.redroid.gps.sh:$(TARGET_COPY_OUT_VENDOR)/bin/hw/init.redroid.gps.sh \ vendor/redroid/gps/init.redroid.gps.sh:$(TARGET_COPY_OUT_VENDOR)/bin/hw/init.redroid.gps.sh \