GnssMetrics

These metrics will pull different metrics that tell the performance of the gnss subsystem.

Metrics include:
Location reports
% of location failure
Num times GPS had to first fix
Mean time to first fix on signal
Num position accuracy logs
Mean position accuracy in meters
Num top 4 Cn0 messages
Mean top 4 average Cn0 (signal quality)
Num L5 top 4 Cn0 messages
Mean L5 top 4 average Cn0 (signal quality)
Num Satellite status messages received
Num of Satellites used in fix
L5 Satellite status messages received
L5 of Satellites used in fix

metric_id: 1111
gauge_metrics {
  data {
    bucket_info {
      atom {
        gnss_stats {
          location_reports: 12
          location_failure_reports: 3
          time_to_first_fix_reports: 2
          time_to_first_fix_milli_s: 43588
          position_accuracy_reports: 9
          position_accuracy_meters: 112
          top_four_average_cn0_reports: 31
          top_four_average_cn0_db_mhz: 734711
          l5_top_four_average_cn0_reports: 1
          l5_top_four_average_cn0_db_mhz: 21500
          sv_status_reports: 1015
          sv_status_reports_used_in_fix: 100
          l5_sv_status_reports: 7
          l5_sv_status_reports_used_in_fix: 0
        }
      }
      elapsed_timestamp_nanos: 537249375445
      start_bucket_elapsed_millis: 522186
      end_bucket_elapsed_millis: 549283
    }
  }
}
time_base_elapsed_nano_seconds: 9283624934
bucket_size_nano_seconds: 60000000000
is_active: true

Bug: 147910698
Test: On Device using test script and gnsslogger.apk
>  make statsd_testdrive
>  ./out/host/linux-x86/bin/statsd_testdrive <ATOM_ID>

Change-Id: I92461eb8533ec810bb67d76a25931295cfa1efbd
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 27c4f4e..652775b 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -396,7 +396,7 @@
     }
 
     // Pulled events will start at field 10000.
-    // Next: 10074
+    // Next: 10075
     oneof pulled {
         WifiBytesTransfer wifi_bytes_transfer = 10000 [(module) = "framework"];
         WifiBytesTransferByFgBg wifi_bytes_transfer_by_fg_bg = 10001 [(module) = "framework"];
@@ -477,6 +477,7 @@
                 10072 [(module) = "framework"];
         PackageNotificationChannelGroupPreferences package_notification_channel_group_preferences =
                 10073 [(module) = "framework"];
+        GnssStats gnss_stats = 10074 [(module) = "framework"];
     }
 
     // DO NOT USE field numbers above 100,000 in AOSP.
