From df8fec5bbe20da972522dfe5b9b32e2cb5127ab6 Mon Sep 17 00:00:00 2001 From: CoderKang Date: Wed, 17 Sep 2025 12:13:58 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E8=87=AA=E5=AE=9A?= =?UTF-8?q?=E4=B9=89GPS=E4=BD=8D=E7=BD=AE=E6=94=AF=E6=8C=81=EF=BC=8C?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=E7=9B=B8=E5=85=B3=E8=84=9A=E6=9C=AC=E5=92=8C?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=EF=BC=8C=E7=A7=BB=E9=99=A4=E6=97=A7=E7=9A=84?= =?UTF-8?q?GPS=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 5 +- frameworks_base_gnss_patch.patch | 160 +++ gps/Android.bp | 67 - gps/BUILD_GUIDE.md | 196 --- ...d_server_location_GnssLocationProvider.cpp | 1231 ----------------- gps/set_gps_location.sh | 82 -- set_custom_gps.sh | 140 ++ vendor.mk | 7 +- 8 files changed, 306 insertions(+), 1582 deletions(-) create mode 100644 frameworks_base_gnss_patch.patch delete mode 100644 gps/Android.bp delete mode 100644 gps/BUILD_GUIDE.md delete mode 100644 gps/com_android_server_location_GnssLocationProvider.cpp delete mode 100644 gps/set_gps_location.sh create mode 100644 set_custom_gps.sh diff --git a/.gitignore b/.gitignore index 1bf98db..8eea079 100644 --- a/.gitignore +++ b/.gitignore @@ -97,7 +97,8 @@ dkms.conf .LSOverride # Icon must end with two \r -Icon +Icon + # Thumbnails ._* @@ -139,3 +140,5 @@ tags [._]*.un~ # End of https://www.toptal.com/developers/gitignore/api/C,C++,Linux,macOS,vim +.idea +.vscode \ No newline at end of file diff --git a/frameworks_base_gnss_patch.patch b/frameworks_base_gnss_patch.patch new file mode 100644 index 0000000..c29649e --- /dev/null +++ b/frameworks_base_gnss_patch.patch @@ -0,0 +1,160 @@ +--- a/frameworks/base/services/core/jni/com_android_server_location_GnssLocationProvider.cpp ++++ b/frameworks/base/services/core/jni/com_android_server_location_GnssLocationProvider.cpp +@@ -66,6 +66,11 @@ + #include "jni.h" + #include "utils/Log.h" + #include "utils/misc.h" ++#include ++#include ++#include ++ ++// Custom GPS location from file support + + static jclass class_gnssPowerStats; + +@@ -78,6 +83,15 @@ + static jmethodID method_gnssPowerStatsCtor; + static jmethodID method_setSubHalPowerIndicationCapabilities; + ++// Custom GPS location from file ++static double customLatitude = 0.0; ++static double customLongitude = 0.0; ++static bool useCustomLocation = false; ++static time_t lastFileModTime = 0; ++static const char* GPS_LOCATION_FILE = "/data/vendor/gps/custom_location.txt"; ++ ++// Function to read GPS coordinates from file ++static bool readGpsLocationFromFile(); ++ + using android::OK; + using android::sp; + using android::status_t; +@@ -200,6 +214,64 @@ + std::unique_ptr gnssMeasurementCorrectionsIface = + nullptr; + ++// Function to read GPS coordinates from file ++static bool readGpsLocationFromFile() { ++ struct stat fileStat; ++ if (stat(GPS_LOCATION_FILE, &fileStat) != 0) { ++ // File doesn't exist, disable custom location ++ useCustomLocation = false; ++ return false; ++ } ++ ++ // Check if file has been modified ++ if (fileStat.st_mtime <= lastFileModTime) { ++ return useCustomLocation; // No change in file ++ } ++ ++ std::ifstream file(GPS_LOCATION_FILE); ++ if (!file.is_open()) { ++ ALOGE("Failed to open GPS location file: %s", GPS_LOCATION_FILE); ++ useCustomLocation = false; ++ return false; ++ } ++ ++ std::string line; ++ if (std::getline(file, line)) { ++ std::istringstream iss(line); ++ std::string latStr, lonStr; ++ ++ // Expected format: "latitude,longitude" or "latitude longitude" ++ if (std::getline(iss, latStr, ',') && std::getline(iss, lonStr)) { ++ // Comma-separated format ++ } else { ++ // Space-separated format ++ iss.clear(); ++ iss.str(line); ++ iss >> latStr >> lonStr; ++ } ++ ++ try { ++ double lat = std::stod(latStr); ++ double lon = std::stod(lonStr); ++ ++ // Validate coordinates ++ if (lat >= -90.0 && lat <= 90.0 && lon >= -180.0 && lon <= 180.0) { ++ customLatitude = lat; ++ customLongitude = lon; ++ useCustomLocation = true; ++ lastFileModTime = fileStat.st_mtime; ++ ALOGI("Custom GPS location loaded: lat=%.6f, lon=%.6f", lat, lon); ++ file.close(); ++ return true; ++ } else { ++ ALOGE("Invalid GPS coordinates: lat=%.6f, lon=%.6f", lat, lon); ++ } ++ } catch (const std::exception& e) { ++ ALOGE("Failed to parse GPS coordinates: %s", e.what()); ++ } ++ } ++ ++ file.close(); ++ useCustomLocation = false; ++ return false; ++} ++ + namespace android { + + namespace { +@@ -367,6 +439,9 @@ + } + + static jboolean android_location_gnss_hal_GnssNative_start(JNIEnv* /* env */, jclass) { ++ // Try to read custom GPS location from file when GNSS starts ++ readGpsLocationFromFile(); ++ + return gnssHal->start(); + } + +@@ -443,8 +518,17 @@ + jfloat speedAccuracyMetersPerSecond, jfloat bearingAccuracyDegrees, jlong timestamp, + jint elapsedRealtimeFlags, jlong elapsedRealtimeNanos, + jdouble elapsedRealtimeUncertaintyNanos) { +- gnssHal->injectBestLocation(gnssLocationFlags, latitudeDegrees, longitudeDegrees, ++ ++ // Check for custom GPS location from file ++ if (readGpsLocationFromFile()) { ++ ALOGI("Using custom GPS location: lat=%.6f, lon=%.6f", customLatitude, customLongitude); ++ gnssHal->injectBestLocation(gnssLocationFlags, customLatitude, customLongitude, ++ altitudeMeters, speedMetersPerSec, bearingDegrees, ++ horizontalAccuracyMeters, verticalAccuracyMeters, ++ speedAccuracyMetersPerSecond, bearingAccuracyDegrees, timestamp, ++ elapsedRealtimeFlags, elapsedRealtimeNanos, ++ elapsedRealtimeUncertaintyNanos); ++ } else { ++ gnssHal->injectBestLocation(gnssLocationFlags, latitudeDegrees, longitudeDegrees, + altitudeMeters, speedMetersPerSec, bearingDegrees, + horizontalAccuracyMeters, verticalAccuracyMeters, + speedAccuracyMetersPerSecond, bearingAccuracyDegrees, timestamp, + elapsedRealtimeFlags, elapsedRealtimeNanos, + elapsedRealtimeUncertaintyNanos); ++ } + } + + static void android_location_gnss_hal_GnssNative_inject_location( +@@ -455,8 +539,17 @@ + jfloat speedAccuracyMetersPerSecond, jfloat bearingAccuracyDegrees, jlong timestamp, + jint elapsedRealtimeFlags, jlong elapsedRealtimeNanos, + jdouble elapsedRealtimeUncertaintyNanos) { +- gnssHal->injectLocation(gnssLocationFlags, latitudeDegrees, longitudeDegrees, altitudeMeters, ++ ++ // Check for custom GPS location from file ++ if (readGpsLocationFromFile()) { ++ ALOGI("Using custom GPS location: lat=%.6f, lon=%.6f", customLatitude, customLongitude); ++ gnssHal->injectLocation(gnssLocationFlags, customLatitude, customLongitude, altitudeMeters, ++ speedMetersPerSec, bearingDegrees, horizontalAccuracyMeters, ++ verticalAccuracyMeters, speedAccuracyMetersPerSecond, ++ bearingAccuracyDegrees, timestamp, elapsedRealtimeFlags, ++ elapsedRealtimeNanos, elapsedRealtimeUncertaintyNanos); ++ } else { ++ gnssHal->injectLocation(gnssLocationFlags, latitudeDegrees, longitudeDegrees, altitudeMeters, + speedMetersPerSec, bearingDegrees, horizontalAccuracyMeters, + verticalAccuracyMeters, speedAccuracyMetersPerSecond, + bearingAccuracyDegrees, timestamp, elapsedRealtimeFlags, + elapsedRealtimeNanos, elapsedRealtimeUncertaintyNanos); ++ } + } + + static jboolean android_location_gnss_hal_GnssNative_supports_psds(JNIEnv* /* env */, jclass) { diff --git a/gps/Android.bp b/gps/Android.bp deleted file mode 100644 index 359476d..0000000 --- a/gps/Android.bp +++ /dev/null @@ -1,67 +0,0 @@ -// 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", - "android.hardware.gnss-V1-cpp", - ], - - 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", -} diff --git a/gps/BUILD_GUIDE.md b/gps/BUILD_GUIDE.md deleted file mode 100644 index d7987c6..0000000 --- a/gps/BUILD_GUIDE.md +++ /dev/null @@ -1,196 +0,0 @@ -# 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. 具体的错误现象描述 diff --git a/gps/com_android_server_location_GnssLocationProvider.cpp b/gps/com_android_server_location_GnssLocationProvider.cpp deleted file mode 100644 index 10eae12..0000000 --- a/gps/com_android_server_location_GnssLocationProvider.cpp +++ /dev/null @@ -1,1231 +0,0 @@ -/* - * Copyright (C) 2008 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 and LOG_NDEBUG before to overwrite the default values. -#define LOG_TAG "GnssLocationProviderJni" -#define LOG_NDEBUG 0 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "android_runtime/AndroidRuntime.h" -#include "android_runtime/Log.h" -#include "gnss/AGnss.h" -#include "gnss/AGnssRil.h" -#include "gnss/Gnss.h" -#include "gnss/GnssAntennaInfo.h" -#include "gnss/GnssAntennaInfoCallback.h" -#include "gnss/GnssBatching.h" -#include "gnss/GnssConfiguration.h" -#include "gnss/GnssDebug.h" -#include "gnss/GnssGeofence.h" -#include "gnss/GnssMeasurement.h" -#include "gnss/GnssNavigationMessage.h" -#include "gnss/GnssVisibilityControl.h" -#include "gnss/MeasurementCorrections.h" -#include "gnss/Utils.h" -#include "hardware_legacy/power.h" -#include "jni.h" -#include "utils/Log.h" -#include "utils/misc.h" -#include -#include -#include - -static jclass class_gnssPowerStats; - -static jmethodID method_reportGnssPowerStats; -static jmethodID method_reportNfwNotification; -static jmethodID method_isInEmergencySession; -static jmethodID method_gnssPowerStatsCtor; -static jmethodID method_setSubHalPowerIndicationCapabilities; - -// Custom GPS location from file -static double customLatitude = 0.0; -static double customLongitude = 0.0; -static bool useCustomLocation = false; -static time_t lastFileModTime = 0; -static const char* GPS_LOCATION_FILE = "/data/vendor/gps/custom_location.txt"; - -// Function to read GPS coordinates from file -static bool readGpsLocationFromFile() { - struct stat fileStat; - if (stat(GPS_LOCATION_FILE, &fileStat) != 0) { - // File doesn't exist, disable custom location - useCustomLocation = false; - return false; - } - - // Check if file has been modified - if (fileStat.st_mtime <= lastFileModTime) { - return useCustomLocation; // No change in file - } - - std::ifstream file(GPS_LOCATION_FILE); - if (!file.is_open()) { - ALOGE("Failed to open GPS location file: %s", GPS_LOCATION_FILE); - useCustomLocation = false; - return false; - } - - std::string line; - if (std::getline(file, line)) { - std::istringstream iss(line); - std::string latStr, lonStr; - - // Expected format: "latitude,longitude" or "latitude longitude" - if (std::getline(iss, latStr, ',') && std::getline(iss, lonStr)) { - // Comma-separated format - } else { - // Space-separated format - iss.clear(); - iss.str(line); - iss >> latStr >> lonStr; - } - - try { - double lat = std::stod(latStr); - double lon = std::stod(lonStr); - - // Validate coordinates - if (lat >= -90.0 && lat <= 90.0 && lon >= -180.0 && lon <= 180.0) { - customLatitude = lat; - customLongitude = lon; - useCustomLocation = true; - lastFileModTime = fileStat.st_mtime; - ALOGI("Custom GPS location loaded: lat=%.6f, lon=%.6f", lat, lon); - file.close(); - return true; - } else { - ALOGE("Invalid GPS coordinates: lat=%.6f, lon=%.6f", lat, lon); - } - } catch (const std::exception& e) { - ALOGE("Failed to parse GPS coordinates: %s", e.what()); - } - } - - file.close(); - useCustomLocation = false; - return false; -} - -using android::OK; -using android::sp; -using android::status_t; -using android::String16; -using android::wp; -using android::binder::Status; - -using android::hardware::Return; -using android::hardware::Void; -using android::hardware::hidl_vec; -using android::hardware::hidl_string; -using android::hardware::hidl_death_recipient; - -using android::hardware::gnss::V1_0::GnssLocationFlags; -using android::hardware::gnss::V1_0::IGnssNavigationMessage; -using android::hardware::gnss::V1_0::IGnssNavigationMessageCallback; -using android::hardware::gnss::V1_0::IGnssXtra; -using android::hardware::gnss::V1_0::IGnssXtraCallback; -using android::hardware::gnss::V2_0::ElapsedRealtimeFlags; - -using android::hidl::base::V1_0::IBase; - -using GnssConstellationType_V1_0 = android::hardware::gnss::V1_0::GnssConstellationType; -using GnssConstellationType_V2_0 = android::hardware::gnss::V2_0::GnssConstellationType; -using GnssLocation_V1_0 = android::hardware::gnss::V1_0::GnssLocation; -using GnssLocation_V2_0 = android::hardware::gnss::V2_0::GnssLocation; -using IGnss_V1_0 = android::hardware::gnss::V1_0::IGnss; -using IGnss_V1_1 = android::hardware::gnss::V1_1::IGnss; -using IGnss_V2_0 = android::hardware::gnss::V2_0::IGnss; -using IGnss_V2_1 = android::hardware::gnss::V2_1::IGnss; -using IGnssCallback_V1_0 = android::hardware::gnss::V1_0::IGnssCallback; -using IGnssCallback_V2_0 = android::hardware::gnss::V2_0::IGnssCallback; -using IGnssCallback_V2_1 = android::hardware::gnss::V2_1::IGnssCallback; - -using android::hardware::gnss::BlocklistedSource; -using android::hardware::gnss::GnssConstellationType; -using android::hardware::gnss::GnssPowerStats; -using android::hardware::gnss::IGnssPowerIndication; -using android::hardware::gnss::IGnssPowerIndicationCallback; - -using IGnssAidl = android::hardware::gnss::IGnss; -using IGnssBatchingAidl = android::hardware::gnss::IGnssBatching; -using IGnssDebugAidl = android::hardware::gnss::IGnssDebug; -using IGnssPsdsAidl = android::hardware::gnss::IGnssPsds; -using IGnssPsdsCallbackAidl = android::hardware::gnss::IGnssPsdsCallback; -using IGnssConfigurationAidl = android::hardware::gnss::IGnssConfiguration; -using GnssLocationAidl = android::hardware::gnss::GnssLocation; -using IGnssAntennaInfoAidl = android::hardware::gnss::IGnssAntennaInfo; - -sp gnssPowerIndicationIface = nullptr; - -std::unique_ptr gnssHal = nullptr; -std::unique_ptr agnssIface = nullptr; -std::unique_ptr agnssRilIface = nullptr; -std::unique_ptr gnssAntennaInfoIface = nullptr; -std::unique_ptr gnssConfigurationIface = nullptr; -std::unique_ptr gnssMeasurementIface = nullptr; -std::unique_ptr gnssNavigationMessageIface = nullptr; -std::unique_ptr gnssBatchingIface = nullptr; -std::unique_ptr gnssDebugIface = nullptr; -std::unique_ptr gnssGeofencingIface = nullptr; -std::unique_ptr gnssPsdsIface = nullptr; -std::unique_ptr gnssVisibilityControlIface = nullptr; -std::unique_ptr gnssMeasurementCorrectionsIface = - nullptr; - -namespace android { - -namespace { - -} // namespace - -/* - * GnssPowerIndicationCallback class implements the callback methods for the IGnssPowerIndication - * interface. - */ -struct GnssPowerIndicationCallback : public android::hardware::gnss::BnGnssPowerIndicationCallback { -public: - Status setCapabilitiesCb(const int capabilities) override; - Status gnssPowerStatsCb(const GnssPowerStats& data) override; -}; - -Status GnssPowerIndicationCallback::setCapabilitiesCb(const int capabilities) { - ALOGD("GnssPowerIndicationCallback::%s: %du\n", __func__, capabilities); - JNIEnv* env = getJniEnv(); - env->CallVoidMethod(mCallbacksObj, method_setSubHalPowerIndicationCapabilities, capabilities); - checkAndClearExceptionFromCallback(env, __FUNCTION__); - return Status::ok(); -} - -Status GnssPowerIndicationCallback::gnssPowerStatsCb(const GnssPowerStats& data) { - JNIEnv* env = getJniEnv(); - - int size = data.otherModesEnergyMilliJoule.size(); - jdoubleArray otherModesEnergy = env->NewDoubleArray(size); - if (size > 0) { - env->SetDoubleArrayRegion(otherModesEnergy, (jsize)0, size, - &(data.otherModesEnergyMilliJoule[0])); - } - jobject gnssPowerStats = - env->NewObject(class_gnssPowerStats, method_gnssPowerStatsCtor, - data.elapsedRealtime.flags, data.elapsedRealtime.timestampNs, - data.elapsedRealtime.timeUncertaintyNs, data.totalEnergyMilliJoule, - data.singlebandTrackingModeEnergyMilliJoule, - data.multibandTrackingModeEnergyMilliJoule, - data.singlebandAcquisitionModeEnergyMilliJoule, - data.multibandAcquisitionModeEnergyMilliJoule, otherModesEnergy); - - env->CallVoidMethod(mCallbacksObj, method_reportGnssPowerStats, gnssPowerStats); - - checkAndClearExceptionFromCallback(env, __FUNCTION__); - env->DeleteLocalRef(gnssPowerStats); - env->DeleteLocalRef(otherModesEnergy); - return Status::ok(); -} - -/* Initializes the GNSS service handle. */ -static void android_location_gnss_hal_GnssNative_set_gps_service_handle() { - gnssHal = std::make_unique(); -} - -/* One time initialization at system boot */ -static void android_location_gnss_hal_GnssNative_class_init_once(JNIEnv* env, jclass clazz) { - // Initialize the top level gnss HAL handle. - android_location_gnss_hal_GnssNative_set_gps_service_handle(); - - // Cache methodIDs and class IDs. - method_reportNfwNotification = env->GetMethodID(clazz, "reportNfwNotification", - "(Ljava/lang/String;BLjava/lang/String;BLjava/lang/String;BZZ)V"); - method_reportGnssPowerStats = - env->GetMethodID(clazz, "reportGnssPowerStats", - "(Lcom/android/server/location/gnss/GnssPowerStats;)V"); - method_isInEmergencySession = env->GetMethodID(clazz, "isInEmergencySession", "()Z"); - - method_setSubHalPowerIndicationCapabilities = - env->GetMethodID(clazz, "setSubHalPowerIndicationCapabilities", "(I)V"); - - jclass gnssPowerStatsClass = env->FindClass("com/android/server/location/gnss/GnssPowerStats"); - class_gnssPowerStats = (jclass)env->NewGlobalRef(gnssPowerStatsClass); - method_gnssPowerStatsCtor = env->GetMethodID(class_gnssPowerStats, "", "(IJDDDDDD[D)V"); - - gnss::AGnss_class_init_once(env, clazz); - gnss::AGnssRil_class_init_once(env, clazz); - gnss::Gnss_class_init_once(env, clazz); - gnss::GnssAntennaInfo_class_init_once(env, clazz); - gnss::GnssBatching_class_init_once(env, clazz); - gnss::GnssConfiguration_class_init_once(env); - gnss::GnssGeofence_class_init_once(env, clazz); - gnss::GnssMeasurement_class_init_once(env, clazz); - gnss::GnssNavigationMessage_class_init_once(env, clazz); - gnss::GnssPsds_class_init_once(env, clazz); - gnss::GnssVisibilityControl_class_init_once(env, clazz); - gnss::MeasurementCorrections_class_init_once(env, clazz); - gnss::MeasurementCorrectionsCallback_class_init_once(env, clazz); - gnss::Utils_class_init_once(env); -} - -/* Initialization needed at system boot and whenever GNSS service dies. */ -static void android_location_gnss_hal_GnssNative_init_once(JNIEnv* env, jobject obj, - jboolean reinitializeGnssServiceHandle) { - /* - * Save a pointer to JVM. - */ - jint jvmStatus = env->GetJavaVM(&android::ScopedJniThreadAttach::sJvm); - if (jvmStatus != JNI_OK) { - LOG_ALWAYS_FATAL("Unable to get Java VM. Error: %d", jvmStatus); - } - - if (reinitializeGnssServiceHandle) { - android_location_gnss_hal_GnssNative_set_gps_service_handle(); - } - - if (gnssHal == nullptr || !gnssHal->isSupported()) { - ALOGE("Unable to get GPS service\n"); - return; - } - - gnssHal->linkToDeath(); - gnssPsdsIface = gnssHal->getGnssPsdsInterface(); - agnssRilIface = gnssHal->getAGnssRilInterface(); - agnssIface = gnssHal->getAGnssInterface(); - gnssNavigationMessageIface = gnssHal->getGnssNavigationMessageInterface(); - gnssMeasurementIface = gnssHal->getGnssMeasurementInterface(); - gnssAntennaInfoIface = gnssHal->getGnssAntennaInfoInterface(); - gnssMeasurementCorrectionsIface = gnssHal->getMeasurementCorrectionsInterface(); - gnssDebugIface = gnssHal->getGnssDebugInterface(); - gnssConfigurationIface = gnssHal->getGnssConfigurationInterface(); - gnssGeofencingIface = gnssHal->getGnssGeofenceInterface(); - gnssBatchingIface = gnssHal->getGnssBatchingInterface(); - gnssVisibilityControlIface = gnssHal->getGnssVisibilityControlInterface(); - gnssPowerIndicationIface = gnssHal->getGnssPowerIndicationInterface(); - - if (mCallbacksObj) { - ALOGE("Callbacks already initialized"); - } else { - mCallbacksObj = env->NewGlobalRef(obj); - } -} - -static jboolean android_location_gnss_hal_GnssNative_is_supported(JNIEnv* /* env */, jclass) { - return (gnssHal != nullptr && gnssHal->isSupported()) ? JNI_TRUE : JNI_FALSE; -} - -static jboolean android_location_GnssNetworkConnectivityHandler_is_agps_ril_supported( - JNIEnv* /* env */, jclass /* clazz */) { - return (agnssRilIface != nullptr) ? JNI_TRUE : JNI_FALSE; -} - -static jobject android_location_GnssConfiguration_get_gnss_configuration_version( - JNIEnv* env, jclass /* jclazz */) { - if (gnssConfigurationIface == nullptr) { - return nullptr; - } - return gnssConfigurationIface->getVersion(env); -} - -/* Initialization needed each time the GPS service is shutdown. */ -static jboolean android_location_gnss_hal_GnssNative_init(JNIEnv* /* env */, jclass) { - /* - * This must be set before calling into the HAL library. - */ - if (!mCallbacksObj) { - ALOGE("No callbacks set during GNSS HAL initialization."); - return JNI_FALSE; - } - - /* - * Fail if the main interface fails to initialize - */ - if (!gnssHal->isSupported()) { - ALOGE("Unable to initialize GNSS HAL."); - return JNI_FALSE; - } - - // Set top level IGnss HAL callback. - gnssHal->setCallback(); - - // Set IGnssPsds callback. - if (gnssPsdsIface == nullptr || - !gnssPsdsIface->setCallback(std::make_unique())) { - ALOGI("Unable to initialize IGnssPsds interface."); - } - - // Set IAGnss callback. - if (agnssIface == nullptr || - !agnssIface->setCallback(std::make_unique())) { - ALOGI("Unable to initialize IAGnss interface."); - } - - // Set GnssGeofence callback. - if (gnssGeofencingIface != nullptr) { - gnssGeofencingIface->setCallback(std::make_unique()); - } else { - ALOGI("Unable to initialize IGnssGeofencing interface."); - } - - // Set IAGnssRil callback. - if (agnssRilIface == nullptr || - !agnssRilIface->setCallback(std::make_unique())) { - ALOGI("Unable to initialize IAGnssRil interface."); - } - - // Set IGnssVisibilityControl callback. - if (gnssVisibilityControlIface != nullptr) { - gnssVisibilityControlIface->setCallback( - std::make_unique()); - } else { - ALOGI("Unable to initialize IGnssVisibilityControl interface."); - } - - // Set IMeasurementCorrection callback. - if (gnssMeasurementCorrectionsIface == nullptr || - !gnssMeasurementCorrectionsIface->setCallback( - std::make_unique())) { - ALOGI("Unable to initialize IGnssMeasurementCorrections interface."); - } - - // Set IGnssPowerIndication.hal callback. - if (gnssPowerIndicationIface != nullptr) { - sp gnssPowerIndicationCallback = - new GnssPowerIndicationCallback(); - auto status = gnssPowerIndicationIface->setCallback(gnssPowerIndicationCallback); - if (!checkAidlStatus(status, "IGnssPowerIndication setCallback() failed.")) { - gnssPowerIndicationIface = nullptr; - } - } - - return JNI_TRUE; -} - -static void android_location_gnss_hal_GnssNative_cleanup(JNIEnv* /* env */, jclass) { - gnssHal->close(); -} - -static jboolean android_location_gnss_hal_GnssNative_set_position_mode( - JNIEnv* /* env */, jclass, jint mode, jint recurrence, jint min_interval, - jint preferred_accuracy, jint preferred_time, jboolean low_power_mode) { - return gnssHal->setPositionMode(mode, recurrence, min_interval, preferred_accuracy, - preferred_time, low_power_mode); -} - -static jboolean android_location_gnss_hal_GnssNative_start(JNIEnv* /* env */, jclass) { - // Try to read custom GPS location from file when GNSS starts - readGpsLocationFromFile(); - - return gnssHal->start(); -} - -static jboolean android_location_gnss_hal_GnssNative_stop(JNIEnv* /* env */, jclass) { - return gnssHal->stop(); -} - -static jboolean android_location_gnss_hal_GnssNative_start_sv_status_collection(JNIEnv* /* env */, - jclass) { - return gnssHal->startSvStatus(); -} - -static jboolean android_location_gnss_hal_GnssNative_stop_sv_status_collection(JNIEnv* /* env */, - jclass) { - return gnssHal->stopSvStatus(); -} - -static jboolean android_location_gnss_hal_GnssNative_start_nmea_message_collection( - JNIEnv* /* env */, jclass) { - return gnssHal->startNmea(); -} - -static jboolean android_location_gnss_hal_GnssNative_stop_nmea_message_collection(JNIEnv* /* env */, - jclass) { - return gnssHal->stopNmea(); -} - -static void android_location_gnss_hal_GnssNative_delete_aiding_data(JNIEnv* /* env */, jclass, - jint flags) { - gnssHal->deleteAidingData(flags); -} - -static void android_location_gnss_hal_GnssNative_agps_set_reference_location_cellid( - JNIEnv* /* env */, jclass, jint type, jint mcc, jint mnc, jint lac, jlong cid, jint tac, - jint pcid, jint arfcn) { - if (agnssRilIface == nullptr) { - ALOGE("%s: IAGnssRil interface not available.", __func__); - return; - } - agnssRilIface->setRefLocation(type, mcc, mnc, lac, cid, tac, pcid, arfcn); -} - -static void android_location_gnss_hal_GnssNative_agps_set_id(JNIEnv* env, jclass, jint type, - jstring setid_string) { - if (agnssRilIface == nullptr) { - ALOGE("%s: IAGnssRil interface not available.", __func__); - return; - } - agnssRilIface->setSetId(type, setid_string); -} - -static void android_location_gnss_hal_GnssNative_inject_ni_supl_message_data(JNIEnv* env, jclass, - jbyteArray data, - jint length, - jint slotIndex) { - if (agnssRilIface == nullptr) { - ALOGE("%s: IAGnssRil interface not available.", __func__); - return; - } - agnssRilIface->injectNiSuplMessageData(data, length, slotIndex); -} - -static jint android_location_gnss_hal_GnssNative_read_nmea(JNIEnv* env, jclass, - jbyteArray nmeaArray, jint buffer_size) { - return gnssHal->readNmea(nmeaArray, buffer_size); -} - -static void android_location_gnss_hal_GnssNative_inject_time(JNIEnv* /* env */, jclass, jlong time, - jlong timeReference, - jint uncertainty) { - gnssHal->injectTime(time, timeReference, uncertainty); -} - -static void android_location_gnss_hal_GnssNative_inject_best_location( - JNIEnv* /* env */, jclass, jint gnssLocationFlags, jdouble latitudeDegrees, - jdouble longitudeDegrees, jdouble altitudeMeters, jfloat speedMetersPerSec, - jfloat bearingDegrees, jfloat horizontalAccuracyMeters, jfloat verticalAccuracyMeters, - jfloat speedAccuracyMetersPerSecond, jfloat bearingAccuracyDegrees, jlong timestamp, - jint elapsedRealtimeFlags, jlong elapsedRealtimeNanos, - jdouble elapsedRealtimeUncertaintyNanos) { - - // Check for custom GPS location from file - if (readGpsLocationFromFile()) { - ALOGI("Using custom GPS location: lat=%.6f, lon=%.6f", customLatitude, customLongitude); - gnssHal->injectBestLocation(gnssLocationFlags, customLatitude, customLongitude, - altitudeMeters, speedMetersPerSec, bearingDegrees, - horizontalAccuracyMeters, verticalAccuracyMeters, - speedAccuracyMetersPerSecond, bearingAccuracyDegrees, timestamp, - elapsedRealtimeFlags, elapsedRealtimeNanos, - elapsedRealtimeUncertaintyNanos); - } else { - gnssHal->injectBestLocation(gnssLocationFlags, latitudeDegrees, longitudeDegrees, - altitudeMeters, speedMetersPerSec, bearingDegrees, - horizontalAccuracyMeters, verticalAccuracyMeters, - speedAccuracyMetersPerSecond, bearingAccuracyDegrees, timestamp, - elapsedRealtimeFlags, elapsedRealtimeNanos, - elapsedRealtimeUncertaintyNanos); - } -} - -static void android_location_gnss_hal_GnssNative_inject_location( - JNIEnv* /* env */, jclass, jint gnssLocationFlags, jdouble latitudeDegrees, - jdouble longitudeDegrees, jdouble altitudeMeters, jfloat speedMetersPerSec, - jfloat bearingDegrees, jfloat horizontalAccuracyMeters, jfloat verticalAccuracyMeters, - jfloat speedAccuracyMetersPerSecond, jfloat bearingAccuracyDegrees, jlong timestamp, - jint elapsedRealtimeFlags, jlong elapsedRealtimeNanos, - jdouble elapsedRealtimeUncertaintyNanos) { - - // Check for custom GPS location from file - if (readGpsLocationFromFile()) { - ALOGI("Using custom GPS location: lat=%.6f, lon=%.6f", customLatitude, customLongitude); - gnssHal->injectLocation(gnssLocationFlags, customLatitude, customLongitude, altitudeMeters, - speedMetersPerSec, bearingDegrees, horizontalAccuracyMeters, - verticalAccuracyMeters, speedAccuracyMetersPerSecond, - bearingAccuracyDegrees, timestamp, elapsedRealtimeFlags, - elapsedRealtimeNanos, elapsedRealtimeUncertaintyNanos); - } else { - gnssHal->injectLocation(gnssLocationFlags, latitudeDegrees, longitudeDegrees, altitudeMeters, - speedMetersPerSec, bearingDegrees, horizontalAccuracyMeters, - verticalAccuracyMeters, speedAccuracyMetersPerSecond, - bearingAccuracyDegrees, timestamp, elapsedRealtimeFlags, - elapsedRealtimeNanos, elapsedRealtimeUncertaintyNanos); - } -} - -static jboolean android_location_gnss_hal_GnssNative_supports_psds(JNIEnv* /* env */, jclass) { - return (gnssPsdsIface != nullptr) ? JNI_TRUE : JNI_FALSE; -} - -static void android_location_gnss_hal_GnssNative_inject_psds_data(JNIEnv* env, jclass, - jbyteArray data, jint length, - jint psdsType) { - if (gnssPsdsIface == nullptr) { - ALOGE("%s: IGnssPsds or IGnssXtra interface not available.", __func__); - return; - } - gnssPsdsIface->injectPsdsData(data, length, psdsType); -} - -static void android_location_GnssNetworkConnectivityHandler_agps_data_conn_open( - JNIEnv* env, jobject /* obj */, jlong networkHandle, jstring apn, jint apnIpType) { - if (apn == nullptr) { - jniThrowException(env, "java/lang/IllegalArgumentException", nullptr); - return; - } - - if (agnssIface != nullptr) { - agnssIface->dataConnOpen(env, networkHandle, apn, apnIpType); - } else { - ALOGE("%s: IAGnss interface not available.", __func__); - return; - } -} - -static void android_location_GnssNetworkConnectivityHandler_agps_data_conn_closed(JNIEnv* /* env */, - jobject /* obj */) { - if (agnssIface != nullptr) { - agnssIface->dataConnClosed(); - } else { - ALOGE("%s: IAGnss interface not available.", __func__); - return; - } -} - -static void android_location_GnssNetworkConnectivityHandler_agps_data_conn_failed(JNIEnv* /* env */, - jobject /* obj */) { - if (agnssIface != nullptr) { - agnssIface->dataConnFailed(); - } else { - ALOGE("%s: IAGnss interface not available.", __func__); - return; - } -} - -static void android_location_gnss_hal_GnssNative_set_agps_server(JNIEnv* env, jclass, jint type, - jstring hostname, jint port) { - if (agnssIface != nullptr) { - agnssIface->setServer(env, type, hostname, port); - } else { - ALOGE("%s: IAGnss interface not available.", __func__); - return; - } -} - -static jstring android_location_gnss_hal_GnssNative_get_internal_state(JNIEnv* env, jclass) { - /* - * TODO: Create a jobject to represent GnssDebug. - */ - - if (gnssDebugIface == nullptr) { - ALOGE("%s: IGnssDebug interface not available.", __func__); - return nullptr; - } - return gnssDebugIface->getDebugData(env); -} - -static void android_location_gnss_hal_GnssNative_request_power_stats(JNIEnv* env) { - if (gnssPowerIndicationIface == nullptr) { - return; - } - auto status = gnssPowerIndicationIface->requestGnssPowerStats(); - checkAidlStatus(status, "IGnssPowerIndication requestGnssPowerStats() failed."); -} - -static jboolean android_location_gnss_hal_GnssNative_is_gnss_visibility_control_supported( - JNIEnv* /* env */, jclass) { - return (gnssVisibilityControlIface != nullptr) ? JNI_TRUE : JNI_FALSE; -} - -static void android_location_GnssNetworkConnectivityHandler_update_network_state(JNIEnv* env, - jobject /* obj */, - jboolean connected, - jint type, - jboolean roaming, - jboolean available, - jstring apn, - jlong networkHandle, - jshort capabilities) { - if (agnssRilIface == nullptr) { - ALOGE("%s: IAGnssRil interface not available.", __func__); - return; - } - agnssRilIface->updateNetworkState(connected, type, roaming, available, apn, networkHandle, - capabilities); -} - -static jboolean android_location_gnss_hal_GnssNative_is_geofence_supported(JNIEnv* /* env */, - jclass) { - if (gnssGeofencingIface == nullptr) { - return JNI_FALSE; - } - return JNI_TRUE; -} - -static jboolean android_location_gnss_hal_GnssNative_add_geofence( - JNIEnv* /* env */, jclass, jint geofenceId, jdouble latitude, jdouble longitude, - jdouble radius, jint last_transition, jint monitor_transition, - jint notification_responsiveness, jint unknown_timer) { - if (gnssGeofencingIface == nullptr) { - ALOGE("%s: IGnssGeofencing interface not available.", __func__); - return JNI_FALSE; - } - return gnssGeofencingIface->addGeofence(geofenceId, latitude, longitude, radius, - last_transition, monitor_transition, - notification_responsiveness, unknown_timer); -} - -static jboolean android_location_gnss_hal_GnssNative_remove_geofence(JNIEnv* /* env */, jclass, - jint geofenceId) { - if (gnssGeofencingIface == nullptr) { - ALOGE("%s: IGnssGeofencing interface not available.", __func__); - return JNI_FALSE; - } - return gnssGeofencingIface->removeGeofence(geofenceId); -} - -static jboolean android_location_gnss_hal_GnssNative_pause_geofence(JNIEnv* /* env */, jclass, - jint geofenceId) { - if (gnssGeofencingIface == nullptr) { - ALOGE("%s: IGnssGeofencing interface not available.", __func__); - return JNI_FALSE; - } - return gnssGeofencingIface->pauseGeofence(geofenceId); -} - -static jboolean android_location_gnss_hal_GnssNative_resume_geofence(JNIEnv* /* env */, jclass, - jint geofenceId, - jint monitor_transition) { - if (gnssGeofencingIface == nullptr) { - ALOGE("%s: IGnssGeofencing interface not available.", __func__); - return JNI_FALSE; - } - return gnssGeofencingIface->resumeGeofence(geofenceId, monitor_transition); -} - -static jboolean android_location_gnss_hal_GnssNative_is_antenna_info_supported(JNIEnv* env, - jclass) { - if (gnssAntennaInfoIface != nullptr) { - return JNI_TRUE; - } - return JNI_FALSE; -} - -static jboolean android_location_gnss_hal_GnssNative_start_antenna_info_listening(JNIEnv* /* env */, - jclass) { - if (gnssAntennaInfoIface == nullptr) { - ALOGE("%s: IGnssAntennaInfo interface not available.", __func__); - return JNI_FALSE; - } - return gnssAntennaInfoIface->setCallback(std::make_unique()); -} - -static jboolean android_location_gnss_hal_GnssNative_stop_antenna_info_listening(JNIEnv* /* env */, - jclass) { - if (gnssAntennaInfoIface == nullptr) { - ALOGE("%s: IGnssAntennaInfo interface not available.", __func__); - return JNI_FALSE; - } - return gnssAntennaInfoIface->close(); -} - -static jboolean android_location_gnss_hal_GnssNative_is_measurement_supported(JNIEnv* env, jclass) { - if (gnssMeasurementIface != nullptr) { - return JNI_TRUE; - } - - return JNI_FALSE; -} - -static jboolean android_location_gnss_hal_GnssNative_start_measurement_collection( - JNIEnv* /* env */, jclass, jboolean enableFullTracking, jboolean enableCorrVecOutputs, - jint intervalMs) { - if (gnssMeasurementIface == nullptr) { - ALOGE("%s: IGnssMeasurement interface not available.", __func__); - return JNI_FALSE; - } - hardware::gnss::IGnssMeasurementInterface::Options options; - options.enableFullTracking = enableFullTracking; - options.enableCorrVecOutputs = enableCorrVecOutputs; - options.intervalMs = intervalMs; - - return gnssMeasurementIface->setCallback(std::make_unique( - gnssMeasurementIface->getInterfaceVersion()), - options); -} - -static jboolean android_location_gnss_hal_GnssNative_stop_measurement_collection(JNIEnv* env, - jclass) { - if (gnssMeasurementIface == nullptr) { - ALOGE("%s: IGnssMeasurement interface not available.", __func__); - return JNI_FALSE; - } - - return gnssMeasurementIface->close(); -} - -static jboolean android_location_gnss_hal_GnssNative_is_measurement_corrections_supported( - JNIEnv* env, jclass) { - if (gnssMeasurementCorrectionsIface != nullptr) { - return JNI_TRUE; - } - - return JNI_FALSE; -} - -static jboolean android_location_gnss_hal_GnssNative_inject_measurement_corrections( - JNIEnv* env, jclass, jobject correctionsObj) { - if (gnssMeasurementCorrectionsIface == nullptr) { - ALOGW("Trying to inject GNSS measurement corrections on a chipset that does not" - " support them."); - return JNI_FALSE; - } - return gnssMeasurementCorrectionsIface->setCorrections(env, correctionsObj); -} - -static jboolean android_location_gnss_hal_GnssNative_is_navigation_message_supported(JNIEnv* env, - jclass) { - if (gnssNavigationMessageIface != nullptr) { - return JNI_TRUE; - } - return JNI_FALSE; -} - -static jboolean android_location_gnss_hal_GnssNative_start_navigation_message_collection( - JNIEnv* env, jclass) { - if (gnssNavigationMessageIface == nullptr) { - ALOGE("%s: IGnssNavigationMessage interface not available.", __func__); - return JNI_FALSE; - } - - return gnssNavigationMessageIface->setCallback( - std::make_unique()); -} - -static jboolean android_location_gnss_hal_GnssNative_stop_navigation_message_collection(JNIEnv* env, - jclass) { - if (gnssNavigationMessageIface == nullptr) { - ALOGE("%s: IGnssNavigationMessage interface not available.", __func__); - return JNI_FALSE; - } - return gnssNavigationMessageIface->close(); -} - -static jboolean android_location_GnssConfiguration_set_emergency_supl_pdn(JNIEnv*, - jobject, - jint emergencySuplPdn) { - if (gnssConfigurationIface == nullptr) { - ALOGE("%s: IGnssConfiguration interface not available.", __func__); - return JNI_FALSE; - } - return gnssConfigurationIface->setEmergencySuplPdn(emergencySuplPdn); -} - -static jboolean android_location_GnssConfiguration_set_supl_version(JNIEnv*, - jobject, - jint version) { - if (gnssConfigurationIface == nullptr) { - ALOGE("%s: IGnssConfiguration interface not available.", __func__); - return JNI_FALSE; - } - return gnssConfigurationIface->setSuplVersion(version); -} - -static jboolean android_location_GnssConfiguration_set_supl_es(JNIEnv*, - jobject, - jint suplEs) { - if (gnssConfigurationIface == nullptr) { - ALOGE("%s: IGnssConfiguration interface not available.", __func__); - return JNI_FALSE; - } - return gnssConfigurationIface->setSuplEs(suplEs); -} - -static jboolean android_location_GnssConfiguration_set_supl_mode(JNIEnv*, - jobject, - jint mode) { - if (gnssConfigurationIface == nullptr) { - ALOGE("%s: IGnssConfiguration interface not available.", __func__); - return JNI_FALSE; - } - return gnssConfigurationIface->setSuplMode(mode); -} - -static jboolean android_location_GnssConfiguration_set_gps_lock(JNIEnv*, - jobject, - jint gpsLock) { - if (gnssConfigurationIface == nullptr) { - ALOGE("%s: IGnssConfiguration interface not available.", __func__); - return JNI_FALSE; - } - return gnssConfigurationIface->setGpsLock(gpsLock); -} - -static jboolean android_location_GnssConfiguration_set_lpp_profile(JNIEnv*, - jobject, - jint lppProfile) { - if (gnssConfigurationIface == nullptr) { - ALOGE("%s: IGnssConfiguration interface not available.", __func__); - return JNI_FALSE; - } - return gnssConfigurationIface->setLppProfile(lppProfile); -} - -static jboolean android_location_GnssConfiguration_set_gnss_pos_protocol_select(JNIEnv*, - jobject, - jint gnssPosProtocol) { - if (gnssConfigurationIface == nullptr) { - ALOGE("%s: IGnssConfiguration interface not available.", __func__); - return JNI_FALSE; - } - return gnssConfigurationIface->setGlonassPositioningProtocol(gnssPosProtocol); -} - -static jboolean android_location_GnssConfiguration_set_satellite_blocklist(JNIEnv* env, jobject, - jintArray constellations, - jintArray sv_ids) { - if (gnssConfigurationIface == nullptr) { - ALOGI("IGnssConfiguration interface does not support satellite blocklist."); - return JNI_FALSE; - } - return gnssConfigurationIface->setBlocklist(env, constellations, sv_ids); -} - -static jboolean android_location_GnssConfiguration_set_es_extension_sec( - JNIEnv*, jobject, jint emergencyExtensionSeconds) { - if (gnssConfigurationIface == nullptr) { - ALOGE("%s: IGnssConfiguration interface not available.", __func__); - return JNI_FALSE; - } - return gnssConfigurationIface->setEsExtensionSec(emergencyExtensionSeconds); -} - -static jint android_location_gnss_hal_GnssNative_get_batch_size(JNIEnv*) { - if (gnssBatchingIface == nullptr) { - return 0; // batching not supported, size = 0 - } - return gnssBatchingIface->getBatchSize(); -} - -static jboolean android_location_gnss_hal_GnssNative_init_batching(JNIEnv*, jclass) { - if (gnssBatchingIface == nullptr) { - return JNI_FALSE; // batching not supported - } - return gnssBatchingIface->init(std::make_unique()); -} - -static void android_location_gnss_hal_GnssNative_cleanup_batching(JNIEnv*, jclass) { - if (gnssBatchingIface == nullptr) { - return; // batching not supported - } - gnssBatchingIface->cleanup(); -} - -static jboolean android_location_gnss_hal_GnssNative_start_batch(JNIEnv*, jclass, jlong periodNanos, - jfloat minUpdateDistanceMeters, - jboolean wakeOnFifoFull) { - if (gnssBatchingIface == nullptr) { - return JNI_FALSE; // batching not supported - } - return gnssBatchingIface->start(periodNanos, minUpdateDistanceMeters, wakeOnFifoFull); -} - -static void android_location_gnss_hal_GnssNative_flush_batch(JNIEnv*, jclass) { - if (gnssBatchingIface == nullptr) { - return; // batching not supported - } - gnssBatchingIface->flush(); -} - -static jboolean android_location_gnss_hal_GnssNative_stop_batch(JNIEnv*, jclass) { - if (gnssBatchingIface == nullptr) { - return JNI_FALSE; // batching not supported - } - return gnssBatchingIface->stop(); -} - -static jboolean android_location_GnssVisibilityControl_enable_nfw_location_access( - JNIEnv* env, jobject, jobjectArray proxyApps) { - if (gnssVisibilityControlIface == nullptr) { - ALOGI("IGnssVisibilityControl interface not available."); - return JNI_FALSE; - } - return gnssVisibilityControlIface->enableNfwLocationAccess(env, proxyApps); -} - -static const JNINativeMethod sCoreMethods[] = { - /* name, signature, funcPtr */ - {"native_class_init_once", "()V", - reinterpret_cast(android_location_gnss_hal_GnssNative_class_init_once)}, - {"native_is_supported", "()Z", - reinterpret_cast(android_location_gnss_hal_GnssNative_is_supported)}, - {"native_init_once", "(Z)V", - reinterpret_cast(android_location_gnss_hal_GnssNative_init_once)}, -}; - -static const JNINativeMethod sLocationProviderMethods[] = { - /* name, signature, funcPtr */ - {"native_init", "()Z", reinterpret_cast(android_location_gnss_hal_GnssNative_init)}, - {"native_cleanup", "()V", - reinterpret_cast(android_location_gnss_hal_GnssNative_cleanup)}, - {"native_set_position_mode", "(IIIIIZ)Z", - reinterpret_cast(android_location_gnss_hal_GnssNative_set_position_mode)}, - {"native_start", "()Z", - reinterpret_cast(android_location_gnss_hal_GnssNative_start)}, - {"native_stop", "()Z", reinterpret_cast(android_location_gnss_hal_GnssNative_stop)}, - {"native_delete_aiding_data", "(I)V", - reinterpret_cast(android_location_gnss_hal_GnssNative_delete_aiding_data)}, - {"native_read_nmea", "([BI)I", - reinterpret_cast(android_location_gnss_hal_GnssNative_read_nmea)}, - {"native_inject_time", "(JJI)V", - reinterpret_cast(android_location_gnss_hal_GnssNative_inject_time)}, - {"native_inject_best_location", "(IDDDFFFFFFJIJD)V", - reinterpret_cast(android_location_gnss_hal_GnssNative_inject_best_location)}, - {"native_inject_location", "(IDDDFFFFFFJIJD)V", - reinterpret_cast(android_location_gnss_hal_GnssNative_inject_location)}, - {"native_supports_psds", "()Z", - reinterpret_cast(android_location_gnss_hal_GnssNative_supports_psds)}, - {"native_inject_psds_data", "([BII)V", - reinterpret_cast(android_location_gnss_hal_GnssNative_inject_psds_data)}, - {"native_agps_set_id", "(ILjava/lang/String;)V", - reinterpret_cast(android_location_gnss_hal_GnssNative_agps_set_id)}, - {"native_agps_set_ref_location_cellid", "(IIIIJIII)V", - reinterpret_cast( - android_location_gnss_hal_GnssNative_agps_set_reference_location_cellid)}, - {"native_set_agps_server", "(ILjava/lang/String;I)V", - reinterpret_cast(android_location_gnss_hal_GnssNative_set_agps_server)}, - {"native_inject_ni_supl_message_data", "([BII)V", - reinterpret_cast(android_location_gnss_hal_GnssNative_inject_ni_supl_message_data)}, - {"native_get_internal_state", "()Ljava/lang/String;", - reinterpret_cast(android_location_gnss_hal_GnssNative_get_internal_state)}, - {"native_is_gnss_visibility_control_supported", "()Z", - reinterpret_cast( - android_location_gnss_hal_GnssNative_is_gnss_visibility_control_supported)}, - {"native_start_sv_status_collection", "()Z", - reinterpret_cast(android_location_gnss_hal_GnssNative_start_sv_status_collection)}, - {"native_stop_sv_status_collection", "()Z", - reinterpret_cast(android_location_gnss_hal_GnssNative_stop_sv_status_collection)}, - {"native_start_nmea_message_collection", "()Z", - reinterpret_cast( - android_location_gnss_hal_GnssNative_start_nmea_message_collection)}, - {"native_stop_nmea_message_collection", "()Z", - reinterpret_cast( - android_location_gnss_hal_GnssNative_stop_nmea_message_collection)}, -}; - -static const JNINativeMethod sBatchingMethods[] = { - /* name, signature, funcPtr */ - {"native_get_batch_size", "()I", - reinterpret_cast(android_location_gnss_hal_GnssNative_get_batch_size)}, - {"native_start_batch", "(JFZ)Z", - reinterpret_cast(android_location_gnss_hal_GnssNative_start_batch)}, - {"native_flush_batch", "()V", - reinterpret_cast(android_location_gnss_hal_GnssNative_flush_batch)}, - {"native_stop_batch", "()Z", - reinterpret_cast(android_location_gnss_hal_GnssNative_stop_batch)}, - {"native_init_batching", "()Z", - reinterpret_cast(android_location_gnss_hal_GnssNative_init_batching)}, - {"native_cleanup_batching", "()V", - reinterpret_cast(android_location_gnss_hal_GnssNative_cleanup_batching)}, -}; - -static const JNINativeMethod sAntennaInfoMethods[] = { - /* name, signature, funcPtr */ - {"native_is_antenna_info_supported", "()Z", - reinterpret_cast(android_location_gnss_hal_GnssNative_is_antenna_info_supported)}, - {"native_start_antenna_info_listening", "()Z", - reinterpret_cast( - android_location_gnss_hal_GnssNative_start_antenna_info_listening)}, - {"native_stop_antenna_info_listening", "()Z", - reinterpret_cast(android_location_gnss_hal_GnssNative_stop_antenna_info_listening)}, -}; - -static const JNINativeMethod sGeofenceMethods[] = { - /* name, signature, funcPtr */ - {"native_is_geofence_supported", "()Z", - reinterpret_cast(android_location_gnss_hal_GnssNative_is_geofence_supported)}, - {"native_add_geofence", "(IDDDIIII)Z", - reinterpret_cast(android_location_gnss_hal_GnssNative_add_geofence)}, - {"native_remove_geofence", "(I)Z", - reinterpret_cast(android_location_gnss_hal_GnssNative_remove_geofence)}, - {"native_pause_geofence", "(I)Z", - reinterpret_cast(android_location_gnss_hal_GnssNative_pause_geofence)}, - {"native_resume_geofence", "(II)Z", - reinterpret_cast(android_location_gnss_hal_GnssNative_resume_geofence)}, -}; - -static const JNINativeMethod sMeasurementMethods[] = { - /* name, signature, funcPtr */ - {"native_is_measurement_supported", "()Z", - reinterpret_cast(android_location_gnss_hal_GnssNative_is_measurement_supported)}, - {"native_start_measurement_collection", "(ZZI)Z", - reinterpret_cast( - android_location_gnss_hal_GnssNative_start_measurement_collection)}, - {"native_stop_measurement_collection", "()Z", - reinterpret_cast(android_location_gnss_hal_GnssNative_stop_measurement_collection)}, -}; - -static const JNINativeMethod sMeasurementCorrectionsMethods[] = { - /* name, signature, funcPtr */ - {"native_is_measurement_corrections_supported", "()Z", - reinterpret_cast( - android_location_gnss_hal_GnssNative_is_measurement_corrections_supported)}, - {"native_inject_measurement_corrections", - "(Landroid/location/GnssMeasurementCorrections;)Z", - reinterpret_cast( - android_location_gnss_hal_GnssNative_inject_measurement_corrections)}, -}; - -static const JNINativeMethod sNavigationMessageMethods[] = { - /* name, signature, funcPtr */ - {"native_is_navigation_message_supported", "()Z", - reinterpret_cast( - android_location_gnss_hal_GnssNative_is_navigation_message_supported)}, - {"native_start_navigation_message_collection", "()Z", - reinterpret_cast( - android_location_gnss_hal_GnssNative_start_navigation_message_collection)}, - {"native_stop_navigation_message_collection", "()Z", - reinterpret_cast( - android_location_gnss_hal_GnssNative_stop_navigation_message_collection)}, -}; - -static const JNINativeMethod sNetworkConnectivityMethods[] = { - /* name, signature, funcPtr */ - {"native_is_agps_ril_supported", "()Z", - reinterpret_cast( - android_location_GnssNetworkConnectivityHandler_is_agps_ril_supported)}, - {"native_update_network_state", "(ZIZZLjava/lang/String;JS)V", - reinterpret_cast( - android_location_GnssNetworkConnectivityHandler_update_network_state)}, - {"native_agps_data_conn_open", "(JLjava/lang/String;I)V", - reinterpret_cast( - android_location_GnssNetworkConnectivityHandler_agps_data_conn_open)}, - {"native_agps_data_conn_closed", "()V", - reinterpret_cast( - android_location_GnssNetworkConnectivityHandler_agps_data_conn_closed)}, - {"native_agps_data_conn_failed", "()V", - reinterpret_cast( - android_location_GnssNetworkConnectivityHandler_agps_data_conn_failed)}, -}; - -static const JNINativeMethod sConfigurationMethods[] = { - /* name, signature, funcPtr */ - {"native_get_gnss_configuration_version", - "()Lcom/android/server/location/gnss/GnssConfiguration$HalInterfaceVersion;", - reinterpret_cast( - android_location_GnssConfiguration_get_gnss_configuration_version)}, - {"native_set_supl_es", "(I)Z", - reinterpret_cast(android_location_GnssConfiguration_set_supl_es)}, - {"native_set_supl_version", "(I)Z", - reinterpret_cast(android_location_GnssConfiguration_set_supl_version)}, - {"native_set_supl_mode", "(I)Z", - reinterpret_cast(android_location_GnssConfiguration_set_supl_mode)}, - {"native_set_lpp_profile", "(I)Z", - reinterpret_cast(android_location_GnssConfiguration_set_lpp_profile)}, - {"native_set_gnss_pos_protocol_select", "(I)Z", - reinterpret_cast(android_location_GnssConfiguration_set_gnss_pos_protocol_select)}, - {"native_set_gps_lock", "(I)Z", - reinterpret_cast(android_location_GnssConfiguration_set_gps_lock)}, - {"native_set_emergency_supl_pdn", "(I)Z", - reinterpret_cast(android_location_GnssConfiguration_set_emergency_supl_pdn)}, - {"native_set_satellite_blocklist", "([I[I)Z", - reinterpret_cast(android_location_GnssConfiguration_set_satellite_blocklist)}, - {"native_set_es_extension_sec", "(I)Z", - reinterpret_cast(android_location_GnssConfiguration_set_es_extension_sec)}, -}; - -static const JNINativeMethod sVisibilityControlMethods[] = { - /* name, signature, funcPtr */ - {"native_enable_nfw_location_access", "([Ljava/lang/String;)Z", - reinterpret_cast( - android_location_GnssVisibilityControl_enable_nfw_location_access)}, -}; - -static const JNINativeMethod sPowerIndicationMethods[] = { - /* name, signature, funcPtr */ - {"native_request_power_stats", "()V", - reinterpret_cast(android_location_gnss_hal_GnssNative_request_power_stats)}, -}; - -int register_android_server_location_GnssLocationProvider(JNIEnv* env) { - int res; - - res = jniRegisterNativeMethods(env, "com/android/server/location/gnss/hal/GnssNative", - sAntennaInfoMethods, NELEM(sAntennaInfoMethods)); - LOG_FATAL_IF(res < 0, "Unable to register native methods."); - - res = jniRegisterNativeMethods(env, "com/android/server/location/gnss/hal/GnssNative", - sBatchingMethods, NELEM(sBatchingMethods)); - LOG_FATAL_IF(res < 0, "Unable to register native methods."); - - res = jniRegisterNativeMethods(env, "com/android/server/location/gnss/hal/GnssNative", - sGeofenceMethods, NELEM(sGeofenceMethods)); - LOG_FATAL_IF(res < 0, "Unable to register native methods."); - - res = jniRegisterNativeMethods(env, "com/android/server/location/gnss/hal/GnssNative", - sMeasurementMethods, NELEM(sMeasurementMethods)); - LOG_FATAL_IF(res < 0, "Unable to register native methods."); - - res = jniRegisterNativeMethods(env, "com/android/server/location/gnss/hal/GnssNative", - sMeasurementCorrectionsMethods, - NELEM(sMeasurementCorrectionsMethods)); - LOG_FATAL_IF(res < 0, "Unable to register native methods."); - - res = jniRegisterNativeMethods(env, "com/android/server/location/gnss/hal/GnssNative", - sNavigationMessageMethods, NELEM(sNavigationMessageMethods)); - LOG_FATAL_IF(res < 0, "Unable to register native methods."); - - res = jniRegisterNativeMethods(env, - "com/android/server/location/gnss/" - "GnssNetworkConnectivityHandler", - sNetworkConnectivityMethods, NELEM(sNetworkConnectivityMethods)); - LOG_FATAL_IF(res < 0, "Unable to register native methods."); - - res = jniRegisterNativeMethods(env, "com/android/server/location/gnss/GnssConfiguration", - sConfigurationMethods, NELEM(sConfigurationMethods)); - LOG_FATAL_IF(res < 0, "Unable to register native methods."); - - res = jniRegisterNativeMethods(env, "com/android/server/location/gnss/GnssVisibilityControl", - sVisibilityControlMethods, NELEM(sVisibilityControlMethods)); - LOG_FATAL_IF(res < 0, "Unable to register native methods."); - - res = jniRegisterNativeMethods(env, "com/android/server/location/gnss/hal/GnssNative", - sPowerIndicationMethods, NELEM(sPowerIndicationMethods)); - LOG_FATAL_IF(res < 0, "Unable to register native methods."); - - res = jniRegisterNativeMethods(env, "com/android/server/location/gnss/hal/GnssNative", - sLocationProviderMethods, NELEM(sLocationProviderMethods)); - LOG_FATAL_IF(res < 0, "Unable to register native methods."); - - res = jniRegisterNativeMethods(env, "com/android/server/location/gnss/hal/GnssNative", - sCoreMethods, NELEM(sCoreMethods)); - LOG_FATAL_IF(res < 0, "Unable to register native methods."); - - return 0; -} - -} /* namespace android */ \ No newline at end of file diff --git a/gps/set_gps_location.sh b/gps/set_gps_location.sh deleted file mode 100644 index bdf355e..0000000 --- a/gps/set_gps_location.sh +++ /dev/null @@ -1,82 +0,0 @@ -#!/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" diff --git a/set_custom_gps.sh b/set_custom_gps.sh new file mode 100644 index 0000000..4d6c030 --- /dev/null +++ b/set_custom_gps.sh @@ -0,0 +1,140 @@ +#!/bin/bash + +# Android自定义GPS位置设置脚本 +# 适用于修改了frameworks/base的Android系统 +# 用法: ./set_custom_gps.sh <纬度> <经度> +# 示例: ./set_custom_gps.sh 39.904989 116.405285 + +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +if [ $# -ne 2 ]; then + echo -e "${RED}用法: $0 <纬度> <经度>${NC}" + echo "" + echo -e "${BLUE}示例位置:${NC}" + echo -e " ${GREEN}北京天安门:${NC} $0 39.904989 116.405285" + echo -e " ${GREEN}上海外滩:${NC} $0 31.239666 121.499809" + echo -e " ${GREEN}广州塔:${NC} $0 23.109831 113.324504" + echo -e " ${GREEN}深圳地王:${NC} $0 22.544249 114.095298" + echo -e " ${GREEN}杭州西湖:${NC} $0 30.281026 120.019348" + echo -e " ${GREEN}东京塔:${NC} $0 35.658651 139.745415" + echo -e " ${GREEN}纽约时代广场:${NC} $0 40.758896 -73.985130" + echo "" + echo -e "${YELLOW}坐标范围:${NC}" + echo -e " 纬度: -90 到 90" + echo -e " 经度: -180 到 180" + exit 1 +fi + +LATITUDE=$1 +LONGITUDE=$2 + +# 验证数字格式 +if ! [[ $LATITUDE =~ ^-?[0-9]+\.?[0-9]*$ ]]; then + echo -e "${RED}错误: 纬度必须是有效的数字${NC}" + exit 1 +fi + +if ! [[ $LONGITUDE =~ ^-?[0-9]+\.?[0-9]*$ ]]; then + echo -e "${RED}错误: 经度必须是有效的数字${NC}" + exit 1 +fi + +# 验证坐标范围 +if (( $(echo "$LATITUDE < -90.0 || $LATITUDE > 90.0" | bc -l 2>/dev/null || echo "1") )); then + echo -e "${RED}错误: 纬度必须在 -90 到 90 之间${NC}" + exit 1 +fi + +if (( $(echo "$LONGITUDE < -180.0 || $LONGITUDE > 180.0" | bc -l 2>/dev/null || echo "1") )); then + echo -e "${RED}错误: 经度必须在 -180 到 180 之间${NC}" + exit 1 +fi + +GPS_FILE="/data/vendor/gps/custom_location.txt" +GPS_DIR="/data/vendor/gps" + +echo -e "${BLUE}🌍 设置GPS位置为: 纬度 ${GREEN}$LATITUDE${BLUE}, 经度 ${GREEN}$LONGITUDE${NC}" + +# 检查ADB连接 +if ! command -v adb >/dev/null 2>&1; then + echo -e "${RED}❌ 错误: 未找到adb命令${NC}" + echo -e "${YELLOW}请确保Android SDK已安装并添加到PATH${NC}" + exit 1 +fi + +# 检查设备连接 +DEVICE_COUNT=$(adb devices | grep -c "device$") +if [ "$DEVICE_COUNT" -eq 0 ]; then + echo -e "${RED}❌ 错误: 未找到连接的Android设备${NC}" + echo -e "${YELLOW}请确保:${NC}" + echo "1. 设备已连接并启用USB调试" + echo "2. 已授权计算机的USB调试请求" + echo "3. 使用 'adb devices' 验证设备连接" + exit 1 +elif [ "$DEVICE_COUNT" -gt 1 ]; then + echo -e "${YELLOW}⚠️ 检测到多个设备,使用第一个设备${NC}" +fi + +# 创建临时文件 +TEMP_FILE=$(mktemp) +echo "$LATITUDE,$LONGITUDE" > "$TEMP_FILE" + +echo -e "${BLUE}📁 正在创建GPS目录...${NC}" +adb shell "mkdir -p $GPS_DIR" 2>/dev/null + +echo -e "${BLUE}📤 正在上传GPS位置文件...${NC}" +adb push "$TEMP_FILE" "$GPS_FILE" >/dev/null 2>&1 + +if [ $? -eq 0 ]; then + echo -e "${GREEN}✅ GPS位置文件上传成功!${NC}" + + # 设置正确权限 + echo -e "${BLUE}🔐 正在设置文件权限...${NC}" + adb shell "chown system:system $GPS_FILE" 2>/dev/null + adb shell "chmod 644 $GPS_FILE" 2>/dev/null + + # 验证文件内容 + echo -e "${BLUE}📍 当前GPS位置配置:${NC}" + CURRENT_LOCATION=$(adb shell "cat $GPS_FILE" 2>/dev/null | tr -d '\r\n') + if [ -n "$CURRENT_LOCATION" ]; then + echo -e " ${GREEN}$CURRENT_LOCATION${NC}" + else + echo -e " ${RED}无法读取配置文件${NC}" + fi + + echo "" + echo -e "${GREEN}🎉 GPS位置设置完成!${NC}" + echo "" + echo -e "${YELLOW}💡 使用提示:${NC}" + echo "• 新位置将在下次GPS请求时生效" + echo "• 重启GPS服务或应用以立即生效" + echo "• 打开地图应用验证位置是否正确" + echo "" + echo -e "${BLUE}🔍 调试命令:${NC}" + echo "• 查看GPS日志: ${GREEN}adb logcat | grep -i 'custom.*gps'${NC}" + echo "• 删除自定义位置: ${GREEN}adb shell 'rm $GPS_FILE'${NC}" + echo "• 重启位置服务: ${GREEN}adb shell 'setprop ctl.restart location'${NC}" + +else + echo -e "${RED}❌ GPS位置文件上传失败${NC}" + echo -e "${YELLOW}可能的原因:${NC}" + echo "1. 设备没有root权限" + echo "2. 系统分区为只读" + echo "3. SELinux策略限制" + echo "" + echo -e "${BLUE}尝试解决方案:${NC}" + echo "• 确保设备已获得root权限" + echo "• 尝试: adb root && adb remount" + echo "• 检查SELinux设置: adb shell getenforce" +fi + +# 清理临时文件 +rm -f "$TEMP_FILE" + +echo "" +echo -e "${BLUE}📱 支持的Android版本: Android 8.0+ (API Level 26+)${NC}" +echo -e "${BLUE}🔧 需要: 已修改frameworks/base的自定义Android系统${NC}" diff --git a/vendor.mk b/vendor.mk index 0c1a398..dec3723 100644 --- a/vendor.mk +++ b/vendor.mk @@ -44,11 +44,8 @@ PRODUCT_COPY_FILES += \ ###################### # gps config ###################### -PRODUCT_PACKAGES += \ - libredroid_gps_jni - -# PRODUCT_PACKAGES += \ -# android.hardware.gnss-service +# GPS functionality now integrated into frameworks/base +# No vendor overlay needed PRODUCT_COPY_FILES += \ vendor/redroid/gps/init.redroid.gps.sh:$(TARGET_COPY_OUT_VENDOR)/bin/hw/init.redroid.gps.sh \