Add GnssExcessPathInfo (frameworks/base)

Also add combinedAttenuationDb in GnssSingleSatCorrection

Bug: 201253590
Test: atest GnssExcessPathInfoTest
      atest GnssSingleSatCorrectionTest
Change-Id: I7f629f2fbca563a36d1b4543f768b8fabd5d91fd
diff --git a/Android.bp b/Android.bp
index 753cefc..edaa11e3 100644
--- a/Android.bp
+++ b/Android.bp
@@ -97,6 +97,7 @@
         ":platform-compat-native-aidl",
 
         // AIDL sources from external directories
+        ":android.hardware.gnss-V2-java-source",
         ":android.hardware.graphics.common-V3-java-source",
         ":android.hardware.security.keymint-V2-java-source",
         ":android.hardware.security.secureclock-V1-java-source",
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 09d1114..8406d1c 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -5488,6 +5488,32 @@
     method @NonNull public android.location.GnssCapabilities.Builder setHasSatellitePvt(boolean);
   }
 
+  public final class GnssExcessPathInfo implements android.os.Parcelable {
+    method public int describeContents();
+    method @FloatRange(from=0.0f) public float getAttenuationDb();
+    method @FloatRange(from=0.0f) public float getExcessPathLengthMeters();
+    method @FloatRange(from=0.0f) public float getExcessPathLengthUncertaintyMeters();
+    method @NonNull public android.location.GnssReflectingPlane getReflectingPlane();
+    method public boolean hasAttenuation();
+    method public boolean hasExcessPathLength();
+    method public boolean hasExcessPathLengthUncertainty();
+    method public boolean hasReflectingPlane();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssExcessPathInfo> CREATOR;
+  }
+
+  public static final class GnssExcessPathInfo.Builder {
+    ctor public GnssExcessPathInfo.Builder();
+    method @NonNull public android.location.GnssExcessPathInfo build();
+    method @NonNull public android.location.GnssExcessPathInfo.Builder clearAttenuationDb();
+    method @NonNull public android.location.GnssExcessPathInfo.Builder clearExcessPathLengthMeters();
+    method @NonNull public android.location.GnssExcessPathInfo.Builder clearExcessPathLengthUncertaintyMeters();
+    method @NonNull public android.location.GnssExcessPathInfo.Builder setAttenuationDb(@FloatRange(from=0.0f) float);
+    method @NonNull public android.location.GnssExcessPathInfo.Builder setExcessPathLengthMeters(@FloatRange(from=0.0f) float);
+    method @NonNull public android.location.GnssExcessPathInfo.Builder setExcessPathLengthUncertaintyMeters(@FloatRange(from=0.0f) float);
+    method @NonNull public android.location.GnssExcessPathInfo.Builder setReflectingPlane(@Nullable android.location.GnssReflectingPlane);
+  }
+
   public final class GnssMeasurement implements android.os.Parcelable {
     method @Nullable public java.util.Collection<android.location.CorrelationVector> getCorrelationVectors();
     method @Nullable public android.location.SatellitePvt getSatellitePvt();
@@ -5569,15 +5595,18 @@
   public final class GnssSingleSatCorrection implements android.os.Parcelable {
     method public int describeContents();
     method @FloatRange(from=0.0f, fromInclusive=false) public float getCarrierFrequencyHz();
+    method @FloatRange(from=0.0f) public float getCombinedAttenuationDb();
     method public int getConstellationType();
     method @FloatRange(from=0.0f) public float getExcessPathLengthMeters();
     method @FloatRange(from=0.0f) public float getExcessPathLengthUncertaintyMeters();
+    method @NonNull public java.util.List<android.location.GnssExcessPathInfo> getGnssExcessPathInfoList();
     method @FloatRange(from=0.0f, to=1.0f) public float getProbabilityLineOfSight();
-    method @Nullable public android.location.GnssReflectingPlane getReflectingPlane();
+    method @Deprecated @Nullable public android.location.GnssReflectingPlane getReflectingPlane();
     method @IntRange(from=0) public int getSatelliteId();
+    method public boolean hasCombinedAttenuation();
     method public boolean hasExcessPathLength();
     method public boolean hasExcessPathLengthUncertainty();
-    method public boolean hasReflectingPlane();
+    method @Deprecated public boolean hasReflectingPlane();
     method public boolean hasValidSatelliteLineOfSight();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.location.GnssSingleSatCorrection> CREATOR;
@@ -5586,15 +5615,18 @@
   public static final class GnssSingleSatCorrection.Builder {
     ctor public GnssSingleSatCorrection.Builder();
     method @NonNull public android.location.GnssSingleSatCorrection build();
+    method @NonNull public android.location.GnssSingleSatCorrection.Builder clearCombinedAttenuationDb();
     method @NonNull public android.location.GnssSingleSatCorrection.Builder clearExcessPathLengthMeters();
     method @NonNull public android.location.GnssSingleSatCorrection.Builder clearExcessPathLengthUncertaintyMeters();
     method @NonNull public android.location.GnssSingleSatCorrection.Builder clearProbabilityLineOfSight();
     method @NonNull public android.location.GnssSingleSatCorrection.Builder setCarrierFrequencyHz(@FloatRange(from=0.0f, fromInclusive=false) float);
+    method @NonNull public android.location.GnssSingleSatCorrection.Builder setCombinedAttenuationDb(@FloatRange(from=0.0f) float);
     method @NonNull public android.location.GnssSingleSatCorrection.Builder setConstellationType(int);
     method @NonNull public android.location.GnssSingleSatCorrection.Builder setExcessPathLengthMeters(@FloatRange(from=0.0f) float);
     method @NonNull public android.location.GnssSingleSatCorrection.Builder setExcessPathLengthUncertaintyMeters(@FloatRange(from=0.0f) float);
+    method @NonNull public android.location.GnssSingleSatCorrection.Builder setGnssExcessPathInfoList(@NonNull java.util.List<android.location.GnssExcessPathInfo>);
     method @NonNull public android.location.GnssSingleSatCorrection.Builder setProbabilityLineOfSight(@FloatRange(from=0.0f, to=1.0f) float);
-    method @NonNull public android.location.GnssSingleSatCorrection.Builder setReflectingPlane(@Nullable android.location.GnssReflectingPlane);
+    method @Deprecated @NonNull public android.location.GnssSingleSatCorrection.Builder setReflectingPlane(@Nullable android.location.GnssReflectingPlane);
     method @NonNull public android.location.GnssSingleSatCorrection.Builder setSatelliteId(@IntRange(from=0) int);
   }
 
diff --git a/location/java/android/location/GnssExcessPathInfo.java b/location/java/android/location/GnssExcessPathInfo.java
new file mode 100644
index 0000000..72b2374
--- /dev/null
+++ b/location/java/android/location/GnssExcessPathInfo.java
@@ -0,0 +1,375 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.location;
+
+import static android.hardware.gnss.measurement_corrections.SingleSatCorrection.ExcessPathInfo.EXCESS_PATH_INFO_HAS_ATTENUATION;
+import static android.hardware.gnss.measurement_corrections.SingleSatCorrection.ExcessPathInfo.EXCESS_PATH_INFO_HAS_EXCESS_PATH_LENGTH;
+import static android.hardware.gnss.measurement_corrections.SingleSatCorrection.ExcessPathInfo.EXCESS_PATH_INFO_HAS_EXCESS_PATH_LENGTH_UNC;
+import static android.hardware.gnss.measurement_corrections.SingleSatCorrection.ExcessPathInfo.EXCESS_PATH_INFO_HAS_REFLECTING_PLANE;
+
+import android.annotation.FloatRange;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.util.Preconditions;
+
+import java.util.Objects;
+
+/**
+ * Contains the info of an excess path signal caused by reflection
+ *
+ * @hide
+ */
+@SystemApi
+public final class GnssExcessPathInfo implements Parcelable {
+
+    private static final int HAS_EXCESS_PATH_LENGTH_MASK = EXCESS_PATH_INFO_HAS_EXCESS_PATH_LENGTH;
+    private static final int HAS_EXCESS_PATH_LENGTH_UNC_MASK =
+            EXCESS_PATH_INFO_HAS_EXCESS_PATH_LENGTH_UNC;
+    private static final int HAS_REFLECTING_PLANE_MASK = EXCESS_PATH_INFO_HAS_REFLECTING_PLANE;
+    private static final int HAS_ATTENUATION_MASK = EXCESS_PATH_INFO_HAS_ATTENUATION;
+
+    /* A bitmask of fields present in this object (see HAS_* constants defined above) */
+    private final int mFlags;
+    private final float mExcessPathLengthMeters;
+    private final float mExcessPathLengthUncertaintyMeters;
+    @Nullable
+    private final GnssReflectingPlane mReflectingPlane;
+    private final float mAttenuationDb;
+
+    private GnssExcessPathInfo(
+            int flags,
+            float excessPathLengthMeters,
+            float excessPathLengthUncertaintyMeters,
+            @Nullable GnssReflectingPlane reflectingPlane,
+            float attenuationDb) {
+        mFlags = flags;
+        mExcessPathLengthMeters = excessPathLengthMeters;
+        mExcessPathLengthUncertaintyMeters = excessPathLengthUncertaintyMeters;
+        mReflectingPlane = reflectingPlane;
+        mAttenuationDb = attenuationDb;
+    }
+
+    /**
+     * Gets a bitmask of fields present in this object.
+     *
+     * <p>This API exists for JNI since it is easier for JNI to get one integer flag than looking up
+     * several has* methods.
+     * @hide
+     */
+    public int getFlags() {
+        return mFlags;
+    }
+
+    /** Returns {@code true} if {@link #getExcessPathLengthMeters()} is valid. */
+    public boolean hasExcessPathLength() {
+        return (mFlags & HAS_EXCESS_PATH_LENGTH_MASK) != 0;
+    }
+
+    /**
+     * Returns the excess path length to be subtracted from pseudorange before using it in
+     * calculating location.
+     *
+     * <p>{@link #hasExcessPathLength()} must be true when calling this method. Otherwise, an
+     * {@link UnsupportedOperationException} will be thrown.
+     */
+    @FloatRange(from = 0.0f)
+    public float getExcessPathLengthMeters() {
+        if (!hasExcessPathLength()) {
+            throw new UnsupportedOperationException(
+                    "getExcessPathLengthMeters() is not supported when hasExcessPathLength() is "
+                            + "false");
+        }
+        return mExcessPathLengthMeters;
+    }
+
+    /** Returns {@code true} if {@link #getExcessPathLengthUncertaintyMeters()} is valid. */
+    public boolean hasExcessPathLengthUncertainty() {
+        return (mFlags & HAS_EXCESS_PATH_LENGTH_UNC_MASK) != 0;
+    }
+
+    /**
+     * Returns the error estimate (1-sigma) for the excess path length estimate.
+     *
+     * <p>{@link #hasExcessPathLengthUncertainty()} must be true when calling this method.
+     * Otherwise, an {@link UnsupportedOperationException} will be thrown.
+     */
+    @FloatRange(from = 0.0f)
+    public float getExcessPathLengthUncertaintyMeters() {
+        if (!hasExcessPathLengthUncertainty()) {
+            throw new UnsupportedOperationException(
+                    "getExcessPathLengthUncertaintyMeters() is not supported when "
+                            + "hasExcessPathLengthUncertainty() is false");
+        }
+        return mExcessPathLengthUncertaintyMeters;
+    }
+
+    /**
+     * Returns {@code true} if {@link #getReflectingPlane()} is valid.
+     *
+     * <p>Returns false if the satellite signal goes through multiple reflections or if reflection
+     * plane serving is not supported.
+     */
+    public boolean hasReflectingPlane() {
+        return (mFlags & HAS_REFLECTING_PLANE_MASK) != 0;
+    }
+
+    /**
+     * Returns the reflecting plane characteristics at which the signal has bounced.
+     *
+     * <p>{@link #hasReflectingPlane()} must be true when calling this method. Otherwise, an
+     * {@link UnsupportedOperationException} will be thrown.
+     */
+    @NonNull
+    public GnssReflectingPlane getReflectingPlane() {
+        if (!hasReflectingPlane()) {
+            throw new UnsupportedOperationException(
+                    "getReflectingPlane() is not supported when hasReflectingPlane() is false");
+        }
+        return mReflectingPlane;
+    }
+
+    /** Returns {@code true} if {@link #getAttenuationDb()} is valid. */
+    public boolean hasAttenuation() {
+        return (mFlags & HAS_ATTENUATION_MASK) != 0;
+    }
+
+    /**
+     * Returns the expected reduction of signal strength of this path in non-negative dB.
+     *
+     * <p>{@link #hasAttenuation()} must be true when calling this method. Otherwise, an
+     * {@link UnsupportedOperationException} will be thrown.
+     */
+    @FloatRange(from = 0.0f)
+    public float getAttenuationDb() {
+        if (!hasAttenuation()) {
+            throw new UnsupportedOperationException(
+                    "getAttenuationDb() is not supported when hasAttenuation() is false");
+        }
+        return mAttenuationDb;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel parcel, int parcelFlags) {
+        parcel.writeInt(mFlags);
+        if (hasExcessPathLength()) {
+            parcel.writeFloat(mExcessPathLengthMeters);
+        }
+        if (hasExcessPathLengthUncertainty()) {
+            parcel.writeFloat(mExcessPathLengthUncertaintyMeters);
+        }
+        if (hasReflectingPlane()) {
+            mReflectingPlane.writeToParcel(parcel, parcelFlags);
+        }
+        if (hasAttenuation()) {
+            parcel.writeFloat(mAttenuationDb);
+        }
+    }
+
+    public static final @NonNull Creator<GnssExcessPathInfo> CREATOR =
+            new Creator<GnssExcessPathInfo>() {
+                @Override
+                @NonNull
+                public GnssExcessPathInfo createFromParcel(@NonNull Parcel parcel) {
+                    int flags = parcel.readInt();
+                    float excessPathLengthMeters =
+                            (flags & HAS_EXCESS_PATH_LENGTH_MASK) != 0
+                                    ? parcel.readFloat() : 0;
+                    float excessPathLengthUncertaintyMeters =
+                            (flags & HAS_EXCESS_PATH_LENGTH_UNC_MASK) != 0
+                                    ? parcel.readFloat() : 0;
+                    GnssReflectingPlane reflectingPlane =
+                            (flags & HAS_REFLECTING_PLANE_MASK) != 0
+                                    ? GnssReflectingPlane.CREATOR.createFromParcel(parcel) : null;
+                    float attenuationDb =
+                            (flags & HAS_ATTENUATION_MASK) != 0
+                                    ? parcel.readFloat() : 0;
+                    return new GnssExcessPathInfo(flags, excessPathLengthMeters,
+                            excessPathLengthUncertaintyMeters, reflectingPlane, attenuationDb);
+                }
+
+                @Override
+                public GnssExcessPathInfo[] newArray(int i) {
+                    return new GnssExcessPathInfo[i];
+                }
+            };
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj instanceof GnssExcessPathInfo) {
+            GnssExcessPathInfo that = (GnssExcessPathInfo) obj;
+            return this.mFlags == that.mFlags
+                    && (!hasExcessPathLength() || Float.compare(this.mExcessPathLengthMeters,
+                    that.mExcessPathLengthMeters) == 0)
+                    && (!hasExcessPathLengthUncertainty() || Float.compare(
+                    this.mExcessPathLengthUncertaintyMeters,
+                    that.mExcessPathLengthUncertaintyMeters) == 0)
+                    && (!hasReflectingPlane() || Objects.equals(this.mReflectingPlane,
+                    that.mReflectingPlane))
+                    && (!hasAttenuation() || Float.compare(this.mAttenuationDb,
+                    that.mAttenuationDb) == 0);
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mFlags,
+                mExcessPathLengthMeters,
+                mExcessPathLengthUncertaintyMeters,
+                mReflectingPlane,
+                mAttenuationDb);
+    }
+
+    @NonNull
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder("GnssExcessPathInfo[");
+        if (hasExcessPathLength()) {
+            builder.append(" ExcessPathLengthMeters=").append(mExcessPathLengthMeters);
+        }
+        if (hasExcessPathLengthUncertainty()) {
+            builder.append(" ExcessPathLengthUncertaintyMeters=").append(
+                    mExcessPathLengthUncertaintyMeters);
+        }
+        if (hasReflectingPlane()) {
+            builder.append(" ReflectingPlane=").append(mReflectingPlane);
+        }
+        if (hasAttenuation()) {
+            builder.append(" AttenuationDb=").append(mAttenuationDb);
+        }
+        builder.append(']');
+        return builder.toString();
+    }
+
+    /** Builder for {@link GnssExcessPathInfo}. */
+    public static final class Builder {
+        private int mFlags;
+        private float mExcessPathLengthMeters;
+        private float mExcessPathLengthUncertaintyMeters;
+        @Nullable
+        private GnssReflectingPlane mReflectingPlane;
+        private float mAttenuationDb;
+
+        /** Constructor for {@link Builder}. */
+        public Builder() {}
+
+        /**
+         * Sets the excess path length to be subtracted from pseudorange before using it in
+         * calculating location.
+         */
+        @NonNull
+        public Builder setExcessPathLengthMeters(
+                @FloatRange(from = 0.0f) float excessPathLengthMeters) {
+            Preconditions.checkArgumentInRange(excessPathLengthMeters, 0, Float.MAX_VALUE,
+                    "excessPathLengthMeters");
+            mExcessPathLengthMeters = excessPathLengthMeters;
+            mFlags |= HAS_EXCESS_PATH_LENGTH_MASK;
+            return this;
+        }
+
+        /**
+         * Clears the excess path length.
+         *
+         * <p>This is to negate {@link #setExcessPathLengthMeters} call.
+         */
+        @NonNull
+        public Builder clearExcessPathLengthMeters() {
+            mExcessPathLengthMeters = 0;
+            mFlags &= ~HAS_EXCESS_PATH_LENGTH_MASK;
+            return this;
+        }
+
+        /** Sets the error estimate (1-sigma) for the excess path length estimate */
+        @NonNull
+        public Builder setExcessPathLengthUncertaintyMeters(
+                @FloatRange(from = 0.0f) float excessPathLengthUncertaintyMeters) {
+            Preconditions.checkArgumentInRange(excessPathLengthUncertaintyMeters, 0,
+                    Float.MAX_VALUE, "excessPathLengthUncertaintyMeters");
+            mExcessPathLengthUncertaintyMeters = excessPathLengthUncertaintyMeters;
+            mFlags |= HAS_EXCESS_PATH_LENGTH_UNC_MASK;
+            return this;
+        }
+
+        /**
+         * Clears the error estimate (1-sigma) for the excess path length estimate
+         *
+         * <p>This is to negate {@link #setExcessPathLengthUncertaintyMeters} call.
+         */
+        @NonNull
+        public Builder clearExcessPathLengthUncertaintyMeters() {
+            mExcessPathLengthUncertaintyMeters = 0;
+            mFlags &= ~HAS_EXCESS_PATH_LENGTH_UNC_MASK;
+            return this;
+        }
+
+        /** Sets the reflecting plane information */
+        @NonNull
+        public Builder setReflectingPlane(@Nullable GnssReflectingPlane reflectingPlane) {
+            mReflectingPlane = reflectingPlane;
+            if (reflectingPlane != null) {
+                mFlags |= HAS_REFLECTING_PLANE_MASK;
+            } else {
+                mFlags &= ~HAS_REFLECTING_PLANE_MASK;
+            }
+            return this;
+        }
+
+        /**
+         * Sets the attenuation value in dB.
+         */
+        @NonNull
+        public Builder setAttenuationDb(@FloatRange(from = 0.0f) float attenuationDb) {
+            Preconditions.checkArgumentInRange(attenuationDb, 0, Float.MAX_VALUE,
+                    "attenuationDb");
+            mAttenuationDb = attenuationDb;
+            mFlags |= HAS_ATTENUATION_MASK;
+            return this;
+        }
+
+        /**
+         * Clears the attenuation value in dB.
+         *
+         * <p>This is to negate {@link #setAttenuationDb(float)} call.
+         */
+        @NonNull
+        public Builder clearAttenuationDb() {
+            mAttenuationDb = 0;
+            mFlags &= ~HAS_ATTENUATION_MASK;
+            return this;
+        }
+
+        /** Builds a {@link GnssExcessPathInfo} instance as specified by this builder. */
+        @NonNull
+        public GnssExcessPathInfo build() {
+            return new GnssExcessPathInfo(
+                    mFlags,
+                    mExcessPathLengthMeters,
+                    mExcessPathLengthUncertaintyMeters,
+                    mReflectingPlane,
+                    mAttenuationDb);
+        }
+    }
+}
diff --git a/location/java/android/location/GnssReflectingPlane.java b/location/java/android/location/GnssReflectingPlane.java
index 1acdd1e..115cbec 100644
--- a/location/java/android/location/GnssReflectingPlane.java
+++ b/location/java/android/location/GnssReflectingPlane.java
@@ -22,9 +22,14 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import java.util.Objects;
+
 /**
  * Holds the characteristics of the reflecting plane that a satellite signal has bounced from.
  *
+ * <p>Starting with Android T, this class supports {@link #equals} and {@link #hashCode}, which
+ * are not supported before that.
+ *
  * @hide
  */
 @SystemApi
