From: CoderKang Date: Fri, 19 Sep 2025 10:00:00 +0800 Subject: [PATCH] Add custom GPS location from file --- diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp index a95a4a8..10eae12 100644 --- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp +++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp @@ -66,6 +66,9 @@ #include "jni.h" #include "utils/Log.h" #include "utils/misc.h" +#include +#include +#include static jclass class_gnssPowerStats; @@ -75,6 +78,79 @@ 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; + } + + // Use strtod for exception-free parsing + char* latEnd; + char* lonEnd; + double lat = strtod(latStr.c_str(), &latEnd); + double lon = strtod(lonStr.c_str(), &lonEnd); + + // Check if parsing was successful (no leftover characters) + if (*latEnd == '\0' && *lonEnd == '\0') { + // 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); + } + } else { + ALOGE("Failed to parse GPS coordinates from file"); + } + } + + file.close(); + useCustomLocation = false; + return false; +} + using android::OK; using android::sp; using android::status_t; @@ -377,6 +453,9 @@ static jboolean android_location_gnss_hal_GnssNative_set_position_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(); } @@ -457,12 +536,24 @@ static void android_location_gnss_hal_GnssNative_inject_best_location( jfloat speedAccuracyMetersPerSecond, jfloat bearingAccuracyDegrees, jlong timestamp, jint elapsedRealtimeFlags, jlong elapsedRealtimeNanos, jdouble elapsedRealtimeUncertaintyNanos) { - gnssHal->injectBestLocation(gnssLocationFlags, latitudeDegrees, longitudeDegrees, - altitudeMeters, speedMetersPerSec, bearingDegrees, - horizontalAccuracyMeters, verticalAccuracyMeters, - speedAccuracyMetersPerSecond, bearingAccuracyDegrees, timestamp, - elapsedRealtimeFlags, elapsedRealtimeNanos, - 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( @@ -472,11 +563,22 @@ static void android_location_gnss_hal_GnssNative_inject_location( jfloat speedAccuracyMetersPerSecond, jfloat bearingAccuracyDegrees, jlong timestamp, jint elapsedRealtimeFlags, jlong elapsedRealtimeNanos, jdouble elapsedRealtimeUncertaintyNanos) { - gnssHal->injectLocation(gnssLocationFlags, latitudeDegrees, longitudeDegrees, altitudeMeters, - speedMetersPerSec, bearingDegrees, horizontalAccuracyMeters, - verticalAccuracyMeters, speedAccuracyMetersPerSecond, - bearingAccuracyDegrees, timestamp, elapsedRealtimeFlags, - elapsedRealtimeNanos, 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) {