Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Xiaomi Mi 8 doesn't show carrier frequency in Status "CF" column #167

Closed
benzfish opened this issue Jul 11, 2018 · 12 comments

Comments

@benzfish
Copy link

commented Jul 11, 2018

Summary:

I can not see getCarrierFrequencyHz used for getting carrier frequency in Status view "CF" column

Steps to reproduce:

I have download source code, but don't see getCarrierFrequencyHz here

Expected behavior:

i think carrier frequency should show at status fragment.

Observed behavior:

I see blank at CF column

Device and Android version:

I use Xiaomi MI8 which support dual frequencies
and it is running at android 8.1 (Oreo)

@barbeau barbeau changed the title carrier frequency can not show at status fregment Xiaomi Mi 8 doesn't show carrier frequency in Status "CF" column Jul 11, 2018

@barbeau barbeau added the bug label Jul 11, 2018

@barbeau barbeau modified the milestones: v3.2, v3.1.x Jul 11, 2018

@barbeau

This comment has been minimized.

Copy link
Owner

commented Jul 11, 2018

@benzfish Thanks for opening this issue! I had been putting off opening it hoping that this was an oversight and Xiaomi would quickly fix it with a firmware update, but given that it was released on May 31st this is looking increasingly unlikely. What firmware version is your Mi 8 on currently?

I outlined some of the background of the problem in the article I wrote on dual-frequency on Android:
https://medium.com/@sjbarbeau/dual-frequency-gnss-on-android-devices-152b8826e1c

...and specifically in the Xiaomi Mi 8 section:
https://medium.com/p/152b8826e1c#3451

Here's the screenshot from another Mi 8 user:
image