@@ -107,18 +112,6 @@
                 }
             };
 
-    @NonNull
-    @Override
-    public String toString() {
-        final String format = "   %-29s = %s\n";
-        StringBuilder builder = new StringBuilder("ReflectingPlane:\n");
-        builder.append(String.format(format, "LatitudeDegrees = ", mLatitudeDegrees));
-        builder.append(String.format(format, "LongitudeDegrees = ", mLongitudeDegrees));
-        builder.append(String.format(format, "AltitudeMeters = ", mAltitudeMeters));
-        builder.append(String.format(format, "AzimuthDegrees = ", mAzimuthDegrees));
-        return builder.toString();
-    }
-
     @Override
     public void writeToParcel(@NonNull Parcel parcel, int flags) {
         parcel.writeDouble(mLatitudeDegrees);
@@ -127,6 +120,35 @@
         parcel.writeDouble(mAzimuthDegrees);
     }
 
+    @NonNull
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder("ReflectingPlane[");
+        builder.append(" LatitudeDegrees=").append(mLatitudeDegrees);
+        builder.append(" LongitudeDegrees=").append(mLongitudeDegrees);
+        builder.append(" AltitudeMeters=").append(mAltitudeMeters);
+        builder.append(" AzimuthDegrees=").append(mAzimuthDegrees);
+        builder.append(']');
+        return builder.toString();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj instanceof GnssReflectingPlane) {
+            GnssReflectingPlane that = (GnssReflectingPlane) obj;
+            return Double.compare(this.mLatitudeDegrees, that.mLatitudeDegrees) == 0
+                    && Double.compare(this.mLongitudeDegrees, that.mLongitudeDegrees) == 0
+                    && Double.compare(this.mAltitudeMeters, that.mAltitudeMeters) == 0
+                    && Double.compare(this.mAzimuthDegrees, that.mAzimuthDegrees) == 0;
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mLatitudeDegrees, mLatitudeDegrees, mAltitudeMeters, mAzimuthDegrees);
+    }
+
     /** Builder for {@link GnssReflectingPlane} */
     public static final class Builder {
         /** For documentation, see corresponding fields in {@link GnssReflectingPlane}. */
diff --git a/location/java/android/location/GnssSingleSatCorrection.java b/location/java/android/location/GnssSingleSatCorrection.java
index 262630b..a7fce0a 100644
--- a/location/java/android/location/GnssSingleSatCorrection.java
+++ b/location/java/android/location/GnssSingleSatCorrection.java
@@ -16,6 +16,11 @@
 
 package android.location;
 
+import static android.hardware.gnss.measurement_corrections.SingleSatCorrection.SINGLE_SAT_CORRECTION_HAS_COMBINED_ATTENUATION;
+import static android.hardware.gnss.measurement_corrections.SingleSatCorrection.SINGLE_SAT_CORRECTION_HAS_COMBINED_EXCESS_PATH_LENGTH;
+import static android.hardware.gnss.measurement_corrections.SingleSatCorrection.SINGLE_SAT_CORRECTION_HAS_COMBINED_EXCESS_PATH_LENGTH_UNC;
+import static android.hardware.gnss.measurement_corrections.SingleSatCorrection.SINGLE_SAT_CORRECTION_HAS_SAT_IS_LOS_PROBABILITY;
+
 import android.annotation.FloatRange;
 import android.annotation.IntRange;
 import android.annotation.NonNull;
@@ -26,6 +31,8 @@
 
 import com.android.internal.util.Preconditions;
 
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Objects;
 
 /**
@@ -36,106 +43,47 @@
 @SystemApi
 public final class GnssSingleSatCorrection implements Parcelable {
 
-    /**
-     * Bit mask for {@link #mSingleSatCorrectionFlags} indicating the presence of {@link
-     * #mProbSatIsLos}.
-     *
-     * @hide
-     */
-    public static final int HAS_PROB_SAT_IS_LOS_MASK = 1 << 0;
+    private static final int HAS_PROB_SAT_IS_LOS_MASK =
+            SINGLE_SAT_CORRECTION_HAS_SAT_IS_LOS_PROBABILITY;
+    private static final int HAS_COMBINED_EXCESS_PATH_LENGTH_MASK =
+            SINGLE_SAT_CORRECTION_HAS_COMBINED_EXCESS_PATH_LENGTH;
+    private static final int HAS_COMBINED_EXCESS_PATH_LENGTH_UNC_MASK =
+            SINGLE_SAT_CORRECTION_HAS_COMBINED_EXCESS_PATH_LENGTH_UNC;
+    private static final int HAS_COMBINED_ATTENUATION_MASK =
+            SINGLE_SAT_CORRECTION_HAS_COMBINED_ATTENUATION;
 
-    /**
-     * Bit mask for {@link #mSingleSatCorrectionFlags} indicating the presence of {@link
-     * #mExcessPathLengthMeters}.
-     *
-     * @hide
-     */
-    public static final int HAS_EXCESS_PATH_LENGTH_MASK = 1 << 1;
-
-    /**
-     * Bit mask for {@link #mSingleSatCorrectionFlags} indicating the presence of {@link
-     * #mExcessPathLengthUncertaintyMeters}.
-     *
-     * @hide
-     */
-    public static final int HAS_EXCESS_PATH_LENGTH_UNC_MASK = 1 << 2;
-
-    /**
-     * Bit mask for {@link #mSingleSatCorrectionFlags} indicating the presence of {@link
-     * #mReflectingPlane}.
-     *
-     * @hide
-     */
-    public static final int HAS_REFLECTING_PLANE_MASK = 1 << 3;
-
-    /** A bitmask of fields present in this object (see HAS_* constants defined above) */
+    /* A bitmask of fields present in this object (see HAS_* constants defined above). */
     private final int mSingleSatCorrectionFlags;
 
-    /** Defines the constellation of the given satellite as defined in {@link GnssStatus}. */
-    @GnssStatus.ConstellationType
     private final int mConstellationType;
-
-    /**
-     * Satellite vehicle ID number
-     *
-     * <p>Interpretation depends on {@link GnssStatus#getSvid(int)}.
-     */
-    @IntRange(from = 0)
     private final int mSatId;
-
-    /**
-     * Carrier frequency of the signal to be corrected, for example it can be the GPS center
-     * frequency for L1 = 1,575,420,000 Hz, varying GLO channels, etc.
-     *
-     * <p>For an L1, L5 receiver tracking a satellite on L1 and L5 at the same time, two correction
-     * objects will be reported for this same satellite, in one of the correction objects, all the
-     * values related to L1 will be filled, and in the other all of the values related to L5 will be
-     * filled.
-     */
-    @FloatRange(from = 0.0f,  fromInclusive = false)
     private final float mCarrierFrequencyHz;
-
-    /**
-     * The probability that the satellite is estimated to be in Line-of-Sight condition at the given
-     * location.
-     */
-    @FloatRange(from = 0.0f, to = 1.0f)
     private final float mProbSatIsLos;
+    private final float mCombinedExcessPathLengthMeters;
+    private final float mCombinedExcessPathLengthUncertaintyMeters;
+    private final float mCombinedAttenuationDb;
 
-    /**
-     * Excess path length to be subtracted from pseudorange before using it in calculating location.
-     */
-    @FloatRange(from = 0.0f)
-    private final float mExcessPathLengthMeters;
-
-    /** Error estimate (1-sigma) for the Excess path length estimate */
-    @FloatRange(from = 0.0f)
-    private final float mExcessPathLengthUncertaintyMeters;
-
-    /**
-     * Defines the reflecting plane location and azimuth information
-     *
-     * <p>The flag HAS_REFLECTING_PLANE will be used to set this value to invalid if the satellite
-     * signal goes through multiple reflections or if reflection plane serving is not supported.
-     */
-    @Nullable
-    private final GnssReflectingPlane mReflectingPlane;
+    @NonNull
+    private final List<GnssExcessPathInfo> mGnssExcessPathInfoList;
 
     private GnssSingleSatCorrection(int singleSatCorrectionFlags, int constellationType, int satId,
             float carrierFrequencyHz, float probSatIsLos, float excessPathLengthMeters,
-            float excessPathLengthUncertaintyMeters, GnssReflectingPlane reflectingPlane) {
+            float excessPathLengthUncertaintyMeters,
+            float combinedAttenuationDb,
+            @NonNull List<GnssExcessPathInfo> gnssExcessPathInfoList) {
         mSingleSatCorrectionFlags = singleSatCorrectionFlags;
         mConstellationType = constellationType;
         mSatId = satId;
         mCarrierFrequencyHz = carrierFrequencyHz;
         mProbSatIsLos = probSatIsLos;
-        mExcessPathLengthMeters = excessPathLengthMeters;
-        mExcessPathLengthUncertaintyMeters = excessPathLengthUncertaintyMeters;
-        mReflectingPlane = reflectingPlane;
+        mCombinedExcessPathLengthMeters = excessPathLengthMeters;
+        mCombinedExcessPathLengthUncertaintyMeters = excessPathLengthUncertaintyMeters;
+        mCombinedAttenuationDb = combinedAttenuationDb;
+        mGnssExcessPathInfoList = gnssExcessPathInfoList;
     }
 
     /**
-     * Gets a bitmask of fields present in this object
+     * Gets a bitmask of fields present in this object.
      *
      * @hide
      */
@@ -193,29 +141,46 @@
     }
 
     /**
-     * Returns the Excess path length to be subtracted from pseudorange before using it in
+     * Returns the combined excess path length to be subtracted from pseudorange before using it in
      * calculating location.
      */
     @FloatRange(from = 0.0f)
     public float getExcessPathLengthMeters() {
-        return mExcessPathLengthMeters;
+        return mCombinedExcessPathLengthMeters;
     }
 