@@ -8475,20 +8476,71 @@
  *   frameworks/base/services/core/java/com/android/server/am/CachedAppOptimizer.java
  */
 message AppFreezeChanged {
-  // The type of event.
-  enum Action {
-    UNKNOWN = 0;
-    FREEZE_APP = 1;
-    UNFREEZE_APP = 2;
-  }
-  optional Action action = 1;
+    // The type of event.
+    enum Action {
+        UNKNOWN = 0;
+        FREEZE_APP = 1;
+        UNFREEZE_APP = 2;
+    }
+    optional Action action = 1;
 
-  // Pid of the process being frozen.
-  optional int32 pid = 2;
+    // Pid of the process being frozen.
+    optional int32 pid = 2;
 
-  // Name of the process being frozen.
-  optional string process_name = 3;
+    // Name of the process being frozen.
+    optional string process_name = 3;
 
-  // Time since last unfrozen.
-  optional int64 time_unfrozen_millis = 4;
+    // Time since last unfrozen.
+    optional int64 time_unfrozen_millis = 4;
+}
+
+/**
+ * Logs gnss stats from location service provider
+ *
+ * Pulled from:
+ *  frameworks/base/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java
+ */
+
+message GnssStats {
+    // Number of location reports since boot
+    optional int64 location_reports = 1;
+
+    // Total pulled reports of Location failures since boot
+    optional int64 location_failure_reports = 2;
+
+    // Number of time to first fix reports since boot
+    optional int64 time_to_first_fix_reports = 3;
+
+    // Total pulled reported time to first fix (in milli-seconds) since boot
+    optional int64 time_to_first_fix_milli_s = 4;
+
+    // Number of position accuracy reports since boot
+    optional int64 position_accuracy_reports = 5;
+
+    // Total pulled reported position accuracy (in meters) since boot
+    optional int64 position_accuracy_meters = 6;
+
+    // Number of top 4 average CN0 reports since boot
+    optional int64 top_four_average_cn0_reports = 7;
+
+    // Total pulled reported of top 4 average CN0 (dB-mHz) since boot
+    optional int64 top_four_average_cn0_db_mhz = 8;
+
+    // Number of l5 top 4 average CN0 reports since boot
+    optional int64 l5_top_four_average_cn0_reports = 9;
+
+    // Total pulled reported of l5 top 4 average CN0 (dB-mHz) since boot
+    optional int64 l5_top_four_average_cn0_db_mhz = 10;
+
+    // Total number of sv status messages reports since boot
+    optional int64 sv_status_reports = 11;
+
+    // Total number of sv status messages reports, where sv is used in fix since boot
+    optional int64 sv_status_reports_used_in_fix = 12;
+
+    // Total number of L5 sv status messages reports since boot
+    optional int64 l5_sv_status_reports = 13;
+
+    // Total number of L5 sv status messages reports, where sv is used in fix since boot
+    optional int64 l5_sv_status_reports_used_in_fix = 14;
 }
diff --git a/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java b/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java
index d571480..1ac4b4b 100644
--- a/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java
+++ b/location/java/com/android/internal/location/gnssmetrics/GnssMetrics.java
@@ -16,6 +16,8 @@
 
 package com.android.internal.location.gnssmetrics;
 
+import android.app.StatsManager;
+import android.content.Context;
 import android.location.GnssStatus;
 import android.os.SystemClock;
 import android.os.SystemProperties;
@@ -24,16 +26,19 @@
 import android.text.format.DateUtils;
 import android.util.Base64;
 import android.util.Log;
+import android.util.StatsEvent;
 import android.util.TimeUtils;
 
 import com.android.internal.app.IBatteryStats;
 import com.android.internal.location.nano.GnssLogsProto.GnssLog;
 import com.android.internal.location.nano.GnssLogsProto.PowerMetrics;
+import com.android.internal.os.BackgroundThread;
 import com.android.internal.util.FrameworkStatsLog;
 
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.List;
 
 /**
  * GnssMetrics: Is used for logging GNSS metrics
@@ -96,7 +101,34 @@
     /** Total number of L5 sv status messages processed, where sv is used in fix */
     private int mNumL5SvStatusUsedInFix;
 
