From 1afbd5f23e0f72b7f03ed15ce973371f18f9d2c3 Mon Sep 17 00:00:00 2001 From: Yu-Han Yang Date: Wed, 24 Nov 2021 16:39:13 -0800 Subject: [PATCH] Add navigation methods to IGnss AIDL HAL (hardware/interfaces) Bug: 205185251 Test: atest VtsHalGnssTargetTest Change-Id: Ib412aeb0b302952d13e236554f00690206b98253 --- .../current/android/hardware/gnss/IAGnss.aidl | 4 +- .../current/android/hardware/gnss/IGnss.aidl | 34 ++ .../android/hardware/gnss/IGnssCallback.aidl | 52 +++ gnss/aidl/android/hardware/gnss/IAGnss.aidl | 5 +- gnss/aidl/android/hardware/gnss/IGnss.aidl | 125 +++++++ .../android/hardware/gnss/IGnssCallback.aidl | 258 ++++++++++++++ gnss/aidl/default/Gnss.cpp | 185 ++++++++-- gnss/aidl/default/Gnss.h | 30 ++ gnss/aidl/default/GnssConfiguration.cpp | 10 + gnss/aidl/default/GnssConfiguration.h | 2 + gnss/aidl/vts/GnssBatchingCallback.cpp | 2 + gnss/aidl/vts/GnssCallbackAidl.cpp | 57 ++- gnss/aidl/vts/GnssCallbackAidl.h | 28 +- gnss/aidl/vts/gnss_hal_test.cpp | 262 +++++++++++++- gnss/aidl/vts/gnss_hal_test.h | 41 +++ gnss/aidl/vts/gnss_hal_test_cases.cpp | 324 ++++++++++-------- gnss/common/utils/default/Utils.cpp | 59 +++- gnss/common/utils/default/include/Utils.h | 5 + gnss/common/utils/vts/Android.bp | 1 + gnss/common/utils/vts/Utils.cpp | 72 +--- gnss/common/utils/vts/include/Utils.h | 78 ++++- .../utils/vts/include/v2_1/GnssCallback.h | 1 - 22 files changed, 1361 insertions(+), 274 deletions(-) diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IAGnss.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IAGnss.aidl index f02e08cc39..1a69f3338a 100644 --- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IAGnss.aidl +++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IAGnss.aidl @@ -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, diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnss.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnss.aidl index 34773805f4..1b4c5817ce 100644 --- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnss.aidl +++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnss.aidl @@ -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, + } } diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssCallback.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssCallback.aidl index fb0931c59a..957a75fe9a 100644 --- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssCallback.aidl +++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssCallback.aidl @@ -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; + } } diff --git a/gnss/aidl/android/hardware/gnss/IAGnss.aidl b/gnss/aidl/android/hardware/gnss/IAGnss.aidl index 3e256e2e23..30b2167445 100644 --- a/gnss/aidl/android/hardware/gnss/IAGnss.aidl +++ b/gnss/aidl/android/hardware/gnss/IAGnss.aidl @@ -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); } diff --git a/gnss/aidl/android/hardware/gnss/IGnss.aidl b/gnss/aidl/android/hardware/gnss/IGnss.aidl index 1351f594e9..4ddc6a6193 100644 --- a/gnss/aidl/android/hardware/gnss/IGnss.aidl +++ b/gnss/aidl/android/hardware/gnss/IGnss.aidl @@ -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); } diff --git a/gnss/aidl/android/hardware/gnss/IGnssCallback.aidl b/gnss/aidl/android/hardware/gnss/IGnssCallback.aidl index aad09ef98b..157c912054 100644 --- a/gnss/aidl/android/hardware/gnss/IGnssCallback.aidl +++ b/gnss/aidl/android/hardware/gnss/IGnssCallback.aidl @@ -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); } diff --git a/gnss/aidl/default/Gnss.cpp b/gnss/aidl/default/Gnss.cpp index afb7b9507a..e296351d95 100644 --- a/gnss/aidl/default/Gnss.cpp +++ b/gnss/aidl/default/Gnss.cpp @@ -17,6 +17,7 @@ #define LOG_TAG "GnssAidl" #include "Gnss.h" +#include #include #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 Gnss::sGnssCallback = nullptr; -ndk::ScopedAStatus Gnss::setCallback(const std::shared_ptr& callback) { - ALOGD("Gnss::setCallback"); +Gnss::Gnss() : mMinIntervalMs(1000), mFirstFixReceived(false) {} + +ScopedAStatus Gnss::setCallback(const std::shared_ptr& 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& 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 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& svInfoList) const { + std::unique_lock 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 Gnss::filterBlocklistedSatellites(std::vector 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 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) { @@ -65,61 +160,93 @@ ndk::ScopedAStatus Gnss::getExtensionAGnss(std::shared_ptr* iAGnss) { return ndk::ScopedAStatus::ok(); } -ndk::ScopedAStatus Gnss::getExtensionPsds(std::shared_ptr* iGnssPsds) { - ALOGD("Gnss::getExtensionPsds"); - *iGnssPsds = SharedRefBase::make(); - 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) { + ALOGD("getExtensionPsds"); + *iGnssPsds = SharedRefBase::make(); + return ScopedAStatus::ok(); +} + +ScopedAStatus Gnss::getExtensionGnssConfiguration( std::shared_ptr* iGnssConfiguration) { - ALOGD("Gnss::getExtensionGnssConfiguration"); + ALOGD("getExtensionGnssConfiguration"); if (mGnssConfiguration == nullptr) { mGnssConfiguration = SharedRefBase::make(); } *iGnssConfiguration = mGnssConfiguration; - return ndk::ScopedAStatus::ok(); + return ScopedAStatus::ok(); } -ndk::ScopedAStatus Gnss::getExtensionGnssPowerIndication( +ScopedAStatus Gnss::getExtensionGnssPowerIndication( std::shared_ptr* iGnssPowerIndication) { - ALOGD("Gnss::getExtensionGnssPowerIndication"); + ALOGD("getExtensionGnssPowerIndication"); if (mGnssPowerIndication == nullptr) { mGnssPowerIndication = SharedRefBase::make(); } *iGnssPowerIndication = mGnssPowerIndication; - return ndk::ScopedAStatus::ok(); + return ScopedAStatus::ok(); } -ndk::ScopedAStatus Gnss::getExtensionGnssMeasurement( +ScopedAStatus Gnss::getExtensionGnssMeasurement( std::shared_ptr* iGnssMeasurement) { - ALOGD("Gnss::getExtensionGnssMeasurement"); + ALOGD("getExtensionGnssMeasurement"); *iGnssMeasurement = SharedRefBase::make(); - return ndk::ScopedAStatus::ok(); + return ScopedAStatus::ok(); } -ndk::ScopedAStatus Gnss::getExtensionGnssBatching(std::shared_ptr* iGnssBatching) { - ALOGD("Gnss::getExtensionGnssBatching"); +ScopedAStatus Gnss::getExtensionGnssBatching(std::shared_ptr* iGnssBatching) { + ALOGD("getExtensionGnssBatching"); *iGnssBatching = SharedRefBase::make(); - return ndk::ScopedAStatus::ok(); + return ScopedAStatus::ok(); } -ndk::ScopedAStatus Gnss::getExtensionGnssGeofence(std::shared_ptr* iGnssGeofence) { - ALOGD("Gnss::getExtensionGnssGeofence"); +ScopedAStatus Gnss::getExtensionGnssGeofence(std::shared_ptr* iGnssGeofence) { + ALOGD("getExtensionGnssGeofence"); *iGnssGeofence = SharedRefBase::make(); - return ndk::ScopedAStatus::ok(); + return ScopedAStatus::ok(); } -ndk::ScopedAStatus Gnss::getExtensionGnssNavigationMessage( +ScopedAStatus Gnss::getExtensionGnssNavigationMessage( std::shared_ptr* iGnssNavigationMessage) { - ALOGD("Gnss::getExtensionGnssNavigationMessage"); + ALOGD("getExtensionGnssNavigationMessage"); *iGnssNavigationMessage = SharedRefBase::make(); - return ndk::ScopedAStatus::ok(); + return ScopedAStatus::ok(); } ndk::ScopedAStatus Gnss::getExtensionGnssDebug(std::shared_ptr* iGnssDebug) { diff --git a/gnss/aidl/default/Gnss.h b/gnss/aidl/default/Gnss.h index 67fef94ee7..384c8629a2 100644 --- a/gnss/aidl/default/Gnss.h +++ b/gnss/aidl/default/Gnss.h @@ -25,6 +25,9 @@ #include #include #include +#include +#include +#include #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& 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) override; ndk::ScopedAStatus getExtensionGnssConfiguration( std::shared_ptr* iGnssConfiguration) override; @@ -57,7 +74,20 @@ class Gnss : public BnGnss { std::shared_ptr mGnssPowerIndication; private: + void reportLocation(const GnssLocation&) const; + void reportSvStatus(const std::vector& svInfoList) const; + std::vector filterBlocklistedSatellites( + std::vector gnssSvInfoList); + void reportGnssStatusValue(const IGnssCallback::GnssStatusValue gnssStatusValue) const; + static std::shared_ptr sGnssCallback; + + std::atomic mMinIntervalMs; + std::atomic mIsActive; + std::atomic mFirstFixReceived; + std::thread mThread; + + mutable std::mutex mMutex; }; } // namespace aidl::android::hardware::gnss diff --git a/gnss/aidl/default/GnssConfiguration.cpp b/gnss/aidl/default/GnssConfiguration.cpp index 30e0d8c8b9..96a1aa2a3f 100644 --- a/gnss/aidl/default/GnssConfiguration.cpp +++ b/gnss/aidl/default/GnssConfiguration.cpp @@ -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 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 diff --git a/gnss/aidl/default/GnssConfiguration.h b/gnss/aidl/default/GnssConfiguration.h index 491733c9ca..3c77f32d1f 100644 --- a/gnss/aidl/default/GnssConfiguration.h +++ b/gnss/aidl/default/GnssConfiguration.h @@ -16,6 +16,7 @@ #pragma once +#include #include #include #include @@ -62,6 +63,7 @@ struct GnssConfiguration : public BnGnssConfiguration { ndk::ScopedAStatus setBlocklist(const vector& blocklist) override; bool isBlocklistedV2_1(const GnssSvInfoV2_1& gnssSvInfo) const; + bool isBlocklisted(const IGnssCallback::GnssSvInfo& gnssSvInfo) const; private: BlocklistedSourceSet mBlocklistedSourceSet; diff --git a/gnss/aidl/vts/GnssBatchingCallback.cpp b/gnss/aidl/vts/GnssBatchingCallback.cpp index 2da3b12e68..d4eb0a58b6 100644 --- a/gnss/aidl/vts/GnssBatchingCallback.cpp +++ b/gnss/aidl/vts/GnssBatchingCallback.cpp @@ -14,6 +14,8 @@ * limitations under the License. */ +#define LOG_TAG "GnssBatchingCallbackAidl" + #include "GnssBatchingCallback.h" #include #include diff --git a/gnss/aidl/vts/GnssCallbackAidl.cpp b/gnss/aidl/vts/GnssCallbackAidl.cpp index f5c745b75c..77a2506820 100644 --- a/gnss/aidl/vts/GnssCallbackAidl.cpp +++ b/gnss/aidl/vts/GnssCallbackAidl.cpp @@ -14,11 +14,62 @@ * limitations under the License. */ +#define LOG_TAG "GnssCallbackAidl" + #include "GnssCallbackAidl.h" #include -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& 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(); } diff --git a/gnss/aidl/vts/GnssCallbackAidl.h b/gnss/aidl/vts/GnssCallbackAidl.h index 7f802ea02e..209728df7f 100644 --- a/gnss/aidl/vts/GnssCallbackAidl.h +++ b/gnss/aidl/vts/GnssCallbackAidl.h @@ -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& 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 capabilities_cbq_; + android::hardware::gnss::common::GnssCallbackEventQueue< + android::hardware::gnss::IGnssCallback::GnssSystemInfo> + info_cbq_; + android::hardware::gnss::common::GnssCallbackEventQueue + location_cbq_; + android::hardware::gnss::common::GnssCallbackEventQueue< + std::vector> + sv_info_list_cbq_; }; \ No newline at end of file diff --git a/gnss/aidl/vts/gnss_hal_test.cpp b/gnss/aidl/vts/gnss_hal_test.cpp index 2447bf8c84..13c32ee8c4 100644 --- a/gnss/aidl/vts/gnss_hal_test.cpp +++ b/gnss/aidl/vts/gnss_hal_test.cpp @@ -14,20 +14,31 @@ * limitations under the License. */ +#define LOG_TAG "GnssHalTest" + #include "gnss_hal_test.h" #include +#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(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::SetUpGnssCallback(); + if (aidl_gnss_hal_->getInterfaceVersion() == 1) { + // Invoke the super method. + GnssHalTestTemplate::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::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::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::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::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> GnssHalTest::convertToAidl( + const std::list>& sv_info_list) { + std::list> aidl_sv_info_list; + for (const auto& sv_info_vec : sv_info_list) { + std::vector 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(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> sv_info_list, + const int min_observations) { + return FindStrongFrequentNonGpsSource(convertToAidl(sv_info_list), min_observations); +} + +BlocklistedSource GnssHalTest::FindStrongFrequentNonGpsSource( + const std::list> sv_info_list, + const int min_observations) { + std::map 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(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( + GnssHalTestTemplate::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 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; } diff --git a/gnss/aidl/vts/gnss_hal_test.h b/gnss/aidl/vts/gnss_hal_test.h index e3ecbed8cc..d479af3445 100644 --- a/gnss/aidl/vts/gnss_hal_test.h +++ b/gnss/aidl/vts/gnss_hal_test.h @@ -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> convertToAidl( + const std::list>& + sv_info_list); + android::hardware::gnss::BlocklistedSource FindStrongFrequentNonGpsSource( + const std::list> + sv_info_list, + const int min_observations); + android::hardware::gnss::BlocklistedSource FindStrongFrequentNonGpsSource( + const std::list> + sv_info_list, + const int min_observations); + sp aidl_gnss_hal_; sp aidl_gnss_cb_; // Primary callback interface }; diff --git a/gnss/aidl/vts/gnss_hal_test_cases.cpp b/gnss/aidl/vts/gnss_hal_test_cases.cpp index 90b643ca86..3aa308fbdb 100644 --- a/gnss/aidl/vts/gnss_hal_test_cases.cpp +++ b/gnss/aidl/vts/gnss_hal_test_cases.cpp @@ -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> 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 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(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(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> 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> 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> 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 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(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 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(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 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 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(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 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(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 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 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(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(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 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(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(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 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 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(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(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 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(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(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 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; diff --git a/gnss/common/utils/default/Utils.cpp b/gnss/common/utils/default/Utils.cpp index c339e72d43..563c6d5d21 100644 --- a/gnss/common/utils/default/Utils.cpp +++ b/gnss/common/utils/default/Utils.cpp @@ -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 Utils::getMockSvInfoList() { + std::vector 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 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; } diff --git a/gnss/common/utils/default/include/Utils.h b/gnss/common/utils/default/include/Utils.h index 4500ee6abf..7065a6fb00 100644 --- a/gnss/common/utils/default/include/Utils.h +++ b/gnss/common/utils/default/include/Utils.h @@ -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 + getMockSvInfoList(); static hidl_vec 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 getMockAntennaInfos(); }; diff --git a/gnss/common/utils/vts/Android.bp b/gnss/common/utils/vts/Android.bp index 47eff2ec9c..f92e609f3c 100644 --- a/gnss/common/utils/vts/Android.bp +++ b/gnss/common/utils/vts/Android.bp @@ -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", diff --git a/gnss/common/utils/vts/Utils.cpp b/gnss/common/utils/vts/Utils.cpp index be22ff6e65..06bce9d3a7 100644 --- a/gnss/common/utils/vts/Utils.cpp +++ b/gnss/common/utils/vts/Utils.cpp @@ -15,6 +15,7 @@ */ #include +#include #include "gtest/gtest.h" #include @@ -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() { diff --git a/gnss/common/utils/vts/include/Utils.h b/gnss/common/utils/vts/include/Utils.h index 91c1167b31..40f31d288e 100644 --- a/gnss/common/utils/vts/include/Utils.h +++ b/gnss/common/utils/vts/include/Utils.h @@ -21,6 +21,7 @@ #include #include #include +#include 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 + 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 + static int64_t getLocationTimestampMillis(const T&); }; +template +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 diff --git a/gnss/common/utils/vts/include/v2_1/GnssCallback.h b/gnss/common/utils/vts/include/v2_1/GnssCallback.h index ab1375d3a5..09a67de717 100644 --- a/gnss/common/utils/vts/include/v2_1/GnssCallback.h +++ b/gnss/common/utils/vts/include/v2_1/GnssCallback.h @@ -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;