-    /** Returns the error estimate (1-sigma) for the Excess path length estimate */
+    /** Returns the error estimate (1-sigma) for the combined excess path length estimate. */
     @FloatRange(from = 0.0f)
     public float getExcessPathLengthUncertaintyMeters() {
-        return mExcessPathLengthUncertaintyMeters;
+        return mCombinedExcessPathLengthUncertaintyMeters;
     }
 
     /**
-     * Returns the reflecting plane characteristics at which the signal has bounced
+     * Returns the combined expected reduction of signal strength for this satellite in
+     * non-negative dB.
+     */
+    @FloatRange(from = 0.0f)
+    public float getCombinedAttenuationDb() {
+        return mCombinedAttenuationDb;
+    }
+
+    /**
+     * Returns the reflecting plane characteristics at which the signal has bounced.
      *
-     * <p>The flag HAS_REFLECTING_PLANE will be used to set this value to invalid if the satellite
-     * signal goes through multiple reflections or if reflection plane serving is not supported
+     * @deprecated Combined excess path does not have a reflecting plane.
      */
     @Nullable
+    @Deprecated
     public GnssReflectingPlane getReflectingPlane() {
-        return mReflectingPlane;
+        return null;
+    }
+
+    /**
+     * Returns the list of {@link GnssExcessPathInfo} associated with this satellite signal.
+     */
+    @NonNull
+    public List<GnssExcessPathInfo> getGnssExcessPathInfoList() {
+        return mGnssExcessPathInfoList;
     }
 
     /** Returns {@code true} if {@link #getProbabilityLineOfSight()} is valid. */
