Merge "Optimized the memory consumption and renamed PRN" into nyc-dev
diff --git a/api/current.txt b/api/current.txt
index ab52161..dc7e280 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -19221,7 +19221,6 @@
     method public double getElevationUncertaintyInDeg();
     method public byte getLossOfLock();
     method public byte getMultipathIndicator();
-    method public byte getPrn();
     method public double getPseudorangeInMeters();
     method public double getPseudorangeRateCarrierInMetersPerSec();
     method public double getPseudorangeRateCarrierUncertaintyInMetersPerSec();
@@ -19232,6 +19231,7 @@
     method public long getReceivedGpsTowUncertaintyInNs();
     method public double getSnrInDb();
     method public short getState();
+    method public short getSvid();
     method public short getTimeFromLastBitInMs();
     method public double getTimeOffsetInNs();
     method public boolean hasAzimuthInDeg();
@@ -19291,7 +19291,6 @@
     method public void setElevationUncertaintyInDeg(double);
     method public void setLossOfLock(byte);
     method public void setMultipathIndicator(byte);
-    method public void setPrn(byte);
     method public void setPseudorangeInMeters(double);
     method public void setPseudorangeRateCarrierInMetersPerSec(double);
     method public void setPseudorangeRateCarrierUncertaintyInMetersPerSec(double);
@@ -19302,6 +19301,7 @@
     method public void setReceivedGpsTowUncertaintyInNs(long);
     method public void setSnrInDb(double);
     method public void setState(short);
+    method public void setSvid(short);
     method public void setTimeFromLastBitInMs(short);
     method public void setTimeOffsetInNs(double);
     method public void setUsedInFix(boolean);
@@ -19356,17 +19356,17 @@
     method public int describeContents();
     method public byte[] getData();
     method public short getMessageId();
-    method public byte getPrn();
     method public short getStatus();
     method public short getSubmessageId();
+    method public short getSvid();
     method public byte getType();
     method public void reset();
     method public void set(android.location.GnssNavigationMessage);
     method public void setData(byte[]);
     method public void setMessageId(short);
-    method public void setPrn(byte);
     method public void setStatus(short);
     method public void setSubmessageId(short);
+    method public void setSvid(short);
     method public void setType(byte);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.location.GnssNavigationMessage> CREATOR;
@@ -19412,8 +19412,8 @@
     method public int getConstellationType(int);
     method public float getElevation(int);
     method public int getNumSatellites();
-    method public int getPrn(int);
     method public float getSnr(int);
+    method public int getSvid(int);
     method public boolean hasAlmanac(int);
     method public boolean hasEphemeris(int);
     method public boolean usedInFix(int);
diff --git a/api/system-current.txt b/api/system-current.txt
index 8ea1854..61f72f3 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -20401,7 +20401,6 @@
     method public double getElevationUncertaintyInDeg();
     method public byte getLossOfLock();
     method public byte getMultipathIndicator();
-    method public byte getPrn();
     method public double getPseudorangeInMeters();
     method public double getPseudorangeRateCarrierInMetersPerSec();
     method public double getPseudorangeRateCarrierUncertaintyInMetersPerSec();
@@ -20412,6 +20411,7 @@
     method public long getReceivedGpsTowUncertaintyInNs();
     method public double getSnrInDb();
     method public short getState();
+    method public short getSvid();
     method public short getTimeFromLastBitInMs();
     method public double getTimeOffsetInNs();
     method public boolean hasAzimuthInDeg();
@@ -20471,7 +20471,6 @@
     method public void setElevationUncertaintyInDeg(double);
     method public void setLossOfLock(byte);
     method public void setMultipathIndicator(byte);
-    method public void setPrn(byte);
     method public void setPseudorangeInMeters(double);
     method public void setPseudorangeRateCarrierInMetersPerSec(double);
     method public void setPseudorangeRateCarrierUncertaintyInMetersPerSec(double);
@@ -20482,6 +20481,7 @@
     method public void setReceivedGpsTowUncertaintyInNs(long);
     method public void setSnrInDb(double);
     method public void setState(short);
+    method public void setSvid(short);
     method public void setTimeFromLastBitInMs(short);
     method public void setTimeOffsetInNs(double);
     method public void setUsedInFix(boolean);
@@ -20536,17 +20536,17 @@
     method public int describeContents();
     method public byte[] getData();
     method public short getMessageId();
-    method public byte getPrn();
     method public short getStatus();
     method public short getSubmessageId();
+    method public short getSvid();
     method public byte getType();
     method public void reset();
     method public void set(android.location.GnssNavigationMessage);
     method public void setData(byte[]);
     method public void setMessageId(short);
-    method public void setPrn(byte);
     method public void setStatus(short);
     method public void setSubmessageId(short);
+    method public void setSvid(short);
     method public void setType(byte);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.location.GnssNavigationMessage> CREATOR;
@@ -20592,8 +20592,8 @@
     method public int getConstellationType(int);
     method public float getElevation(int);
     method public int getNumSatellites();
-    method public int getPrn(int);
     method public float getSnr(int);
+    method public int getSvid(int);
     method public boolean hasAlmanac(int);
     method public boolean hasEphemeris(int);
     method public boolean usedInFix(int);
diff --git a/api/test-current.txt b/api/test-current.txt
index e716292..17d788f 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -19229,7 +19229,6 @@
     method public double getElevationUncertaintyInDeg();
     method public byte getLossOfLock();
     method public byte getMultipathIndicator();
-    method public byte getPrn();
     method public double getPseudorangeInMeters();
     method public double getPseudorangeRateCarrierInMetersPerSec();
     method public double getPseudorangeRateCarrierUncertaintyInMetersPerSec();
@@ -19240,6 +19239,7 @@
     method public long getReceivedGpsTowUncertaintyInNs();
     method public double getSnrInDb();
     method public short getState();
+    method public short getSvid();
     method public short getTimeFromLastBitInMs();
     method public double getTimeOffsetInNs();
     method public boolean hasAzimuthInDeg();
@@ -19299,7 +19299,6 @@
     method public void setElevationUncertaintyInDeg(double);
     method public void setLossOfLock(byte);
     method public void setMultipathIndicator(byte);
-    method public void setPrn(byte);
     method public void setPseudorangeInMeters(double);
     method public void setPseudorangeRateCarrierInMetersPerSec(double);
     method public void setPseudorangeRateCarrierUncertaintyInMetersPerSec(double);
@@ -19310,6 +19309,7 @@
     method public void setReceivedGpsTowUncertaintyInNs(long);
     method public void setSnrInDb(double);
     method public void setState(short);
+    method public void setSvid(short);
     method public void setTimeFromLastBitInMs(short);
     method public void setTimeOffsetInNs(double);
     method public void setUsedInFix(boolean);
@@ -19364,17 +19364,17 @@
     method public int describeContents();
     method public byte[] getData();
     method public short getMessageId();
-    method public byte getPrn();
     method public short getStatus();
     method public short getSubmessageId();
+    method public short getSvid();
     method public byte getType();
     method public void reset();
     method public void set(android.location.GnssNavigationMessage);
     method public void setData(byte[]);
     method public void setMessageId(short);
-    method public void setPrn(byte);
     method public void setStatus(short);
     method public void setSubmessageId(short);
+    method public void setSvid(short);
     method public void setType(byte);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.location.GnssNavigationMessage> CREATOR;
@@ -19420,8 +19420,8 @@
     method public int getConstellationType(int);
     method public float getElevation(int);
     method public int getNumSatellites();
-    method public int getPrn(int);
     method public float getSnr(int);
+    method public int getSvid(int);
     method public boolean hasAlmanac(int);
     method public boolean hasEphemeris(int);
     method public boolean usedInFix(int);