Here's what I see:

  1. 👍 Dual frequency appears to be in use for GPS (1, 8, 27, and 30), Galileo (12), and QZSS (193), as they all have two entries in the list!
  2. 👎 This Mi 8 with firmware MIUI 9.5 | Stable 9.5.6.0(OEACNFA) and Android 8.1.0 doesn’t appear to support the GnssStatus.getCarrierFrequencyHz() method to get the carrier frequency for each satellite. GPSTest will show the text classification of the carrier frequency (e.g. L1, L5) if it’s in a recognized range, and it will display the raw float value if it’s not in a recognized range. So blanks mean that the API isn’t returning any data at all (more info on how GPSTest processes this info is [here])(https://medium.com/p/152b8826e1c#6b24). UPDATE June 20 — MIUI 9.5 firmware 9.5.8.0 OEACNFA doesn’t show CF either. UPDATE June 21 — MIUI 10 8.6.21 firmware also doesn’t show CF.

Based on user screenshots of GnssLogger it appears that the Xiaomi Mi 8 is populating carrier frequency information for the GnssMeasurement.getCarrierFrequencyHz() method:
https://developer.android.com/reference/android/location/GnssMeasurement#getCarrierFrequencyHz()

...but NOT for the GnssStatus.getCarrierFrequencyHz() method:
https://developer.android.com/reference/android/location/GnssStatus.html#getCarrierFrequencyHz(int)

image

GnssStatus.getCarrierFrequencyHz() Android docs say:

Gets the 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 not set, 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 measurements will be reported for this same satellite, in one all the values related to L1 will be filled, and in the other all of the values related to L5 will be filled.

It seems to me, then, as a corollary of:

If the field is not set, it is the primary common use central frequency, e.g. L1 = 1575.45 MHz for GPS

...if Xiaomi is returning L5 signals in GnssStatus, getCarrierFrequencyHz() MUST be set - otherwise, it implies that the signal is on the L1 (primary) frequency, which is wrong.

I asked for clarification of this Android documentation in a few places, including:

...but so far haven't heard back. Assuming that I'm interpreting the Android docs correctly, then Xiaomi shouldn't have shipped the device in this state, especially when they are touting dual-frequency on the device. However, it looks like the Android CTS tests, which are supposed to flag any issues before devices ship, doesn't cover carrier frequency very well. I went digging into the Android CTS to see if there were any test cases for correct values in GnssStatus.getCarrierFrequencyHz(), and from GnssStatusTest it looks like there aren't:
https://android.googlesource.com/platform/cts/+/master/tests/tests/location/src/android/location/cts/GnssStatusTest.java#75

Here's the only code related to carrier frequency:

      if (status.hasCarrierFrequencyHz(i)) {
        softAssert.assertTrue("carrier_frequency_hz: Carrier frequency in hz",
            "X > 0.0",
            String.valueOf(status.getCarrierFrequencyHz(i)),
            status.getCarrierFrequencyHz(i) > 0.0);
      }

I'm assuming that because CTS didn't flag the issue, the device shipped.

Possible workarounds for showing CF values in GPSTest on the current Mi 8 would be:

  1. Trying to pair values from GnssMeasurement.getCarrierFrequencyHz() with GnssStatus objects - I don't think that works, as without carrier frequency for GnssStatus objects you can't guarantee you're matching the correct L1 or L5 object for the used-in-fix flag (assuming that the other values like azimuth, elevation, alamanac, and ephemeris are the same for both carrier frequencies).
  2. Parse carrier info from NMEA strings - NMEA seems like the only possible solution, but as far as I know carrier frequency isn't published in existing NMEA documentation (?) - or if it is it's behind a paywall. Even if I get documentation for this it's still going to be a headache to try and implement as a workaround for a single device, as there is no guarantee that the NMEA and GnssStatus listeners fire at the same time, which results in potential data sync issues.

I'm following up with some contacts to see if I can get more info on the NMEA strings and carrier info. Until then, my hands are tied on this, and it's up to Xiaomi to fix the issue with a firmware update. And, even if I do get the NMEA documentation, it's a messy workaround fix for an issue that shouldn't exist.

So, in summary - IMHO this is a firmware issue with the Xiaomi Mi 8, and they need to fix it. I'll leave this issue open until the problem is resolved one way or another.

@barbeau

This comment has been minimized.

Copy link
Owner

commented Jul 12, 2018

Here is a PDF from Broadcom, presumably for the BCM47755:
Howto_check_SV_band_in_android.pdf

It says:

GNSS Android hardware interface

  • There are two HAL interfaces in AOSP (Android Open Source Project):
    • Legacy gps.h interface
      • That was the only interface until Oreo
    • Gnss 1.0 IGnssCallback.hal interface
      • Introduced in Oreo version
  • The two interfaces are coexisting in Oreo
  • The legacy interface does not have a field for the carrier frequency in GnssStatus while the new interface has
  • GNSS Vendors are transitioning from legacy interface to the new one

Reading between the lines, the phrase "GNSS Vendors are transitioning from legacy interface to the new one" seems to indicate that Broadcomm doesn't yet support the IGnssCallback.hal, and therefore it can't pass the carrier frequency to the Android platform, which is why GnssStatus, getCarrierFrequencyHz() is left empty on the Xiaomi Mi 8. But, carrier frequency IS available from the GnssMeasurement.getCarrierFrequencyHz() method, and therefore somehow carrier frequency is getting through the HAL to Android, so this is a bit confusing.

Here's the NMEA section:

GNSS NMEA SV Info

  • The NMEA generated by the vendor is also sent through the HAL interface
  • Newer versions of the NMEA spec have fields to identify the band of the signals in track
  • An extra parameter has been added to the GSV sentence in the latest spec
    • Old version of NMEA
      • $GPGSV,l,L,N,SV,El,Az,dBHz,SV,El,Ax,dBHz,...*Chk
        • l :line number
        • L:Total GPGSV sentences
        • N:Total number of SVs
        • SV: Satellite ID
        • El: Elevation
        • Az: Azimuth
        • dBHz: Field with the SNR of the SV
        • Chk: Checksum of the NMEA sentence
  • New version of NMEA
    • $GPGSV,l,L,N,SV,El,Az,dBHz,SV,El,Ax,dBHz,...,Band*Chk
      • Band: carrier frequency of the SVs in track
        • 1 -> E5A
        • 8 -> L5

$GAGSV,2,1,04,126,70,243,47,101,61,303,48*FF
$GAGSV,2,2,04,126,,,49,101,,,49,1*FF
$GPGSV,2,1,06,21,60,152,48,25,25,107,45,26,58,316,50,29,43,04 9,49*FF
$GPGSV,2,2,06,26,,,49,25,,,47,8*FF

In previous example Galileo NMEA SVs 126 and 101 are tracked:

  • E1 (47dBHz for SV 126, 48dBHz for SV 101)
    • The lack of flags in the last field (before the *) is E1/L1 by default
  • E5A (49dBHz for SV 126, 49dBHZ for SV 101)
  • L1 (48 dBHz for SV 21, 45dBHz for SV 25…)
  • L5 (49dBHz for SV 26, 47dBHz for SV 25)
    • You can see SV21 is in the L1 list but not in the L5 NMEA sentence

From https://www.u-blox.com/sites/default/files/products/documents/u-blox8-M8_ReceiverDescrProtSpec_(UBX-13003221)_Public.pdf#page=112:

31.1.2 Talker ID
One of the ways the NMEA standard differentiates between GNSS is by using a two-letter message identifier, the 'Talker ID'. The specific Talker ID used by a u-blox receiver will depend on the device model and system configuration. The table below shows the Talker ID that will be used for various GNSS configurations.

Configured GNSS Talker ID
GPS, SBAS, QZSS GP
GLONASS GL
Galileo GA
BeiDou GB
Any combination of GNSS GN

So the GA prefix is for Galileo, and the GP prefix is for GPS

Here is a NMEA reference for GSV strings:
http://www.trimble.com/oem_receiverhelp/v4.44/en/NMEA-0183messages_GSV.html

The GSV message string identifies the number of SVs in view, the PRN numbers, elevations, azimuths, and SNR values. An example of the GSV message string is:

$GPGSV,4,1,13,02,02,213,,03,-3,000,,11,00,121,,14,13,172,05*67

GSV message fields

Field Meaning
0 Message ID $GPGSV
1 Total number of messages of this type in this cycle
2 Message number
3 Total number of SVs visible
4 SV PRN number
5 Elevation, in degrees, 90° maximum
6 Azimuth, degrees from True North, 000° through 359°
7 SNR, 00 through 99 dB (null when not tracking)
8–11 Information about second SV, same format as fields 4 through 7
12–15 Information about third SV, same format as fields 4 through 7
16–19 Information about fourth SV, same format as fields 4 through 7
20 The checksum data, always begins with *
@barbeau

This comment has been minimized.

Copy link
Owner

commented Jul 12, 2018

So, digesting the above - given a NMEA GSV string like:

$GAGSV,2,1,04,126,70,243,47,101,61,303,48*FF

Indexes 4, 8,12, and 16 (assuming 0-indexed) are the svids (indexes 8, 12, and 16 may be empty). If index 12 is *, there is no carrier information, so by default this is the L1 signal for GPS/QZSS (GPGSV strings) or E1 signal for Galileo (GAGSV strings).

For example, in this NMEA string:

$GAGSV,2,2,04,126,,,49,101,,,49,1*FF

...index 12 is 1 so it's the E5A band (for Galileo) and if it's 8 then it's L5 (for GPS/QZSS).

@barbeau

This comment has been minimized.

Copy link
Owner

commented Jul 29, 2018

After reviewing the Broadcom slides further, it looks like I can't extract all needed information to link the NMEA strings to the GnssStatus objects that are used in the GPSTest "Status" view.

Specifically, there is a boolean value in the GnssStatus object for whether or not a specific signal is "used" to compute the location of the device, and this same field doesn't exist in the NMEA string. So from the NMEA strings I can't see if a particular signal is used. And, without the carrier frequency info in the GnssStatus object, I can't link the NMEA string uniquely to a GnssStatus object.

So unfortunately it looks like I'm still stuck waiting for Xiaomi to add support for GnssStatus.getCarrierFrequencyHz() to the Mi 8.

@barbeau barbeau modified the milestones: v3.1.x, v3.2 Aug 21, 2018

@barbeau

This comment has been minimized.

Copy link
Owner

commented Sep 5, 2018

Google has updated the Android CTS suite to include a new unit test for carrier frequency:
https://android.googlesource.com/platform/cts/+/a106fb6b114d63a16759728360a49cd5b5dc645a

It says:

Check presence of Carrier Frequency in GnssStatus

CDD Section 7.3.3 / C-3-3 If GPS/GNSS receiver of the device reports
the year "2017" or newer, they MUST report Frequency of GNSS measurement.

This is being enforced from Year 2018 onwards

The Mi 8 is GNSS HW year 2018, so it will currently fail this CTS test, as it does not provide carrier frequency via GnssStatus. So, I hope Xiaomi will acknowledge this and fix it in an update.

@goldfndr

This comment has been minimized.

Copy link
Contributor

commented Sep 6, 2018

They'll perhaps get to eventually update the test, as the ranges (1100-1300, 1500-1700) exclude the IRNSS "S" frequency.

@barbeau

This comment has been minimized.

Copy link
Owner

commented Sep 10, 2018

Looks like Xiaomi has fixed this issue in the latest Android P update:
https://medium.com/@trungthanh1288/this-is-mi-8-with-newest-android-p-in-beta-testing-program-655f95a5e376

image

So that's great news! The Beidou frequency looks strange, but I'll open another issue for that.

@barbeau barbeau closed this Sep 10, 2018

@barbeau barbeau added the wontfix label Sep 10, 2018

@barbeau

This comment has been minimized.

Copy link
Owner

commented Sep 10, 2018

Invalid Beidou frequency ticketed in #202.

@claudiaareneee

This comment has been minimized.

Copy link

commented Feb 25, 2019

Hey! Does anyone know why on the Xiaomi all of the C/N0, azimuth, and elevation values all end in a ".0" for the GnssStatus callback? It seems like there is some double to integer to double conversion happening somewhere.

screen shot 2019-02-24 at 10 18 35 pm

I have worked with a Samsung too, and the C/N0 does have other decimal values than ".0"

@barbeau

This comment has been minimized.

Copy link
Owner

commented Feb 28, 2019

@claudiaareneee From the devices I've seen it's fairly common to have all .0 for Elevation and Azimuth, but not common to have all .0 for C/N0 values. It's strange that the Mi 8 does that.

All 3 data types are floats coming from the Android API:
https://developer.android.com/reference/android/location/GnssStatus

...and they all get rounded to 1 decimal place in the formatting for GPSTest.

Also, what version of the GPSTest app are you running? It looks like an old version, as the CF value for those Beidou satellites should be shown properly in the latest version.

@claudiaareneee

This comment has been minimized.

Copy link

commented Mar 2, 2019

@barbeau I'm currently running version 3.1.0. I have looked into the documentation and seen that the data types are all doubles. I thought it strange too.

@goldfndr

This comment has been minimized.

Copy link
Contributor

commented Mar 15, 2019

Hey! Does anyone know why on the Xiaomi all of the C/N0, azimuth, and elevation values all end in a ".0" for the GnssStatus callback? It seems like there is some double to integer to double conversion happening somewhere.

See also #130 regarding dropping the ".0" for elevation and azimuth.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
4 participants
You can’t perform that action at this time.