@@ -225,17 +190,27 @@
 
     /** Returns {@code true} if {@link #getExcessPathLengthMeters()} is valid. */
     public boolean hasExcessPathLength() {
-        return (mSingleSatCorrectionFlags & HAS_EXCESS_PATH_LENGTH_MASK) != 0;
+        return (mSingleSatCorrectionFlags & HAS_COMBINED_EXCESS_PATH_LENGTH_MASK) != 0;
     }
 
     /** Returns {@code true} if {@link #getExcessPathLengthUncertaintyMeters()} is valid. */
     public boolean hasExcessPathLengthUncertainty() {
-        return (mSingleSatCorrectionFlags & HAS_EXCESS_PATH_LENGTH_UNC_MASK) != 0;
+        return (mSingleSatCorrectionFlags & HAS_COMBINED_EXCESS_PATH_LENGTH_UNC_MASK) != 0;
     }
 
-    /** Returns {@code true} if {@link #getReflectingPlane()} is valid. */
+    /**
+     * Returns {@code true} if {@link #getReflectingPlane()} is valid.
+     *
+     * @deprecated Combined excess path does not have a reflecting plane.
+     */
+    @Deprecated
     public boolean hasReflectingPlane() {
-        return (mSingleSatCorrectionFlags & HAS_REFLECTING_PLANE_MASK) != 0;
+        return false;
+    }
+
+    /** Returns {@code true} if {@link #getCombinedAttenuationDb()} is valid. */
+    public boolean hasCombinedAttenuation() {
+        return (mSingleSatCorrectionFlags & HAS_COMBINED_ATTENUATION_MASK) != 0;
     }
 
     @Override
@@ -253,14 +228,15 @@
             parcel.writeFloat(mProbSatIsLos);
         }
         if (hasExcessPathLength()) {
-            parcel.writeFloat(mExcessPathLengthMeters);
+            parcel.writeFloat(mCombinedExcessPathLengthMeters);
         }
         if (hasExcessPathLengthUncertainty()) {
-            parcel.writeFloat(mExcessPathLengthUncertaintyMeters);
+            parcel.writeFloat(mCombinedExcessPathLengthUncertaintyMeters);
         }