diff --git a/location/java/android/location/GnssMeasurement.java b/location/java/android/location/GnssMeasurement.java
index d8f507c..a490685 100644
--- a/location/java/android/location/GnssMeasurement.java
+++ b/location/java/android/location/GnssMeasurement.java
@@ -28,7 +28,7 @@
  */
 public final class GnssMeasurement implements Parcelable {
     private int mFlags;
-    private byte mPrn;
+    private short mSvid;
     private double mTimeOffsetInNs;
     private short mState;
     private long mReceivedGpsTowInNs;
@@ -198,7 +198,7 @@
      */
     public void set(GnssMeasurement measurement) {
         mFlags = measurement.mFlags;
-        mPrn = measurement.mPrn;
+        mSvid = measurement.mSvid;
         mTimeOffsetInNs = measurement.mTimeOffsetInNs;
         mState = measurement.mState;
         mReceivedGpsTowInNs = measurement.mReceivedGpsTowInNs;
@@ -248,15 +248,15 @@
      * Gets the Pseudo-random number (PRN).
      * Range: [1, 32]
      */
-    public byte getPrn() {
-        return mPrn;
+    public short getSvid() {
+        return mSvid;
     }
 
     /**
      * Sets the Pseud-random number (PRN).
      */
-    public void setPrn(byte value) {
-        mPrn = value;
+    public void setSvid(short value) {
+        mSvid = value;
     }
 
     /**
@@ -1210,7 +1210,7 @@
             GnssMeasurement gnssMeasurement = new GnssMeasurement();
 
             gnssMeasurement.mFlags = parcel.readInt();
-            gnssMeasurement.mPrn = parcel.readByte();
+            gnssMeasurement.mSvid = (short) parcel.readInt();
             gnssMeasurement.mTimeOffsetInNs = parcel.readDouble();
             gnssMeasurement.mState = (short) parcel.readInt();
             gnssMeasurement.mReceivedGpsTowInNs = parcel.readLong();
@@ -1253,9 +1253,10 @@
         }
     };
 
+    @Override
     public void writeToParcel(Parcel parcel, int flags) {
         parcel.writeInt(mFlags);
-        parcel.writeByte(mPrn);
+        parcel.writeInt(mSvid);
         parcel.writeDouble(mTimeOffsetInNs);
         parcel.writeInt(mState);
         parcel.writeLong(mReceivedGpsTowInNs);
@@ -1301,7 +1302,7 @@
         final String formatWithUncertainty = "   %-29s = %-25s   %-40s = %s\n";
         StringBuilder builder = new StringBuilder("GnssMeasurement:\n");
 
-        builder.append(String.format(format, "Prn", mPrn));
+        builder.append(String.format(format, "Svid", mSvid));
 
         builder.append(String.format(format, "TimeOffsetInNs", mTimeOffsetInNs));
 
@@ -1422,7 +1423,7 @@
 
     private void initialize() {
         mFlags = HAS_NO_FLAGS;
-        setPrn(Byte.MIN_VALUE);
+        setSvid((short) 0);
         setTimeOffsetInNs(Long.MIN_VALUE);
         setState(STATE_UNKNOWN);
         setReceivedGpsTowInNs(Long.MIN_VALUE);
diff --git a/location/java/android/location/GnssNavigationMessage.java b/location/java/android/location/GnssNavigationMessage.java
index 0e011d5..86328eb 100644
--- a/location/java/android/location/GnssNavigationMessage.java
+++ b/location/java/android/location/GnssNavigationMessage.java
@@ -26,7 +26,7 @@
 import java.security.InvalidParameterException;
 
 /**
- * A class containing a GPS satellite Navigation Message.
+ * A class containing a GNSS satellite Navigation Message.
  */
 public final class GnssNavigationMessage implements Parcelable {
 
@@ -84,7 +84,7 @@
     // End enumerations in sync with gps.h
 
     private byte mType;
-    private byte mPrn;
+    private short mSvid;
     private short mMessageId;
     private short mSubmessageId;
     private byte[] mData;
@@ -99,7 +99,7 @@
      */
     public void set(GnssNavigationMessage navigationMessage) {
         mType = navigationMessage.mType;
-        mPrn = navigationMessage.mPrn;
+        mSvid = navigationMessage.mSvid;
         mMessageId = navigationMessage.mMessageId;
         mSubmessageId = navigationMessage.mSubmessageId;
         mData = navigationMessage.mData;
@@ -153,15 +153,15 @@
      * Gets the Pseudo-random number.
      * Range: [1, 32].
      */
-    public byte getPrn() {
-        return mPrn;
+    public short getSvid() {
+        return mSvid;
     }
 
     /**
      * Sets the Pseud-random number.
      */
-    public void setPrn(byte value) {
-        mPrn = value;
+    public void setSvid(short value) {
+        mSvid = value;
     }
 
     /**
@@ -256,7 +256,7 @@
             GnssNavigationMessage navigationMessage = new GnssNavigationMessage();
 
             navigationMessage.setType(parcel.readByte());
-            navigationMessage.setPrn(parcel.readByte());
+            navigationMessage.setSvid((short) parcel.readInt());
             navigationMessage.setMessageId((short) parcel.readInt());
             navigationMessage.setSubmessageId((short) parcel.readInt());
 
@@ -281,9 +281,10 @@
         }
     };
 
+    @Override
     public void writeToParcel(Parcel parcel, int flags) {
         parcel.writeByte(mType);
-        parcel.writeByte(mPrn);
+        parcel.writeInt(mSvid);
         parcel.writeInt(mMessageId);
         parcel.writeInt(mSubmessageId);
         parcel.writeInt(mData.length);
@@ -302,7 +303,7 @@
         StringBuilder builder = new StringBuilder("GnssNavigationMessage:\n");
 
         builder.append(String.format(format, "Type", getTypeString()));
-        builder.append(String.format(format, "Prn", mPrn));
+        builder.append(String.format(format, "Svid", mSvid));
         builder.append(String.format(format, "Status", getStatusString()));
         builder.append(String.format(format, "MessageId", mMessageId));
         builder.append(String.format(format, "SubmessageId", mSubmessageId));
@@ -321,7 +322,7 @@
 
     private void initialize() {
         mType = MESSAGE_TYPE_UNKNOWN;
-        mPrn = 0;
+        mSvid = 0;
         mMessageId = -1;
         mSubmessageId = -1;
         mData = EMPTY_ARRAY;
diff --git a/location/java/android/location/GnssStatus.java b/location/java/android/location/GnssStatus.java
index 77e8a5b..906e944 100644
--- a/location/java/android/location/GnssStatus.java
+++ b/location/java/android/location/GnssStatus.java
@@ -47,24 +47,26 @@
     public static final int GNSS_SV_FLAGS_USED_IN_FIX = (1 << 2);
 
     /** @hide */
-    public static final int PRN_SHIFT_WIDTH = 3;
+    public static final int SVID_SHIFT_WIDTH = 7;
+    /** @hide */
+    public static final int CONSTELLATION_TYPE_SHIFT_WIDTH = 3;
+    /** @hide */
+    public static final int CONSTELLATION_TYPE_MASK = 0xf;
 
     /* These package private values are modified by the LocationManager class */
-    /* package */ int[] mPrnWithFlags;
+    /* package */ int[] mSvidWithFlags;
     /* package */ float[] mSnrs;
     /* package */ float[] mElevations;
     /* package */ float[] mAzimuths;
-    /* package */ int[] mConstellationTypes;
     /* package */ int mSvCount;
 
-    GnssStatus(int svCount, int[] prnWithFlags, float[] snrs, float[] elevations, float[] azimuths,
-            int[] constellationTypes) {
+    GnssStatus(int svCount, int[] svidWithFlags, float[] snrs, float[] elevations,
+            float[] azimuths) {
         mSvCount = svCount;
-        mPrnWithFlags = prnWithFlags;
+        mSvidWithFlags = svidWithFlags;
         mSnrs = snrs;
         mElevations = elevations;
         mAzimuths = azimuths;
-        mConstellationTypes = constellationTypes;
     }
 
     /**
@@ -79,15 +81,16 @@
      * @param satIndex the index of the satellite in the list.
      */
     public int getConstellationType(int satIndex) {
-        return mConstellationTypes[satIndex];
+        return (mSvidWithFlags[satIndex] >> CONSTELLATION_TYPE_SHIFT_WIDTH)
+                & CONSTELLATION_TYPE_MASK;
     }
 
     /**
      * Retrieves the pseudo-random number of the satellite at the specified position.
      * @param satIndex the index of the satellite in the list.
      */
-    public int getPrn(int satIndex) {
-        return mPrnWithFlags[satIndex] >> PRN_SHIFT_WIDTH;
+    public int getSvid(int satIndex) {
+        return mSvidWithFlags[satIndex] >> SVID_SHIFT_WIDTH;
     }
 
     /**
@@ -119,7 +122,7 @@
      * @param satIndex the index of the satellite in the list.
      */
     public boolean hasEphemeris(int satIndex) {
-        return (mPrnWithFlags[satIndex] & GNSS_SV_FLAGS_HAS_EPHEMERIS_DATA) != 0;
+        return (mSvidWithFlags[satIndex] & GNSS_SV_FLAGS_HAS_EPHEMERIS_DATA) != 0;
     }
 
     /**
@@ -127,7 +130,7 @@
      * @param satIndex the index of the satellite in the list.
      */
     public boolean hasAlmanac(int satIndex) {
-        return (mPrnWithFlags[satIndex] & GNSS_SV_FLAGS_HAS_ALMANAC_DATA) != 0;
+        return (mSvidWithFlags[satIndex] & GNSS_SV_FLAGS_HAS_ALMANAC_DATA) != 0;
     }
 
     /**
@@ -135,6 +138,6 @@
      * @param satIndex the index of the satellite in the list.
      */
     public boolean usedInFix(int satIndex) {
-        return (mPrnWithFlags[satIndex] & GNSS_SV_FLAGS_USED_IN_FIX) != 0;
+        return (mSvidWithFlags[satIndex] & GNSS_SV_FLAGS_USED_IN_FIX) != 0;
     }
 }
diff --git a/location/java/android/location/GpsStatus.java b/location/java/android/location/GpsStatus.java
index 8d2f781..e41e20c 100644
--- a/location/java/android/location/GpsStatus.java
+++ b/location/java/android/location/GpsStatus.java
@@ -138,15 +138,19 @@
     // For API-compat a public ctor() is not available
     GpsStatus() {}
 
-    private void setStatus(int svCount, int[] prnWithFlags, float[] snrs, float[] elevations,
-            float[] azimuths, int[] constellationTypes) { 
+    private void setStatus(int svCount, int[] svidWithFlags, float[] snrs, float[] elevations,
+            float[] azimuths) {
         clearSatellites();
         for (int i = 0; i < svCount; i++) {
+            final int constellationType =
+                    (svidWithFlags[i] >> GnssStatus.CONSTELLATION_TYPE_SHIFT_WIDTH)
+                    & GnssStatus.CONSTELLATION_TYPE_MASK;
             // Skip all non-GPS satellites.
-            if (constellationTypes[i] != GnssStatus.CONSTELLATION_GPS) {
+            if (constellationType != GnssStatus.CONSTELLATION_GPS) {
+                // TODO: translate the defacto pre-N use of  prn's >32 to new struct
                 continue;
             }
-            int prn = prnWithFlags[i] >> GnssStatus.PRN_SHIFT_WIDTH;
+            int prn = svidWithFlags[i] >> GnssStatus.SVID_SHIFT_WIDTH;
             if (prn > 0 && prn <= NUM_SATELLITES) {
                 GpsSatellite satellite = mSatellites.get(prn);
                 if (satellite == null) {
@@ -159,11 +163,11 @@
                 satellite.mElevation = elevations[i];
                 satellite.mAzimuth = azimuths[i];
                 satellite.mHasEphemeris =
-                        (prnWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_HAS_EPHEMERIS_DATA) != 0;
+                        (svidWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_HAS_EPHEMERIS_DATA) != 0;
                 satellite.mHasAlmanac =
-                        (prnWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_HAS_ALMANAC_DATA) != 0;
+                        (svidWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_HAS_ALMANAC_DATA) != 0;
                 satellite.mUsedInFix =
-                        (prnWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_USED_IN_FIX) != 0;
+                        (svidWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_USED_IN_FIX) != 0;
             }
         }
     }
@@ -176,8 +180,8 @@
      */
     void setStatus(GnssStatus status, int timeToFirstFix) {
         mTimeToFirstFix = timeToFirstFix;
-        setStatus(status.mSvCount, status.mPrnWithFlags, status.mSnrs, status.mElevations,
-                status.mAzimuths, status.mConstellationTypes);
+        setStatus(status.mSvCount, status.mSvidWithFlags, status.mSnrs, status.mElevations,
+                status.mAzimuths);
     }
 
     void setTimeToFirstFix(int ttff) {
diff --git a/location/java/android/location/IGnssStatusListener.aidl b/location/java/android/location/IGnssStatusListener.aidl
index d1c6a85..8c7d06e 100644
--- a/location/java/android/location/IGnssStatusListener.aidl
+++ b/location/java/android/location/IGnssStatusListener.aidl
@@ -26,7 +26,7 @@
     void onGnssStarted();
     void onGnssStopped();
     void onFirstFix(int ttff);
-    void onSvStatusChanged(int svCount, in int[] prnWithFlags, in float[] snrs,
-            in float[] elevations, in float[] azimuths, in int[] constellationTypes);
+    void onSvStatusChanged(int svCount, in int[] svidWithFlags, in float[] snrs,
+            in float[] elevations, in float[] azimuths);
     void onNmeaReceived(long timestamp, String nmea);
 }
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index 30cf101..23f0710 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -1562,10 +1562,9 @@
 
         @Override
         public void onSvStatusChanged(int svCount, int[] prnWithFlags,
-                float[] snrs, float[] elevations, float[] azimuths, int[] constellationTypes) {
+                float[] snrs, float[] elevations, float[] azimuths) {
             if (mGnssCallback != null) {
-                mGnssStatus = new GnssStatus(svCount, prnWithFlags, snrs, elevations, azimuths,
-                        constellationTypes);
+                mGnssStatus = new GnssStatus(svCount, prnWithFlags, snrs, elevations, azimuths);
 
                 Message msg = Message.obtain();
                 msg.what = GpsStatus.GPS_EVENT_SATELLITE_STATUS;
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index ffc52b3..c1eb844 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -1557,15 +1557,13 @@
      * called from native code to update SV info
      */
     private void reportSvStatus() {
-        int svCount = native_read_sv_status(mPrnWithFlags, mSnrs, mSvElevations, mSvAzimuths,
-                mConstellationTypes);
+        int svCount = native_read_sv_status(mSvidWithFlags, mSnrs, mSvElevations, mSvAzimuths);
         mListenerHelper.onSvStatusChanged(
                 svCount,
-                mPrnWithFlags,
+                mSvidWithFlags,
                 mSnrs,
                 mSvElevations,
-                mSvAzimuths,
-                mConstellationTypes);
+                mSvAzimuths);
 
         if (VERBOSE) {
             Log.v(TAG, "SV count: " + svCount);
@@ -1573,19 +1571,19 @@
         // Calculate number of sets used in fix.
         int usedInFixCount = 0;
         for (int i = 0; i < svCount; i++) {
-            if ((mPrnWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_USED_IN_FIX) != 0) {
+            if ((mSvidWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_USED_IN_FIX) != 0) {
                 ++usedInFixCount;
             }
             if (VERBOSE) {
-                Log.v(TAG, "prn: " + (mPrnWithFlags[i] >> GnssStatus.PRN_SHIFT_WIDTH) +
+                Log.v(TAG, "svid: " + (mSvidWithFlags[i] >> GnssStatus.SVID_SHIFT_WIDTH) +
                         " snr: " + mSnrs[i]/10 +
                         " elev: " + mSvElevations[i] +
                         " azimuth: " + mSvAzimuths[i] +
-                        ((mPrnWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_HAS_EPHEMERIS_DATA) == 0
+                        ((mSvidWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_HAS_EPHEMERIS_DATA) == 0
                                 ? "  " : " E") +
-                        ((mPrnWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_HAS_ALMANAC_DATA) == 0
+                        ((mSvidWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_HAS_ALMANAC_DATA) == 0
                                 ? "  " : " A") +
-                        ((mPrnWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_USED_IN_FIX) == 0
+                        ((mSvidWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_USED_IN_FIX) == 0
                                 ? "" : "U"));
             }
         }
@@ -2398,14 +2396,13 @@
     }
 
     // for GPS SV statistics
-    private static final int MAX_SVS = 512;
+    private static final int MAX_SVS = 64;
 
     // preallocated arrays, to avoid memory allocation in reportStatus()
-    private int mPrnWithFlags[] = new int[MAX_SVS];
+    private int mSvidWithFlags[] = new int[MAX_SVS];
     private float mSnrs[] = new float[MAX_SVS];
     private float mSvElevations[] = new float[MAX_SVS];
     private float mSvAzimuths[] = new float[MAX_SVS];
-    private int mConstellationTypes[] = new int[MAX_SVS];
     private int mSvCount;
     // preallocated to avoid memory allocation in reportNmea()
     private byte[] mNmeaBuffer = new byte[120];
@@ -2426,7 +2423,7 @@
     // returns number of SVs
     // mask[0] is ephemeris mask and mask[1] is almanac mask
     private native int native_read_sv_status(int[] prnWithFlags, float[] snrs, float[] elevations,
-            float[] azimuths, int[] constellationTypes);
+            float[] azimuths);
     private native int native_read_nmea(byte[] buffer, int bufferSize);
     private native void native_inject_location(double latitude, double longitude, float accuracy);
 
diff --git a/services/core/java/com/android/server/location/GnssStatusListenerHelper.java b/services/core/java/com/android/server/location/GnssStatusListenerHelper.java
index 9840c61..0b3111c 100644
--- a/services/core/java/com/android/server/location/GnssStatusListenerHelper.java
+++ b/services/core/java/com/android/server/location/GnssStatusListenerHelper.java
@@ -77,8 +77,7 @@
             final int[] prnWithFlags,
             final float[] snrs,
             final float[] elevations,
-            final float[] azimuths,
-            final int[] constellationTypes) {
+            final float[] azimuths) {
         Operation operation = new Operation() {
             @Override
             public void execute(IGnssStatusListener listener) throws RemoteException {
@@ -87,8 +86,7 @@
                         prnWithFlags,
                         snrs,
                         elevations,
-                        azimuths,
-                        constellationTypes);
+                        azimuths);
             }
         };
         foreach(operation);
diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
index e75775f..310d660 100644
--- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
@@ -68,13 +68,14 @@
 static const GpsNavigationMessageInterface* sGpsNavigationMessageInterface = NULL;
 static const GnssConfigurationInterface* sGnssConfigurationInterface = NULL;
 
-#define MAX_SATELLITE_COUNT 512
-#define MAX_GPS_SATELLITE_COUNT 512
+#define GPS_MAX_SATELLITE_COUNT 32
+#define GNSS_MAX_SATELLITE_COUNT 64
 
-#define PRN_SHIFT_WIDTH 3
+#define SVID_SHIFT_WIDTH 7
+#define CONSTELLATION_TYPE_SHIFT_WIDTH 3
 
 // temporary storage for GPS callbacks
-static GnssSvInfo sGnssSvList[MAX_SATELLITE_COUNT];
+static GnssSvInfo sGnssSvList[GNSS_MAX_SATELLITE_COUNT];
 static size_t sGnssSvListSize;
 static const char* sNmeaString;
 static int sNmeaStringLength;
@@ -113,56 +114,75 @@
 {
     JNIEnv* env = AndroidRuntime::getJNIEnv();
     size_t status_size = sv_status->size;
-    // Some drive doesn't set the size field correctly. Assume GpsSvStatus_v1 if
-    // it doesn't provide a valid size.
+    // Some drives doesn't set the size field correctly. Assume GpsSvStatus_v1
+    // if it doesn't provide a valid size.
     if (status_size == 0) {
-        status_size = sizeof(GpsSvStatus_v1);
+        ALOGW("Invalid size of GpsSvStatus found: %zd.", status_size);
     }
-    if (status_size == sizeof(GpsSvStatus)) {
-        sGnssSvListSize = sv_status->gnss_sv_list_size;
-        // Cramp the list size
-        if (sGnssSvListSize > MAX_SATELLITE_COUNT) {
-            sGnssSvListSize = MAX_SATELLITE_COUNT;
-        }
-        // Copy GNSS SV info into sGnssSvList, if any.
-        if (sGnssSvListSize > 0 && sv_status->gnss_sv_list) {
-            memcpy(sGnssSvList, sv_status->gnss_sv_list, sizeof(GnssSvInfo) * sGnssSvListSize);
-        }
-    } else if (status_size == sizeof(GpsSvStatus_v1)) {
-        sGnssSvListSize = sv_status->num_svs;
-        // Cramp the list size
-        if (sGnssSvListSize > MAX_GPS_SATELLITE_COUNT) {
-            sGnssSvListSize = MAX_GPS_SATELLITE_COUNT;
-        }
-        uint32_t ephemeris_mask = sv_status->ephemeris_mask;
-        uint32_t almanac_mask = sv_status->almanac_mask;
-        uint32_t used_in_fix_mask = sv_status->used_in_fix_mask;
-        for (size_t i = 0; i < sGnssSvListSize; i++) {
-            GnssSvInfo& info = sGnssSvList[i];
+    sGnssSvListSize = sv_status->num_svs;
+    // Clamp the list size. Legacy GpsSvStatus has only 32 elements in sv_list.
+    if (sGnssSvListSize > GPS_MAX_SATELLITE_COUNT) {
+        ALOGW("Too many satellites %d. Clamps to %d.",
+              sGnssSvListSize,
+              GPS_MAX_SATELLITE_COUNT);
+        sGnssSvListSize = GPS_MAX_SATELLITE_COUNT;
+    }
+    uint32_t ephemeris_mask = sv_status->ephemeris_mask;
+    uint32_t almanac_mask = sv_status->almanac_mask;
+    uint32_t used_in_fix_mask = sv_status->used_in_fix_mask;
+    for (size_t i = 0; i < sGnssSvListSize; i++) {
+        GnssSvInfo& info = sGnssSvList[i];
+        info.svid = sv_status->sv_list[i].prn;
+        // TODO: implement the correct logic to derive the constellation type
+        // based on PRN ranges.
+        if (info.svid >=1 && info.svid <= 32) {
             info.constellation = GNSS_CONSTELLATION_GPS;
-            info.prn = sv_status->sv_list[i].prn;
-            info.snr = sv_status->sv_list[i].snr;
-            info.elevation = sv_status->sv_list[i].elevation;
-            info.azimuth = sv_status->sv_list[i].azimuth;
-            info.flags = GNSS_SV_FLAGS_NONE;
-            if (info.prn > 0 && info.prn <= 32) {
-              int32_t this_prn_mask = (1 << (info.prn - 1));
-              if ((ephemeris_mask & this_prn_mask) != 0) {
+        } else {
+            info.constellation = GNSS_CONSTELLATION_UNKNOWN;
+        }
+        info.snr = sv_status->sv_list[i].snr;
+        info.elevation = sv_status->sv_list[i].elevation;
+        info.azimuth = sv_status->sv_list[i].azimuth;
+        info.flags = GNSS_SV_FLAGS_NONE;
+        if (info.svid > 0 && info.svid <= 32) {
+            int32_t this_svid_mask = (1 << (info.svid - 1));
+            if ((ephemeris_mask & this_svid_mask) != 0) {
                 info.flags |= GNSS_SV_FLAGS_HAS_EPHEMERIS_DATA;
-              }
-              if ((almanac_mask & this_prn_mask) != 0) {
+            }
+            if ((almanac_mask & this_svid_mask) != 0) {
                 info.flags |= GNSS_SV_FLAGS_HAS_ALMANAC_DATA;
-              }
-              if ((used_in_fix_mask & this_prn_mask) != 0) {
+            }
+            if ((used_in_fix_mask & this_svid_mask) != 0) {
                 info.flags |= GNSS_SV_FLAGS_USED_IN_FIX;
-              }
             }
         }
-    } else {
-        sGnssSvListSize = 0;
-        ALOGE("Invalid size of GpsSvStatus found: %zd.", status_size);
+    }
+    env->CallVoidMethod(mCallbacksObj, method_reportSvStatus);
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+}
+
+static void gnss_sv_status_callback(GnssSvStatus* sv_status) {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    size_t status_size = sv_status->size;
+    // Check the size, and reject the object that has invalid size.
+    if (status_size != sizeof(GnssSvStatus)) {
+        ALOGE("Invalid size of GnssSvStatus found: %zd.", status_size);
         return;
     }
+    sGnssSvListSize = sv_status->num_svs;
+    // Clamp the list size
+    if (sGnssSvListSize > GNSS_MAX_SATELLITE_COUNT) {
+        ALOGD("Too many satellites %d. Clamps to %d.",
+              sGnssSvListSize,
+              GNSS_MAX_SATELLITE_COUNT);
+        sGnssSvListSize = GNSS_MAX_SATELLITE_COUNT;
+    }
+    // Copy GNSS SV info into sGnssSvList, if any.
+    if (sGnssSvListSize > 0) {
+        memcpy(sGnssSvList,
+               sv_status->gnss_sv_list,
+               sizeof(GnssSvInfo) * sGnssSvListSize);
+    }
     env->CallVoidMethod(mCallbacksObj, method_reportSvStatus);
     checkAndClearExceptionFromCallback(env, __FUNCTION__);
 }
@@ -228,6 +248,7 @@
     create_thread_callback,
     request_utc_time_callback,
     set_system_info_callback,
+    gnss_sv_status_callback,
 };
 
 static void xtra_download_request_callback()
@@ -677,31 +698,30 @@
 }
 
 static jint android_location_GnssLocationProvider_read_sv_status(JNIEnv* env, jobject /* obj */,
-        jintArray prnWithFlagArray, jfloatArray snrArray, jfloatArray elevArray,
-        jfloatArray azumArray, jintArray constellationTypeArray)
+        jintArray svidWithFlagArray, jfloatArray snrArray, jfloatArray elevArray,
+        jfloatArray azumArray)
 {
     // this should only be called from within a call to reportSvStatus
-    jint* prnWithFlags = env->GetIntArrayElements(prnWithFlagArray, 0);
+    jint* svidWithFlags = env->GetIntArrayElements(svidWithFlagArray, 0);
     jfloat* snrs = env->GetFloatArrayElements(snrArray, 0);
     jfloat* elev = env->GetFloatArrayElements(elevArray, 0);
     jfloat* azim = env->GetFloatArrayElements(azumArray, 0);
-    jint* constellationTypes = env->GetIntArrayElements(constellationTypeArray, 0);
 
     // GNSS SV info.
     for (size_t i = 0; i < sGnssSvListSize; ++i) {
         const GnssSvInfo& info = sGnssSvList[i];
-        constellationTypes[i] = info.constellation;
-        prnWithFlags[i] = (info.prn << PRN_SHIFT_WIDTH) | info.flags;
+        svidWithFlags[i] = (info.svid << SVID_SHIFT_WIDTH) |
+            (info.constellation << CONSTELLATION_TYPE_SHIFT_WIDTH) |
+            info.flags;
         snrs[i] = info.snr;
         elev[i] = info.elevation;
         azim[i] = info.azimuth;
     }
 
-    env->ReleaseIntArrayElements(prnWithFlagArray, prnWithFlags, 0);
+    env->ReleaseIntArrayElements(svidWithFlagArray, svidWithFlags, 0);
     env->ReleaseFloatArrayElements(snrArray, snrs, 0);
     env->ReleaseFloatArrayElements(elevArray, elev, 0);
     env->ReleaseFloatArrayElements(azumArray, azim, 0);
-    env->ReleaseIntArrayElements(constellationTypeArray, constellationTypes, 0);
     return (jint) sGnssSvListSize;
 }
 
@@ -968,370 +988,341 @@
     return JNI_FALSE;
 }
 
-static jobject translate_gps_clock(JNIEnv* env, void* data, size_t size) {
-    const char* doubleSignature = "(D)V";
-    const char* longSignature = "(J)V";
+template<class T>
+class JavaMethodHelper {
+  public:
+   // Helper function to call setter on a Java object.
+   static void callJavaMethod(
+           JNIEnv* env,
+           jclass clazz,
+           jobject object,
+           const char* method_name,
+           T value);
 
-    GpsClock* clock = reinterpret_cast<GpsClock*>(data);
+  private:
+    static const char *const signature_;
+};
 
-    jclass gpsClockClass = env->FindClass("android/location/GnssClock");
-    jmethodID gpsClockCtor = env->GetMethodID(gpsClockClass, "<init>", "()V");
+template<class T>
+void JavaMethodHelper<T>::callJavaMethod(
+        JNIEnv* env,
+        jclass clazz,
+        jobject object,
+        const char* method_name,
+        T value) {
+    jmethodID method = env->GetMethodID(clazz, method_name, signature_);
+    env->CallVoidMethod(object, method, value);
+}
 
-    jobject gpsClockObject = env->NewObject(gpsClockClass, gpsClockCtor);
+class JavaObject {
+  public:
+   JavaObject(JNIEnv* env, const char* class_name);
+   virtual ~JavaObject();
+
+   template<class T>
+   void callSetter(const char* method_name, T value);
+   template<class T>
+   void callSetter(const char* method_name, T* value, size_t size);
+   jobject get();
+
+  private:
+   JNIEnv* env_;
+   jclass clazz_;
+   jobject object_;
+};
+
+JavaObject::JavaObject(JNIEnv* env, const char* class_name) : env_(env) {
+    clazz_ = env_->FindClass(class_name);
+    jmethodID ctor = env->GetMethodID(clazz_, "<init>", "()V");
+    object_ = env_->NewObject(clazz_, ctor);
+}
+
+JavaObject::~JavaObject() {
+    env_->DeleteLocalRef(clazz_);
+}
+
+template<class T>
+void JavaObject::callSetter(const char* method_name, T value) {
+    JavaMethodHelper<T>::callJavaMethod(
+            env_, clazz_, object_, method_name, value);
+}
+
+template<>
+void JavaObject::callSetter(
+        const char* method_name, uint8_t* value, size_t size) {
+    jbyteArray array = env_->NewByteArray(size);
+    env_->SetByteArrayRegion(array, 0, size, (jbyte*) value);
+    jmethodID method = env_->GetMethodID(
+            clazz_,
+            method_name,
+            "([B)V");
+    env_->CallVoidMethod(object_, method, array);
+}
+
+jobject JavaObject::get() {
+    return object_;
+}
+
+// Define Java method signatures for all known types.
+
+template<>
+const char *const JavaMethodHelper<uint8_t>::signature_ = "(B)V";
+template<>
+const char *const JavaMethodHelper<int8_t>::signature_ = "(B)V";
+template<>
+const char *const JavaMethodHelper<int16_t>::signature_ = "(S)V";
+template<>
+const char *const JavaMethodHelper<uint16_t>::signature_ = "(S)V";
+template<>
+const char *const JavaMethodHelper<int>::signature_ = "(I)V";
+template<>
+const char *const JavaMethodHelper<int64_t>::signature_ = "(J)V";
+template<>
+const char *const JavaMethodHelper<float>::signature_ = "(F)V";
+template<>
+const char *const JavaMethodHelper<double>::signature_ = "(D)V";
+template<>
+const char *const JavaMethodHelper<bool>::signature_ = "(Z)V";
+
+#define SET(setter, value) object.callSetter("set" # setter, (value))
+#define SET_IF(flag, setter, value) \
+        if (flags & (flag)) object.callSetter("set" # setter, (value))
+
+static jobject translate_gps_clock(JNIEnv* env, GpsClock* clock) {
+    JavaObject object(env, "android/location/GnssClock");
     GpsClockFlags flags = clock->flags;
 
-    if (flags & GPS_CLOCK_HAS_LEAP_SECOND) {
-        jmethodID setterMethod = env->GetMethodID(gpsClockClass, "setLeapSecond", "(S)V");
-        env->CallVoidMethod(gpsClockObject, setterMethod, clock->leap_second);
-   }
+    SET_IF(GPS_CLOCK_HAS_LEAP_SECOND, LeapSecond, clock->leap_second);
+    SET(Type, clock->type);
+    SET(TimeInNs, clock->time_ns);
+    SET_IF(GPS_CLOCK_HAS_TIME_UNCERTAINTY,
+           TimeUncertaintyInNs,
+           clock->time_uncertainty_ns);
+    SET_IF(GPS_CLOCK_HAS_FULL_BIAS, FullBiasInNs, clock->full_bias_ns);
+    SET_IF(GPS_CLOCK_HAS_BIAS, BiasInNs, clock->bias_ns);
+    SET_IF(GPS_CLOCK_HAS_BIAS_UNCERTAINTY,
+           BiasUncertaintyInNs,
+           clock->bias_uncertainty_ns);
+    SET_IF(GPS_CLOCK_HAS_DRIFT, DriftInNsPerSec, clock->drift_nsps);
+    SET_IF(GPS_CLOCK_HAS_DRIFT_UNCERTAINTY,
+           DriftUncertaintyInNsPerSec,
+           clock->drift_uncertainty_nsps);
 
-   jmethodID typeSetterMethod = env->GetMethodID(gpsClockClass, "setType", "(B)V");
-   env->CallVoidMethod(gpsClockObject, typeSetterMethod, clock->type);
-
-    jmethodID setterMethod = env->GetMethodID(gpsClockClass, "setTimeInNs", longSignature);
-    env->CallVoidMethod(gpsClockObject, setterMethod, clock->time_ns);
-
-    if (flags & GPS_CLOCK_HAS_TIME_UNCERTAINTY) {
-        jmethodID setterMethod =
-                env->GetMethodID(gpsClockClass, "setTimeUncertaintyInNs", doubleSignature);
-        env->CallVoidMethod(gpsClockObject, setterMethod, clock->time_uncertainty_ns);
-    }
-
-    if (flags & GPS_CLOCK_HAS_FULL_BIAS) {
-        jmethodID setterMethod = env->GetMethodID(gpsClockClass, "setFullBiasInNs", longSignature);
-        env->CallVoidMethod(gpsClockObject, setterMethod, clock->full_bias_ns);
-    }
-
-    if (flags & GPS_CLOCK_HAS_BIAS) {
-        jmethodID setterMethod = env->GetMethodID(gpsClockClass, "setBiasInNs", doubleSignature);
-        env->CallVoidMethod(gpsClockObject, setterMethod, clock->bias_ns);
-    }
-
-    if (flags & GPS_CLOCK_HAS_BIAS_UNCERTAINTY) {
-        jmethodID setterMethod =
-                env->GetMethodID(gpsClockClass, "setBiasUncertaintyInNs", doubleSignature);
-        env->CallVoidMethod(gpsClockObject, setterMethod, clock->bias_uncertainty_ns);
-    }
-
-    if (flags & GPS_CLOCK_HAS_DRIFT) {
-        jmethodID setterMethod =
-                env->GetMethodID(gpsClockClass, "setDriftInNsPerSec", doubleSignature);
-        env->CallVoidMethod(gpsClockObject, setterMethod, clock->drift_nsps);
-    }
-
-    if (flags & GPS_CLOCK_HAS_DRIFT_UNCERTAINTY) {
-        jmethodID setterMethod =
-                env->GetMethodID(gpsClockClass, "setDriftUncertaintyInNsPerSec", doubleSignature);
-        env->CallVoidMethod(gpsClockObject, setterMethod, clock->drift_uncertainty_nsps);
-    }
-
+    /*
     if (flags & GPS_CLOCK_TYPE_LOCAL_HW_TIME) {
-        if (size == sizeof(GpsClock)) {
+        if (size == sizeof(GnssClock)) {
             jmethodID setterMethod =
                     env->GetMethodID(gpsClockClass,
                                      "setTimeOfLastHwClockDiscontinuityInNs",
                                      longSignature);
             env->CallVoidMethod(gpsClockObject,
                                 setterMethod,
-                                clock->time_of_last_hw_clock_discontinuity_ns);
+                                reinterpret_cast<GnssClock*>(clock)->time_of_last_hw_clock_discontinuity_ns);
         }
     }
+    */
 
-    env->DeleteLocalRef(gpsClockClass);
-    return gpsClockObject;
+    return object.get();
 }
 
-static jobject translate_gps_measurement(JNIEnv* env, void* data, size_t size) {
-    const char* byteSignature = "(B)V";
-    const char* shortSignature = "(S)V";
-    const char* intSignature = "(I)V";
-    const char* longSignature = "(J)V";
-    const char* floatSignature = "(F)V";
-    const char* doubleSignature = "(D)V";
+static jobject translate_gnss_clock(JNIEnv* env, GnssClock* clock) {
+    JavaObject object(env, "android/location/GnssClock");
+    GpsClockFlags flags = clock->flags;
 
-    jclass gnssMeasurementClass = env->FindClass("android/location/GnssMeasurement");
-    jmethodID gnssMeasurementCtor = env->GetMethodID(gnssMeasurementClass, "<init>", "()V");
-    GpsMeasurement* measurement = reinterpret_cast<GpsMeasurement*>(data);
+    SET_IF(GPS_CLOCK_HAS_LEAP_SECOND, LeapSecond, clock->leap_second);
+    SET(Type, clock->type);
+    SET(TimeInNs, clock->time_ns);
+    SET_IF(GPS_CLOCK_HAS_TIME_UNCERTAINTY,
+           TimeUncertaintyInNs,
+           clock->time_uncertainty_ns);
+    SET_IF(GPS_CLOCK_HAS_FULL_BIAS, FullBiasInNs, clock->full_bias_ns);
+    SET_IF(GPS_CLOCK_HAS_BIAS, BiasInNs, clock->bias_ns);
+    SET_IF(GPS_CLOCK_HAS_BIAS_UNCERTAINTY,
+           BiasUncertaintyInNs,
+           clock->bias_uncertainty_ns);
+    SET_IF(GPS_CLOCK_HAS_DRIFT, DriftInNsPerSec, clock->drift_nsps);
+    SET_IF(GPS_CLOCK_HAS_DRIFT_UNCERTAINTY,
+           DriftUncertaintyInNsPerSec,
+           clock->drift_uncertainty_nsps);
 
-    jobject gnssMeasurementObject = env->NewObject(gnssMeasurementClass, gnssMeasurementCtor);
+    SET_IF(GPS_CLOCK_TYPE_LOCAL_HW_TIME,
+           TimeOfLastHwClockDiscontinuityInNs,
+           clock->time_of_last_hw_clock_discontinuity_ns);
+
+    return object.get();
+}
+
+static jobject translate_gps_measurement(JNIEnv* env,
+                                         GpsMeasurement* measurement) {
+    JavaObject object(env, "android/location/GnssMeasurement");
     GpsMeasurementFlags flags = measurement->flags;
 
-    jmethodID prnSetterMethod = env->GetMethodID(gnssMeasurementClass, "setPrn", byteSignature);
-    env->CallVoidMethod(gnssMeasurementObject, prnSetterMethod, measurement->prn);
+    SET(Svid, static_cast<int16_t>(measurement->prn));
+    SET(TimeOffsetInNs, measurement->time_offset_ns);
+    SET(State, measurement->state);
+    SET(ReceivedGpsTowInNs, measurement->received_gps_tow_ns);
+    SET(ReceivedGpsTowUncertaintyInNs,
+        measurement->received_gps_tow_uncertainty_ns);
+    SET(Cn0InDbHz, measurement->c_n0_dbhz);
+    SET(PseudorangeRateInMetersPerSec, measurement->pseudorange_rate_mps);
+    SET(PseudorangeRateUncertaintyInMetersPerSec,
+        measurement->pseudorange_rate_uncertainty_mps);
+    SET(AccumulatedDeltaRangeState, measurement->accumulated_delta_range_state);
+    SET(AccumulatedDeltaRangeInMeters, measurement->accumulated_delta_range_m);
+    SET(AccumulatedDeltaRangeUncertaintyInMeters,
+        measurement->accumulated_delta_range_uncertainty_m);
+    SET_IF(GPS_MEASUREMENT_HAS_PSEUDORANGE,
+           PseudorangeInMeters,
+           measurement->pseudorange_m);
+    SET_IF(GPS_MEASUREMENT_HAS_PSEUDORANGE_UNCERTAINTY,
+           PseudorangeUncertaintyInMeters,
+           measurement->pseudorange_uncertainty_m);
+    SET_IF(GPS_MEASUREMENT_HAS_CODE_PHASE,
+           CodePhaseInChips,
+           measurement->code_phase_chips);
+    SET_IF(GPS_MEASUREMENT_HAS_CODE_PHASE_UNCERTAINTY,
+           CodePhaseUncertaintyInChips,
+           measurement->code_phase_uncertainty_chips);
+    SET_IF(GPS_MEASUREMENT_HAS_CARRIER_FREQUENCY,
+           CarrierFrequencyInHz,
+           measurement->carrier_frequency_hz);
+    SET_IF(GPS_MEASUREMENT_HAS_CARRIER_CYCLES,
+           CarrierCycles,
+           measurement->carrier_cycles);
+    SET_IF(GPS_MEASUREMENT_HAS_CARRIER_PHASE,
+           CarrierPhase,
+           measurement->carrier_phase);
+    SET_IF(GPS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY,
+           CarrierPhaseUncertainty,
+           measurement->carrier_phase_uncertainty);
+    SET(LossOfLock, measurement->loss_of_lock);
+    SET_IF(GPS_MEASUREMENT_HAS_BIT_NUMBER, BitNumber, measurement->bit_number);
+    SET_IF(GPS_MEASUREMENT_HAS_TIME_FROM_LAST_BIT,
+           TimeFromLastBitInMs,
+           measurement->time_from_last_bit_ms);
+    SET_IF(GPS_MEASUREMENT_HAS_DOPPLER_SHIFT,
+           DopplerShiftInHz,
+           measurement->doppler_shift_hz);
+    SET_IF(GPS_MEASUREMENT_HAS_DOPPLER_SHIFT_UNCERTAINTY,
+           DopplerShiftUncertaintyInHz,
+           measurement->doppler_shift_uncertainty_hz);
+    SET(MultipathIndicator, measurement->multipath_indicator);
+    SET_IF(GPS_MEASUREMENT_HAS_SNR, SnrInDb, measurement->snr_db);
+    SET_IF(GPS_MEASUREMENT_HAS_ELEVATION,
+           ElevationInDeg,
+           measurement->elevation_deg);
+    SET_IF(GPS_MEASUREMENT_HAS_ELEVATION_UNCERTAINTY,
+           ElevationUncertaintyInDeg,
+           measurement->elevation_uncertainty_deg);
+    SET_IF(GPS_MEASUREMENT_HAS_AZIMUTH,
+           AzimuthInDeg,
+           measurement->azimuth_deg);
+    SET_IF(GPS_MEASUREMENT_HAS_AZIMUTH_UNCERTAINTY,
+           AzimuthUncertaintyInDeg,
+           measurement->azimuth_uncertainty_deg);
+    SET(UsedInFix,
+        (flags & GPS_MEASUREMENT_HAS_USED_IN_FIX) && measurement->used_in_fix);
 
-    jmethodID timeOffsetSetterMethod =
-            env->GetMethodID(gnssMeasurementClass, "setTimeOffsetInNs", doubleSignature);
-    env->CallVoidMethod(
-            gnssMeasurementObject,
-            timeOffsetSetterMethod,
-            measurement->time_offset_ns);
-
-    jmethodID stateSetterMethod = env->GetMethodID(gnssMeasurementClass, "setState", shortSignature);
-    env->CallVoidMethod(gnssMeasurementObject, stateSetterMethod, measurement->state);
-
-    jmethodID receivedGpsTowSetterMethod =
-            env->GetMethodID(gnssMeasurementClass, "setReceivedGpsTowInNs", longSignature);
-    env->CallVoidMethod(
-            gnssMeasurementObject,
-            receivedGpsTowSetterMethod,
-            measurement->received_gps_tow_ns);
-
-    jmethodID receivedGpsTowUncertaintySetterMethod = env->GetMethodID(
-            gnssMeasurementClass,
-            "setReceivedGpsTowUncertaintyInNs",
-            longSignature);
-    env->CallVoidMethod(
-            gnssMeasurementObject,
-            receivedGpsTowUncertaintySetterMethod,
-            measurement->received_gps_tow_uncertainty_ns);
-
-    jmethodID cn0SetterMethod =
-            env->GetMethodID(gnssMeasurementClass, "setCn0InDbHz", doubleSignature);
-    env->CallVoidMethod(gnssMeasurementObject, cn0SetterMethod, measurement->c_n0_dbhz);
-
-    jmethodID pseudorangeRateSetterMethod = env->GetMethodID(
-            gnssMeasurementClass,
-            "setPseudorangeRateInMetersPerSec",
-            doubleSignature);
-    env->CallVoidMethod(
-            gnssMeasurementObject,
-            pseudorangeRateSetterMethod,
-            measurement->pseudorange_rate_mps);
-
-    jmethodID pseudorangeRateUncertaintySetterMethod = env->GetMethodID(
-            gnssMeasurementClass,
-            "setPseudorangeRateUncertaintyInMetersPerSec",
-            doubleSignature);
-    env->CallVoidMethod(
-            gnssMeasurementObject,
-            pseudorangeRateUncertaintySetterMethod,
-            measurement->pseudorange_rate_uncertainty_mps);
-
-    jmethodID accumulatedDeltaRangeStateSetterMethod =
-            env->GetMethodID(gnssMeasurementClass, "setAccumulatedDeltaRangeState", shortSignature);
-    env->CallVoidMethod(
-            gnssMeasurementObject,
-            accumulatedDeltaRangeStateSetterMethod,
-            measurement->accumulated_delta_range_state);
-
-    jmethodID accumulatedDeltaRangeSetterMethod = env->GetMethodID(
-            gnssMeasurementClass,
-            "setAccumulatedDeltaRangeInMeters",
-            doubleSignature);
-    env->CallVoidMethod(
-            gnssMeasurementObject,
-            accumulatedDeltaRangeSetterMethod,
-            measurement->accumulated_delta_range_m);
-
-    jmethodID accumulatedDeltaRangeUncertaintySetterMethod = env->GetMethodID(
-            gnssMeasurementClass,
-            "setAccumulatedDeltaRangeUncertaintyInMeters",
-            doubleSignature);
-    env->CallVoidMethod(
-            gnssMeasurementObject,
-            accumulatedDeltaRangeUncertaintySetterMethod,
-            measurement->accumulated_delta_range_uncertainty_m);
-
-    if (flags & GPS_MEASUREMENT_HAS_PSEUDORANGE) {
-        jmethodID setterMethod =
-                env->GetMethodID(gnssMeasurementClass, "setPseudorangeInMeters", doubleSignature);
-        env->CallVoidMethod(gnssMeasurementObject, setterMethod, measurement->pseudorange_m);
-    }
-
-    if (flags & GPS_MEASUREMENT_HAS_PSEUDORANGE_UNCERTAINTY) {
-        jmethodID setterMethod = env->GetMethodID(
-                gnssMeasurementClass,
-                "setPseudorangeUncertaintyInMeters",
-                doubleSignature);
-        env->CallVoidMethod(
-                gnssMeasurementObject,
-                setterMethod,
-                measurement->pseudorange_uncertainty_m);
-    }
-
-    if (flags & GPS_MEASUREMENT_HAS_CODE_PHASE) {
-        jmethodID setterMethod =
-                env->GetMethodID(gnssMeasurementClass, "setCodePhaseInChips", doubleSignature);
-        env->CallVoidMethod(gnssMeasurementObject, setterMethod, measurement->code_phase_chips);
-    }
-
-    if (flags & GPS_MEASUREMENT_HAS_CODE_PHASE_UNCERTAINTY) {
-        jmethodID setterMethod = env->GetMethodID(
-                gnssMeasurementClass,
-                "setCodePhaseUncertaintyInChips",
-                doubleSignature);
-        env->CallVoidMethod(
-                gnssMeasurementObject,
-                setterMethod,
-                measurement->code_phase_uncertainty_chips);
-    }
-
-    if (flags & GPS_MEASUREMENT_HAS_CARRIER_FREQUENCY) {
-        jmethodID setterMethod =
-                env->GetMethodID(gnssMeasurementClass, "setCarrierFrequencyInHz", floatSignature);
-        env->CallVoidMethod(
-                gnssMeasurementObject,
-                setterMethod,
-                measurement->carrier_frequency_hz);
-    }
-
-    if (flags & GPS_MEASUREMENT_HAS_CARRIER_CYCLES) {
-        jmethodID setterMethod =
-                env->GetMethodID(gnssMeasurementClass, "setCarrierCycles", longSignature);
-        env->CallVoidMethod(gnssMeasurementObject, setterMethod, measurement->carrier_cycles);
-    }
-
-    if (flags & GPS_MEASUREMENT_HAS_CARRIER_PHASE) {
-        jmethodID setterMethod =
-                env->GetMethodID(gnssMeasurementClass, "setCarrierPhase", doubleSignature);
-        env->CallVoidMethod(gnssMeasurementObject, setterMethod, measurement->carrier_phase);
-    }
-
-    if (flags & GPS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY) {
-        jmethodID setterMethod = env->GetMethodID(
-                gnssMeasurementClass,
-                "setCarrierPhaseUncertainty",
-                doubleSignature);
-        env->CallVoidMethod(
-                gnssMeasurementObject,
-                setterMethod,
-                measurement->carrier_phase_uncertainty);
-    }
-
-    jmethodID lossOfLockSetterMethod =
-            env->GetMethodID(gnssMeasurementClass, "setLossOfLock", byteSignature);
-    env->CallVoidMethod(gnssMeasurementObject, lossOfLockSetterMethod, measurement->loss_of_lock);
-
-    if (flags & GPS_MEASUREMENT_HAS_BIT_NUMBER) {
-        jmethodID setterMethod =
-                env->GetMethodID(gnssMeasurementClass, "setBitNumber", intSignature);
-        env->CallVoidMethod(gnssMeasurementObject, setterMethod, measurement->bit_number);
-    }
-
-    if (flags & GPS_MEASUREMENT_HAS_TIME_FROM_LAST_BIT) {
-        jmethodID setterMethod =
-                env->GetMethodID(gnssMeasurementClass, "setTimeFromLastBitInMs", shortSignature);
-        env->CallVoidMethod(
-                gnssMeasurementObject,
-                setterMethod,
-                measurement->time_from_last_bit_ms);
-    }
-
-    if (flags & GPS_MEASUREMENT_HAS_DOPPLER_SHIFT) {
-        jmethodID setterMethod =
-                env->GetMethodID(gnssMeasurementClass, "setDopplerShiftInHz", doubleSignature);
-        env->CallVoidMethod(gnssMeasurementObject, setterMethod, measurement->doppler_shift_hz);
-    }
-
-    if (flags & GPS_MEASUREMENT_HAS_DOPPLER_SHIFT_UNCERTAINTY) {
-        jmethodID setterMethod = env->GetMethodID(
-                gnssMeasurementClass,
-                "setDopplerShiftUncertaintyInHz",
-                doubleSignature);
-        env->CallVoidMethod(
-                gnssMeasurementObject,
-                setterMethod,
-                measurement->doppler_shift_uncertainty_hz);
-    }
-
-    jmethodID multipathIndicatorSetterMethod =
-            env->GetMethodID(gnssMeasurementClass, "setMultipathIndicator", byteSignature);
-    env->CallVoidMethod(
-            gnssMeasurementObject,
-            multipathIndicatorSetterMethod,
-            measurement->multipath_indicator);
-
-    if (flags & GPS_MEASUREMENT_HAS_SNR) {
-        jmethodID setterMethod =
-                env->GetMethodID(gnssMeasurementClass, "setSnrInDb", doubleSignature);
-        env->CallVoidMethod(gnssMeasurementObject, setterMethod, measurement->snr_db);
-    }
-
-    if (flags & GPS_MEASUREMENT_HAS_ELEVATION) {
-        jmethodID setterMethod =
-                env->GetMethodID(gnssMeasurementClass, "setElevationInDeg", doubleSignature);
-        env->CallVoidMethod(gnssMeasurementObject, setterMethod, measurement->elevation_deg);
-    }
-
-    if (flags & GPS_MEASUREMENT_HAS_ELEVATION_UNCERTAINTY) {
-        jmethodID setterMethod =
-                env->GetMethodID(gnssMeasurementClass, "setElevationUncertaintyInDeg", doubleSignature);
-        env->CallVoidMethod(
-                gnssMeasurementObject,
-                setterMethod,
-                measurement->elevation_uncertainty_deg);
-    }
-
-    if (flags & GPS_MEASUREMENT_HAS_AZIMUTH) {
-        jmethodID setterMethod =
-                env->GetMethodID(gnssMeasurementClass, "setAzimuthInDeg", doubleSignature);
-        env->CallVoidMethod(gnssMeasurementObject, setterMethod, measurement->azimuth_deg);
-    }
-
-    if (flags & GPS_MEASUREMENT_HAS_AZIMUTH_UNCERTAINTY) {
-        jmethodID setterMethod = env->GetMethodID(
-                gnssMeasurementClass,
-                "setAzimuthUncertaintyInDeg",
-                doubleSignature);
-        env->CallVoidMethod(
-                gnssMeasurementObject,
-                setterMethod,
-                measurement->azimuth_uncertainty_deg);
-    }
-
-    jmethodID usedInFixSetterMethod = env->GetMethodID(gnssMeasurementClass, "setUsedInFix", "(Z)V");
-    env->CallVoidMethod(
-            gnssMeasurementObject,
-            usedInFixSetterMethod,
-            (flags & GPS_MEASUREMENT_HAS_USED_IN_FIX) && measurement->used_in_fix);
-
-    if (size == sizeof(GpsMeasurement)) {
-      jmethodID setterMethod =
-          env->GetMethodID(gnssMeasurementClass,
-                           "setPseudorangeRateCarrierInMetersPerSec",
-                           doubleSignature);
-      env->CallVoidMethod(
-          gnssMeasurementObject,
-          setterMethod,
-          measurement->pseudorange_rate_carrier_mps);
-
-      setterMethod =
-          env->GetMethodID(gnssMeasurementClass,
-                           "setPseudorangeRateCarrierUncertaintyInMetersPerSec",
-                           doubleSignature);
-      env->CallVoidMethod(
-          gnssMeasurementObject,
-          setterMethod,
-          measurement->pseudorange_rate_carrier_uncertainty_mps);
-    }
-
-    env->DeleteLocalRef(gnssMeasurementClass);
-    return gnssMeasurementObject;
+    return object.get();
 }
 
-/**
- * <T> can only be GpsData or GpsData_v1. Must rewrite this function if more
- * types are introduced in the future releases.
- */
-template<class T>
-static jobjectArray translate_gps_measurements(JNIEnv* env, void* data) {
-    T* gps_data = reinterpret_cast<T*>(data);
-    size_t measurementCount = gps_data->measurement_count;
-    if (measurementCount == 0) {
+static jobject translate_gnss_measurement(JNIEnv* env,
+                                          GnssMeasurement* measurement) {
+    JavaObject object(env, "android/location/GnssMeasurement");
+    GpsMeasurementFlags flags = measurement->flags;
+
+    SET(Svid, measurement->svid);
+    SET(TimeOffsetInNs, measurement->time_offset_ns);
+    SET(State, measurement->state);
+    SET(ReceivedGpsTowInNs, measurement->received_gps_tow_ns);
+    SET(ReceivedGpsTowUncertaintyInNs,
+        measurement->received_gps_tow_uncertainty_ns);
+    SET(Cn0InDbHz, measurement->c_n0_dbhz);
+    SET(PseudorangeRateInMetersPerSec, measurement->pseudorange_rate_mps);
+    SET(PseudorangeRateUncertaintyInMetersPerSec,
+        measurement->pseudorange_rate_uncertainty_mps);
+    SET(AccumulatedDeltaRangeState, measurement->accumulated_delta_range_state);
+    SET(AccumulatedDeltaRangeInMeters, measurement->accumulated_delta_range_m);
+    SET(AccumulatedDeltaRangeUncertaintyInMeters,
+        measurement->accumulated_delta_range_uncertainty_m);
+    SET_IF(GPS_MEASUREMENT_HAS_PSEUDORANGE,
+           PseudorangeInMeters,
+           measurement->pseudorange_m);
+    SET_IF(GPS_MEASUREMENT_HAS_PSEUDORANGE_UNCERTAINTY,
+           PseudorangeUncertaintyInMeters,
+           measurement->pseudorange_uncertainty_m);
+    SET_IF(GPS_MEASUREMENT_HAS_CODE_PHASE,
+           CodePhaseInChips,
+           measurement->code_phase_chips);
+    SET_IF(GPS_MEASUREMENT_HAS_CODE_PHASE_UNCERTAINTY,
+           CodePhaseUncertaintyInChips,
+           measurement->code_phase_uncertainty_chips);
+    SET_IF(GPS_MEASUREMENT_HAS_CARRIER_FREQUENCY,
+           CarrierFrequencyInHz,
+           measurement->carrier_frequency_hz);
+    SET_IF(GPS_MEASUREMENT_HAS_CARRIER_CYCLES,
+           CarrierCycles,
+           measurement->carrier_cycles);
+    SET_IF(GPS_MEASUREMENT_HAS_CARRIER_PHASE,
+           CarrierPhase,
+           measurement->carrier_phase);
+    SET_IF(GPS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY,
+           CarrierPhaseUncertainty,
+           measurement->carrier_phase_uncertainty);
+    SET(LossOfLock, measurement->loss_of_lock);
+    SET_IF(GPS_MEASUREMENT_HAS_BIT_NUMBER, BitNumber, measurement->bit_number);
+    SET_IF(GPS_MEASUREMENT_HAS_TIME_FROM_LAST_BIT,
+           TimeFromLastBitInMs,
+           measurement->time_from_last_bit_ms);
+    SET_IF(GPS_MEASUREMENT_HAS_DOPPLER_SHIFT,
+           DopplerShiftInHz,
+           measurement->doppler_shift_hz);
+    SET_IF(GPS_MEASUREMENT_HAS_DOPPLER_SHIFT_UNCERTAINTY,
+           DopplerShiftUncertaintyInHz,
+           measurement->doppler_shift_uncertainty_hz);
+    SET(MultipathIndicator, measurement->multipath_indicator);
+    SET_IF(GPS_MEASUREMENT_HAS_SNR, SnrInDb, measurement->snr_db);
+    SET_IF(GPS_MEASUREMENT_HAS_ELEVATION,
+           ElevationInDeg,
+           measurement->elevation_deg);
+    SET_IF(GPS_MEASUREMENT_HAS_ELEVATION_UNCERTAINTY,
+           ElevationUncertaintyInDeg,
+           measurement->elevation_uncertainty_deg);
+    SET_IF(GPS_MEASUREMENT_HAS_AZIMUTH,
+           AzimuthInDeg,
+           measurement->azimuth_deg);
+    SET_IF(GPS_MEASUREMENT_HAS_AZIMUTH_UNCERTAINTY,
+           AzimuthUncertaintyInDeg,
+           measurement->azimuth_uncertainty_deg);
+    SET(UsedInFix,
+        (flags & GPS_MEASUREMENT_HAS_USED_IN_FIX) && measurement->used_in_fix);
+
+    SET(PseudorangeRateCarrierInMetersPerSec,
+        measurement->pseudorange_rate_carrier_mps);
+    SET(PseudorangeRateCarrierUncertaintyInMetersPerSec,
+        measurement->pseudorange_rate_carrier_uncertainty_mps);
+
+    return object.get();
+}
+
+static jobjectArray translate_gps_measurements(JNIEnv* env,
+                                               GpsMeasurement* measurements,
+                                               size_t count) {
+    if (count == 0) {
         return NULL;
     }
 
-    jclass gnssMeasurementClass = env->FindClass("android/location/GnssMeasurement");
+    jclass gnssMeasurementClass = env->FindClass(
+            "android/location/GnssMeasurement");
     jobjectArray gnssMeasurementArray = env->NewObjectArray(
-            measurementCount,
+            count,
             gnssMeasurementClass,
             NULL /* initialElement */);
 
-    for (uint16_t i = 0; i < measurementCount; ++i) {
+    for (uint16_t i = 0; i < count; ++i) {
         jobject gnssMeasurement = translate_gps_measurement(
             env,
-            &(gps_data->measurements[i]),
-            sizeof(gps_data->measurements[0]));
+            &measurements[i]);
         env->SetObjectArrayElement(gnssMeasurementArray, i, gnssMeasurement);
         env->DeleteLocalRef(gnssMeasurement);
     }
@@ -1340,27 +1331,37 @@
     return gnssMeasurementArray;
 }
 
-static void measurement_callback(GpsData* data) {
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
-    if (data == NULL) {
-        ALOGE("Invalid data provided to gps_measurement_callback");
-        return;
-    }
-    if (data->size != sizeof(GpsData) && data->size != sizeof(GpsData_v1)) {
-        ALOGE("Invalid GpsData size found in gps_measurement_callback, size=%zd", data->size);
-        return;
+static jobjectArray translate_gnss_measurements(JNIEnv* env,
+                                                GnssMeasurement* measurements,
+                                                size_t count) {
+    if (count == 0) {
+        return NULL;
     }
 
-    jobject gpsClock;
-    jobjectArray measurementArray;
-    if (data->size == sizeof(GpsData)) {
-        gpsClock = translate_gps_clock(env, &data->clock, sizeof(GpsClock));
-        measurementArray = translate_gps_measurements<GpsData>(env, data);
-    } else {
-        gpsClock = translate_gps_clock(env, &data->clock, sizeof(GpsClock_v1));
-        measurementArray = translate_gps_measurements<GpsData_v1>(env, data);
+    jclass gnssMeasurementClass = env->FindClass(
+            "android/location/GnssMeasurement");
+    jobjectArray gnssMeasurementArray = env->NewObjectArray(
+            count,
+            gnssMeasurementClass,
+            NULL /* initialElement */);
+
+    for (uint16_t i = 0; i < count; ++i) {
+        jobject gnssMeasurement = translate_gnss_measurement(
+            env,
+            &measurements[i]);
+        env->SetObjectArrayElement(gnssMeasurementArray, i, gnssMeasurement);
+        env->DeleteLocalRef(gnssMeasurement);
     }
-    jclass gnssMeasurementsEventClass = env->FindClass("android/location/GnssMeasurementsEvent");
+
+    env->DeleteLocalRef(gnssMeasurementClass);
+    return gnssMeasurementArray;
+}
+
+static void set_measurement_data(JNIEnv *env,
+                                 jobject clock,
+                                 jobjectArray measurementArray) {
+    jclass gnssMeasurementsEventClass = env->FindClass(
+            "android/location/GnssMeasurementsEvent");
     jmethodID gnssMeasurementsEventCtor = env->GetMethodID(
         gnssMeasurementsEventClass,
         "<init>",
@@ -1369,21 +1370,68 @@
     jobject gnssMeasurementsEvent = env->NewObject(
         gnssMeasurementsEventClass,
         gnssMeasurementsEventCtor,
-        gpsClock,
+        clock,
         measurementArray);
-
-    env->CallVoidMethod(mCallbacksObj, method_reportMeasurementData, gnssMeasurementsEvent);
+    env->CallVoidMethod(mCallbacksObj,
+                        method_reportMeasurementData,
+                        gnssMeasurementsEvent);
     checkAndClearExceptionFromCallback(env, __FUNCTION__);
-
-    env->DeleteLocalRef(gpsClock);
-    env->DeleteLocalRef(measurementArray);
     env->DeleteLocalRef(gnssMeasurementsEventClass);
     env->DeleteLocalRef(gnssMeasurementsEvent);
 }
 
+static void measurement_callback(GpsData* data) {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    if (data == NULL) {
+        ALOGE("Invalid data provided to gps_measurement_callback");
+        return;
+    }
+    if (data->size != sizeof(GpsData)) {
+        ALOGE("Invalid GpsData size found in gps_measurement_callback, "
+              "size=%zd",
+              data->size);
+        return;
+    }
+
+    jobject clock;
+    jobjectArray measurementArray;
+    clock = translate_gps_clock(env, &data->clock);
+    measurementArray = translate_gps_measurements(
+            env, data->measurements, data->measurement_count);
+    set_measurement_data(env, clock, measurementArray);
+
+    env->DeleteLocalRef(clock);
+    env->DeleteLocalRef(measurementArray);
+}
+
+static void gnss_measurement_callback(GnssData* data) {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    if (data == NULL) {
+        ALOGE("Invalid data provided to gps_measurement_callback");
+        return;
+    }
+    if (data->size != sizeof(GpsData)) {
+        ALOGE("Invalid GpsData size found in gps_measurement_callback, "
+              "size=%zd",
+              data->size);
+        return;
+    }
+
+    jobject clock;
+    jobjectArray measurementArray;
+    clock = translate_gnss_clock(env, &data->clock);
+    measurementArray = translate_gnss_measurements(
+            env, data->measurements, data->measurement_count);
+    set_measurement_data(env, clock, measurementArray);
+
+    env->DeleteLocalRef(clock);
+    env->DeleteLocalRef(measurementArray);
+}
+
 GpsMeasurementCallbacks sGpsMeasurementCallbacks = {
     sizeof(GpsMeasurementCallbacks),
     measurement_callback,
+    gnss_measurement_callback,
 };
 
 static jboolean android_location_GnssLocationProvider_is_measurement_supported(
@@ -1431,69 +1479,86 @@
         ALOGE("Invalid Navigation Message found: data=%p, length=%zd", data, dataLength);
         return NULL;
     }
+    JavaObject object(env, "android/location/GnssNavigationMessage");
+    SET(Type, message->type);
+    SET(Svid, static_cast<int16_t>(message->prn));
+    SET(MessageId, message->message_id);
+    SET(SubmessageId, message->submessage_id);
+    object.callSetter("setData", data, dataLength);
+    return object.get();
+}
 
-    jclass navigationMessageClass = env->FindClass("android/location/GnssNavigationMessage");
-    jmethodID navigationMessageCtor = env->GetMethodID(navigationMessageClass, "<init>", "()V");
-    jobject navigationMessageObject = env->NewObject(navigationMessageClass, navigationMessageCtor);
+static jobject translate_gnss_navigation_message(
+        JNIEnv* env, GnssNavigationMessage* message) {
+    size_t dataLength = message->data_length;
+    uint8_t* data = message->data;
+    if (dataLength == 0 || data == NULL) {
+        ALOGE("Invalid Navigation Message found: data=%p, length=%zd", data, dataLength);
+        return NULL;
+    }
+    JavaObject object(env, "android/location/GnssNavigationMessage");
+    SET(Type, message->type);
+    SET(Svid, message->svid);
+    SET(MessageId, message->message_id);
+    SET(SubmessageId, message->submessage_id);
+    object.callSetter("setData", data, dataLength);
+    return object.get();
+}
 
-    jmethodID setTypeMethod = env->GetMethodID(navigationMessageClass, "setType", "(B)V");
-    env->CallVoidMethod(navigationMessageObject, setTypeMethod, message->type);
-
-    jmethodID setPrnMethod = env->GetMethodID(navigationMessageClass, "setPrn", "(B)V");
-    env->CallVoidMethod(navigationMessageObject, setPrnMethod, message->prn);
-
-    jmethodID setMessageIdMethod = env->GetMethodID(navigationMessageClass, "setMessageId", "(S)V");
-    env->CallVoidMethod(navigationMessageObject, setMessageIdMethod, message->message_id);
-
-    jmethodID setSubmessageIdMethod =
-            env->GetMethodID(navigationMessageClass, "setSubmessageId", "(S)V");
-    env->CallVoidMethod(navigationMessageObject, setSubmessageIdMethod, message->submessage_id);
-
-    jbyteArray dataArray = env->NewByteArray(dataLength);
-    env->SetByteArrayRegion(dataArray, 0, dataLength, (jbyte*) data);
-    jmethodID setDataMethod = env->GetMethodID(navigationMessageClass, "setData", "([B)V");
-    env->CallVoidMethod(navigationMessageObject, setDataMethod, dataArray);
-
-    env->DeleteLocalRef(navigationMessageClass);
-    env->DeleteLocalRef(dataArray);
-    return navigationMessageObject;
+static void set_navigation_message(jobject navigationMessage) {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    jclass navigationMessageEventClass =
+            env->FindClass("android/location/GnssNavigationMessageEvent");
+    jmethodID navigationMessageEventCtor = env->GetMethodID(
+            navigationMessageEventClass,
+            "<init>",
+            "(Landroid/location/GnssNavigationMessage;)V");
+    jobject navigationMessageEvent = env->NewObject(
+            navigationMessageEventClass,
+            navigationMessageEventCtor,
+            navigationMessage);
+    env->CallVoidMethod(mCallbacksObj,
+                        method_reportNavigationMessages,
+                        navigationMessageEvent);
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+    env->DeleteLocalRef(navigationMessageEventClass);
+    env->DeleteLocalRef(navigationMessageEvent);
 }
 
 static void navigation_message_callback(GpsNavigationMessage* message) {
-    JNIEnv* env = AndroidRuntime::getJNIEnv();
     if (message == NULL) {
         ALOGE("Invalid Navigation Message provided to callback");
         return;
     }
-
-    if (message->size == sizeof(GpsNavigationMessage)) {
-        jobject navigationMessage = translate_gps_navigation_message(env, message);
-
-        jclass navigationMessageEventClass =
-                env->FindClass("android/location/GnssNavigationMessageEvent");
-        jmethodID navigationMessageEventCtor = env->GetMethodID(
-                navigationMessageEventClass,
-                "<init>",
-                "(Landroid/location/GnssNavigationMessage;)V");
-        jobject navigationMessageEvent = env->NewObject(
-                navigationMessageEventClass,
-                navigationMessageEventCtor,
-                navigationMessage);
-
-        env->CallVoidMethod(mCallbacksObj, method_reportNavigationMessages, navigationMessageEvent);
-        checkAndClearExceptionFromCallback(env, __FUNCTION__);
-
-        env->DeleteLocalRef(navigationMessage);
-        env->DeleteLocalRef(navigationMessageEventClass);
-        env->DeleteLocalRef(navigationMessageEvent);
-    } else {
+    if (message->size != sizeof(GpsNavigationMessage)) {
         ALOGE("Invalid GpsNavigationMessage size found: %zd", message->size);
+        return;
     }
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    jobject navigationMessage = translate_gps_navigation_message(env, message);
+    set_navigation_message(navigationMessage);
+    env->DeleteLocalRef(navigationMessage);
+}
+
+static void gnss_navigation_message_callback(GnssNavigationMessage* message) {
+    if (message == NULL) {
+        ALOGE("Invalid Navigation Message provided to callback");
+        return;
+    }
+    if (message->size != sizeof(GnssNavigationMessage)) {
+        ALOGE("Invalid GnssNavigationMessage size found: %zd", message->size);
+        return;
+    }
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    jobject navigationMessage = translate_gnss_navigation_message(env, message);
+    set_navigation_message(navigationMessage);
+    env->DeleteLocalRef(navigationMessage);
 }
 
 GpsNavigationMessageCallbacks sGpsNavigationMessageCallbacks = {
     sizeof(GpsNavigationMessageCallbacks),
     navigation_message_callback,
+    gnss_navigation_message_callback,
 };
 
 static jboolean android_location_GnssLocationProvider_is_navigation_message_supported(
@@ -1567,7 +1632,7 @@
             "(I)V",
             (void*)android_location_GnssLocationProvider_delete_aiding_data},
     {"native_read_sv_status",
-            "([I[F[F[F[I)I",
+            "([I[F[F[F)I",
             (void*)android_location_GnssLocationProvider_read_sv_status},
     {"native_read_nmea", "([BI)I", (void*)android_location_GnssLocationProvider_read_nmea},
     {"native_inject_time", "(JJI)V", (void*)android_location_GnssLocationProvider_inject_time},