Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 91e58646 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Implement requestLocationCb"

parents 3bd2d738 e7baef38
Loading
Loading
Loading
Loading
+154 −23
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.server.location;

import android.annotation.Nullable;
import android.app.AlarmManager;
import android.app.AppOpsManager;
import android.app.PendingIntent;
@@ -28,11 +29,11 @@ import android.hardware.location.GeofenceHardware;
import android.hardware.location.GeofenceHardwareImpl;
import android.location.Criteria;
import android.location.FusedBatchOptions;
import android.location.GnssMeasurementsEvent;
import android.location.GnssNavigationMessage;
import android.location.GnssStatus;
import android.location.IGnssStatusListener;
import android.location.IGnssStatusProvider;
import android.location.GnssMeasurementsEvent;
import android.location.GnssNavigationMessage;
import android.location.IGpsGeofenceHardware;
import android.location.ILocationManager;
import android.location.INetInitiatedListener;
@@ -48,16 +49,16 @@ import android.net.NetworkInfo;
import android.net.NetworkRequest;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.PowerManager.ServiceType;
import android.os.PowerSaveState;
import android.os.BatteryStats;
import android.os.Binder;
import android.os.Bundle;
import android.os.PersistableBundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.PersistableBundle;
import android.os.PowerManager;
import android.os.PowerManager.ServiceType;
import android.os.PowerSaveState;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
@@ -68,25 +69,21 @@ import android.os.WorkSource.WorkChain;
import android.provider.Settings;
import android.provider.Telephony.Carriers;
import android.provider.Telephony.Sms.Intents;
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager;
import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
import android.telephony.TelephonyManager;
import android.telephony.CarrierConfigManager;
import android.telephony.gsm.GsmCellLocation;
import android.text.TextUtils;
import android.util.Log;
import android.util.NtpTrustedTime;

import com.android.internal.app.IAppOpsService;
import com.android.internal.app.IBatteryStats;
import com.android.internal.location.gnssmetrics.GnssMetrics;
import com.android.internal.location.GpsNetInitiatedHandler;
import com.android.internal.location.GpsNetInitiatedHandler.GpsNiNotification;
import com.android.internal.location.ProviderProperties;
import com.android.internal.location.ProviderRequest;

import libcore.io.IoUtils;

import com.android.internal.location.gnssmetrics.GnssMetrics;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
@@ -97,11 +94,13 @@ import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Map;
import java.util.HashMap;

import libcore.io.IoUtils;