-    public GnssMetrics(IBatteryStats stats) {
+    /* Statsd Logging Variables Section Start */
+    /** Location failure reports since boot used for statsd logging */
+    private Statistics mLocationFailureReportsStatistics;
+    /** Time to first fix milli-seconds since boot used for statsd logging */
+    private Statistics mTimeToFirstFixMilliSReportsStatistics;
+    /** Position accuracy meters since boot used for statsd logging  */
+    private Statistics mPositionAccuracyMetersReportsStatistics;
+    /** Top 4 average CN0 (db-mHz) since boot used for statsd logging  */
+    private Statistics mTopFourAverageCn0DbmHzReportsStatistics;
+    /** Top 4 average CN0 (db-mHz) L5 since boot used for statsd logging  */
+    private Statistics mL5TopFourAverageCn0DbmHzReportsStatistics;
+    /** Total number of sv status reports processed since boot used for statsd logging  */
+    private long mSvStatusReports;
+    /** Total number of L5 sv status reports processed since boot used for statsd logging  */
+    private long mL5SvStatusReports;
+    /** Total number of sv status reports processed, where sv is used in fix since boot used for
+     * statsd logging  */
+    private long mSvStatusReportsUsedInFix;
+    /** Total number of L5 sv status reports processed, where sv is used in fix since boot used for
+     * statsd logging  */
+    private long mL5SvStatusReportsUsedInFix;
+    /** Stats manager service for reporting atoms */
+    private StatsManager mStatsManager;
+    /** Pull atom callback, this is called when atom pull request occurs */
+    private StatsPullAtomCallbackImpl mPullAtomCallback;
+    /* Statds Logging Variables Section End */
+
+    public GnssMetrics(Context context, IBatteryStats stats) {
         mGnssPowerMetrics = new GnssPowerMetrics(stats);
         mLocationFailureStatistics = new Statistics();
         mTimeToFirstFixSecStatistics = new Statistics();
@@ -104,6 +136,13 @@
         mTopFourAverageCn0Statistics = new Statistics();
         mTopFourAverageCn0StatisticsL5 = new Statistics();
         reset();
+        mLocationFailureReportsStatistics = new Statistics();
+        mTimeToFirstFixMilliSReportsStatistics = new Statistics();
+        mPositionAccuracyMetersReportsStatistics = new Statistics();
+        mTopFourAverageCn0DbmHzReportsStatistics = new Statistics();
+        mL5TopFourAverageCn0DbmHzReportsStatistics = new Statistics();
+        mStatsManager = (StatsManager) context.getSystemService(Context.STATS_MANAGER);
+        registerGnssStats();
     }
 
     /**
@@ -112,9 +151,11 @@
     public void logReceivedLocationStatus(boolean isSuccessful) {
         if (!isSuccessful) {
             mLocationFailureStatistics.addItem(1.0);
+            mLocationFailureReportsStatistics.addItem(1.0);
             return;
         }
         mLocationFailureStatistics.addItem(0.0);
+        mLocationFailureReportsStatistics.addItem(0.0);
     }
 
     /**
@@ -127,6 +168,7 @@
         if (numReportMissed > 0) {
             for (int i = 0; i < numReportMissed; i++) {
                 mLocationFailureStatistics.addItem(1.0);
+                mLocationFailureReportsStatistics.addItem(1.0);
             }
         }
     }
@@ -136,6 +178,7 @@
      */
     public void logTimeToFirstFixMilliSecs(int timeToFirstFixMilliSeconds) {
         mTimeToFirstFixSecStatistics.addItem((double) (timeToFirstFixMilliSeconds / 1000));
+        mTimeToFirstFixMilliSReportsStatistics.addItem(timeToFirstFixMilliSeconds);
     }
 
     /**
@@ -143,6 +186,7 @@
      */
     public void logPositionAccuracyMeters(float positionAccuracyMeters) {
         mPositionAccuracyMeterStatistics.addItem((double) positionAccuracyMeters);
+        mPositionAccuracyMetersReportsStatistics.addItem(positionAccuracyMeters);
     }
 
     /**
@@ -174,6 +218,8 @@
             }
             top4AvgCn0 /= 4;
             mTopFourAverageCn0Statistics.addItem(top4AvgCn0);
+            // Convert to mHz for accuracy
+            mTopFourAverageCn0DbmHzReportsStatistics.addItem(top4AvgCn0 * 1000);
         }
     }
     /* Helper function to check if a SV is L5 */
@@ -191,14 +237,18 @@
         for (int i = 0; i < status.getSatelliteCount(); i++) {
             if (status.hasCarrierFrequencyHz(i)) {
                 mNumSvStatus++;
+                mSvStatusReports++;
                 isL5 = isL5Sv(status.getCarrierFrequencyHz(i));
                 if (isL5) {
                     mNumL5SvStatus++;
+                    mL5SvStatusReports++;
                 }
                 if (status.usedInFix(i)) {
                     mNumSvStatusUsedInFix++;
+                    mSvStatusReportsUsedInFix++;
                     if (isL5) {
                         mNumL5SvStatusUsedInFix++;
+                        mL5SvStatusReportsUsedInFix++;
                     }
                 }
             }
@@ -233,6 +283,8 @@
             }
             top4AvgCn0 /= 4;
             mTopFourAverageCn0StatisticsL5.addItem(top4AvgCn0);
+            // Convert to mHz for accuracy
+            mL5TopFourAverageCn0DbmHzReportsStatistics.addItem(top4AvgCn0 * 1000);
         }
         return;
     }
