--- 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) {