-        if (hasReflectingPlane()) {
-            mReflectingPlane.writeToParcel(parcel, flags);
+        if (hasCombinedAttenuation()) {
+            parcel.writeFloat(mCombinedAttenuationDb);
         }
+        parcel.writeTypedList(mGnssExcessPathInfoList);
     }
 
     public static final Creator<GnssSingleSatCorrection> CREATOR =
@@ -274,18 +250,21 @@
                     float carrierFrequencyHz = parcel.readFloat();
                     float probSatIsLos = (singleSatCorrectionFlags & HAS_PROB_SAT_IS_LOS_MASK) != 0
                             ? parcel.readFloat() : 0;
-                    float excessPathLengthMeters =
-                            (singleSatCorrectionFlags & HAS_EXCESS_PATH_LENGTH_MASK) != 0
+                    float combinedExcessPathLengthMeters =
+                            (singleSatCorrectionFlags & HAS_COMBINED_EXCESS_PATH_LENGTH_MASK) != 0
                                     ? parcel.readFloat() : 0;
-                    float excessPathLengthUncertaintyMeters =
-                            (singleSatCorrectionFlags & HAS_EXCESS_PATH_LENGTH_UNC_MASK) != 0
+                    float combinedExcessPathLengthUncertaintyMeters =
+                            (singleSatCorrectionFlags & HAS_COMBINED_EXCESS_PATH_LENGTH_UNC_MASK)
+                                    != 0 ? parcel.readFloat() : 0;
+                    float combinedAttenuationDb =
+                            (singleSatCorrectionFlags & HAS_COMBINED_ATTENUATION_MASK) != 0
                                     ? parcel.readFloat() : 0;
-                    GnssReflectingPlane reflectingPlane =
-                            (singleSatCorrectionFlags & HAS_REFLECTING_PLANE_MASK) != 0
-                                    ? GnssReflectingPlane.CREATOR.createFromParcel(parcel) : null;
+                    List<GnssExcessPathInfo> gnssExcessPathInfoList = parcel.createTypedArrayList(
+                            GnssExcessPathInfo.CREATOR);
                     return new GnssSingleSatCorrection(singleSatCorrectionFlags, constellationType,
-                            satId, carrierFrequencyHz, probSatIsLos, excessPathLengthMeters,
-                            excessPathLengthUncertaintyMeters, reflectingPlane);
+                            satId, carrierFrequencyHz, probSatIsLos, combinedExcessPathLengthMeters,
+                            combinedExcessPathLengthUncertaintyMeters, combinedAttenuationDb,
+                            gnssExcessPathInfoList);
                 }
 
                 @Override
@@ -296,56 +275,24 @@
 
     @Override
     public boolean equals(Object obj) {
-        if (this == obj) {
-            return true;
+        if (obj instanceof GnssSingleSatCorrection) {
+            GnssSingleSatCorrection that = (GnssSingleSatCorrection) obj;
+            return this.mSingleSatCorrectionFlags == that.mSingleSatCorrectionFlags
+                    && this.mConstellationType == that.mConstellationType
+                    && this.mSatId == that.mSatId
+                    && Float.compare(mCarrierFrequencyHz, that.mCarrierFrequencyHz) == 0
+                    && (!hasValidSatelliteLineOfSight() || Float.compare(mProbSatIsLos,
+                    that.mProbSatIsLos) == 0)
+                    && (!hasExcessPathLength() || Float.compare(mCombinedExcessPathLengthMeters,
+                    that.mCombinedExcessPathLengthMeters) == 0)
+                    && (!hasExcessPathLengthUncertainty() || Float.compare(
+                    mCombinedExcessPathLengthUncertaintyMeters,
+                    that.mCombinedExcessPathLengthUncertaintyMeters) == 0)
+                    && (!hasCombinedAttenuation() || Float.compare(mCombinedAttenuationDb,
+                    that.mCombinedAttenuationDb) == 0)
+                    && mGnssExcessPathInfoList.equals(that.mGnssExcessPathInfoList);
         }
-        if (!(obj instanceof GnssSingleSatCorrection)) {
-            return false;
-        }
-
-        GnssSingleSatCorrection other = (GnssSingleSatCorrection) obj;
-        if (mConstellationType != other.mConstellationType) {
-            return false;
-        }
-        if (mSatId != other.mSatId) {
-            return false;
-        }
-        if (Float.compare(mCarrierFrequencyHz, other.mCarrierFrequencyHz) != 0) {
-            return false;
-        }
-
-        if (hasValidSatelliteLineOfSight() != other.hasValidSatelliteLineOfSight()) {
-            return false;
-        }
-        if (hasValidSatelliteLineOfSight()
-                && Float.compare(mProbSatIsLos, other.mProbSatIsLos) != 0) {
-            return false;
-        }
-
-        if (hasExcessPathLength() != other.hasExcessPathLength()) {
-            return false;
-        }
-        if (hasExcessPathLength()
-                && Float.compare(mExcessPathLengthMeters, other.mExcessPathLengthMeters) != 0) {
-            return false;
-        }
-
-        if (hasExcessPathLengthUncertainty() != other.hasExcessPathLengthUncertainty()) {
-            return false;
-        }
-        if (hasExcessPathLengthUncertainty() && Float.compare(mExcessPathLengthUncertaintyMeters,
-                other.mExcessPathLengthUncertaintyMeters) != 0) {
-            return false;
-        }
-
-        if (hasReflectingPlane() != other.hasReflectingPlane()) {
-            return false;
-        }
-        if (hasReflectingPlane()
-                && !mReflectingPlane.equals(other.mReflectingPlane)) {
-            return false;
-        }
-        return true;
+        return false;
     }
 
     @Override
@@ -355,9 +302,10 @@
                 mSatId,
                 mCarrierFrequencyHz,
                 mProbSatIsLos,
-                mExcessPathLengthMeters,
-                mExcessPathLengthUncertaintyMeters,
-                mReflectingPlane);
+                mCombinedExcessPathLengthMeters,
+                mCombinedExcessPathLengthUncertaintyMeters,
+                mCombinedAttenuationDb,
+                mGnssExcessPathInfoList);
     }
 
     @NonNull
@@ -371,14 +319,19 @@
             builder.append(" ProbSatIsLos=").append(mProbSatIsLos);
         }
         if (hasExcessPathLength()) {
-            builder.append(" ExcessPathLengthMeters=").append(mExcessPathLengthMeters);
+            builder.append(" CombinedExcessPathLengthMeters=").append(
+                    mCombinedExcessPathLengthMeters);
         }
         if (hasExcessPathLengthUncertainty()) {
-            builder.append(" ExcessPathLengthUncertaintyMeters=").append(
-                    mExcessPathLengthUncertaintyMeters);
+            builder.append(" CombinedExcessPathLengthUncertaintyMeters=").append(
+                    mCombinedExcessPathLengthUncertaintyMeters);
         }
