Add navigation methods to IGnss AIDL HAL (hardware/interfaces)

Bug: 205185251
Test: atest VtsHalGnssTargetTest
Change-Id: Ib412aeb0b302952d13e236554f00690206b98253
This commit is contained in:
Yu-Han Yang 2021-11-24 16:39:13 -08:00
parent 219d915b22
commit 1afbd5f23e
22 changed files with 1361 additions and 274 deletions

View file

@ -37,8 +37,8 @@ interface IAGnss {
void setCallback(in android.hardware.gnss.IAGnssCallback callback);
void dataConnClosed();
void dataConnFailed();
void setServer(in android.hardware.gnss.IAGnssCallback.AGnssType type, in String hostname, in int port);
void dataConnOpen(in long networkHandle, in String apn, in android.hardware.gnss.IAGnss.ApnIpType apnIpType);
void setServer(in android.hardware.gnss.IAGnssCallback.AGnssType type, in @utf8InCpp String hostname, in int port);
void dataConnOpen(in long networkHandle, in @utf8InCpp String apn, in android.hardware.gnss.IAGnss.ApnIpType apnIpType);
@Backing(type="int") @VintfStability
enum ApnIpType {
INVALID = 0,

View file

@ -46,7 +46,41 @@ interface IGnss {
android.hardware.gnss.IAGnss getExtensionAGnss();
android.hardware.gnss.IGnssDebug getExtensionGnssDebug();
android.hardware.gnss.visibility_control.IGnssVisibilityControl getExtensionGnssVisibilityControl();
void start();
void stop();
void injectTime(in long timeMs, in long timeReferenceMs, in int uncertaintyMs);
void injectLocation(in android.hardware.gnss.GnssLocation location);
void injectBestLocation(in android.hardware.gnss.GnssLocation location);
void deleteAidingData(in android.hardware.gnss.IGnss.GnssAidingData aidingDataFlags);
void setPositionMode(in android.hardware.gnss.IGnss.GnssPositionMode mode, in android.hardware.gnss.IGnss.GnssPositionRecurrence recurrence, in int minIntervalMs, in int preferredAccuracyMeters, in int preferredTimeMs, in boolean lowPowerMode);
const int ERROR_INVALID_ARGUMENT = 1;
const int ERROR_ALREADY_INIT = 2;
const int ERROR_GENERIC = 3;
@Backing(type="int") @VintfStability
enum GnssPositionMode {
STANDALONE = 0,
MS_BASED = 1,
MS_ASSISTED = 2,
}
@Backing(type="int") @VintfStability
enum GnssPositionRecurrence {
RECURRENCE_PERIODIC = 0,
RECURRENCE_SINGLE = 1,
}
@Backing(type="int") @VintfStability
enum GnssAidingData {
DELETE_EPHEMERIS = 1,
DELETE_ALMANAC = 2,
DELETE_POSITION = 4,
DELETE_TIME = 8,
DELETE_IONO = 16,
DELETE_UTC = 32,
DELETE_HEALTH = 64,
DELETE_SVDIR = 128,
DELETE_SVSTEER = 256,
DELETE_SADATA = 512,
DELETE_RTI = 1024,
DELETE_CELLDB_INFO = 32768,
DELETE_ALL = 65535,
}
}

View file

@ -35,8 +35,60 @@ package android.hardware.gnss;
@VintfStability
interface IGnssCallback {
void gnssSetCapabilitiesCb(in int capabilities);
void gnssStatusCb(in android.hardware.gnss.IGnssCallback.GnssStatusValue status);
void gnssSvStatusCb(in android.hardware.gnss.IGnssCallback.GnssSvInfo[] svInfoList);
void gnssLocationCb(in android.hardware.gnss.GnssLocation location);
void gnssNmeaCb(in long timestamp, in @utf8InCpp String nmea);
void gnssAcquireWakelockCb();
void gnssReleaseWakelockCb();
void gnssSetSystemInfoCb(in android.hardware.gnss.IGnssCallback.GnssSystemInfo info);
void gnssRequestTimeCb();
void gnssRequestLocationCb(in boolean independentFromGnss, in boolean isUserEmergency);
const int CAPABILITY_SCHEDULING = 1;
const int CAPABILITY_MSB = 2;
const int CAPABILITY_MSA = 4;
const int CAPABILITY_SINGLE_SHOT = 8;
const int CAPABILITY_ON_DEMAND_TIME = 16;
const int CAPABILITY_GEOFENCING = 32;
const int CAPABILITY_MEASUREMENTS = 64;
const int CAPABILITY_NAV_MESSAGES = 128;
const int CAPABILITY_LOW_POWER_MODE = 256;
const int CAPABILITY_SATELLITE_BLOCKLIST = 512;
const int CAPABILITY_MEASUREMENT_CORRECTIONS = 1024;
const int CAPABILITY_ANTENNA_INFO = 2048;
const int CAPABILITY_CORRELATION_VECTOR = 4096;
const int CAPABILITY_SATELLITE_PVT = 8192;
const int CAPABILITY_MEASUREMENT_CORRECTIONS_FOR_DRIVING = 16384;
@Backing(type="int") @VintfStability
enum GnssStatusValue {
NONE = 0,
SESSION_BEGIN = 1,
SESSION_END = 2,
ENGINE_ON = 3,
ENGINE_OFF = 4,
}
@Backing(type="int") @VintfStability
enum GnssSvFlags {
NONE = 0,
HAS_EPHEMERIS_DATA = 1,
HAS_ALMANAC_DATA = 2,
USED_IN_FIX = 4,
HAS_CARRIER_FREQUENCY = 8,
}
@VintfStability
parcelable GnssSvInfo {
int svid;
android.hardware.gnss.GnssConstellationType constellation;
float cN0Dbhz;
float basebandCN0DbHz;
float elevationDegrees;
float azimuthDegrees;
long carrierFrequencyHz;
int svFlag;
}
@VintfStability
parcelable GnssSystemInfo {
int yearOfHw;
@utf8InCpp String name;
}
}

View file

@ -60,7 +60,7 @@ interface IAGnss {
* @param hostname Hostname of the AGNSS server.
* @param port Port number associated with the server.
*/
void setServer(in AGnssType type, in String hostname, in int port);
void setServer(in AGnssType type, in @utf8InCpp String hostname, in int port);
/**
* Notifies GNSS that a data connection is available and sets the network handle,
@ -75,5 +75,6 @@ interface IAGnss {
* @param apn Access Point Name (follows regular APN naming convention).
* @param apnIpType Specifies IP type of APN.
*/
void dataConnOpen(in long networkHandle, in String apn, in ApnIpType apnIpType);
void dataConnOpen(
in long networkHandle, in @utf8InCpp String apn, in ApnIpType apnIpType);
}

View file

@ -16,6 +16,7 @@
package android.hardware.gnss;
import android.hardware.gnss.GnssLocation;
import android.hardware.gnss.IAGnss;
import android.hardware.gnss.IGnssBatching;
import android.hardware.gnss.IGnssCallback;
@ -45,6 +46,53 @@ interface IGnss {
/** Any other error. */
const int ERROR_GENERIC = 3;
/** Requested operational mode for GNSS operation. */
@VintfStability
@Backing(type="int")
enum GnssPositionMode {
/** Mode for running GNSS standalone (no assistance). */
STANDALONE = 0,
/** AGNSS MS-Based mode. */
MS_BASED = 1,
/**
* AGNSS MS-Assisted mode. This mode is not maintained by the platform anymore.
* It is strongly recommended to use MS_BASED instead.
*/
MS_ASSISTED = 2,
}
/** Requested recurrence mode for GNSS operation. */
@VintfStability
@Backing(type="int")
enum GnssPositionRecurrence {
/** Receive GNSS fixes on a recurring basis at a specified period. */
RECURRENCE_PERIODIC = 0,
/** Request a single shot GNSS fix. */
RECURRENCE_SINGLE = 1,
}
/**
* Flags used to specify which aiding data to delete when calling
* deleteAidingData().
*/
@VintfStability
@Backing(type="int")
enum GnssAidingData {
DELETE_EPHEMERIS = 0x0001,
DELETE_ALMANAC = 0x0002,
DELETE_POSITION = 0x0004,
DELETE_TIME = 0x0008,
DELETE_IONO = 0x0010,
DELETE_UTC = 0x0020,
DELETE_HEALTH = 0x0040,
DELETE_SVDIR = 0x0080,
DELETE_SVSTEER = 0x0100,
DELETE_SADATA = 0x0200,
DELETE_RTI = 0x0400,
DELETE_CELLDB_INFO = 0x8000,
DELETE_ALL = 0xFFFF
}
/**
* Opens the interface and provides the callback routines to the implementation of this
* interface.
@ -152,4 +200,81 @@ interface IGnss {
* @return Handle to the IGnssVisibilityControl.
*/
IGnssVisibilityControl getExtensionGnssVisibilityControl();
/**
* Starts a location output stream using the IGnssCallback gnssLocationCb(), following the
* settings from the most recent call to setPositionMode().
*
* This output must operate independently of any GNSS location batching operations,
* see the IGnssBatching for details.
*/
void start();
/**
* Stops the location output stream.
*/
void stop();
/**
* Injects the current time.
*
* @param timeMs This is the UTC time received from the NTP server, its value is given in
* milliseconds since January 1, 1970.
* @param timeReferenceMs The corresponding value of SystemClock.elapsedRealtime() from the
* device when the NTP response was received in milliseconds.
* @param uncertaintyMs Uncertainty associated with the value represented by time. Represented
* in milliseconds.
*/
void injectTime(in long timeMs, in long timeReferenceMs, in int uncertaintyMs);
/**
* Injects current location from another (typically network) location provider.
*
* @param location Current location from the location provider
*/
void injectLocation(in GnssLocation location);
/**
* Injects current location from the best available location provider.
*
* Unlike injectLocation, this method may inject a recent GNSS location from the HAL
* implementation, if that is the best available location known to the framework.
*
* @param location Location information from the best available location provider.
*/
void injectBestLocation(in GnssLocation location);
/**
* Specifies that the next call to start will not use the information defined in the flags.
* GnssAidingData value of DELETE_ALL is passed for a cold start.
*
* @param aidingDataFlags Flags specifying the aiding data to be deleted.
*/
void deleteAidingData(in GnssAidingData aidingDataFlags);
/**
* Sets the GnssPositionMode parameter, its associated recurrence value, the time between fixes,
* requested fix accuracy, time to first fix.
*
* @param mode Parameter must be one of MS_BASED or STANDALONE. It is allowed by the platform
* (and it is recommended) to fallback to MS_BASED if MS_ASSISTED is passed in, and MS_BASED
* is supported.
* @param recurrence GNSS position recurrence value, either periodic or single.
* @param minIntervalMs Represents the time between fixes in milliseconds.
* @param preferredAccuracyMeters Represents the requested fix accuracy in meters.
* @param preferredTimeMs Represents the requested time to first fix in milliseconds.
* @param lowPowerMode When true, and IGnss is the only client to the GNSS hardware, the GNSS
* hardware must make strong tradeoffs to substantially restrict power use. Specifically, in
* the case of a several second long minIntervalMs, the GNSS hardware must not, on average,
* run power hungry operations like RF and signal searches for more than one second per
* interval, and must make exactly one call to gnssSvStatusCb(), and either zero or one call
* to GnssLocationCb() at each interval. When false, HAL must operate in the nominal mode
* and is expected to make power and performance tradoffs such as duty-cycling when signal
* conditions are good and more active searches to reacquire GNSS signals when no signals
* are present. When there are additional clients using the GNSS hardware other than IGnss,
* the GNSS hardware may operate in a higher power mode, on behalf of those clients.
*/
void setPositionMode(in GnssPositionMode mode, in GnssPositionRecurrence recurrence,
in int minIntervalMs, in int preferredAccuracyMeters, in int preferredTimeMs,
in boolean lowPowerMode);
}

View file

@ -16,6 +16,8 @@
package android.hardware.gnss;
import android.hardware.gnss.GnssConstellationType;
import android.hardware.gnss.GnssLocation;
import android.hardware.gnss.IGnssConfiguration;
import android.hardware.gnss.IGnssPsds;
@ -26,9 +28,48 @@ import android.hardware.gnss.IGnssPsds;
*/
@VintfStability
interface IGnssCallback {
/**
* Capability bit mask indicating that GNSS supports scheduling fixes for RECURRENCE_PERIODIC
* mode.
*
* If this is not set, then the framework will use 1000ms for minInterval and will call start()
* and stop() to schedule the GNSS.
*/
const int CAPABILITY_SCHEDULING = 1 << 0;
/** Capability bit mask indicating that GNSS supports MS-Based AGNSS mode */
const int CAPABILITY_MSB = 1 << 1;
/** Capability bit mask indicating that GNSS supports MS-Assisted AGNSS mode */
const int CAPABILITY_MSA = 1 << 2;
/** Capability bit mask indicating that GNSS supports single-shot fixes */
const int CAPABILITY_SINGLE_SHOT = 1 << 3;
/** Capability bit mask indicating that GNSS supports on demand time injection */
const int CAPABILITY_ON_DEMAND_TIME = 1 << 4;
/** Capability bit mask indicating that GNSS supports Geofencing */
const int CAPABILITY_GEOFENCING = 1 << 5;
/** Capability bit mask indicating that GNSS supports Measurements. */
const int CAPABILITY_MEASUREMENTS = 1 << 6;
/** Capability bit mask indicating that GNSS supports Navigation Messages */
const int CAPABILITY_NAV_MESSAGES = 1 << 7;
/** Capability bit mask indicating that GNSS supports low power mode */
const int CAPABILITY_LOW_POWER_MODE = 1 << 8;
/** Capability bit mask indicating that GNSS supports blocklisting satellites */
const int CAPABILITY_SATELLITE_BLOCKLIST = 1 << 9;
/** Capability bit mask indicating that GNSS supports measurement corrections */
const int CAPABILITY_MEASUREMENT_CORRECTIONS = 1 << 10;
/** Capability bit mask indicating that GNSS supports measurement corrections */
const int CAPABILITY_ANTENNA_INFO = 1 << 11;
/** Capability bit mask indicating that GNSS supports correlation vector */
const int CAPABILITY_CORRELATION_VECTOR = 1 << 12;
@ -44,4 +85,221 @@ interface IGnssCallback {
* @param capabilities Capability parameter is a bit field of the Capability bit masks.
*/
void gnssSetCapabilitiesCb(in int capabilities);
/** GNSS status event values. */
@VintfStability
@Backing(type="int")
enum GnssStatusValue {
/** GNSS status unknown. */
NONE = 0,
/** GNSS has begun navigating. */
SESSION_BEGIN = 1,
/** GNSS has stopped navigating. */
SESSION_END = 2,
/** GNSS has powered on but is not navigating. */
ENGINE_ON = 3,
/** GNSS is powered off. */
ENGINE_OFF = 4
}
/**
* Flags that indicate information about the satellite
*/
@VintfStability
@Backing(type="int")
enum GnssSvFlags {
NONE = 0,
HAS_EPHEMERIS_DATA = 1 << 0,
HAS_ALMANAC_DATA = 1 << 1,
USED_IN_FIX = 1 << 2,
HAS_CARRIER_FREQUENCY = 1 << 3,
}
@VintfStability
parcelable GnssSvInfo {
/**
* Pseudo-random or satellite ID number for the satellite, a.k.a. Space Vehicle (SV), or
* FCN/OSN number for Glonass. The distinction is made by looking at constellation field.
* Values must be in the range of:
*
* - GNSS: 1-32
* - SBAS: 120-151, 183-192
* - GLONASS: 1-24, the orbital slot number (OSN), if known. Or, if not:
* 93-106, the frequency channel number (FCN) (-7 to +6) offset by
* + 100
* i.e. report an FCN of -7 as 93, FCN of 0 as 100, and FCN of +6
* as 106.
* - QZSS: 193-200
* - Galileo: 1-36
* - Beidou: 1-37
* - IRNSS: 1-14
*/
int svid;
/**
* Defines the constellation of the given SV.
*/
GnssConstellationType constellation;
/**
* Carrier-to-noise density in dB-Hz, typically in the range [0, 63].
* It contains the measured C/N0 value for the signal at the antenna port.
*
* This is a mandatory field.
*/
float cN0Dbhz;
/**
* Baseband Carrier-to-noise density in dB-Hz, typically in the range [0, 63]. It contains
* the measured C/N0 value for the signal measured at the baseband.
*
* This is typically a few dB weaker than the value estimated for C/N0 at the antenna port,
* which is reported in cN0DbHz.
*
* If a signal has separate components (e.g. Pilot and Data channels) and the receiver only
* processes one of the components, then the reported basebandCN0DbHz reflects only the
* component that is processed.
*
* This field is mandatory. Like cN0DbHz, it may be reported as 0 for satellites being
* reported that may be searched for, but not yet tracked.
*/
float basebandCN0DbHz;
/** Elevation of SV in degrees. */
float elevationDegrees;
/** Azimuth of SV in degrees. */
float azimuthDegrees;
/**
* Carrier frequency of the signal tracked, for example it can be the
* GPS central frequency for L1 = 1575.45 MHz, or L2 = 1227.60 MHz, L5 =
* 1176.45 MHz, varying GLO channels, etc. If the field is zero, it is
* the primary common use central frequency, e.g. L1 = 1575.45 MHz for
* GPS.
*
* For an L1, L5 receiver tracking a satellite on L1 and L5 at the same
* time, two GnssSvInfo structs must be reported for this same
* satellite, in one of the structs, all the values related
* to L1 must be filled, and in the other all of the values related to
* L5 must be filled.
*
* If the data is available, svFlag must contain HAS_CARRIER_FREQUENCY.
*/
long carrierFrequencyHz;
/** A bit field of the GnssSvFlags. */
int svFlag;
}
/**
* Called to communicate the status of the GNSS engine.
*
* @param status Status information from HAL.
*/
void gnssStatusCb(in GnssStatusValue status);
/**
* Callback for the HAL to pass a vector of GnssSvInfo back to the client.
*
* @param svInfo SV status information from HAL.
*/
void gnssSvStatusCb(in GnssSvInfo[] svInfoList);
/**
* Called when a GNSS location is available.
*
* @param location Location information from HAL.
*/
void gnssLocationCb(in GnssLocation location);
/**
* Callback for reporting NMEA sentences. Called when NMEA data is available.
*
* @param timestamp Marks the instance of reporting.
* @param nmea Follows standard NMEA 0183. Each sentence begins with a '$'
* and ends with a carriage return/line feed sequence and can be no longer
* than 80 characters of visible text (plus the line terminators). The data
* is contained within this single line with data items separated by commas.
* The data itself is just ascii text and may extend over multiple sentences
* in certain specialized instances but is normally fully contained in one
* variable length sentence. The data may vary in the amount of precision
* contained in the message. For example time might be indicated to decimal
* parts of a second or location may be shown with 3 or even 4 digits after
* the decimal point. Programs that read the data must only use the commas
* to determine the field boundaries and not depend on column positions.
* There is a provision for a checksum at the end of each sentence which may
* or may not be checked by the unit that reads the data. The checksum field
* consists of a '*' and two hex digits representing an 8 bit exclusive OR
* of all characters between, but not including, the '$' and '*'.
*/
void gnssNmeaCb(in long timestamp, in @utf8InCpp String nmea);
/**
* Callback utility for acquiring the GNSS wakelock. This can be used to prevent
* the CPU from suspending while handling GNSS events.
*/
void gnssAcquireWakelockCb();
/** Callback utility for releasing the GNSS wakelock. */
void gnssReleaseWakelockCb();
/**
* Provides information about how new the underlying GPS/GNSS hardware and software is.
*/
@VintfStability
parcelable GnssSystemInfo {
/**
* The year in which the last update was made to the underlying hardware/firmware used to
* capture GNSS signals, e.g. 2016.
*/
int yearOfHw;
/**
* The name of the GNSS HAL implementation model and version name.
*
* This is a user-visible string that identifies the model and version of the GNSS HAL.
* For example "ABC Co., Baseband Part 1234, RF Part 567, Software version 3.14.159"
*
* For privacy reasons, this string must not contain any device-specific serial number or
* other identifier that uniquely identifies an individual device.
*/
@utf8InCpp String name;
}
/**
* Callback to inform the framework of the GNSS system information.
*
* This must be called in response to IGnss::setCallback
*
* @param info GnssSystemInfo about the GPS/GNSS hardware.
*/
void gnssSetSystemInfoCb(in GnssSystemInfo info);
/** Callback for requesting NTP time */
void gnssRequestTimeCb();
/**
* Callback for requesting Location.
*
* HAL implementation must call this when it wants the framework to provide locations to assist
* with GNSS HAL operation, for example, to assist with time to first fix, error recovery, or to
* supplement GNSS location for other clients of the GNSS HAL.
*
* If a request is made with independentFromGnss set to true, the framework must avoid
* providing locations derived from GNSS locations (such as "fused" location), to help improve
* information independence for situations such as error recovery.
*
* In response to this method call, GNSS HAL can expect zero, one, or more calls to
* IGnss::injectLocation or IGnss::injectBestLocation, dependent on availability of location
* from other sources, which may happen at some arbitrary delay. Generally speaking, HAL
* implementations must be able to handle calls to IGnss::injectLocation or
* IGnss::injectBestLocation at any time.
*
* @param independentFromGnss True if requesting a location that is independent from GNSS.
* @param isUserEmergency True if the location request is for delivery of this location to an
* emergency services endpoint, during a user-initiated emergency session (e.g.
* during-call to E911, or up to 5 minutes after end-of-call or text to E911).
*/
void gnssRequestLocationCb(in boolean independentFromGnss, in boolean isUserEmergency);
}

View file

@ -17,6 +17,7 @@
#define LOG_TAG "GnssAidl"
#include "Gnss.h"
#include <inttypes.h>
#include <log/log.h>
#include "AGnss.h"
#include "GnssBatching.h"
@ -27,16 +28,24 @@
#include "GnssNavigationMessageInterface.h"
#include "GnssPsds.h"
#include "GnssVisibilityControl.h"
#include "Utils.h"
namespace aidl::android::hardware::gnss {
using ::android::hardware::gnss::common::Utils;
using ndk::ScopedAStatus;
using GnssSvInfo = IGnssCallback::GnssSvInfo;
constexpr int TTFF_MILLIS = 2200;
std::shared_ptr<IGnssCallback> Gnss::sGnssCallback = nullptr;
ndk::ScopedAStatus Gnss::setCallback(const std::shared_ptr<IGnssCallback>& callback) {
ALOGD("Gnss::setCallback");
Gnss::Gnss() : mMinIntervalMs(1000), mFirstFixReceived(false) {}
ScopedAStatus Gnss::setCallback(const std::shared_ptr<IGnssCallback>& callback) {
ALOGD("setCallback");
if (callback == nullptr) {
ALOGE("%s: Null callback ignored", __func__);
return ndk::ScopedAStatus::fromExceptionCode(STATUS_INVALID_OPERATION);
return ScopedAStatus::fromExceptionCode(STATUS_INVALID_OPERATION);
}
sGnssCallback = callback;
@ -50,13 +59,99 @@ ndk::ScopedAStatus Gnss::setCallback(const std::shared_ptr<IGnssCallback>& callb
ALOGE("%s: Unable to invoke callback.gnssSetCapabilities", __func__);
}
return ndk::ScopedAStatus::ok();
return ScopedAStatus::ok();
}
ndk::ScopedAStatus Gnss::close() {
ALOGD("Gnss::close");
ScopedAStatus Gnss::start() {
ALOGD("start()");
if (mIsActive) {
ALOGW("Gnss has started. Restarting...");
stop();
}
mIsActive = true;
this->reportGnssStatusValue(IGnssCallback::GnssStatusValue::SESSION_BEGIN);
mThread = std::thread([this]() {
auto svStatus = filterBlocklistedSatellites(Utils::getMockSvInfoList());
this->reportSvStatus(svStatus);
if (!mFirstFixReceived) {
std::this_thread::sleep_for(std::chrono::milliseconds(TTFF_MILLIS));
mFirstFixReceived = true;
}
while (mIsActive == true) {
auto svStatus = filterBlocklistedSatellites(Utils::getMockSvInfoList());
this->reportSvStatus(svStatus);
mGnssPowerIndication->notePowerConsumption();
const auto location = Utils::getMockLocation();
this->reportLocation(location);
std::this_thread::sleep_for(std::chrono::milliseconds(mMinIntervalMs));
}
});
return ScopedAStatus::ok();
}
void Gnss::reportLocation(const GnssLocation& location) const {
std::unique_lock<std::mutex> lock(mMutex);
if (sGnssCallback == nullptr) {
ALOGE("%s: GnssCallback is null.", __func__);
return;
}
auto status = sGnssCallback->gnssLocationCb(location);
if (!status.isOk()) {
ALOGE("%s: Unable to invoke gnssLocationCb", __func__);
}
return;
}
void Gnss::reportSvStatus(const std::vector<GnssSvInfo>& svInfoList) const {
std::unique_lock<std::mutex> lock(mMutex);
if (sGnssCallback == nullptr) {
ALOGE("%s: sGnssCallback is null.", __func__);
return;
}
auto status = sGnssCallback->gnssSvStatusCb(svInfoList);
if (!status.isOk()) {
ALOGE("%s: Unable to invoke callback", __func__);
}
}
std::vector<GnssSvInfo> Gnss::filterBlocklistedSatellites(std::vector<GnssSvInfo> gnssSvInfoList) {
ALOGD("filterBlocklistedSatellites");
for (uint32_t i = 0; i < gnssSvInfoList.size(); i++) {
if (mGnssConfiguration->isBlocklisted(gnssSvInfoList[i])) {
gnssSvInfoList[i].svFlag &= ~(uint32_t)IGnssCallback::GnssSvFlags::USED_IN_FIX;
}
}
return gnssSvInfoList;
}
void Gnss::reportGnssStatusValue(const IGnssCallback::GnssStatusValue gnssStatusValue) const {
std::unique_lock<std::mutex> lock(mMutex);
if (sGnssCallback == nullptr) {
ALOGE("%s: sGnssCallback is null.", __func__);
return;
}
auto status = sGnssCallback->gnssStatusCb(gnssStatusValue);
if (!status.isOk()) {
ALOGE("%s: Unable to invoke gnssStatusCb", __func__);
}
}
ScopedAStatus Gnss::stop() {
ALOGD("stop");
mIsActive = false;
this->reportGnssStatusValue(IGnssCallback::GnssStatusValue::SESSION_END);
if (mThread.joinable()) {
mThread.join();
}
return ScopedAStatus::ok();
}
ScopedAStatus Gnss::close() {
ALOGD("close");
sGnssCallback = nullptr;
return ndk::ScopedAStatus::ok();
return ScopedAStatus::ok();
}
ndk::ScopedAStatus Gnss::getExtensionAGnss(std::shared_ptr<IAGnss>* iAGnss) {
@ -65,61 +160,93 @@ ndk::ScopedAStatus Gnss::getExtensionAGnss(std::shared_ptr<IAGnss>* iAGnss) {
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus Gnss::getExtensionPsds(std::shared_ptr<IGnssPsds>* iGnssPsds) {
ALOGD("Gnss::getExtensionPsds");
*iGnssPsds = SharedRefBase::make<GnssPsds>();
return ndk::ScopedAStatus::ok();
ScopedAStatus Gnss::injectTime(int64_t timeMs, int64_t timeReferenceMs, int uncertaintyMs) {
ALOGD("injectTime. timeMs:%" PRId64 ", timeReferenceMs:%" PRId64 ", uncertaintyMs:%d", timeMs,
timeReferenceMs, uncertaintyMs);
return ScopedAStatus::ok();
}
ndk::ScopedAStatus Gnss::getExtensionGnssConfiguration(
ScopedAStatus Gnss::injectLocation(const GnssLocation& location) {
ALOGD("injectLocation. lat:%lf, lng:%lf, acc:%f", location.latitudeDegrees,
location.longitudeDegrees, location.horizontalAccuracyMeters);
return ScopedAStatus::ok();
}
ScopedAStatus Gnss::injectBestLocation(const GnssLocation& location) {
ALOGD("injectBestLocation. lat:%lf, lng:%lf, acc:%f", location.latitudeDegrees,
location.longitudeDegrees, location.horizontalAccuracyMeters);
return ScopedAStatus::ok();
}
ScopedAStatus Gnss::deleteAidingData(GnssAidingData aidingDataFlags) {
ALOGD("deleteAidingData. flags:%d", (int)aidingDataFlags);
mFirstFixReceived = false;
return ScopedAStatus::ok();
}
ScopedAStatus Gnss::setPositionMode(GnssPositionMode, GnssPositionRecurrence, int minIntervalMs,
int /* preferredAccuracyMeters */, int /* preferredTimeMs */,
bool lowPowerMode) {
ALOGD("setPositionMode. minIntervalMs:%d, lowPowerMode:%d", minIntervalMs, (int)lowPowerMode);
mMinIntervalMs = minIntervalMs;
return ScopedAStatus::ok();
}
ScopedAStatus Gnss::getExtensionPsds(std::shared_ptr<IGnssPsds>* iGnssPsds) {
ALOGD("getExtensionPsds");
*iGnssPsds = SharedRefBase::make<GnssPsds>();
return ScopedAStatus::ok();
}
ScopedAStatus Gnss::getExtensionGnssConfiguration(
std::shared_ptr<IGnssConfiguration>* iGnssConfiguration) {
ALOGD("Gnss::getExtensionGnssConfiguration");
ALOGD("getExtensionGnssConfiguration");
if (mGnssConfiguration == nullptr) {
mGnssConfiguration = SharedRefBase::make<GnssConfiguration>();
}
*iGnssConfiguration = mGnssConfiguration;
return ndk::ScopedAStatus::ok();
return ScopedAStatus::ok();
}
ndk::ScopedAStatus Gnss::getExtensionGnssPowerIndication(
ScopedAStatus Gnss::getExtensionGnssPowerIndication(
std::shared_ptr<IGnssPowerIndication>* iGnssPowerIndication) {
ALOGD("Gnss::getExtensionGnssPowerIndication");
ALOGD("getExtensionGnssPowerIndication");
if (mGnssPowerIndication == nullptr) {
mGnssPowerIndication = SharedRefBase::make<GnssPowerIndication>();
}
*iGnssPowerIndication = mGnssPowerIndication;
return ndk::ScopedAStatus::ok();
return ScopedAStatus::ok();
}
ndk::ScopedAStatus Gnss::getExtensionGnssMeasurement(
ScopedAStatus Gnss::getExtensionGnssMeasurement(
std::shared_ptr<IGnssMeasurementInterface>* iGnssMeasurement) {
ALOGD("Gnss::getExtensionGnssMeasurement");
ALOGD("getExtensionGnssMeasurement");
*iGnssMeasurement = SharedRefBase::make<GnssMeasurementInterface>();
return ndk::ScopedAStatus::ok();
return ScopedAStatus::ok();
}
ndk::ScopedAStatus Gnss::getExtensionGnssBatching(std::shared_ptr<IGnssBatching>* iGnssBatching) {
ALOGD("Gnss::getExtensionGnssBatching");
ScopedAStatus Gnss::getExtensionGnssBatching(std::shared_ptr<IGnssBatching>* iGnssBatching) {
ALOGD("getExtensionGnssBatching");
*iGnssBatching = SharedRefBase::make<GnssBatching>();
return ndk::ScopedAStatus::ok();
return ScopedAStatus::ok();
}
ndk::ScopedAStatus Gnss::getExtensionGnssGeofence(std::shared_ptr<IGnssGeofence>* iGnssGeofence) {
ALOGD("Gnss::getExtensionGnssGeofence");
ScopedAStatus Gnss::getExtensionGnssGeofence(std::shared_ptr<IGnssGeofence>* iGnssGeofence) {
ALOGD("getExtensionGnssGeofence");
*iGnssGeofence = SharedRefBase::make<GnssGeofence>();
return ndk::ScopedAStatus::ok();
return ScopedAStatus::ok();
}
ndk::ScopedAStatus Gnss::getExtensionGnssNavigationMessage(
ScopedAStatus Gnss::getExtensionGnssNavigationMessage(
std::shared_ptr<IGnssNavigationMessageInterface>* iGnssNavigationMessage) {
ALOGD("Gnss::getExtensionGnssNavigationMessage");
ALOGD("getExtensionGnssNavigationMessage");
*iGnssNavigationMessage = SharedRefBase::make<GnssNavigationMessageInterface>();
return ndk::ScopedAStatus::ok();
return ScopedAStatus::ok();
}
ndk::ScopedAStatus Gnss::getExtensionGnssDebug(std::shared_ptr<IGnssDebug>* iGnssDebug) {

View file

@ -25,6 +25,9 @@
#include <aidl/android/hardware/gnss/BnGnssPowerIndication.h>
#include <aidl/android/hardware/gnss/BnGnssPsds.h>
#include <aidl/android/hardware/gnss/visibility_control/BnGnssVisibilityControl.h>
#include <atomic>
#include <mutex>
#include <thread>
#include "GnssConfiguration.h"
#include "GnssPowerIndication.h"
@ -32,8 +35,22 @@ namespace aidl::android::hardware::gnss {
class Gnss : public BnGnss {
public:
Gnss();
~Gnss() { stop(); };
ndk::ScopedAStatus setCallback(const std::shared_ptr<IGnssCallback>& callback) override;
ndk::ScopedAStatus start() override;
ndk::ScopedAStatus stop() override;
ndk::ScopedAStatus close() override;
ndk::ScopedAStatus injectTime(int64_t timeMs, int64_t timeReferenceMs,
int uncertaintyMs) override;
ndk::ScopedAStatus injectLocation(const GnssLocation& location) override;
ndk::ScopedAStatus injectBestLocation(const GnssLocation& location) override;
ndk::ScopedAStatus deleteAidingData(GnssAidingData aidingDataFlags) override;
ndk::ScopedAStatus setPositionMode(GnssPositionMode mode, GnssPositionRecurrence recurrence,
int minIntervalMs, int preferredAccuracyMeters,
int preferredTimeMs, bool lowPowerMode) override;
ndk::ScopedAStatus getExtensionPsds(std::shared_ptr<IGnssPsds>* iGnssPsds) override;
ndk::ScopedAStatus getExtensionGnssConfiguration(
std::shared_ptr<IGnssConfiguration>* iGnssConfiguration) override;
@ -57,7 +74,20 @@ class Gnss : public BnGnss {
std::shared_ptr<GnssPowerIndication> mGnssPowerIndication;
private:
void reportLocation(const GnssLocation&) const;
void reportSvStatus(const std::vector<IGnssCallback::GnssSvInfo>& svInfoList) const;
std::vector<IGnssCallback::GnssSvInfo> filterBlocklistedSatellites(
std::vector<IGnssCallback::GnssSvInfo> gnssSvInfoList);
void reportGnssStatusValue(const IGnssCallback::GnssStatusValue gnssStatusValue) const;
static std::shared_ptr<IGnssCallback> sGnssCallback;
std::atomic<long> mMinIntervalMs;
std::atomic<bool> mIsActive;
std::atomic<bool> mFirstFixReceived;
std::thread mThread;
mutable std::mutex mMutex;
};
} // namespace aidl::android::hardware::gnss

View file

@ -49,4 +49,14 @@ bool GnssConfiguration::isBlocklistedV2_1(const GnssSvInfoV2_1& gnssSvInfo) cons
return (mBlocklistedSourceSet.find(source) != mBlocklistedSourceSet.end());
}
bool GnssConfiguration::isBlocklisted(const IGnssCallback::GnssSvInfo& gnssSvInfo) const {
std::unique_lock<std::recursive_mutex> lock(mMutex);
if (mBlocklistedConstellationSet.find(gnssSvInfo.constellation) !=
mBlocklistedConstellationSet.end()) {
return true;
}
BlocklistedSource source = {.constellation = gnssSvInfo.constellation, .svid = gnssSvInfo.svid};
return (mBlocklistedSourceSet.find(source) != mBlocklistedSourceSet.end());
}
} // namespace aidl::android::hardware::gnss

View file

@ -16,6 +16,7 @@
#pragma once
#include <aidl/android/hardware/gnss/BnGnssCallback.h>
#include <aidl/android/hardware/gnss/BnGnssConfiguration.h>
#include <android/hardware/gnss/2.1/IGnssCallback.h>
#include <mutex>
@ -62,6 +63,7 @@ struct GnssConfiguration : public BnGnssConfiguration {
ndk::ScopedAStatus setBlocklist(const vector<BlocklistedSource>& blocklist) override;
bool isBlocklistedV2_1(const GnssSvInfoV2_1& gnssSvInfo) const;
bool isBlocklisted(const IGnssCallback::GnssSvInfo& gnssSvInfo) const;
private:
BlocklistedSourceSet mBlocklistedSourceSet;

View file

@ -14,6 +14,8 @@
* limitations under the License.
*/
#define LOG_TAG "GnssBatchingCallbackAidl"
#include "GnssBatchingCallback.h"
#include <inttypes.h>
#include <log/log.h>

View file

@ -14,11 +14,62 @@
* limitations under the License.
*/
#define LOG_TAG "GnssCallbackAidl"
#include "GnssCallbackAidl.h"
#include <log/log.h>
android::binder::Status GnssCallbackAidl::gnssSetCapabilitiesCb(const int capabilities) {
ALOGI("Capabilities received %d", capabilities);
using android::binder::Status;
using android::hardware::gnss::GnssLocation;
using GnssSvInfo = android::hardware::gnss::IGnssCallback::GnssSvInfo;
using GnssSystemInfo = android::hardware::gnss::IGnssCallback::GnssSystemInfo;
Status GnssCallbackAidl::gnssSetCapabilitiesCb(const int capabilities) {
ALOGI("Capabilities received %#08x", capabilities);
capabilities_cbq_.store(capabilities);
return android::binder::Status::ok();
return Status::ok();
}
Status GnssCallbackAidl::gnssStatusCb(const GnssStatusValue /* status */) {
ALOGI("gnssSvStatusCb");
return Status::ok();
}
Status GnssCallbackAidl::gnssSvStatusCb(const std::vector<GnssSvInfo>& svInfoList) {
ALOGI("gnssSvStatusCb. Size = %d", (int)svInfoList.size());
sv_info_list_cbq_.store(svInfoList);
return Status::ok();
}
Status GnssCallbackAidl::gnssLocationCb(const GnssLocation& location) {
ALOGI("Location received");
location_cbq_.store(location);
return Status::ok();
}
Status GnssCallbackAidl::gnssNmeaCb(const int64_t /* timestamp */, const std::string& /* nmea */) {
return Status::ok();
}
Status GnssCallbackAidl::gnssAcquireWakelockCb() {
return Status::ok();
}
Status GnssCallbackAidl::gnssReleaseWakelockCb() {
return Status::ok();
}
Status GnssCallbackAidl::gnssSetSystemInfoCb(const GnssSystemInfo& info) {
ALOGI("gnssSetSystemInfoCb, year=%d, name=%s", info.yearOfHw, info.name.c_str());
info_cbq_.store(info);
return Status::ok();
}
Status GnssCallbackAidl::gnssRequestTimeCb() {
return Status::ok();
}
Status GnssCallbackAidl::gnssRequestLocationCb(const bool /* independentFromGnss */,
const bool /* isUserEmergency */) {
return Status::ok();
}

View file

@ -22,11 +22,37 @@
/* Callback class for data & Event. */
class GnssCallbackAidl : public android::hardware::gnss::BnGnssCallback {
public:
GnssCallbackAidl() : capabilities_cbq_("capabilities"){};
GnssCallbackAidl()
: capabilities_cbq_("capabilities"),
info_cbq_("system_info"),
location_cbq_("location"),
sv_info_list_cbq_("sv_info"){};
~GnssCallbackAidl(){};
android::binder::Status gnssSetCapabilitiesCb(const int capabilities) override;
android::binder::Status gnssStatusCb(const GnssStatusValue status) override;
android::binder::Status gnssSvStatusCb(const std::vector<GnssSvInfo>& svInfoList) override;
android::binder::Status gnssLocationCb(
const android::hardware::gnss::GnssLocation& location) override;
android::binder::Status gnssNmeaCb(const int64_t timestamp, const std::string& nmea) override;
android::binder::Status gnssAcquireWakelockCb() override;
android::binder::Status gnssReleaseWakelockCb() override;
android::binder::Status gnssSetSystemInfoCb(const GnssSystemInfo& info) override;
android::binder::Status gnssRequestTimeCb() override;
android::binder::Status gnssRequestLocationCb(const bool independentFromGnss,
const bool isUserEmergency) override;
int last_capabilities_;
android::hardware::gnss::IGnssCallback::GnssSystemInfo last_info_;
android::hardware::gnss::GnssLocation last_location_;
android::hardware::gnss::common::GnssCallbackEventQueue<int> capabilities_cbq_;
android::hardware::gnss::common::GnssCallbackEventQueue<
android::hardware::gnss::IGnssCallback::GnssSystemInfo>
info_cbq_;
android::hardware::gnss::common::GnssCallbackEventQueue<android::hardware::gnss::GnssLocation>
location_cbq_;
android::hardware::gnss::common::GnssCallbackEventQueue<
std::vector<android::hardware::gnss::IGnssCallback::GnssSvInfo>>
sv_info_list_cbq_;
};

View file

@ -14,20 +14,31 @@
* limitations under the License.
*/
#define LOG_TAG "GnssHalTest"
#include "gnss_hal_test.h"
#include <hidl/ServiceManagement.h>
#include "Utils.h"
using GnssConstellationTypeAidl = android::hardware::gnss::GnssConstellationType;
using android::hardware::gnss::GnssConstellationType;
using android::hardware::gnss::GnssLocation;
using android::hardware::gnss::IGnss;
using android::hardware::gnss::IGnssCallback;
using android::hardware::gnss::common::Utils;
using GnssConstellationTypeV2_0 = android::hardware::gnss::V2_0::GnssConstellationType;
void GnssHalTest::SetUp() {
// Get AIDL handle
aidl_gnss_hal_ = android::waitForDeclaredService<IGnssAidl>(String16(GetParam().c_str()));
ASSERT_NE(aidl_gnss_hal_, nullptr);
ALOGD("AIDL Interface Version = %d", aidl_gnss_hal_->getInterfaceVersion());
const auto& hidlInstanceNames = android::hardware::getAllHalInstanceNames(
android::hardware::gnss::V2_1::IGnss::descriptor);
gnss_hal_ = IGnss_V2_1::getService(hidlInstanceNames[0]);
ASSERT_NE(gnss_hal_, nullptr);
if (aidl_gnss_hal_->getInterfaceVersion() == 1) {
const auto& hidlInstanceNames = android::hardware::getAllHalInstanceNames(
android::hardware::gnss::V2_1::IGnss::descriptor);
gnss_hal_ = IGnss_V2_1::getService(hidlInstanceNames[0]);
ASSERT_NE(gnss_hal_, nullptr);
}
SetUpGnssCallback();
}
@ -40,7 +51,6 @@ void GnssHalTest::SetUpGnssCallback() {
if (!status.isOk()) {
ALOGE("Failed to setCallback");
}
ASSERT_TRUE(status.isOk());
/*
@ -48,9 +58,243 @@ void GnssHalTest::SetUpGnssCallback() {
*/
EXPECT_TRUE(aidl_gnss_cb_->capabilities_cbq_.retrieve(aidl_gnss_cb_->last_capabilities_,
TIMEOUT_SEC));
EXPECT_EQ(aidl_gnss_cb_->capabilities_cbq_.calledCount(), 1);
// Invoke the super method.
GnssHalTestTemplate<IGnss_V2_1>::SetUpGnssCallback();
if (aidl_gnss_hal_->getInterfaceVersion() == 1) {
// Invoke the super method.
GnssHalTestTemplate<IGnss_V2_1>::SetUpGnssCallback();
}
}
void GnssHalTest::CheckLocation(const GnssLocation& location, bool check_speed) {
Utils::checkLocation(location, check_speed, /* check_more_accuracies= */ true);
}
void GnssHalTest::SetPositionMode(const int min_interval_msec, const bool low_power_mode) {
if (aidl_gnss_hal_->getInterfaceVersion() == 1) {
// Invoke the super method.
return GnssHalTestTemplate<IGnss_V2_1>::SetPositionMode(min_interval_msec, low_power_mode);
}
const int kPreferredAccuracy = 0; // Ideally perfect (matches GnssLocationProvider)
const int kPreferredTimeMsec = 0; // Ideally immediate
auto status = aidl_gnss_hal_->setPositionMode(
IGnss::GnssPositionMode::MS_BASED, IGnss::GnssPositionRecurrence::RECURRENCE_PERIODIC,
min_interval_msec, kPreferredAccuracy, kPreferredTimeMsec, low_power_mode);
ASSERT_TRUE(status.isOk());
}
bool GnssHalTest::StartAndCheckFirstLocation(const int min_interval_msec,
const bool low_power_mode) {
if (aidl_gnss_hal_->getInterfaceVersion() == 1) {
// Invoke the super method.
return GnssHalTestTemplate<IGnss_V2_1>::StartAndCheckFirstLocation(min_interval_msec,
low_power_mode);
}
SetPositionMode(min_interval_msec, low_power_mode);
auto result = aidl_gnss_hal_->start();
EXPECT_TRUE(result.isOk());
/*
* GnssLocationProvider support of AGPS SUPL & XtraDownloader is not available in VTS,
* so allow time to demodulate ephemeris over the air.
*/
const int kFirstGnssLocationTimeoutSeconds = 75;
EXPECT_TRUE(aidl_gnss_cb_->location_cbq_.retrieve(aidl_gnss_cb_->last_location_,
kFirstGnssLocationTimeoutSeconds));
int locationCalledCount = aidl_gnss_cb_->location_cbq_.calledCount();
EXPECT_EQ(locationCalledCount, 1);
if (locationCalledCount > 0) {
// don't require speed on first fix
CheckLocation(aidl_gnss_cb_->last_location_, false);
return true;
}
return false;
}
void GnssHalTest::StopAndClearLocations() {
ALOGD("StopAndClearLocations");
if (aidl_gnss_hal_->getInterfaceVersion() == 1) {
// Invoke the super method.
return GnssHalTestTemplate<IGnss_V2_1>::StopAndClearLocations();
}
auto status = aidl_gnss_hal_->stop();
EXPECT_TRUE(status.isOk());
/*
* Clear notify/waiting counter, allowing up till the timeout after
* the last reply for final startup messages to arrive (esp. system
* info.)
*/
while (aidl_gnss_cb_->location_cbq_.retrieve(aidl_gnss_cb_->last_location_, TIMEOUT_SEC)) {
}
aidl_gnss_cb_->location_cbq_.reset();
}
void GnssHalTest::StartAndCheckLocations(int count) {
if (aidl_gnss_hal_->getInterfaceVersion() == 1) {
// Invoke the super method.
return GnssHalTestTemplate<IGnss_V2_1>::StartAndCheckLocations(count);
}
const int kMinIntervalMsec = 500;
const int kLocationTimeoutSubsequentSec = 2;
const bool kLowPowerMode = false;
EXPECT_TRUE(StartAndCheckFirstLocation(kMinIntervalMsec, kLowPowerMode));
for (int i = 1; i < count; i++) {
EXPECT_TRUE(aidl_gnss_cb_->location_cbq_.retrieve(aidl_gnss_cb_->last_location_,
kLocationTimeoutSubsequentSec));
int locationCalledCount = aidl_gnss_cb_->location_cbq_.calledCount();
EXPECT_EQ(locationCalledCount, i + 1);
// Don't cause confusion by checking details if no location yet
if (locationCalledCount > 0) {
// Should be more than 1 location by now, but if not, still don't check first fix speed
CheckLocation(aidl_gnss_cb_->last_location_, locationCalledCount > 1);
}
}
}
std::list<std::vector<IGnssCallback::GnssSvInfo>> GnssHalTest::convertToAidl(
const std::list<hidl_vec<IGnssCallback_2_1::GnssSvInfo>>& sv_info_list) {
std::list<std::vector<IGnssCallback::GnssSvInfo>> aidl_sv_info_list;
for (const auto& sv_info_vec : sv_info_list) {
std::vector<IGnssCallback::GnssSvInfo> aidl_sv_info_vec;
for (const auto& sv_info : sv_info_vec) {
IGnssCallback::GnssSvInfo aidl_sv_info;
aidl_sv_info.svid = sv_info.v2_0.v1_0.svid;
aidl_sv_info.constellation =
static_cast<GnssConstellationType>(sv_info.v2_0.constellation);
aidl_sv_info.cN0Dbhz = sv_info.v2_0.v1_0.cN0Dbhz;
aidl_sv_info.basebandCN0DbHz = sv_info.basebandCN0DbHz;
aidl_sv_info.elevationDegrees = sv_info.v2_0.v1_0.elevationDegrees;
aidl_sv_info.azimuthDegrees = sv_info.v2_0.v1_0.azimuthDegrees;
aidl_sv_info.carrierFrequencyHz = (int64_t)sv_info.v2_0.v1_0.carrierFrequencyHz;
aidl_sv_info.svFlag = (int)sv_info.v2_0.v1_0.svFlag;
aidl_sv_info_vec.push_back(aidl_sv_info);
}
aidl_sv_info_list.push_back(aidl_sv_info_vec);
}
return aidl_sv_info_list;
}
/*
* FindStrongFrequentNonGpsSource:
*
* Search through a GnssSvStatus list for the strongest non-GPS satellite observed enough times
*
* returns the strongest source,
* or a source with constellation == UNKNOWN if none are found sufficient times
*/
BlocklistedSource GnssHalTest::FindStrongFrequentNonGpsSource(
const std::list<hidl_vec<IGnssCallback_2_1::GnssSvInfo>> sv_info_list,
const int min_observations) {
return FindStrongFrequentNonGpsSource(convertToAidl(sv_info_list), min_observations);
}
BlocklistedSource GnssHalTest::FindStrongFrequentNonGpsSource(
const std::list<std::vector<IGnssCallback::GnssSvInfo>> sv_info_list,
const int min_observations) {
std::map<ComparableBlocklistedSource, SignalCounts> mapSignals;
for (const auto& sv_info_vec : sv_info_list) {
for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) {
const auto& gnss_sv = sv_info_vec[iSv];
if ((gnss_sv.svFlag & (int)IGnssCallback::GnssSvFlags::USED_IN_FIX) &&
(gnss_sv.constellation != GnssConstellationType::GPS)) {
ComparableBlocklistedSource source;
source.id.svid = gnss_sv.svid;
source.id.constellation = gnss_sv.constellation;
const auto& itSignal = mapSignals.find(source);
if (itSignal == mapSignals.end()) {
SignalCounts counts;
counts.observations = 1;
counts.max_cn0_dbhz = gnss_sv.cN0Dbhz;
mapSignals.insert(
std::pair<ComparableBlocklistedSource, SignalCounts>(source, counts));
} else {
itSignal->second.observations++;
if (itSignal->second.max_cn0_dbhz < gnss_sv.cN0Dbhz) {
itSignal->second.max_cn0_dbhz = gnss_sv.cN0Dbhz;
}
}
}
}
}
float max_cn0_dbhz_with_sufficient_count = 0.;
int total_observation_count = 0;
int blocklisted_source_count_observation = 0;
ComparableBlocklistedSource source_to_blocklist; // initializes to zero = UNKNOWN constellation
for (auto const& pairSignal : mapSignals) {
total_observation_count += pairSignal.second.observations;
if ((pairSignal.second.observations >= min_observations) &&
(pairSignal.second.max_cn0_dbhz > max_cn0_dbhz_with_sufficient_count)) {
source_to_blocklist = pairSignal.first;
blocklisted_source_count_observation = pairSignal.second.observations;
max_cn0_dbhz_with_sufficient_count = pairSignal.second.max_cn0_dbhz;
}
}
ALOGD("Among %d observations, chose svid %d, constellation %d, "
"with %d observations at %.1f max CNo",
total_observation_count, source_to_blocklist.id.svid,
(int)source_to_blocklist.id.constellation, blocklisted_source_count_observation,
max_cn0_dbhz_with_sufficient_count);
return source_to_blocklist.id;
}
GnssConstellationType GnssHalTest::startLocationAndGetNonGpsConstellation(
const int locations_to_await, const int gnss_sv_info_list_timeout) {
if (aidl_gnss_hal_->getInterfaceVersion() == 1) {
return static_cast<GnssConstellationType>(
GnssHalTestTemplate<IGnss_V2_1>::startLocationAndGetNonGpsConstellation(
locations_to_await, gnss_sv_info_list_timeout));
}
aidl_gnss_cb_->location_cbq_.reset();
StartAndCheckLocations(locations_to_await);
const int location_called_count = aidl_gnss_cb_->location_cbq_.calledCount();
// Tolerate 1 less sv status to handle edge cases in reporting.
int sv_info_list_cbq_size = aidl_gnss_cb_->sv_info_list_cbq_.size();
EXPECT_GE(sv_info_list_cbq_size + 1, locations_to_await);
ALOGD("Observed %d GnssSvInfo, while awaiting %d Locations (%d received)",
sv_info_list_cbq_size, locations_to_await, location_called_count);
// Find first non-GPS constellation to blocklist
GnssConstellationType constellation_to_blocklist = GnssConstellationType::UNKNOWN;
for (int i = 0; i < sv_info_list_cbq_size; ++i) {
std::vector<IGnssCallback::GnssSvInfo> sv_info_vec;
aidl_gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, gnss_sv_info_list_timeout);
for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) {
auto& gnss_sv = sv_info_vec[iSv];
if ((gnss_sv.svFlag & (uint32_t)IGnssCallback::GnssSvFlags::USED_IN_FIX) &&
(gnss_sv.constellation != GnssConstellationType::UNKNOWN) &&
(gnss_sv.constellation != GnssConstellationType::GPS)) {
// found a non-GPS constellation
constellation_to_blocklist = gnss_sv.constellation;
break;
}
}
if (constellation_to_blocklist != GnssConstellationType::UNKNOWN) {
break;
}
}
if (constellation_to_blocklist == GnssConstellationType::UNKNOWN) {
ALOGI("No non-GPS constellations found, constellation blocklist test less effective.");
// Proceed functionally to blocklist something.
constellation_to_blocklist = GnssConstellationType::GLONASS;
}
return constellation_to_blocklist;
}

View file

@ -41,9 +41,50 @@ class GnssHalTest : public android::hardware::gnss::common::GnssHalTestTemplate<
public:
GnssHalTest(){};
~GnssHalTest(){};
struct ComparableBlocklistedSource {
android::hardware::gnss::BlocklistedSource id;
ComparableBlocklistedSource() {
id.constellation = android::hardware::gnss::GnssConstellationType::UNKNOWN;
id.svid = 0;
}
bool operator<(const ComparableBlocklistedSource& compare) const {
return ((id.svid < compare.id.svid) || ((id.svid == compare.id.svid) &&
(id.constellation < compare.id.constellation)));
}
};
struct SignalCounts {
int observations;
float max_cn0_dbhz;
};
virtual void SetUp() override;
virtual void SetUpGnssCallback() override;
void CheckLocation(const android::hardware::gnss::GnssLocation& location,
const bool check_speed);
void SetPositionMode(const int min_interval_msec, const bool low_power_mode);
bool StartAndCheckFirstLocation(const int min_interval_msec, const bool low_power_mode);
void StopAndClearLocations();
void StartAndCheckLocations(int count);
android::hardware::gnss::GnssConstellationType startLocationAndGetNonGpsConstellation(
const int locations_to_await, const int gnss_sv_info_list_timeout);
std::list<std::vector<android::hardware::gnss::IGnssCallback::GnssSvInfo>> convertToAidl(
const std::list<hidl_vec<android::hardware::gnss::V2_1::IGnssCallback::GnssSvInfo>>&
sv_info_list);
android::hardware::gnss::BlocklistedSource FindStrongFrequentNonGpsSource(
const std::list<hidl_vec<android::hardware::gnss::V2_1::IGnssCallback::GnssSvInfo>>
sv_info_list,
const int min_observations);
android::hardware::gnss::BlocklistedSource FindStrongFrequentNonGpsSource(
const std::list<std::vector<android::hardware::gnss::IGnssCallback::GnssSvInfo>>
sv_info_list,
const int min_observations);
sp<IGnssAidl> aidl_gnss_hal_;
sp<GnssCallbackAidl> aidl_gnss_cb_; // Primary callback interface
};

View file

@ -46,6 +46,7 @@ using android::hardware::gnss::IAGnss;
using android::hardware::gnss::IGnss;
using android::hardware::gnss::IGnssBatching;
using android::hardware::gnss::IGnssBatchingCallback;
using android::hardware::gnss::IGnssCallback;
using android::hardware::gnss::IGnssConfiguration;
using android::hardware::gnss::IGnssDebug;
using android::hardware::gnss::IGnssGeofence;
@ -59,6 +60,7 @@ using android::hardware::gnss::PsdsType;
using android::hardware::gnss::SatellitePvt;
using android::hardware::gnss::visibility_control::IGnssVisibilityControl;
using GnssConstellationTypeV2_0 = android::hardware::gnss::V2_0::GnssConstellationType;
using GnssConstellationTypeAidl = android::hardware::gnss::GnssConstellationType;
static bool IsAutomotiveDevice() {
@ -324,7 +326,11 @@ TEST_P(GnssHalTest, TestGnssPowerIndication) {
auto powerStats1 = gnssPowerIndicationCallback->last_gnss_power_stats_;
// Get a location and request another GnssPowerStats
gnss_cb_->location_cbq_.reset();
if (aidl_gnss_hal_->getInterfaceVersion() == 1) {
gnss_cb_->location_cbq_.reset();
} else {
aidl_gnss_cb_->location_cbq_.reset();
}
StartAndCheckFirstLocation(/* min_interval_msec= */ 1000, /* low_power_mode= */ false);
// Request and verify the 2nd GnssPowerStats has larger values than the 1st one
@ -374,88 +380,6 @@ TEST_P(GnssHalTest, TestGnssPowerIndication) {
StopAndClearLocations();
}
/*
* FindStrongFrequentNonGpsSource:
*
* Search through a GnssSvStatus list for the strongest non-GPS satellite observed enough times
*
* returns the strongest source,
* or a source with constellation == UNKNOWN if none are found sufficient times
*/
BlocklistedSource FindStrongFrequentNonGpsSource(
const std::list<hidl_vec<IGnssCallback_2_1::GnssSvInfo>> sv_info_list,
const int min_observations) {
struct ComparableBlocklistedSource {
BlocklistedSource id;
ComparableBlocklistedSource() {
id.constellation = GnssConstellationTypeAidl::UNKNOWN;
id.svid = 0;
}
bool operator<(const ComparableBlocklistedSource& compare) const {
return ((id.svid < compare.id.svid) || ((id.svid == compare.id.svid) &&
(id.constellation < compare.id.constellation)));
}
};
struct SignalCounts {
int observations;
float max_cn0_dbhz;
};
std::map<ComparableBlocklistedSource, SignalCounts> mapSignals;
for (const auto& sv_info_vec : sv_info_list) {
for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) {
const auto& gnss_sv = sv_info_vec[iSv];
if ((gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX) &&
(gnss_sv.v2_0.constellation != GnssConstellationType::GPS)) {
ComparableBlocklistedSource source;
source.id.svid = gnss_sv.v2_0.v1_0.svid;
source.id.constellation =
static_cast<GnssConstellationTypeAidl>(gnss_sv.v2_0.constellation);
const auto& itSignal = mapSignals.find(source);
if (itSignal == mapSignals.end()) {
SignalCounts counts;
counts.observations = 1;
counts.max_cn0_dbhz = gnss_sv.v2_0.v1_0.cN0Dbhz;
mapSignals.insert(
std::pair<ComparableBlocklistedSource, SignalCounts>(source, counts));
} else {
itSignal->second.observations++;
if (itSignal->second.max_cn0_dbhz < gnss_sv.v2_0.v1_0.cN0Dbhz) {
itSignal->second.max_cn0_dbhz = gnss_sv.v2_0.v1_0.cN0Dbhz;
}
}
}
}
}
float max_cn0_dbhz_with_sufficient_count = 0.;
int total_observation_count = 0;
int blocklisted_source_count_observation = 0;
ComparableBlocklistedSource source_to_blocklist; // initializes to zero = UNKNOWN constellation
for (auto const& pairSignal : mapSignals) {
total_observation_count += pairSignal.second.observations;
if ((pairSignal.second.observations >= min_observations) &&
(pairSignal.second.max_cn0_dbhz > max_cn0_dbhz_with_sufficient_count)) {
source_to_blocklist = pairSignal.first;
blocklisted_source_count_observation = pairSignal.second.observations;
max_cn0_dbhz_with_sufficient_count = pairSignal.second.max_cn0_dbhz;
}
}
ALOGD("Among %d observations, chose svid %d, constellation %d, "
"with %d observations at %.1f max CNo",
total_observation_count, source_to_blocklist.id.svid,
(int)source_to_blocklist.id.constellation, blocklisted_source_count_observation,
max_cn0_dbhz_with_sufficient_count);
return source_to_blocklist.id;
}
/*
* BlocklistIndividualSatellites:
*
@ -481,12 +405,20 @@ TEST_P(GnssHalTest, BlocklistIndividualSatellites) {
const int kLocationsToAwait = 3;
const int kRetriesToUnBlocklist = 10;
gnss_cb_->location_cbq_.reset();
if (aidl_gnss_hal_->getInterfaceVersion() == 1) {
gnss_cb_->location_cbq_.reset();
} else {
aidl_gnss_cb_->location_cbq_.reset();
}
StartAndCheckLocations(kLocationsToAwait);
int location_called_count = gnss_cb_->location_cbq_.calledCount();
int location_called_count = (aidl_gnss_hal_->getInterfaceVersion() == 1)
? gnss_cb_->location_cbq_.calledCount()
: aidl_gnss_cb_->location_cbq_.calledCount();
// Tolerate 1 less sv status to handle edge cases in reporting.
int sv_info_list_cbq_size = gnss_cb_->sv_info_list_cbq_.size();
int sv_info_list_cbq_size = (aidl_gnss_hal_->getInterfaceVersion() == 1)
? gnss_cb_->sv_info_list_cbq_.size()
: aidl_gnss_cb_->sv_info_list_cbq_.size();
EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait);
ALOGD("Observed %d GnssSvInfo, while awaiting %d Locations (%d received)",
sv_info_list_cbq_size, kLocationsToAwait, location_called_count);
@ -498,14 +430,22 @@ TEST_P(GnssHalTest, BlocklistIndividualSatellites) {
*/
const int kGnssSvInfoListTimeout = 2;
std::list<hidl_vec<IGnssCallback_2_1::GnssSvInfo>> sv_info_vec_list;
int count = gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec_list, sv_info_list_cbq_size,
kGnssSvInfoListTimeout);
ASSERT_EQ(count, sv_info_list_cbq_size);
BlocklistedSource source_to_blocklist =
FindStrongFrequentNonGpsSource(sv_info_vec_list, kLocationsToAwait - 1);
BlocklistedSource source_to_blocklist;
if (aidl_gnss_hal_->getInterfaceVersion() == 1) {
std::list<hidl_vec<IGnssCallback_2_1::GnssSvInfo>> sv_info_vec_list;
int count = gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec_list, sv_info_list_cbq_size,
kGnssSvInfoListTimeout);
ASSERT_EQ(count, sv_info_list_cbq_size);
source_to_blocklist =
FindStrongFrequentNonGpsSource(sv_info_vec_list, kLocationsToAwait - 1);
} else {
std::list<std::vector<IGnssCallback::GnssSvInfo>> sv_info_vec_list;
int count = aidl_gnss_cb_->sv_info_list_cbq_.retrieve(
sv_info_vec_list, sv_info_list_cbq_size, kGnssSvInfoListTimeout);
ASSERT_EQ(count, sv_info_list_cbq_size);
source_to_blocklist =
FindStrongFrequentNonGpsSource(sv_info_vec_list, kLocationsToAwait - 1);
}
if (source_to_blocklist.constellation == GnssConstellationTypeAidl::UNKNOWN) {
// Cannot find a non-GPS satellite. Let the test pass.
@ -529,32 +469,53 @@ TEST_P(GnssHalTest, BlocklistIndividualSatellites) {
ASSERT_TRUE(status.isOk());
// retry and ensure satellite not used
gnss_cb_->sv_info_list_cbq_.reset();
if (aidl_gnss_hal_->getInterfaceVersion() == 1) {
gnss_cb_->sv_info_list_cbq_.reset();
gnss_cb_->location_cbq_.reset();
} else {
aidl_gnss_cb_->sv_info_list_cbq_.reset();
aidl_gnss_cb_->location_cbq_.reset();
}
gnss_cb_->location_cbq_.reset();
StartAndCheckLocations(kLocationsToAwait);
// early exit if test is being run with insufficient signal
location_called_count = gnss_cb_->location_cbq_.calledCount();
location_called_count = (aidl_gnss_hal_->getInterfaceVersion() == 1)
? gnss_cb_->location_cbq_.calledCount()
: aidl_gnss_cb_->location_cbq_.calledCount();
if (location_called_count == 0) {
ALOGE("0 Gnss locations received - ensure sufficient signal and retry");
}
ASSERT_TRUE(location_called_count > 0);
// Tolerate 1 less sv status to handle edge cases in reporting.
sv_info_list_cbq_size = gnss_cb_->sv_info_list_cbq_.size();
sv_info_list_cbq_size = (aidl_gnss_hal_->getInterfaceVersion() == 1)
? gnss_cb_->sv_info_list_cbq_.size()
: aidl_gnss_cb_->sv_info_list_cbq_.size();
EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait);
ALOGD("Observed %d GnssSvInfo, while awaiting %d Locations (%d received)",
sv_info_list_cbq_size, kLocationsToAwait, location_called_count);
for (int i = 0; i < sv_info_list_cbq_size; ++i) {
hidl_vec<IGnssCallback_2_1::GnssSvInfo> sv_info_vec;
gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, kGnssSvInfoListTimeout);
for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) {
const auto& gnss_sv = sv_info_vec[iSv];
EXPECT_FALSE((gnss_sv.v2_0.v1_0.svid == source_to_blocklist.svid) &&
(static_cast<GnssConstellationTypeAidl>(gnss_sv.v2_0.constellation) ==
source_to_blocklist.constellation) &&
(gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX));
if (aidl_gnss_hal_->getInterfaceVersion() == 1) {
hidl_vec<IGnssCallback_2_1::GnssSvInfo> sv_info_vec;
gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, kGnssSvInfoListTimeout);
for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) {
auto& gnss_sv = sv_info_vec[iSv];
EXPECT_FALSE(
(gnss_sv.v2_0.v1_0.svid == source_to_blocklist.svid) &&
(static_cast<GnssConstellationTypeAidl>(gnss_sv.v2_0.constellation) ==
source_to_blocklist.constellation) &&
(gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX));
}
} else {
std::vector<IGnssCallback::GnssSvInfo> sv_info_vec;
aidl_gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, kGnssSvInfoListTimeout);
for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) {
auto& gnss_sv = sv_info_vec[iSv];
EXPECT_FALSE((gnss_sv.svid == source_to_blocklist.svid) &&
(gnss_sv.constellation == source_to_blocklist.constellation) &&
(gnss_sv.svFlag & (int)IGnssCallback::GnssSvFlags::USED_IN_FIX));
}
}
}
@ -569,36 +530,59 @@ TEST_P(GnssHalTest, BlocklistIndividualSatellites) {
int unblocklist_loops_remaining = kRetriesToUnBlocklist;
while (!strongest_sv_is_reobserved && (unblocklist_loops_remaining-- > 0)) {
StopAndClearLocations();
gnss_cb_->sv_info_list_cbq_.reset();
gnss_cb_->location_cbq_.reset();
if (aidl_gnss_hal_->getInterfaceVersion() == 1) {
gnss_cb_->sv_info_list_cbq_.reset();
gnss_cb_->location_cbq_.reset();
} else {
aidl_gnss_cb_->sv_info_list_cbq_.reset();
aidl_gnss_cb_->location_cbq_.reset();
}
StartAndCheckLocations(kLocationsToAwait);
// early exit loop if test is being run with insufficient signal
location_called_count = gnss_cb_->location_cbq_.calledCount();
location_called_count = (aidl_gnss_hal_->getInterfaceVersion() == 1)
? gnss_cb_->location_cbq_.calledCount()
: aidl_gnss_cb_->location_cbq_.calledCount();
if (location_called_count == 0) {
ALOGE("0 Gnss locations received - ensure sufficient signal and retry");
}
ASSERT_TRUE(location_called_count > 0);
// Tolerate 1 less sv status to handle edge cases in reporting.
sv_info_list_cbq_size = gnss_cb_->sv_info_list_cbq_.size();
sv_info_list_cbq_size = (aidl_gnss_hal_->getInterfaceVersion() == 1)
? gnss_cb_->sv_info_list_cbq_.size()
: aidl_gnss_cb_->sv_info_list_cbq_.size();
EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait);
ALOGD("Clear blocklist, observed %d GnssSvInfo, while awaiting %d Locations"
", tries remaining %d",
sv_info_list_cbq_size, kLocationsToAwait, unblocklist_loops_remaining);
for (int i = 0; i < sv_info_list_cbq_size; ++i) {
hidl_vec<IGnssCallback_2_1::GnssSvInfo> sv_info_vec;
gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, kGnssSvInfoListTimeout);
for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) {
const auto& gnss_sv = sv_info_vec[iSv];
if ((gnss_sv.v2_0.v1_0.svid == source_to_blocklist.svid) &&
(static_cast<GnssConstellationTypeAidl>(gnss_sv.v2_0.constellation) ==
source_to_blocklist.constellation) &&
(gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX)) {
strongest_sv_is_reobserved = true;
break;
if (aidl_gnss_hal_->getInterfaceVersion() == 1) {
hidl_vec<IGnssCallback_2_1::GnssSvInfo> sv_info_vec;
gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, kGnssSvInfoListTimeout);
for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) {
auto& gnss_sv = sv_info_vec[iSv];
if ((gnss_sv.v2_0.v1_0.svid == source_to_blocklist.svid) &&
(static_cast<GnssConstellationTypeAidl>(gnss_sv.v2_0.constellation) ==
source_to_blocklist.constellation) &&
(gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX)) {
strongest_sv_is_reobserved = true;
break;
}
}
} else {
std::vector<IGnssCallback::GnssSvInfo> sv_info_vec;
aidl_gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, kGnssSvInfoListTimeout);
for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) {
auto& gnss_sv = sv_info_vec[iSv];
if ((gnss_sv.svid == source_to_blocklist.svid) &&
(gnss_sv.constellation == source_to_blocklist.constellation) &&
(gnss_sv.svFlag & (int)IGnssCallback::GnssSvFlags::USED_IN_FIX)) {
strongest_sv_is_reobserved = true;
break;
}
}
}
if (strongest_sv_is_reobserved) break;
@ -660,27 +644,47 @@ TEST_P(GnssHalTest, BlocklistConstellationLocationOff) {
ASSERT_TRUE(status.isOk());
// retry and ensure constellation not used
gnss_cb_->sv_info_list_cbq_.reset();
gnss_cb_->location_cbq_.reset();
if (aidl_gnss_hal_->getInterfaceVersion() == 1) {
gnss_cb_->sv_info_list_cbq_.reset();
gnss_cb_->location_cbq_.reset();
} else {
aidl_gnss_cb_->sv_info_list_cbq_.reset();
aidl_gnss_cb_->location_cbq_.reset();
}
StartAndCheckLocations(kLocationsToAwait);
// Tolerate 1 less sv status to handle edge cases in reporting.
int sv_info_list_cbq_size = gnss_cb_->sv_info_list_cbq_.size();
int sv_info_list_cbq_size = (aidl_gnss_hal_->getInterfaceVersion() == 1)
? gnss_cb_->sv_info_list_cbq_.size()
: aidl_gnss_cb_->sv_info_list_cbq_.size();
EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait);
ALOGD("Observed %d GnssSvInfo, while awaiting %d Locations", sv_info_list_cbq_size,
kLocationsToAwait);
for (int i = 0; i < sv_info_list_cbq_size; ++i) {
hidl_vec<IGnssCallback_2_1::GnssSvInfo> sv_info_vec;
gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, kGnssSvInfoListTimeout);
for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) {
const auto& gnss_sv = sv_info_vec[iSv];
EXPECT_FALSE((static_cast<GnssConstellationTypeAidl>(gnss_sv.v2_0.constellation) ==
source_to_blocklist_1.constellation) &&
(gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX));
EXPECT_FALSE((static_cast<GnssConstellationTypeAidl>(gnss_sv.v2_0.constellation) ==
source_to_blocklist_2.constellation) &&
(gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX));
if (aidl_gnss_hal_->getInterfaceVersion() == 1) {
hidl_vec<IGnssCallback_2_1::GnssSvInfo> sv_info_vec;
gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, kGnssSvInfoListTimeout);
for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) {
const auto& gnss_sv = sv_info_vec[iSv];
EXPECT_FALSE(
(static_cast<GnssConstellationTypeAidl>(gnss_sv.v2_0.constellation) ==
source_to_blocklist_1.constellation) &&
(gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX));
EXPECT_FALSE(
(static_cast<GnssConstellationTypeAidl>(gnss_sv.v2_0.constellation) ==
source_to_blocklist_2.constellation) &&
(gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX));
}
} else {
std::vector<IGnssCallback::GnssSvInfo> sv_info_vec;
aidl_gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, kGnssSvInfoListTimeout);
for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) {
const auto& gnss_sv = sv_info_vec[iSv];
EXPECT_FALSE((gnss_sv.constellation == source_to_blocklist_1.constellation) &&
(gnss_sv.svFlag & (int)IGnssCallback::GnssSvFlags::USED_IN_FIX));
EXPECT_FALSE((gnss_sv.constellation == source_to_blocklist_2.constellation) &&
(gnss_sv.svFlag & (int)IGnssCallback::GnssSvFlags::USED_IN_FIX));
}
}
}
@ -743,27 +747,47 @@ TEST_P(GnssHalTest, BlocklistConstellationLocationOn) {
StopAndClearLocations();
// retry and ensure constellation not used
gnss_cb_->sv_info_list_cbq_.reset();
gnss_cb_->location_cbq_.reset();
if (aidl_gnss_hal_->getInterfaceVersion() == 1) {
gnss_cb_->sv_info_list_cbq_.reset();
gnss_cb_->location_cbq_.reset();
} else {
aidl_gnss_cb_->sv_info_list_cbq_.reset();
aidl_gnss_cb_->location_cbq_.reset();
}
StartAndCheckLocations(kLocationsToAwait);
// Tolerate 1 less sv status to handle edge cases in reporting.
int sv_info_list_cbq_size = gnss_cb_->sv_info_list_cbq_.size();
int sv_info_list_cbq_size = (aidl_gnss_hal_->getInterfaceVersion() == 1)
? gnss_cb_->sv_info_list_cbq_.size()
: aidl_gnss_cb_->sv_info_list_cbq_.size();
EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait);
ALOGD("Observed %d GnssSvInfo, while awaiting %d Locations", sv_info_list_cbq_size,
kLocationsToAwait);
for (int i = 0; i < sv_info_list_cbq_size; ++i) {
hidl_vec<IGnssCallback_2_1::GnssSvInfo> sv_info_vec;
gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, kGnssSvInfoListTimeout);
for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) {
const auto& gnss_sv = sv_info_vec[iSv];
EXPECT_FALSE((static_cast<GnssConstellationTypeAidl>(gnss_sv.v2_0.constellation) ==
source_to_blocklist_1.constellation) &&
(gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX));
EXPECT_FALSE((static_cast<GnssConstellationTypeAidl>(gnss_sv.v2_0.constellation) ==
source_to_blocklist_2.constellation) &&
(gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX));
if (aidl_gnss_hal_->getInterfaceVersion() == 1) {
hidl_vec<IGnssCallback_2_1::GnssSvInfo> sv_info_vec;
gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, kGnssSvInfoListTimeout);
for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) {
const auto& gnss_sv = sv_info_vec[iSv];
EXPECT_FALSE(
(static_cast<GnssConstellationTypeAidl>(gnss_sv.v2_0.constellation) ==
source_to_blocklist_1.constellation) &&
(gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX));
EXPECT_FALSE(
(static_cast<GnssConstellationTypeAidl>(gnss_sv.v2_0.constellation) ==
source_to_blocklist_2.constellation) &&
(gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX));
}
} else {
std::vector<IGnssCallback::GnssSvInfo> sv_info_vec;
aidl_gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, kGnssSvInfoListTimeout);
for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) {
const auto& gnss_sv = sv_info_vec[iSv];
EXPECT_FALSE((gnss_sv.constellation == source_to_blocklist_1.constellation) &&
(gnss_sv.svFlag & (int)IGnssCallback::GnssSvFlags::USED_IN_FIX));
EXPECT_FALSE((gnss_sv.constellation == source_to_blocklist_2.constellation) &&
(gnss_sv.svFlag & (int)IGnssCallback::GnssSvFlags::USED_IN_FIX));
}
}
}
@ -829,7 +853,7 @@ TEST_P(GnssHalTest, TestAGnssExtension) {
ASSERT_TRUE(status.isOk());
// Set SUPL server host/port
status = iAGnss->setServer(AGnssType::SUPL, String16("supl.google.com"), 7275);
status = iAGnss->setServer(AGnssType::SUPL, std::string("supl.google.com"), 7275);
ASSERT_TRUE(status.isOk());
}
@ -845,7 +869,7 @@ TEST_P(GnssHalTest, GnssDebugValuesSanityTest) {
auto status = aidl_gnss_hal_->getExtensionGnssDebug(&iGnssDebug);
ASSERT_TRUE(status.isOk());
if (!IsAutomotiveDevice() && gnss_cb_->info_cbq_.calledCount() > 0) {
if (!IsAutomotiveDevice()) {
ASSERT_TRUE(iGnssDebug != nullptr);
IGnssDebug::DebugData data;

View file

@ -27,14 +27,17 @@ namespace common {
using aidl::android::hardware::gnss::ElapsedRealtime;
using aidl::android::hardware::gnss::GnssClock;
using aidl::android::hardware::gnss::GnssConstellationType;
using aidl::android::hardware::gnss::GnssData;
using aidl::android::hardware::gnss::GnssLocation;
using aidl::android::hardware::gnss::GnssMeasurement;
using aidl::android::hardware::gnss::IGnss;
using aidl::android::hardware::gnss::IGnssMeasurementCallback;
using aidl::android::hardware::gnss::SatellitePvt;
using GnssSvInfo = aidl::android::hardware::gnss::IGnssCallback::GnssSvInfo;
using GnssSvFlags = aidl::android::hardware::gnss::IGnssCallback::GnssSvFlags;
using GnssSvFlags = V1_0::IGnssCallback::GnssSvFlags;
using GnssSvFlagsV1_0 = V1_0::IGnssCallback::GnssSvFlags;
using GnssMeasurementFlagsV1_0 = V1_0::IGnssMeasurementCallback::GnssMeasurementFlags;
using GnssMeasurementFlagsV2_1 = V2_1::IGnssMeasurementCallback::GnssMeasurementFlags;
using GnssMeasurementStateV2_0 = V2_0::IGnssMeasurementCallback::GnssMeasurementState;
@ -144,7 +147,7 @@ GnssDataV2_0 Utils::getMockMeasurementV2_0() {
GnssData Utils::getMockMeasurement(const bool enableCorrVecOutputs) {
aidl::android::hardware::gnss::GnssSignalType signalType = {
.constellation = aidl::android::hardware::gnss::GnssConstellationType::GLONASS,
.constellation = GnssConstellationType::GLONASS,
.carrierFrequencyHz = 1.59975e+09,
.codeType = aidl::android::hardware::gnss::GnssSignalType::CODE_TYPE_C,
};
@ -289,6 +292,40 @@ V1_0::GnssLocation Utils::getMockLocationV1_0() {
return location;
}
namespace {
GnssSvInfo getMockSvInfo(int svid, GnssConstellationType type, float cN0DbHz, float basebandCN0DbHz,
float elevationDegrees, float azimuthDegrees, long carrierFrequencyHz) {
GnssSvInfo svInfo = {
.svid = svid,
.constellation = type,
.cN0Dbhz = cN0DbHz,
.basebandCN0DbHz = basebandCN0DbHz,
.elevationDegrees = elevationDegrees,
.azimuthDegrees = azimuthDegrees,
.carrierFrequencyHz = carrierFrequencyHz,
.svFlag = (int)GnssSvFlags::USED_IN_FIX | (int)GnssSvFlags::HAS_EPHEMERIS_DATA |
(int)GnssSvFlags::HAS_ALMANAC_DATA | (int)GnssSvFlags::HAS_CARRIER_FREQUENCY};
return svInfo;
}
} // anonymous namespace
std::vector<GnssSvInfo> Utils::getMockSvInfoList() {
std::vector<GnssSvInfo> gnssSvInfoList = {
getMockSvInfo(3, GnssConstellationType::GPS, 32.5, 27.5, 59.1, 166.5, kGpsL1FreqHz),
getMockSvInfo(5, GnssConstellationType::GPS, 27.0, 22.0, 29.0, 56.5, kGpsL1FreqHz),
getMockSvInfo(17, GnssConstellationType::GPS, 30.5, 25.5, 71.0, 77.0, kGpsL5FreqHz),
getMockSvInfo(26, GnssConstellationType::GPS, 24.1, 19.1, 28.0, 253.0, kGpsL5FreqHz),
getMockSvInfo(5, GnssConstellationType::GLONASS, 20.5, 15.5, 11.5, 116.0, kGloG1FreqHz),
getMockSvInfo(17, GnssConstellationType::GLONASS, 21.5, 16.5, 28.5, 186.0,
kGloG1FreqHz),
getMockSvInfo(18, GnssConstellationType::GLONASS, 28.3, 25.3, 38.8, 69.0, kGloG1FreqHz),
getMockSvInfo(10, GnssConstellationType::GLONASS, 25.0, 20.0, 66.0, 247.0,
kGloG1FreqHz),
getMockSvInfo(3, GnssConstellationType::IRNSS, 22.0, 19.7, 35.0, 112.0, kIrnssL5FreqHz),
};
return gnssSvInfoList;
}
hidl_vec<GnssSvInfoV2_1> Utils::getMockSvInfoListV2_1() {
GnssSvInfoV1_0 gnssSvInfoV1_0 = Utils::getMockSvInfoV1_0(3, V1_0::GnssConstellationType::GPS,
32.5, 59.1, 166.5, kGpsL1FreqHz);
@ -360,15 +397,15 @@ GnssSvInfoV2_0 Utils::getMockSvInfoV2_0(GnssSvInfoV1_0 gnssSvInfoV1_0,
GnssSvInfoV1_0 Utils::getMockSvInfoV1_0(int16_t svid, V1_0::GnssConstellationType type,
float cN0DbHz, float elevationDegrees, float azimuthDegrees,
float carrierFrequencyHz) {
GnssSvInfoV1_0 svInfo = {.svid = svid,
.constellation = type,
.cN0Dbhz = cN0DbHz,
.elevationDegrees = elevationDegrees,
.azimuthDegrees = azimuthDegrees,
.carrierFrequencyHz = carrierFrequencyHz,
.svFlag = GnssSvFlags::USED_IN_FIX | GnssSvFlags::HAS_EPHEMERIS_DATA |
GnssSvFlags::HAS_ALMANAC_DATA |
GnssSvFlags::HAS_CARRIER_FREQUENCY};
GnssSvInfoV1_0 svInfo = {
.svid = svid,
.constellation = type,
.cN0Dbhz = cN0DbHz,
.elevationDegrees = elevationDegrees,
.azimuthDegrees = azimuthDegrees,
.carrierFrequencyHz = carrierFrequencyHz,
.svFlag = GnssSvFlagsV1_0::USED_IN_FIX | GnssSvFlagsV1_0::HAS_EPHEMERIS_DATA |
GnssSvFlagsV1_0::HAS_ALMANAC_DATA | GnssSvFlagsV1_0::HAS_CARRIER_FREQUENCY};
return svInfo;
}

View file

@ -35,9 +35,13 @@ struct Utils {
const bool enableCorrVecOutputs);
static V2_0::IGnssMeasurementCallback::GnssData getMockMeasurementV2_0();
static V2_1::IGnssMeasurementCallback::GnssData getMockMeasurementV2_1();
static aidl::android::hardware::gnss::GnssLocation getMockLocation();
static V2_0::GnssLocation getMockLocationV2_0();
static V1_0::GnssLocation getMockLocationV1_0();
static std::vector<aidl::android::hardware::gnss::IGnssCallback::GnssSvInfo>
getMockSvInfoList();
static hidl_vec<V2_1::IGnssCallback::GnssSvInfo> getMockSvInfoListV2_1();
static V2_1::IGnssCallback::GnssSvInfo getMockSvInfoV2_1(
V2_0::IGnssCallback::GnssSvInfo gnssSvInfoV2_0, float basebandCN0DbHz);
@ -48,6 +52,7 @@ struct Utils {
float cN0DbHz, float elevationDegrees,
float azimuthDegrees,
float carrierFrequencyHz);
static hidl_vec<V2_1::IGnssAntennaInfoCallback::GnssAntennaInfo> getMockAntennaInfos();
};

View file

@ -44,6 +44,7 @@ cc_library_static {
"android.hardware.gnss@2.1",
"android.hardware.gnss.measurement_corrections@1.0",
"android.hardware.gnss.measurement_corrections@1.1",
"android.hardware.gnss-V2-cpp",
],
static_libs: [
"libgtest",

View file

@ -15,6 +15,7 @@
*/
#include <Utils.h>
#include <android/hardware/gnss/IGnss.h>
#include "gtest/gtest.h"
#include <cutils/properties.h>
@ -27,71 +28,14 @@ namespace common {
using namespace measurement_corrections::V1_0;
using V1_0::GnssLocationFlags;
void Utils::checkLocation(const V1_0::GnssLocation& location, bool check_speed,
bool check_more_accuracies) {
EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_LAT_LONG);
EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_ALTITUDE);
if (check_speed) {
EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_SPEED);
}
EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_HORIZONTAL_ACCURACY);
// New uncertainties available in O must be provided,
// at least when paired with modern hardware (2017+)
if (check_more_accuracies) {
EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_VERTICAL_ACCURACY);
if (check_speed) {
EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_SPEED_ACCURACY);
if (location.gnssLocationFlags & GnssLocationFlags::HAS_BEARING) {
EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_BEARING_ACCURACY);
}
}
}
EXPECT_GE(location.latitudeDegrees, -90.0);
EXPECT_LE(location.latitudeDegrees, 90.0);
EXPECT_GE(location.longitudeDegrees, -180.0);
EXPECT_LE(location.longitudeDegrees, 180.0);
EXPECT_GE(location.altitudeMeters, -1000.0);
EXPECT_LE(location.altitudeMeters, 30000.0);
if (check_speed) {
EXPECT_GE(location.speedMetersPerSec, 0.0);
EXPECT_LE(location.speedMetersPerSec, 5.0); // VTS tests are stationary.
template <>
int64_t Utils::getLocationTimestampMillis(const android::hardware::gnss::GnssLocation& location) {
return location.timestampMillis;
}
// Non-zero speeds must be reported with an associated bearing
if (location.speedMetersPerSec > 0.0) {
EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_BEARING);
}
}
/*
* Tolerating some especially high values for accuracy estimate, in case of
* first fix with especially poor geometry (happens occasionally)
*/
EXPECT_GT(location.horizontalAccuracyMeters, 0.0);
EXPECT_LE(location.horizontalAccuracyMeters, 250.0);
/*
* Some devices may define bearing as -180 to +180, others as 0 to 360.
* Both are okay & understandable.
*/
if (location.gnssLocationFlags & GnssLocationFlags::HAS_BEARING) {
EXPECT_GE(location.bearingDegrees, -180.0);
EXPECT_LE(location.bearingDegrees, 360.0);
}
if (location.gnssLocationFlags & GnssLocationFlags::HAS_VERTICAL_ACCURACY) {
EXPECT_GT(location.verticalAccuracyMeters, 0.0);
EXPECT_LE(location.verticalAccuracyMeters, 500.0);
}
if (location.gnssLocationFlags & GnssLocationFlags::HAS_SPEED_ACCURACY) {
EXPECT_GT(location.speedAccuracyMetersPerSecond, 0.0);
EXPECT_LE(location.speedAccuracyMetersPerSecond, 50.0);
}
if (location.gnssLocationFlags & GnssLocationFlags::HAS_BEARING_ACCURACY) {
EXPECT_GT(location.bearingAccuracyDegrees, 0.0);
EXPECT_LE(location.bearingAccuracyDegrees, 360.0);
}
// Check timestamp > 1.48e12 (47 years in msec - 1970->2017+)
EXPECT_GT(location.timestamp, 1.48e12);
template <>
int64_t Utils::getLocationTimestampMillis(const V1_0::GnssLocation& location) {
return location.timestamp;
}
const MeasurementCorrections Utils::getMockMeasurementCorrections() {

View file

@ -21,6 +21,7 @@
#include <android/hardware/gnss/2.0/IGnss.h>
#include <android/hardware/gnss/measurement_corrections/1.0/IMeasurementCorrections.h>
#include <android/hardware/gnss/measurement_corrections/1.1/IMeasurementCorrections.h>
#include <gtest/gtest.h>
namespace android {
namespace hardware {
@ -28,8 +29,9 @@ namespace gnss {
namespace common {
struct Utils {
static void checkLocation(const V1_0::GnssLocation& location, bool check_speed,
bool check_more_accuracies);
public:
template <class T>
static void checkLocation(const T& location, bool check_speed, bool check_more_accuracies);
static const measurement_corrections::V1_0::MeasurementCorrections
getMockMeasurementCorrections();
static const measurement_corrections::V1_1::MeasurementCorrections
@ -39,8 +41,80 @@ struct Utils {
V2_0::GnssConstellationType constellation);
static bool isAutomotiveDevice();
private:
template <class T>
static int64_t getLocationTimestampMillis(const T&);
};
template <class T>
void Utils::checkLocation(const T& location, bool check_speed, bool check_more_accuracies) {
EXPECT_TRUE(location.gnssLocationFlags & V1_0::GnssLocationFlags::HAS_LAT_LONG);
EXPECT_TRUE(location.gnssLocationFlags & V1_0::GnssLocationFlags::HAS_ALTITUDE);
if (check_speed) {
EXPECT_TRUE(location.gnssLocationFlags & V1_0::GnssLocationFlags::HAS_SPEED);
}
EXPECT_TRUE(location.gnssLocationFlags & V1_0::GnssLocationFlags::HAS_HORIZONTAL_ACCURACY);
// New uncertainties available in O must be provided,
// at least when paired with modern hardware (2017+)
if (check_more_accuracies) {
EXPECT_TRUE(location.gnssLocationFlags & V1_0::GnssLocationFlags::HAS_VERTICAL_ACCURACY);
if (check_speed) {
EXPECT_TRUE(location.gnssLocationFlags & V1_0::GnssLocationFlags::HAS_SPEED_ACCURACY);
if (location.gnssLocationFlags & V1_0::GnssLocationFlags::HAS_BEARING) {
EXPECT_TRUE(location.gnssLocationFlags &
V1_0::GnssLocationFlags::HAS_BEARING_ACCURACY);
}
}
}
EXPECT_GE(location.latitudeDegrees, -90.0);
EXPECT_LE(location.latitudeDegrees, 90.0);
EXPECT_GE(location.longitudeDegrees, -180.0);
EXPECT_LE(location.longitudeDegrees, 180.0);
EXPECT_GE(location.altitudeMeters, -1000.0);
EXPECT_LE(location.altitudeMeters, 30000.0);
if (check_speed) {
EXPECT_GE(location.speedMetersPerSec, 0.0);
EXPECT_LE(location.speedMetersPerSec, 5.0); // VTS tests are stationary.
// Non-zero speeds must be reported with an associated bearing
if (location.speedMetersPerSec > 0.0) {
EXPECT_TRUE(location.gnssLocationFlags & V1_0::GnssLocationFlags::HAS_BEARING);
}
}
/*
* Tolerating some especially high values for accuracy estimate, in case of
* first fix with especially poor geometry (happens occasionally)
*/
EXPECT_GT(location.horizontalAccuracyMeters, 0.0);
EXPECT_LE(location.horizontalAccuracyMeters, 250.0);
/*
* Some devices may define bearing as -180 to +180, others as 0 to 360.
* Both are okay & understandable.
*/
if (location.gnssLocationFlags & V1_0::GnssLocationFlags::HAS_BEARING) {
EXPECT_GE(location.bearingDegrees, -180.0);
EXPECT_LE(location.bearingDegrees, 360.0);
}
if (location.gnssLocationFlags & V1_0::GnssLocationFlags::HAS_VERTICAL_ACCURACY) {
EXPECT_GT(location.verticalAccuracyMeters, 0.0);
EXPECT_LE(location.verticalAccuracyMeters, 500.0);
}
if (location.gnssLocationFlags & V1_0::GnssLocationFlags::HAS_SPEED_ACCURACY) {
EXPECT_GT(location.speedAccuracyMetersPerSecond, 0.0);
EXPECT_LE(location.speedAccuracyMetersPerSecond, 50.0);
}
if (location.gnssLocationFlags & V1_0::GnssLocationFlags::HAS_BEARING_ACCURACY) {
EXPECT_GT(location.bearingAccuracyDegrees, 0.0);
EXPECT_LE(location.bearingAccuracyDegrees, 360.0);
}
// Check timestamp > 1.48e12 (47 years in msec - 1970->2017+)
EXPECT_GT(getLocationTimestampMillis(location), 1.48e12);
}
} // namespace common
} // namespace gnss
} // namespace hardware

View file

@ -28,7 +28,6 @@ using android::hardware::Void;
using android::hardware::gnss::common::GnssCallbackEventQueue;
using android::hardware::gnss::measurement_corrections::V1_0::IMeasurementCorrectionsCallback;
using android::hardware::gnss::V1_0::GnssLocationFlags;
using android::hardware::gnss::V2_0::GnssConstellationType;
using GnssLocation_1_0 = android::hardware::gnss::V1_0::GnssLocation;
using GnssLocation_2_0 = android::hardware::gnss::V2_0::GnssLocation;