@@ -421,12 +473,14 @@
         private int mCount;
         private double mSum;
         private double mSumSquare;
+        private long mLongSum;
 
         /** Resets statistics */
         public void reset() {
             mCount = 0;
             mSum = 0.0;
             mSumSquare = 0.0;
+            mLongSum = 0;
         }
 
         /** Adds an item */
@@ -434,6 +488,7 @@
             mCount++;
             mSum += item;
             mSumSquare += item * item;
+            mLongSum += item;
         }
 
         /** Returns number of items added */
@@ -456,6 +511,11 @@
             }
             return 0;
         }
+
+        /** Returns long sum */
+        public long getLongSum() {
+            return mLongSum;
+        }
     }
 
     /* Class for handling GNSS power related metrics */
@@ -561,4 +621,44 @@
             return GnssMetrics.GPS_SIGNAL_QUALITY_POOR;
         }
     }
+
+    private void registerGnssStats() {
+        mPullAtomCallback = new StatsPullAtomCallbackImpl();
+        mStatsManager.registerPullAtomCallback(
+                FrameworkStatsLog.GNSS_STATS,
+                null, // use default PullAtomMetadata values
+                BackgroundThread.getExecutor(), mPullAtomCallback);
+    }
+
+    /**
+     * Stats Pull Atom Callback
+     * Calls the pull method to fill out gnss stats
+     */
+    private class StatsPullAtomCallbackImpl implements StatsManager.StatsPullAtomCallback {
+        @Override
+        public int onPullAtom(int atomTag, List<StatsEvent> data) {
+            if (atomTag != FrameworkStatsLog.GNSS_STATS) {
+                throw new UnsupportedOperationException("Unknown tagId = " + atomTag);
+            }
+            StatsEvent e = StatsEvent.newBuilder()
+                    .setAtomId(atomTag)
+                    .writeLong(mLocationFailureReportsStatistics.getCount())
+                    .writeLong(mLocationFailureReportsStatistics.getLongSum())
+                    .writeLong(mTimeToFirstFixMilliSReportsStatistics.getCount())
+                    .writeLong(mTimeToFirstFixMilliSReportsStatistics.getLongSum())
+                    .writeLong(mPositionAccuracyMetersReportsStatistics.getCount())
+                    .writeLong(mPositionAccuracyMetersReportsStatistics.getLongSum())
+                    .writeLong(mTopFourAverageCn0DbmHzReportsStatistics.getCount())
+                    .writeLong(mTopFourAverageCn0DbmHzReportsStatistics.getLongSum())
+                    .writeLong(mL5TopFourAverageCn0DbmHzReportsStatistics.getCount())
+                    .writeLong(mL5TopFourAverageCn0DbmHzReportsStatistics.getLongSum())
+                    .writeLong(mSvStatusReports)
+                    .writeLong(mSvStatusReportsUsedInFix)
+                    .writeLong(mL5SvStatusReports)
+                    .writeLong(mL5SvStatusReportsUsedInFix)
+                    .build();
+            data.add(e);
+            return StatsManager.PULL_SUCCESS;
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index 36136f4..c0e4ab25 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -714,7 +714,7 @@
             }
         };
 
-        mGnssMetrics = new GnssMetrics(mBatteryStats);
+        mGnssMetrics = new GnssMetrics(mContext, mBatteryStats);
         mNtpTimeHelper = new NtpTimeHelper(mContext, mLooper, this);
         GnssSatelliteBlacklistHelper gnssSatelliteBlacklistHelper =
                 new GnssSatelliteBlacklistHelper(mContext,