-        if (hasReflectingPlane()) {
-            builder.append(" ReflectingPlane=").append(mReflectingPlane);
+        if (hasCombinedAttenuation()) {
+            builder.append(" CombinedAttenuationDb=").append(
+                    mCombinedAttenuationDb);
+        }
+        if (!mGnssExcessPathInfoList.isEmpty()) {
+            builder.append(' ').append(mGnssExcessPathInfoList.toString());
         }
         builder.append(']');
         return builder.toString();
@@ -386,21 +339,16 @@
 
     /** Builder for {@link GnssSingleSatCorrection} */
     public static final class Builder {
-
-        /**
-         * For documentation of below fields, see corresponding fields in {@link
-         * GnssSingleSatCorrection}.
-         */
         private int mSingleSatCorrectionFlags;
-
         private int mConstellationType;
         private int mSatId;
         private float mCarrierFrequencyHz;
         private float mProbSatIsLos;
-        private float mExcessPathLengthMeters;
-        private float mExcessPathLengthUncertaintyMeters;
-        @Nullable
-        private GnssReflectingPlane mReflectingPlane;
+        private float mCombinedExcessPathLengthMeters;
+        private float mCombinedExcessPathLengthUncertaintyMeters;
+        private float mCombinedAttenuationDb;
+        @NonNull
+        private List<GnssExcessPathInfo> mGnssExcessInfoList = new ArrayList<>();
 
         /** Sets the constellation type. */
         @NonNull public Builder setConstellationType(
@@ -409,18 +357,18 @@
             return this;
         }
 
-        /** Sets the Satellite ID defined in the ICD of the given constellation. */
+        /** Sets the satellite ID defined in the ICD of the given constellation. */
         @NonNull public Builder setSatelliteId(@IntRange(from = 0) int satId) {
             Preconditions.checkArgumentNonnegative(satId, "satId should be non-negative.");
             mSatId = satId;
             return this;
         }
 
-        /** Sets the Carrier frequency in Hz. */
+        /** Sets the carrier frequency in Hz. */
         @NonNull public Builder setCarrierFrequencyHz(
                 @FloatRange(from = 0.0f,  fromInclusive = false) float carrierFrequencyHz) {
-            Preconditions.checkArgument(
-                    carrierFrequencyHz >= 0, "carrierFrequencyHz should be non-negative.");
+            Preconditions.checkArgumentInRange(
+                    carrierFrequencyHz, 0, Float.MAX_VALUE, "carrierFrequencyHz");
             mCarrierFrequencyHz = carrierFrequencyHz;
             return this;
         }
@@ -450,58 +398,90 @@
         }
 
         /**
-         * Sets the Excess path length to be subtracted from pseudorange before using it in
+         * Sets the combined excess path length to be subtracted from pseudorange before using it in
          * calculating location.
          */
-        @NonNull public Builder setExcessPathLengthMeters(
-                @FloatRange(from = 0.0f) float excessPathLengthMeters) {
-            Preconditions.checkArgument(excessPathLengthMeters >= 0,
-                    "excessPathLengthMeters should be non-negative.");
-            mExcessPathLengthMeters = excessPathLengthMeters;
-            mSingleSatCorrectionFlags |= HAS_EXCESS_PATH_LENGTH_MASK;
+        @NonNull
+        public Builder setExcessPathLengthMeters(
+                @FloatRange(from = 0.0f) float combinedExcessPathLengthMeters) {
+            Preconditions.checkArgumentInRange(combinedExcessPathLengthMeters, 0, Float.MAX_VALUE,
+                    "excessPathLengthMeters");
+            mCombinedExcessPathLengthMeters = combinedExcessPathLengthMeters;
+            mSingleSatCorrectionFlags |= HAS_COMBINED_EXCESS_PATH_LENGTH_MASK;
             return this;
         }
 
         /**
-         * Clears the Excess path length.
+         * Clears the combined excess path length.
          *
          * <p>This is to negate {@link #setExcessPathLengthMeters} call.
          */
         @NonNull public Builder clearExcessPathLengthMeters() {
-            mExcessPathLengthMeters = 0;
-            mSingleSatCorrectionFlags &= ~HAS_EXCESS_PATH_LENGTH_MASK;
+            mCombinedExcessPathLengthMeters = 0;
+            mSingleSatCorrectionFlags &= ~HAS_COMBINED_EXCESS_PATH_LENGTH_MASK;
             return this;
         }
 
-        /** Sets the error estimate (1-sigma) for the Excess path length estimate */
+        /** Sets the error estimate (1-sigma) for the combined excess path length estimate. */
         @NonNull public Builder setExcessPathLengthUncertaintyMeters(
-                @FloatRange(from = 0.0f) float excessPathLengthUncertaintyMeters) {
-            Preconditions.checkArgument(excessPathLengthUncertaintyMeters >= 0,
-                    "excessPathLengthUncertaintyMeters should be non-negative.");
-            mExcessPathLengthUncertaintyMeters = excessPathLengthUncertaintyMeters;
-            mSingleSatCorrectionFlags |= HAS_EXCESS_PATH_LENGTH_UNC_MASK;
+                @FloatRange(from = 0.0f) float combinedExcessPathLengthUncertaintyMeters) {
+            Preconditions.checkArgumentInRange(combinedExcessPathLengthUncertaintyMeters, 0,
+                    Float.MAX_VALUE, "excessPathLengthUncertaintyMeters");
+            mCombinedExcessPathLengthUncertaintyMeters = combinedExcessPathLengthUncertaintyMeters;
+            mSingleSatCorrectionFlags |= HAS_COMBINED_EXCESS_PATH_LENGTH_UNC_MASK;
             return this;
         }
 
         /**
-         * Clears the error estimate (1-sigma) for the Excess path length estimate
+         * Clears the error estimate (1-sigma) for the combined excess path length estimate.
          *
          * <p>This is to negate {@link #setExcessPathLengthUncertaintyMeters} call.
          */
         @NonNull public Builder clearExcessPathLengthUncertaintyMeters() {
-            mExcessPathLengthUncertaintyMeters = 0;
-            mSingleSatCorrectionFlags &= ~HAS_EXCESS_PATH_LENGTH_UNC_MASK;
+            mCombinedExcessPathLengthUncertaintyMeters = 0;
+            mSingleSatCorrectionFlags &= ~HAS_COMBINED_EXCESS_PATH_LENGTH_UNC_MASK;
             return this;
         }
 
-        /** Sets the reflecting plane information */
+        /**
+         * Sets the combined attenuation in Db.
+         */
+        @NonNull public Builder setCombinedAttenuationDb(
+                @FloatRange(from = 0.0f) float combinedAttenuationDb) {
+            Preconditions.checkArgumentInRange(combinedAttenuationDb, 0, Float.MAX_VALUE,
+                    "combinedAttenuationDb");
+            mCombinedAttenuationDb = combinedAttenuationDb;
+            mSingleSatCorrectionFlags |= HAS_COMBINED_ATTENUATION_MASK;
+            return this;
+        }
+
+        /**
+         * Clears the combined attenuation.
+         *
+         * <p>This is to negate {@link #setCombinedAttenuationDb} call.
+         */
+        @NonNull public Builder clearCombinedAttenuationDb() {
+            mCombinedAttenuationDb = 0;
+            mSingleSatCorrectionFlags &= ~HAS_COMBINED_ATTENUATION_MASK;
+            return this;
+        }
+
+        /**
+         * Sets the reflecting plane information.
+         *
+         * @deprecated Combined excess path does not have a reflecting plane.
+         */
+        @Deprecated
         @NonNull public Builder setReflectingPlane(@Nullable GnssReflectingPlane reflectingPlane) {
-            mReflectingPlane = reflectingPlane;
-            if (reflectingPlane != null) {
-                mSingleSatCorrectionFlags |= HAS_REFLECTING_PLANE_MASK;
-            } else {
-                mSingleSatCorrectionFlags &= ~HAS_REFLECTING_PLANE_MASK;
-            }
+            return this;
+        }
+
+        /**
+         * Sets the collection of {@link GnssExcessPathInfo}.
+         */
+        @NonNull
+        public Builder setGnssExcessPathInfoList(@NonNull List<GnssExcessPathInfo> infoList) {
+            mGnssExcessInfoList = new ArrayList<>(infoList);
             return this;
         }
 
@@ -512,9 +492,10 @@
                     mSatId,
                     mCarrierFrequencyHz,
                     mProbSatIsLos,
-                    mExcessPathLengthMeters,
-                    mExcessPathLengthUncertaintyMeters,
-                    mReflectingPlane);
+                    mCombinedExcessPathLengthMeters,
+                    mCombinedExcessPathLengthUncertaintyMeters,
+                    mCombinedAttenuationDb,
+                    mGnssExcessInfoList);
         }
     }
 }
diff --git a/services/core/jni/gnss/MeasurementCorrections.cpp b/services/core/jni/gnss/MeasurementCorrections.cpp
index 8a3d84c..07d0a45 100644
--- a/services/core/jni/gnss/MeasurementCorrections.cpp
+++ b/services/core/jni/gnss/MeasurementCorrections.cpp
@@ -44,6 +44,7 @@
 using ReflectingPlane_V1_0 =
         android::hardware::gnss::measurement_corrections::V1_0::ReflectingPlane;
 using ReflectingPlane_Aidl = android::hardware::gnss::measurement_corrections::ReflectingPlane;
+using ExcessPathInfo = SingleSatCorrection_Aidl::ExcessPathInfo;
 using GnssConstellationType_V1_0 = android::hardware::gnss::V1_0::GnssConstellationType;
 using GnssConstellationType_V2_0 = android::hardware::gnss::V2_0::GnssConstellationType;
 using GnssConstellationType_Aidl = android::hardware::gnss::GnssConstellationType;
@@ -62,7 +63,7 @@
 jmethodID method_correctionsGetEnvironmentBearingDegrees;
 jmethodID method_correctionsGetEnvironmentBearingUncertaintyDegrees;
 jmethodID method_listSize;
-jmethodID method_correctionListGet;
+jmethodID method_listGet;
 jmethodID method_correctionSatFlags;
 jmethodID method_correctionSatConstType;
 jmethodID method_correctionSatId;
@@ -71,10 +72,17 @@
 jmethodID method_correctionSatEpl;
 jmethodID method_correctionSatEplUnc;
 jmethodID method_correctionSatRefPlane;
+jmethodID method_correctionSatAttenuation;
+jmethodID method_correctionSatExcessPathInfoList;
 jmethodID method_correctionPlaneLatDeg;
 jmethodID method_correctionPlaneLngDeg;
 jmethodID method_correctionPlaneAltDeg;
 jmethodID method_correctionPlaneAzimDeg;