/**
 * A GNSS implementation of LocationProvider used by LocationManager.
@@ -215,6 +214,7 @@ public class GnssLocationProvider implements LocationProviderInterface {
    private static final int INITIALIZE_HANDLER = 13;
    private static final int REQUEST_SUPL_CONNECTION = 14;
    private static final int RELEASE_SUPL_CONNECTION = 15;
    private static final int REQUEST_LOCATION = 16;

    // Request setid
    private static final int AGPS_RIL_REQUEST_SETID_IMSI = 1;
@@ -248,6 +248,13 @@ public class GnssLocationProvider implements LocationProviderInterface {
    private static final int TCP_MIN_PORT = 0;
    private static final int TCP_MAX_PORT = 0xffff;

    // 10 seconds.
    private static final long LOCATION_TIME_FRESHNESS_THESHOLD_MILLIS = 10 * 1000;
    // 1 second, or 1 Hz frequency.
    private static final long LOCATION_UPDATE_MIN_TIME_INTERVAL_MILLIS = 1000;
    // 30 seconds.
    private static final long LOCATION_UPDATE_DURATION_MILLIS = 30 * 1000;

    /** simpler wrapper for ProviderRequest + Worksource */
    private static class GpsRequest {
        public ProviderRequest request;
@@ -409,6 +416,8 @@ public class GnssLocationProvider implements LocationProviderInterface {
    private final GnssStatusListenerHelper mListenerHelper;
    private final GnssMeasurementsProvider mGnssMeasurementsProvider;
    private final GnssNavigationMessageProvider mGnssNavigationMessageProvider;
    private final FusedLocationListener mFusedLocationListener = new FusedLocationListener();
    private static int sNumFusedLocationUpdatesRequests = 0;

    // Handler for processing events
    private Handler mHandler;
@@ -1074,6 +1083,89 @@ public class GnssLocationProvider implements LocationProviderInterface {
        });
    }

    private void handleRequestLocation(boolean independentFromGnss) {
        if (isRequestLocationRateLimited()) {
            if (DEBUG) {
                Log.d(TAG, "RequestLocation is denied due to too frequent requests.");
            }
            return;
        }

        LocationManager locationManager = (LocationManager) mContext.getSystemService(
                Context.LOCATION_SERVICE);

        if (independentFromGnss) {
            // For fast GNSS TTFF
            Location networkLocation = getLastFreshLocation(locationManager,
                    LocationManager.NETWORK_PROVIDER);
            if (networkLocation != null) {
                handleUpdateLocation(networkLocation);
                return;
            }
            locationManager.requestSingleUpdate(LocationManager.NETWORK_PROVIDER,
                    new NetworkLocationListener(),
                    mHandler.getLooper());
        } else {
            // For Device-Based Hybrid (E911)
            locationManager.requestLocationUpdates(LocationManager.FUSED_PROVIDER,
                    LOCATION_UPDATE_MIN_TIME_INTERVAL_MILLIS, /*minDistance=*/ 0,
                    mFusedLocationListener, mHandler.getLooper());
            sNumFusedLocationUpdatesRequests++;
            mHandler.postDelayed(() -> {
                if (--sNumFusedLocationUpdatesRequests == 0) {
                    locationManager.removeUpdates(mFusedLocationListener);
                }
            }, LOCATION_UPDATE_DURATION_MILLIS);
        }
    }

    private void injectBestLocation(Location location) {
        int gnssLocationFlags = LOCATION_HAS_LAT_LONG |
                (location.hasAltitude() ? LOCATION_HAS_ALTITUDE : 0) |
                (location.hasSpeed() ? LOCATION_HAS_SPEED : 0) |
                (location.hasBearing() ? LOCATION_HAS_BEARING : 0) |
                (location.hasAccuracy() ? LOCATION_HAS_HORIZONTAL_ACCURACY : 0) |
                (location.hasVerticalAccuracy() ? LOCATION_HAS_VERTICAL_ACCURACY : 0) |
                (location.hasSpeedAccuracy() ? LOCATION_HAS_SPEED_ACCURACY : 0) |
                (location.hasBearingAccuracy() ? LOCATION_HAS_BEARING_ACCURACY : 0);

        double latitudeDegrees = location.getLatitude();
        double longitudeDegrees = location.getLongitude();
        double altitudeMeters = location.getAltitude();
        float speedMetersPerSec = location.getSpeed();
        float bearingDegrees = location.getBearing();
        float horizontalAccuracyMeters = location.getAccuracy();
        float verticalAccuracyMeters = location.getVerticalAccuracyMeters();
        float speedAccuracyMetersPerSecond = location.getSpeedAccuracyMetersPerSecond();
        float bearingAccuracyDegrees = location.getBearingAccuracyDegrees();
        long timestamp = location.getTime();
        native_inject_best_location(gnssLocationFlags, latitudeDegrees, longitudeDegrees,
                altitudeMeters, speedMetersPerSec, bearingDegrees, horizontalAccuracyMeters,
                verticalAccuracyMeters, speedAccuracyMetersPerSecond, bearingAccuracyDegrees,
                timestamp);
    }

    /**
     * Get the last fresh location.
     *
     * Return null if the last location is not available or not fresh.
     */
    private @Nullable
    Location getLastFreshLocation(LocationManager locationManager, String provider) {
        Location location = locationManager.getLastKnownLocation(provider);
        if (location != null && System.currentTimeMillis() - location.getTime()
                < LOCATION_TIME_FRESHNESS_THESHOLD_MILLIS) {
            return location;
        }
        return null;
    }

    /** Returns true if the location request is too frequent. */
    private boolean isRequestLocationRateLimited() {
        // TODO(b/73198123): implement exponential backoff.
        return false;
    }

    private void handleDownloadXtraData() {
        if (!mSupportsXtra) {
            // native code reports xtra not supported, don't try
@@ -2270,6 +2362,16 @@ public class GnssLocationProvider implements LocationProviderInterface {
        native_agps_set_id(type, data);
    }

    /**
     * Called from native code to request location info.
     */
    private void requestLocation(boolean independentFromGnss) {
        if (DEBUG) {
            Log.d(TAG, "requestLocation. independentFromGnss: " + independentFromGnss);
        }
        sendMessage(REQUEST_LOCATION, 0, independentFromGnss);
    }

    /**
     * Called from native code to request utc time info
     */
@@ -2281,7 +2383,6 @@ public class GnssLocationProvider implements LocationProviderInterface {
    /**
     * Called from native code to request reference location info
     */

    private void requestRefLocation() {
        TelephonyManager phone = (TelephonyManager)
                mContext.getSystemService(Context.TELEPHONY_SERVICE);
@@ -2357,6 +2458,9 @@ public class GnssLocationProvider implements LocationProviderInterface {
                case INJECT_NTP_TIME:
                    handleInjectNtpTime();
                    break;
                case REQUEST_LOCATION:
                    handleRequestLocation((boolean) msg.obj);
                    break;
                case DOWNLOAD_XTRA_DATA:
                    handleDownloadXtraData();
                    break;
@@ -2482,25 +2586,37 @@ public class GnssLocationProvider implements LocationProviderInterface {
        }
    }

    private final class NetworkLocationListener implements LocationListener {
    private abstract class LocationChangeListener implements LocationListener {
        @Override
        public void onLocationChanged(Location location) {
            // this callback happens on mHandler looper
            if (LocationManager.NETWORK_PROVIDER.equals(location.getProvider())) {
                handleUpdateLocation(location);
        public void onStatusChanged(String provider, int status, Bundle extras) {
        }

        @Override
        public void onProviderEnabled(String provider) {
        }

        @Override
        public void onStatusChanged(String provider, int status, Bundle extras) {
        public void onProviderDisabled(String provider) {
        }
    }

    private final class NetworkLocationListener extends LocationChangeListener {
        @Override
        public void onProviderEnabled(String provider) {
        public void onLocationChanged(Location location) {
            // this callback happens on mHandler looper
            if (LocationManager.NETWORK_PROVIDER.equals(location.getProvider())) {
                handleUpdateLocation(location);
            }
        }
    }

    private final class FusedLocationListener extends LocationChangeListener {
        @Override
        public void onProviderDisabled(String provider) {
        public void onLocationChanged(Location location) {
            if (LocationManager.FUSED_PROVIDER.equals(location.getProvider())) {
                Log.d(TAG, "fused location listener: " + location);
                injectBestLocation(location);
            }
        }
    }

@@ -2668,6 +2784,8 @@ public class GnssLocationProvider implements LocationProviderInterface {
                return "RELEASE_SUPL_CONNECTION";
            case INJECT_NTP_TIME:
                return "INJECT_NTP_TIME";
            case REQUEST_LOCATION:
                return "REQUEST_LOCATION";
            case DOWNLOAD_XTRA_DATA:
                return "DOWNLOAD_XTRA_DATA";
            case INJECT_NTP_TIME_FINISHED:
@@ -2788,6 +2906,19 @@ public class GnssLocationProvider implements LocationProviderInterface {

    private native int native_read_nmea(byte[] buffer, int bufferSize);

    private native void native_inject_best_location(
            int gnssLocationFlags,
            double latitudeDegrees,
            double longitudeDegrees,
            double altitudeMeters,
            float speedMetersPerSec,
            float bearingDegrees,
            float horizontalAccuracyMeters,
            float verticalAccuracyMeters,
            float speedAccuracyMetersPerSecond,
            float bearingAccuracyDegrees,
            long timestamp);

    private native void native_inject_location(double latitude, double longitude, float accuracy);

    // XTRA Support
+72 −1
Original line number Diff line number Diff line
@@ -51,6 +51,7 @@ static jmethodID method_setGnssYearOfHardware;
static jmethodID method_setGnssHardwareModelName;
static jmethodID method_xtraDownloadRequest;
static jmethodID method_reportNiNotification;
static jmethodID method_requestLocation;
static jmethodID method_requestRefLocation;
static jmethodID method_requestSetID;
static jmethodID method_requestUtcTime;
@@ -346,6 +347,34 @@ static jobject translateLocation(JNIEnv* env, const GnssLocation& location) {
    return object.get();
}

static GnssLocation createGnssLocation(
        jint gnssLocationFlags,
        jdouble latitudeDegrees,
        jdouble longitudeDegrees,
        jdouble altitudeMeters,
        jfloat speedMetersPerSec,
        jfloat bearingDegrees,
        jfloat horizontalAccuracyMeters,
        jfloat verticalAccuracyMeters,
        jfloat speedAccuracyMetersPerSecond,
        jfloat bearingAccuracyDegrees,
        jlong timestamp) {
    GnssLocation location;
    location.gnssLocationFlags = static_cast<uint16_t>(gnssLocationFlags);
    location.latitudeDegrees = static_cast<double>(latitudeDegrees);
    location.longitudeDegrees = static_cast<double>(longitudeDegrees);
    location.altitudeMeters = static_cast<double>(altitudeMeters);
    location.speedMetersPerSec = static_cast<float>(speedMetersPerSec);
    location.bearingDegrees = static_cast<float>(bearingDegrees);
    location.horizontalAccuracyMeters = static_cast<float>(horizontalAccuracyMeters);
    location.verticalAccuracyMeters = static_cast<float>(verticalAccuracyMeters);
    location.speedAccuracyMetersPerSecond = static_cast<float>(speedAccuracyMetersPerSecond);
    location.bearingAccuracyDegrees = static_cast<float>(bearingAccuracyDegrees);
    location.timestamp = static_cast<uint64_t>(timestamp);

    return location;
}

/*
 * GnssCallback class implements the callback methods for IGnss interface.
 */
@@ -474,7 +503,9 @@ Return<void> GnssCallback::gnssRequestTimeCb() {
}

Return<void> GnssCallback::gnssRequestLocationCb(const bool independentFromGnss) {
    // TODO(b/72405645): call into java implementation
    JNIEnv* env = getJniEnv();
    env->CallVoidMethod(mCallbacksObj, method_requestLocation, boolToJbool(independentFromGnss));
    checkAndClearExceptionFromCallback(env, __FUNCTION__);
    return Void();
}

@@ -1042,6 +1073,7 @@ static void android_location_GnssLocationProvider_class_init_native(JNIEnv* env,
    method_xtraDownloadRequest = env->GetMethodID(clazz, "xtraDownloadRequest", "()V");
    method_reportNiNotification = env->GetMethodID(clazz, "reportNiNotification",
            "(IIIIILjava/lang/String;Ljava/lang/String;II)V");
    method_requestLocation = env->GetMethodID(clazz, "requestLocation", "(Z)V");
    method_requestRefLocation = env->GetMethodID(clazz, "requestRefLocation", "()V");
    method_requestSetID = env->GetMethodID(clazz, "requestSetID", "(I)V");
    method_requestUtcTime = env->GetMethodID(clazz, "requestUtcTime", "()V");
@@ -1441,6 +1473,42 @@ static void android_location_GnssLocationProvider_inject_time(JNIEnv* /* env */,
    }
}

static void android_location_GnssLocationProvider_inject_best_location(
        JNIEnv*,
        jobject,
        jint gnssLocationFlags,
        jdouble latitudeDegrees,
        jdouble longitudeDegrees,
        jdouble altitudeMeters,
        jfloat speedMetersPerSec,
        jfloat bearingDegrees,
        jfloat horizontalAccuracyMeters,
        jfloat verticalAccuracyMeters,
        jfloat speedAccuracyMetersPerSecond,
        jfloat bearingAccuracyDegrees,
        jlong timestamp) {
    if (gnssHal_V1_1 != nullptr) {
        GnssLocation location = createGnssLocation(
                gnssLocationFlags,
                latitudeDegrees,
                longitudeDegrees,
                altitudeMeters,
                speedMetersPerSec,
                bearingDegrees,
                horizontalAccuracyMeters,
                verticalAccuracyMeters,
                speedAccuracyMetersPerSecond,
                bearingAccuracyDegrees,
                timestamp);
        auto result = gnssHal_V1_1->injectBestLocation(location);
        if (!result.isOk() || !result) {
            ALOGE("%s: Gnss injectBestLocation() failed.", __func__);
        }
    } else {
        ALOGE("%s: injectBestLocation() is called but gnssHal_V1_1 is not available.", __func__);
    }
}

static void android_location_GnssLocationProvider_inject_location(JNIEnv* /* env */,
        jobject /* obj */, jdouble latitude, jdouble longitude, jfloat accuracy) {
    if (gnssHal != nullptr) {
@@ -1996,6 +2064,9 @@ static const JNINativeMethod sMethods[] = {
            android_location_GnssLocationProvider_read_nmea)},
    {"native_inject_time", "(JJI)V", reinterpret_cast<void *>(
            android_location_GnssLocationProvider_inject_time)},
    {"native_inject_best_location",
            "(IDDDFFFFFFJ)V",
            reinterpret_cast<void *>(android_location_GnssLocationProvider_inject_best_location)},
    {"native_inject_location",
            "(DDF)V",
            reinterpret_cast<void *>(android_location_GnssLocationProvider_inject_location)},