High speed GPS/GNSS Navigation Information Block am: 5d5bac8383
am: 0021090eb9

Change-Id: I77d910e9cfd33d5b4aeabfa0f2c2db7fa73120b4
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index 9ae496f..45f54a9 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -415,6 +415,12 @@
 
     private int mYearOfHardware = 0;
 
+    // Set lower than the current ITAR limit of 600m/s to allow this to trigger even if GPS HAL
+    // stops output right at 600m/s, depriving this of the information of a device that reaches
+    // greater than 600m/s, and higher than the speed of sound to avoid impacting most use cases.
+    private static final float ITAR_SPEED_LIMIT_METERS_PER_SECOND = 400.0F;
+    private boolean mItarSpeedLimitExceeded = false;
+
     private final IGnssStatusProvider mGnssStatusProvider = new IGnssStatusProvider.Stub() {
         @Override
         public void registerGnssStatusCallback(IGnssStatusListener callback) {
@@ -1400,6 +1406,12 @@
             mStarted = true;
             mSingleShot = singleShot;
             mPositionMode = GPS_POSITION_MODE_STANDALONE;
+            // Notify about suppressed output, if speed limit was previously exceeded.
+            // Elsewhere, we check again with every speed output reported.
+            if (mItarSpeedLimitExceeded) {
+                Log.i(TAG, "startNavigating with ITAR limit in place. Output limited  " +
+                        "until slow enough speed reported.");
+            }
 
             boolean agpsEnabled =
                     (Settings.Global.getInt(mContext.getContentResolver(),
@@ -1486,7 +1498,17 @@
      * called from native code to update our position.
      */
     private void reportLocation(int flags, double latitude, double longitude, double altitude,
-            float speed, float bearing, float accuracy, long timestamp) {
+            float speedMetersPerSecond, float bearing, float accuracy, long timestamp) {
+        if ((flags & LOCATION_HAS_SPEED) == LOCATION_HAS_SPEED) {
+            mItarSpeedLimitExceeded = speedMetersPerSecond > ITAR_SPEED_LIMIT_METERS_PER_SECOND;
+        }
+
+        if (mItarSpeedLimitExceeded) {
+            Log.i(TAG, "Hal reported a speed in excess of ITAR limit." +
+                    "  GPS/GNSS Navigation output blocked.");
+            return;  // No output of location allowed
+        }
+
         if (VERBOSE) Log.v(TAG, "reportLocation lat: " + latitude + " long: " + longitude +
                 " timestamp: " + timestamp);
 
@@ -1506,7 +1528,7 @@
                 mLocation.removeAltitude();
             }
             if ((flags & LOCATION_HAS_SPEED) == LOCATION_HAS_SPEED) {
-                mLocation.setSpeed(speed);
+                mLocation.setSpeed(speedMetersPerSecond);
             } else {
                 mLocation.removeSpeed();
             }
@@ -1690,23 +1712,29 @@
      * called from native code to report NMEA data received
      */
     private void reportNmea(long timestamp) {
-        int length = native_read_nmea(mNmeaBuffer, mNmeaBuffer.length);
-        String nmea = new String(mNmeaBuffer, 0 /* offset */, length);
-        mListenerHelper.onNmeaReceived(timestamp, nmea);
+        if (!mItarSpeedLimitExceeded) {
+            int length = native_read_nmea(mNmeaBuffer, mNmeaBuffer.length);
+            String nmea = new String(mNmeaBuffer, 0 /* offset */, length);
+            mListenerHelper.onNmeaReceived(timestamp, nmea);
+        }
     }
 
     /**
      * called from native code - Gps measurements callback
      */
     private void reportMeasurementData(GnssMeasurementsEvent event) {
-        mGnssMeasurementsProvider.onMeasurementsAvailable(event);
+        if (!mItarSpeedLimitExceeded) {
+            mGnssMeasurementsProvider.onMeasurementsAvailable(event);
+        }
     }
 
     /**
      * called from native code - GPS navigation message callback
      */
     private void reportNavigationMessage(GnssNavigationMessage event) {
-        mGnssNavigationMessageProvider.onNavigationMessageAvailable(event);
+        if (!mItarSpeedLimitExceeded) {
+            mGnssNavigationMessageProvider.onNavigationMessageAvailable(event);
+        }
     }
 
     /**