+jmethodID method_excessPathInfoFlags;
+jmethodID method_excessPathInfoEpl;
+jmethodID method_excessPathInfoEplUnc;
+jmethodID method_excessPathInfoRefPlane;
+jmethodID method_excessPathInfoAttenuation;
 } // anonymous namespace
 
 void MeasurementCorrections_class_init_once(JNIEnv* env, jclass clazz) {
@@ -103,7 +111,7 @@
 
     jclass corrListClass = env->FindClass("java/util/List");
     method_listSize = env->GetMethodID(corrListClass, "size", "()I");
-    method_correctionListGet = env->GetMethodID(corrListClass, "get", "(I)Ljava/lang/Object;");
+    method_listGet = env->GetMethodID(corrListClass, "get", "(I)Ljava/lang/Object;");
 
     jclass singleSatCorrClass = env->FindClass("android/location/GnssSingleSatCorrection");
     method_correctionSatFlags =
@@ -121,12 +129,27 @@
             env->GetMethodID(singleSatCorrClass, "getExcessPathLengthUncertaintyMeters", "()F");
     method_correctionSatRefPlane = env->GetMethodID(singleSatCorrClass, "getReflectingPlane",
                                                     "()Landroid/location/GnssReflectingPlane;");
+    method_correctionSatAttenuation =
+            env->GetMethodID(singleSatCorrClass, "getCombinedAttenuationDb", "()F");
+    method_correctionSatExcessPathInfoList =
+            env->GetMethodID(singleSatCorrClass, "getGnssExcessPathInfoList", "()Ljava/util/List;");
 
     jclass refPlaneClass = env->FindClass("android/location/GnssReflectingPlane");
     method_correctionPlaneLatDeg = env->GetMethodID(refPlaneClass, "getLatitudeDegrees", "()D");
     method_correctionPlaneLngDeg = env->GetMethodID(refPlaneClass, "getLongitudeDegrees", "()D");
     method_correctionPlaneAltDeg = env->GetMethodID(refPlaneClass, "getAltitudeMeters", "()D");
     method_correctionPlaneAzimDeg = env->GetMethodID(refPlaneClass, "getAzimuthDegrees", "()D");
+
+    jclass excessPathInfoClass = env->FindClass("android/location/GnssExcessPathInfo");
+    method_excessPathInfoFlags = env->GetMethodID(excessPathInfoClass, "getFlags", "()I");
+    method_excessPathInfoEpl =
+            env->GetMethodID(excessPathInfoClass, "getExcessPathLengthMeters", "()F");
+    method_excessPathInfoEplUnc =
+            env->GetMethodID(excessPathInfoClass, "getExcessPathLengthUncertaintyMeters", "()F");
+    method_excessPathInfoRefPlane = env->GetMethodID(excessPathInfoClass, "getReflectingPlane",
+                                                     "()Landroid/location/GnssReflectingPlane;");
+    method_excessPathInfoAttenuation =
+            env->GetMethodID(excessPathInfoClass, "getAttenuationDb", "()F");
 }
 
 template <>
@@ -324,7 +347,8 @@
 SingleSatCorrection_V1_0
 MeasurementCorrectionsUtil::getSingleSatCorrection_1_0_withoutConstellation(
         JNIEnv* env, jobject singleSatCorrectionObj) {
-    jint correctionFlags = env->CallIntMethod(singleSatCorrectionObj, method_correctionSatFlags);
+    uint16_t corrFlags = static_cast<uint16_t>(
+            env->CallIntMethod(singleSatCorrectionObj, method_correctionSatFlags));
     jint satId = env->CallIntMethod(singleSatCorrectionObj, method_correctionSatId);
     jfloat carrierFreqHz =
             env->CallFloatMethod(singleSatCorrectionObj, method_correctionSatCarrierFreq);
@@ -332,14 +356,16 @@
             env->CallFloatMethod(singleSatCorrectionObj, method_correctionSatIsLosProb);
     jfloat eplMeters = env->CallFloatMethod(singleSatCorrectionObj, method_correctionSatEpl);
     jfloat eplUncMeters = env->CallFloatMethod(singleSatCorrectionObj, method_correctionSatEplUnc);
-    uint16_t corrFlags = static_cast<uint16_t>(correctionFlags);
 
     ReflectingPlane_V1_0 reflectingPlane;
-    if ((corrFlags & GnssSingleSatCorrectionFlags_V1_0::HAS_REFLECTING_PLANE) != 0)
-        MeasurementCorrectionsUtil::getReflectingPlane<ReflectingPlane_V1_0>(env,
-                                                                             singleSatCorrectionObj,
+    if ((corrFlags & GnssSingleSatCorrectionFlags_V1_0::HAS_REFLECTING_PLANE) != 0) {
+        jobject reflectingPlaneObj =
+                env->CallObjectMethod(singleSatCorrectionObj, method_correctionSatRefPlane);
+        MeasurementCorrectionsUtil::setReflectingPlane<ReflectingPlane_V1_0>(env,
+                                                                             reflectingPlaneObj,
                                                                              reflectingPlane);
-
+        env->DeleteLocalRef(reflectingPlaneObj);
+    }
     SingleSatCorrection_V1_0 singleSatCorrection = {
             .singleSatCorrectionFlags = corrFlags,
             .svid = static_cast<uint16_t>(satId),
@@ -349,13 +375,14 @@
             .excessPathLengthUncertaintyMeters = eplUncMeters,
             .reflectingPlane = reflectingPlane,
     };
-
     return singleSatCorrection;
 }
 
 SingleSatCorrection_Aidl MeasurementCorrectionsUtil::getSingleSatCorrection_Aidl(
         JNIEnv* env, jobject singleSatCorrectionObj) {
-    jint correctionFlags = env->CallIntMethod(singleSatCorrectionObj, method_correctionSatFlags);
+    int32_t corrFlags = static_cast<int32_t>(
+            env->CallIntMethod(singleSatCorrectionObj, method_correctionSatFlags));
+    jint constType = env->CallIntMethod(singleSatCorrectionObj, method_correctionSatConstType);
     jint satId = env->CallIntMethod(singleSatCorrectionObj, method_correctionSatId);
     jfloat carrierFreqHz =
             env->CallFloatMethod(singleSatCorrectionObj, method_correctionSatCarrierFreq);
@@ -363,15 +390,10 @@
             env->CallFloatMethod(singleSatCorrectionObj, method_correctionSatIsLosProb);
     jfloat eplMeters = env->CallFloatMethod(singleSatCorrectionObj, method_correctionSatEpl);
     jfloat eplUncMeters = env->CallFloatMethod(singleSatCorrectionObj, method_correctionSatEplUnc);
-    int32_t corrFlags = static_cast<int32_t>(correctionFlags);
-
-    ReflectingPlane_Aidl reflectingPlane;
-    if ((corrFlags & SingleSatCorrection_Aidl::SINGLE_SAT_CORRECTION_HAS_REFLECTING_PLANE) != 0)
-        MeasurementCorrectionsUtil::getReflectingPlane<ReflectingPlane_Aidl>(env,
-                                                                             singleSatCorrectionObj,
-                                                                             reflectingPlane);
-
-    jint constType = env->CallIntMethod(singleSatCorrectionObj, method_correctionSatConstType);
+    jfloat attenuationDb =
+            env->CallFloatMethod(singleSatCorrectionObj, method_correctionSatAttenuation);
+    std::vector<ExcessPathInfo> excessPathInfos =
+            MeasurementCorrectionsUtil::getExcessPathInfoList(env, singleSatCorrectionObj);
 
     SingleSatCorrection_Aidl singleSatCorrection;
     singleSatCorrection.singleSatCorrectionFlags = corrFlags;
@@ -379,9 +401,10 @@
     singleSatCorrection.svid = static_cast<int32_t>(satId);
     singleSatCorrection.carrierFrequencyHz = carrierFreqHz;
     singleSatCorrection.probSatIsLos = probSatIsLos;
-    singleSatCorrection.excessPathLengthMeters = eplMeters;
-    singleSatCorrection.excessPathLengthUncertaintyMeters = eplUncMeters;
-    singleSatCorrection.reflectingPlane = reflectingPlane;
+    singleSatCorrection.combinedExcessPathLengthMeters = eplMeters;
+    singleSatCorrection.combinedExcessPathLengthUncertaintyMeters = eplUncMeters;
+    singleSatCorrection.combinedAttenuationDb = attenuationDb;
+    singleSatCorrection.excessPathInfos = excessPathInfos;
 
     return singleSatCorrection;
 }
@@ -391,8 +414,7 @@
         hardware::hidl_vec<SingleSatCorrection_V1_0>& list) {
     for (uint16_t i = 0; i < list.size(); ++i) {
         jobject singleSatCorrectionObj =
-                env->CallObjectMethod(singleSatCorrectionList, method_correctionListGet, i);
-
+                env->CallObjectMethod(singleSatCorrectionList, method_listGet, i);
         SingleSatCorrection_V1_0 singleSatCorrection =
                 getSingleSatCorrection_1_0_withoutConstellation(env, singleSatCorrectionObj);
 
@@ -410,7 +432,7 @@
         hardware::hidl_vec<SingleSatCorrection_V1_1>& list) {
     for (uint16_t i = 0; i < list.size(); ++i) {
         jobject singleSatCorrectionObj =
-                env->CallObjectMethod(singleSatCorrectionList, method_correctionListGet, i);
+                env->CallObjectMethod(singleSatCorrectionList, method_listGet, i);
 
         SingleSatCorrection_V1_0 singleSatCorrection_1_0 =
                 getSingleSatCorrection_1_0_withoutConstellation(env, singleSatCorrectionObj);
@@ -431,7 +453,7 @@
         JNIEnv* env, jobject singleSatCorrectionList, std::vector<SingleSatCorrection_Aidl>& list) {
     for (uint16_t i = 0; i < list.size(); ++i) {
         jobject singleSatCorrectionObj =
-                env->CallObjectMethod(singleSatCorrectionList, method_correctionListGet, i);
+                env->CallObjectMethod(singleSatCorrectionList, method_listGet, i);
 
         SingleSatCorrection_Aidl singleSatCorrection_Aidl =
                 getSingleSatCorrection_Aidl(env, singleSatCorrectionObj);
@@ -441,4 +463,63 @@
     }
 }
 
+template <>
+void MeasurementCorrectionsUtil::setReflectingPlaneAzimuthDegrees<ReflectingPlane_V1_0>(
+        ReflectingPlane_V1_0& reflectingPlane, double azimuthDegreeRefPlane) {
+    reflectingPlane.azimuthDegrees = azimuthDegreeRefPlane;
+}
+
+template <>
+void MeasurementCorrectionsUtil::setReflectingPlaneAzimuthDegrees<ReflectingPlane_Aidl>(
+        ReflectingPlane_Aidl& reflectingPlane, double azimuthDegreeRefPlane) {
+    reflectingPlane.reflectingPlaneAzimuthDegrees = azimuthDegreeRefPlane;
+}
+
+std::vector<ExcessPathInfo> MeasurementCorrectionsUtil::getExcessPathInfoList(
+        JNIEnv* env, jobject singleSatCorrectionObj) {
+    jobject excessPathInfoListObj =
+            env->CallObjectMethod(singleSatCorrectionObj, method_correctionSatExcessPathInfoList);
+
+    int len = env->CallIntMethod(excessPathInfoListObj, method_listSize);
+    std::vector<ExcessPathInfo> list(len);
+    for (int i = 0; i < len; ++i) {
+        jobject excessPathInfoObj = env->CallObjectMethod(excessPathInfoListObj, method_listGet, i);
+        list[i] = getExcessPathInfo(env, excessPathInfoObj);
+        env->DeleteLocalRef(excessPathInfoObj);
+    }
+    env->DeleteLocalRef(excessPathInfoListObj);
+    return list;
+}
+
+ExcessPathInfo MeasurementCorrectionsUtil::getExcessPathInfo(JNIEnv* env,
+                                                             jobject excessPathInfoObj) {
+    ExcessPathInfo excessPathInfo;
+    jint flags = env->CallIntMethod(excessPathInfoObj, method_excessPathInfoFlags);
+    excessPathInfo.excessPathInfoFlags = flags;
+    if ((flags & ExcessPathInfo::EXCESS_PATH_INFO_HAS_EXCESS_PATH_LENGTH) != 0) {
+        jfloat epl = env->CallFloatMethod(excessPathInfoObj, method_excessPathInfoEpl);
+        excessPathInfo.excessPathLengthMeters = epl;
+    }
+    if ((flags & ExcessPathInfo::EXCESS_PATH_INFO_HAS_EXCESS_PATH_LENGTH_UNC) != 0) {
+        jfloat eplUnc = env->CallFloatMethod(excessPathInfoObj, method_excessPathInfoEplUnc);
+        excessPathInfo.excessPathLengthUncertaintyMeters = eplUnc;
+    }
+    if ((flags & ExcessPathInfo::EXCESS_PATH_INFO_HAS_REFLECTING_PLANE) != 0) {
+        ReflectingPlane_Aidl reflectingPlane;
+        jobject reflectingPlaneObj =
+                env->CallObjectMethod(excessPathInfoObj, method_excessPathInfoRefPlane);
+        MeasurementCorrectionsUtil::setReflectingPlane<ReflectingPlane_Aidl>(env,
+                                                                             reflectingPlaneObj,
+                                                                             reflectingPlane);
+        env->DeleteLocalRef(reflectingPlaneObj);
+        excessPathInfo.reflectingPlane = reflectingPlane;
+    }
+    if ((flags & ExcessPathInfo::EXCESS_PATH_INFO_HAS_ATTENUATION) != 0) {
+        jfloat attenuation =
+                env->CallFloatMethod(excessPathInfoObj, method_excessPathInfoAttenuation);
+        excessPathInfo.attenuationDb = attenuation;
+    }
+    return excessPathInfo;
+}
+
 } // namespace android::gnss
diff --git a/services/core/jni/gnss/MeasurementCorrections.h b/services/core/jni/gnss/MeasurementCorrections.h
index a2e6027..598ad48 100644
--- a/services/core/jni/gnss/MeasurementCorrections.h
+++ b/services/core/jni/gnss/MeasurementCorrections.h
@@ -43,7 +43,7 @@
 extern jmethodID method_correctionsGetEnvironmentBearingDegrees;
 extern jmethodID method_correctionsGetEnvironmentBearingUncertaintyDegrees;
 extern jmethodID method_listSize;
-extern jmethodID method_correctionListGet;
+extern jmethodID method_listGet;
 extern jmethodID method_correctionSatFlags;
 extern jmethodID method_correctionSatConstType;
 extern jmethodID method_correctionSatId;
@@ -52,6 +52,7 @@
 extern jmethodID method_correctionSatEpl;
 extern jmethodID method_correctionSatEplUnc;
 extern jmethodID method_correctionSatRefPlane;
+extern jmethodID method_correctionSatExcessPathInfos;
 extern jmethodID method_correctionPlaneLatDeg;
 extern jmethodID method_correctionPlaneLngDeg;
 extern jmethodID method_correctionPlaneAltDeg;
@@ -130,14 +131,20 @@
     static bool translateMeasurementCorrections(JNIEnv* env, jobject correctionsObj,
                                                 T& corrections);
     template <class T>
-    static void getReflectingPlane(JNIEnv* env, jobject singleSatCorrectionObj, T& reflectingPlane);
+    static void setReflectingPlane(JNIEnv* env, jobject reflectingPlaneObj, T& reflectingPlane);
+    template <class T>
+    static void setReflectingPlaneAzimuthDegrees(T& reflectingPlane, double azimuthDegreeRefPlane);
+
+    static std::vector<
+            android::hardware::gnss::measurement_corrections::SingleSatCorrection::ExcessPathInfo>
+    getExcessPathInfoList(JNIEnv* env, jobject correctionsObj);
+    static android::hardware::gnss::measurement_corrections::SingleSatCorrection::ExcessPathInfo
+    getExcessPathInfo(JNIEnv* env, jobject correctionsObj);
 };
 
 template <class T>
-void MeasurementCorrectionsUtil::getReflectingPlane(JNIEnv* env, jobject singleSatCorrectionObj,
+void MeasurementCorrectionsUtil::setReflectingPlane(JNIEnv* env, jobject reflectingPlaneObj,
                                                     T& reflectingPlane) {
-    jobject reflectingPlaneObj =
-            env->CallObjectMethod(singleSatCorrectionObj, method_correctionSatRefPlane);
     jdouble latitudeDegreesRefPlane =
             env->CallDoubleMethod(reflectingPlaneObj, method_correctionPlaneLatDeg);
     jdouble longitudeDegreesRefPlane =
@@ -149,8 +156,7 @@
     reflectingPlane.latitudeDegrees = latitudeDegreesRefPlane;
     reflectingPlane.longitudeDegrees = longitudeDegreesRefPlane;
     reflectingPlane.altitudeMeters = altitudeDegreesRefPlane;
-    reflectingPlane.azimuthDegrees = azimuthDegreeRefPlane;
-    env->DeleteLocalRef(reflectingPlaneObj);
+    setReflectingPlaneAzimuthDegrees<T>(reflectingPlane, azimuthDegreeRefPlane);
 }
 
 } // namespace android::gnss