diff options
author | Sasha Kuznetsov <sashakuznetsov@google.com> | 2020-02-11 22:29:33 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2020-02-11 22:29:33 +0000 |
commit | db44f628cdf0cdc2ffe4026b976c70d2a0cd0b35 (patch) | |
tree | 2ab5718a739590e266afdb98b51c451ba4f810c2 /location | |
parent | 68ac69b0a50ff1b9015c533695a2cb50fffb3f07 (diff) | |
parent | a68a7a3d2316baf4acb8761d27c9ec67f8ec53af (diff) |
Merge "Revert^2 "Add GnssAntennaInfo framework APIs" + added fixes"
Diffstat (limited to 'location')
6 files changed, 800 insertions, 2 deletions
diff --git a/location/java/android/location/GnssAntennaInfo.aidl b/location/java/android/location/GnssAntennaInfo.aidl new file mode 100644 index 000000000000..2b956afda01f --- /dev/null +++ b/location/java/android/location/GnssAntennaInfo.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2020, 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; + +parcelable GnssAntennaInfo;
\ No newline at end of file diff --git a/location/java/android/location/GnssAntennaInfo.java b/location/java/android/location/GnssAntennaInfo.java new file mode 100644 index 000000000000..dfcaf814f9c9 --- /dev/null +++ b/location/java/android/location/GnssAntennaInfo.java @@ -0,0 +1,654 @@ +/* + * Copyright (C) 2020 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 android.annotation.IntDef; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.os.Parcel; +import android.os.Parcelable; + +import com.android.internal.annotations.VisibleForTesting; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.List; + +/** + * A class that contains information about a GNSS antenna. GNSS antenna characteristics can change + * with device configuration, such as when a device is folded open or closed. Antenna information is + * delivered to registered instances of {@link Callback}. + */ +public final class GnssAntennaInfo implements Parcelable { + private final double mCarrierFrequencyMHz; + private final PhaseCenterOffsetCoordinates mPhaseCenterOffsetCoordinates; + private final PhaseCenterVariationCorrections mPhaseCenterVariationCorrections; + private final SignalGainCorrections mSignalGainCorrections; + + /** + * Used for receiving GNSS antenna info from the GNSS engine. You can implement this interface + * and call {@link LocationManager#registerAntennaInfoCallback}; + */ + public abstract static class Callback { + /** + * The status of GNSS antenna info. + * + * @hide + */ + @Retention(RetentionPolicy.SOURCE) + @IntDef({STATUS_NOT_SUPPORTED, STATUS_READY, STATUS_LOCATION_DISABLED}) + public @interface GnssAntennaInfoStatus { + } + + /** + * The system does not support GNSS antenna info. + * + * This status will not change in the future. + */ + public static final int STATUS_NOT_SUPPORTED = 0; + + /** + * GNSS antenna info updates are being successfully tracked. + */ + public static final int STATUS_READY = 1; + + /** + * GNSS provider or Location is disabled, updated will not be received until they are + * enabled. + */ + public static final int STATUS_LOCATION_DISABLED = 2; + + /** + * Returns the latest GNSS antenna info. This event is triggered when a callback is + * registered, and whenever the antenna info changes (due to a device configuration change). + */ + public void onGnssAntennaInfoReceived(@NonNull List<GnssAntennaInfo> gnssAntennaInfos) {} + + /** + * Returns the latest status of the GNSS antenna info sub-system. + */ + public void onStatusChanged(@GnssAntennaInfoStatus int status) {} + } + + /** + * Class containing information about the antenna phase center offset (PCO). PCO is defined with + * respect to the origin of the Android sensor coordinate system, e.g., center of primary screen + * for mobiles - see sensor or form factor documents for details. Uncertainties are reported + * to 1-sigma. + */ + public static final class PhaseCenterOffsetCoordinates implements Parcelable { + private final double mPhaseCenterOffsetCoordinateXMillimeters; + private final double mPhaseCenterOffsetCoordinateXUncertaintyMillimeters; + private final double mPhaseCenterOffsetCoordinateYMillimeters; + private final double mPhaseCenterOffsetCoordinateYUncertaintyMillimeters; + private final double mPhaseCenterOffsetCoordinateZMillimeters; + private final double mPhaseCenterOffsetCoordinateZUncertaintyMillimeters; + + @VisibleForTesting + public PhaseCenterOffsetCoordinates(double phaseCenterOffsetCoordinateXMillimeters, + double phaseCenterOffsetCoordinateXUncertaintyMillimeters, + double phaseCenterOffsetCoordinateYMillimeters, + double phaseCenterOffsetCoordinateYUncertaintyMillimeters, + double phaseCenterOffsetCoordinateZMillimeters, + double phaseCenterOffsetCoordinateZUncertaintyMillimeters) { + mPhaseCenterOffsetCoordinateXMillimeters = phaseCenterOffsetCoordinateXMillimeters; + mPhaseCenterOffsetCoordinateYMillimeters = phaseCenterOffsetCoordinateYMillimeters; + mPhaseCenterOffsetCoordinateZMillimeters = phaseCenterOffsetCoordinateZMillimeters; + mPhaseCenterOffsetCoordinateXUncertaintyMillimeters = + phaseCenterOffsetCoordinateXUncertaintyMillimeters; + mPhaseCenterOffsetCoordinateYUncertaintyMillimeters = + phaseCenterOffsetCoordinateYUncertaintyMillimeters; + mPhaseCenterOffsetCoordinateZUncertaintyMillimeters = + phaseCenterOffsetCoordinateZUncertaintyMillimeters; + } + + public static final @NonNull Creator<PhaseCenterOffsetCoordinates> CREATOR = + new Creator<PhaseCenterOffsetCoordinates>() { + @Override + public PhaseCenterOffsetCoordinates createFromParcel(Parcel in) { + return new PhaseCenterOffsetCoordinates( + in.readDouble(), + in.readDouble(), + in.readDouble(), + in.readDouble(), + in.readDouble(), + in.readDouble() + ); + } + + @Override + public PhaseCenterOffsetCoordinates[] newArray(int size) { + return new PhaseCenterOffsetCoordinates[size]; + } + }; + + public double getXCoordMillimeters() { + return mPhaseCenterOffsetCoordinateXMillimeters; + } + + public double getXCoordUncertaintyMillimeters() { + return mPhaseCenterOffsetCoordinateXUncertaintyMillimeters; + } + + public double getYCoordMillimeters() { + return mPhaseCenterOffsetCoordinateYMillimeters; + } + + public double getYCoordUncertaintyMillimeters() { + return mPhaseCenterOffsetCoordinateYUncertaintyMillimeters; + } + + public double getZCoordMillimeters() { + return mPhaseCenterOffsetCoordinateZMillimeters; + } + + public double getZCoordUncertaintyMillimeters() { + return mPhaseCenterOffsetCoordinateZUncertaintyMillimeters; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + dest.writeDouble(mPhaseCenterOffsetCoordinateXMillimeters); + dest.writeDouble(mPhaseCenterOffsetCoordinateXUncertaintyMillimeters); + dest.writeDouble(mPhaseCenterOffsetCoordinateYMillimeters); + dest.writeDouble(mPhaseCenterOffsetCoordinateYUncertaintyMillimeters); + dest.writeDouble(mPhaseCenterOffsetCoordinateZMillimeters); + dest.writeDouble(mPhaseCenterOffsetCoordinateZUncertaintyMillimeters); + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder("PhaseCenteroffset:\n"); + builder.append("X: " + mPhaseCenterOffsetCoordinateXMillimeters + " +/- " + + mPhaseCenterOffsetCoordinateXUncertaintyMillimeters + "\n"); + builder.append("Y: " + mPhaseCenterOffsetCoordinateYMillimeters + " +/- " + + mPhaseCenterOffsetCoordinateYUncertaintyMillimeters + "\n"); + builder.append("Z: " + mPhaseCenterOffsetCoordinateZMillimeters + " +/- " + + mPhaseCenterOffsetCoordinateZUncertaintyMillimeters + "\n"); + return builder.toString(); + } + } + + /** + * Class containing information about the phase center variation (PCV) corrections. The PCV + * correction is added to the phase measurement to obtain the corrected value. + * + * The corrections and associated (1-sigma) uncertainties are represented by respect 2D arrays. + * + * Each row (major indices) represents a fixed theta. The first row corresponds to a + * theta angle of 0 degrees. The last row corresponds to a theta angle of (360 - deltaTheta) + * degrees, where deltaTheta is the regular spacing between azimuthal angles, i.e., deltaTheta + * = 360 / (number of rows). + * + * The columns (minor indices) represent fixed zenith angles, beginning at 0 degrees and ending + * at 180 degrees. They are separated by deltaPhi, the regular spacing between zenith angles, + * i.e., deltaPhi = 180 / (number of columns - 1). + */ + public static final class PhaseCenterVariationCorrections extends SphericalCorrections { + + @VisibleForTesting + public PhaseCenterVariationCorrections( + @NonNull double[][] phaseCenterVariationCorrectionsMillimeters, + @NonNull double[][] phaseCenterVariationCorrectionUncertaintiesMillimeters) { + super(phaseCenterVariationCorrectionsMillimeters, + phaseCenterVariationCorrectionUncertaintiesMillimeters); + } + + private PhaseCenterVariationCorrections(@NonNull Parcel in) { + super(in); + } + + /** + * Get the phase center variation correction in millimeters at the specified row and column + * in the underlying 2D array. + * @param row zero-based major index in the array + * @param column zero-based minor index in the array + * @return phase center correction in millimeters + */ + public double getPhaseCenterVariationCorrectionMillimetersAt(int row, int column) { + return super.getCorrectionAt(row, column); + } + + /** + * Get the phase center variation correction uncertainty in millimeters at the specified row + * and column in the underlying 2D array. + * @param row zero-based major index in the array + * @param column zero-based minor index in the array + * @return 1-sigma phase center correction uncertainty in millimeters + */ + public double getPhaseCenterVariationCorrectionUncertaintyMillimetersAt( + int row, int column) { + return super.getCorrectionUncertaintyAt(row, column); + } + + public @NonNull double[][] getRawCorrectionsArray() { + return super.getRawCorrectionsArray().clone(); + } + + public @NonNull double[][] getRawCorrectionUncertaintiesArray() { + return super.getRawCorrectionUncertaintiesArray().clone(); + } + + public int getNumRows() { + return super.getNumRows(); + } + + public int getNumColumns() { + return super.getNumColumns(); + } + + /** + * The fixed theta angle separation between successive rows. + */ + public double getDeltaTheta() { + return super.getDeltaTheta(); + } + + /** + * The fixed phi angle separation between successive columns. + */ + public double getDeltaPhi() { + return super.getDeltaPhi(); + } + + public static final @NonNull Creator<PhaseCenterVariationCorrections> CREATOR = + new Creator<PhaseCenterVariationCorrections>() { + @Override + public PhaseCenterVariationCorrections createFromParcel(Parcel in) { + return new PhaseCenterVariationCorrections(in); + } + + @Override + public PhaseCenterVariationCorrections[] newArray(int size) { + return new PhaseCenterVariationCorrections[size]; + } + }; + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + super.writeToParcel(dest, flags); + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder("PhaseCenterVariationCorrections:\n"); + builder.append(super.toString()); + return builder.toString(); + } + } + + /** + * Class containing information about the signal gain (SG) corrections. The SG + * correction is added to the signal gain to obtain the corrected value. + * + * The corrections and associated (1-sigma) uncertainties are represented by respect 2D arrays. + * + * Each row (major indices) represents a fixed theta. The first row corresponds to a + * theta angle of 0 degrees. The last row corresponds to a theta angle of (360 - deltaTheta) + * degrees, where deltaTheta is the regular spacing between azimuthal angles, i.e., deltaTheta + * = 360 / (number of rows). + * + * The columns (minor indices) represent fixed zenith angles, beginning at 0 degrees and ending + * at 180 degrees. They are separated by deltaPhi, the regular spacing between zenith angles, + * i.e., deltaPhi = 180 / (number of columns - 1). + */ + public static final class SignalGainCorrections extends SphericalCorrections { + + @VisibleForTesting + public SignalGainCorrections( + @NonNull double[][] signalGainCorrectionsDbi, + @NonNull double[][] signalGainCorrectionUncertaintiesDbi) { + super(signalGainCorrectionsDbi, + signalGainCorrectionUncertaintiesDbi); + } + + private SignalGainCorrections(@NonNull Parcel in) { + super(in); + } + + /** + * Get the signal gain correction in dbi at the specified row and column + * in the underlying 2D array. + * @param row zero-based major index in the array + * @param column zero-based minor index in the array + * @return signal gain correction in dbi + */ + public double getSignalGainCorrectionDbiAt(int row, int column) { + return super.getCorrectionAt(row, column); + } + + /** + * Get the signal gain correction correction uncertainty in dbi at the specified row + * and column in the underlying 2D array. + * @param row zero-based major index in the array + * @param column zero-based minor index in the array + * @return 1-sigma signal gain correction uncertainty in dbi + */ + public double getSignalGainCorrectionUncertaintyDbiAt(int row, int column) { + return super.getCorrectionUncertaintyAt(row, column); + } + + public @NonNull double[][] getRawCorrectionsArray() { + return super.getRawCorrectionsArray().clone(); + } + + public @NonNull double[][] getRawCorrectionUncertaintiesArray() { + return super.getRawCorrectionUncertaintiesArray().clone(); + } + + public int getNumRows() { + return super.getNumRows(); + } + + public int getNumColumns() { + return super.getNumColumns(); + } + + /** + * The fixed theta angle separation between successive rows. + */ + public double getDeltaTheta() { + return super.getDeltaTheta(); + } + + /** + * The fixed phi angle separation between successive columns. + */ + public double getDeltaPhi() { + return super.getDeltaPhi(); + } + + public static final @NonNull Creator<SignalGainCorrections> CREATOR = + new Creator<SignalGainCorrections>() { + @Override + public SignalGainCorrections createFromParcel(Parcel in) { + return new SignalGainCorrections(in); + } + + @Override + public SignalGainCorrections[] newArray(int size) { + return new SignalGainCorrections[size]; + } + }; + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + super.writeToParcel(dest, flags); + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder("SignalGainCorrections:\n"); + builder.append(super.toString()); + return builder.toString(); + } + } + + /** + * Represents corrections on a spherical mapping. + * + * Each row (major indices) represents a fixed theta. The first row corresponds to a + * theta angle of 0 degrees. The last row corresponds to a theta angle of (360 - deltaTheta) + * degrees, where deltaTheta is the regular spacing between azimuthal angles, i.e., deltaTheta + * = 360 / (number of rows). + * + * The columns (minor indices) represent fixed zenith angles, beginning at 0 degrees and ending + * at 180 degrees. They are separated by deltaPhi, the regular spacing between zenith angles, + * i.e., deltaPhi = 180 / (number of columns - 1). + */ + private abstract static class SphericalCorrections implements Parcelable { + private final double[][] mCorrections; + private final double[][] mCorrectionUncertainties; + private final double mDeltaTheta; + private final double mDeltaPhi; + private final int mNumRows; + private final int mNumColumns; + + SphericalCorrections(@NonNull double[][] corrections, + @NonNull double[][] correctionUncertainties) { + if (corrections.length != correctionUncertainties.length + || corrections[0].length != correctionUncertainties[0].length) { + throw new IllegalArgumentException("Correction and correction uncertainty arrays " + + "must have the same dimensions."); + } + + mNumRows = corrections.length; + if (mNumRows < 1) { + throw new IllegalArgumentException("Arrays must have at least one row."); + } + + mNumColumns = corrections[0].length; + if (mNumColumns < 2) { + throw new IllegalArgumentException("Arrays must have at least two columns."); + } + + mCorrections = corrections; + mCorrectionUncertainties = correctionUncertainties; + mDeltaTheta = 360.0d / mNumRows; + mDeltaPhi = 180.0d / (mNumColumns - 1); + } + + SphericalCorrections(Parcel in) { + int numRows = in.readInt(); + int numColumns = in.readInt(); + + double[][] corrections = + new double[numRows][numColumns]; + double[][] correctionUncertainties = + new double[numRows][numColumns]; + + for (int row = 0; row < numRows; row++) { + in.readDoubleArray(corrections[row]); + } + + for (int row = 0; row < numRows; row++) { + in.readDoubleArray(correctionUncertainties[row]); + } + + mNumRows = corrections.length; + mNumColumns = corrections[0].length; + mCorrections = corrections; + mCorrectionUncertainties = correctionUncertainties; + mDeltaTheta = 360.0d / mNumRows; + mDeltaPhi = 180.0d / (mNumColumns - 1); + } + + private double getCorrectionAt(int row, int column) { + return mCorrections[row][column]; + } + + private double getCorrectionUncertaintyAt(int row, int column) { + return mCorrectionUncertainties[row][column]; + } + + @NonNull + private double[][] getRawCorrectionsArray() { + return mCorrections; + } + + @NonNull + private double[][] getRawCorrectionUncertaintiesArray() { + return mCorrectionUncertainties; + } + + private int getNumRows() { + return mNumRows; + } + + private int getNumColumns() { + return mNumColumns; + } + + /** + * The fixed theta angle separation between successive rows. + */ + private double getDeltaTheta() { + return mDeltaTheta; + } + + /** + * The fixed phi angle separation between successive columns. + */ + private double getDeltaPhi() { + return mDeltaPhi; + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + dest.writeInt(mNumRows); + dest.writeInt(mNumColumns); + for (double[] row: mCorrections) { + dest.writeDoubleArray(row); + } + for (double[] row: mCorrectionUncertainties) { + dest.writeDoubleArray(row); + } + } + + private String arrayToString(double[][] array) { + StringBuilder builder = new StringBuilder(); + for (int row = 0; row < mNumRows; row++) { + builder.append("[ "); + for (int column = 0; column < mNumColumns - 1; column++) { + builder.append(array[row][column] + ", "); + } + builder.append(array[row][mNumColumns - 1] + " ]\n"); + } + return builder.toString(); + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("DeltaTheta: " + mDeltaTheta + "\n"); + builder.append("DeltaPhi: " + mDeltaPhi + "\n"); + builder.append("CorrectionsArray:\n"); + builder.append(arrayToString(mCorrections)); + builder.append("CorrectionUncertaintiesArray:\n"); + builder.append(arrayToString(mCorrectionUncertainties)); + return builder.toString(); + } + } + + @VisibleForTesting + public GnssAntennaInfo( + double carrierFrequencyMHz, + @NonNull PhaseCenterOffsetCoordinates phaseCenterOffsetCoordinates, + @Nullable PhaseCenterVariationCorrections phaseCenterVariationCorrections, + @Nullable SignalGainCorrections signalGainCorrectionDbi) { + if (phaseCenterOffsetCoordinates == null) { + throw new IllegalArgumentException("Phase Center Offset Coordinates cannot be null."); + } + mCarrierFrequencyMHz = carrierFrequencyMHz; + mPhaseCenterOffsetCoordinates = phaseCenterOffsetCoordinates; + mPhaseCenterVariationCorrections = phaseCenterVariationCorrections; + mSignalGainCorrections = signalGainCorrectionDbi; + } + + public double getCarrierFrequencyMHz() { + return mCarrierFrequencyMHz; + } + + @NonNull + public PhaseCenterOffsetCoordinates getPhaseCenterOffsetCoordinates() { + return mPhaseCenterOffsetCoordinates; + } + + @Nullable + public PhaseCenterVariationCorrections getPhaseCenterVariationCorrections() { + return mPhaseCenterVariationCorrections; + } + + @Nullable + public SignalGainCorrections getSignalGainCorrections() { + return mSignalGainCorrections; + } + + public static final @android.annotation.NonNull + Creator<GnssAntennaInfo> CREATOR = new Creator<GnssAntennaInfo>() { + @Override + public GnssAntennaInfo createFromParcel(Parcel in) { + double carrierFrequencyMHz = in.readDouble(); + + ClassLoader classLoader = getClass().getClassLoader(); + PhaseCenterOffsetCoordinates phaseCenterOffsetCoordinates = + in.readParcelable(classLoader); + PhaseCenterVariationCorrections phaseCenterVariationCorrections = + in.readParcelable(classLoader); + SignalGainCorrections signalGainCorrections = + in.readParcelable(classLoader); + + return new GnssAntennaInfo(carrierFrequencyMHz, + phaseCenterOffsetCoordinates, + phaseCenterVariationCorrections, signalGainCorrections); + } + + @Override + public GnssAntennaInfo[] newArray(int size) { + return new GnssAntennaInfo[size]; + } + }; + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@NonNull Parcel parcel, int flags) { + parcel.writeDouble(mCarrierFrequencyMHz); + + // Write Phase Center Offset + parcel.writeParcelable(mPhaseCenterOffsetCoordinates, flags); + + // Write Phase Center Variation Corrections + parcel.writeParcelable(mPhaseCenterVariationCorrections, flags); + + // Write Signal Gain Corrections + parcel.writeParcelable(mSignalGainCorrections, flags); + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder("[ GnssAntennaInfo:\n"); + builder.append("CarrierFrequencyMHz: " + mCarrierFrequencyMHz + "\n"); + builder.append(mPhaseCenterOffsetCoordinates.toString()); + builder.append(mPhaseCenterVariationCorrections == null + ? "PhaseCenterVariationCorrections: null\n" + : mPhaseCenterVariationCorrections.toString()); + builder.append(mSignalGainCorrections == null + ? "SignalGainCorrections: null\n" + : mSignalGainCorrections.toString()); + builder.append("]"); + return builder.toString(); + } +} diff --git a/location/java/android/location/GnssCapabilities.java b/location/java/android/location/GnssCapabilities.java index 2e2f98432d2e..930180c6870f 100644 --- a/location/java/android/location/GnssCapabilities.java +++ b/location/java/android/location/GnssCapabilities.java @@ -82,6 +82,12 @@ public final class GnssCapabilities { */ public static final long MEASUREMENT_CORRECTIONS_REFLECTING_PLANE = 1L << 8; + /** + * Bit mask indicating GNSS chipset supports GNSS antenna info. + * @hide + */ + public static final long ANTENNA_INFO = 1L << 9; + /** @hide */ public static final long INVALID_CAPABILITIES = -1; @@ -165,6 +171,13 @@ public final class GnssCapabilities { return hasCapability(MEASUREMENT_CORRECTIONS_REFLECTING_PLANE); } + /** + * Returns {@code true} if GNSS chipset supports antenna info, {@code false} otherwise. + */ + public boolean hasGnssAntennaInfo() { + return hasCapability(ANTENNA_INFO); + } + @NonNull @Override public String toString() { @@ -172,6 +185,7 @@ public final class GnssCapabilities { if (hasLowPowerMode()) sb.append("LOW_POWER_MODE "); if (hasSatelliteBlacklist()) sb.append("SATELLITE_BLACKLIST "); if (hasGeofencing()) sb.append("GEOFENCING "); + if (hasGnssAntennaInfo()) sb.append("ANTENNA_INFO "); if (hasMeasurements()) sb.append("MEASUREMENTS "); if (hasNavMessages()) sb.append("NAV_MESSAGES "); if (hasMeasurementCorrections()) sb.append("MEASUREMENT_CORRECTIONS "); diff --git a/location/java/android/location/IGnssAntennaInfoListener.aidl b/location/java/android/location/IGnssAntennaInfoListener.aidl new file mode 100644 index 000000000000..30bf546759f1 --- /dev/null +++ b/location/java/android/location/IGnssAntennaInfoListener.aidl @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2020, 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 android.location.GnssAntennaInfo; + +/** + * {@hide} + */ +oneway interface IGnssAntennaInfoListener { + void onGnssAntennaInfoReceived(in List<GnssAntennaInfo> gnssAntennaInfo); + void onStatusChanged(in int status); +}
\ No newline at end of file diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl index 7de4d89dfa4f..8600dc48c6a4 100644 --- a/location/java/android/location/ILocationManager.aidl +++ b/location/java/android/location/ILocationManager.aidl @@ -24,6 +24,7 @@ import android.location.Geofence; import android.location.GnssMeasurementCorrections; import android.location.GnssRequest; import android.location.IBatchedLocationCallback; +import android.location.IGnssAntennaInfoListener; import android.location.IGnssMeasurementsListener; import android.location.IGnssStatusListener; import android.location.IGnssNavigationMessageListener; @@ -79,6 +80,10 @@ interface ILocationManager long getGnssCapabilities(in String packageName); void removeGnssMeasurementsListener(in IGnssMeasurementsListener listener); + boolean addGnssAntennaInfoListener(in IGnssAntennaInfoListener listener, + String packageName, String featureId, String listenerIdentifier); + void removeGnssAntennaInfoListener(in IGnssAntennaInfoListener listener); + boolean addGnssNavigationMessageListener(in IGnssNavigationMessageListener listener, String packageName, String featureId, String listenerIdentifier); void removeGnssNavigationMessageListener(in IGnssNavigationMessageListener listener); diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java index 0fec611bc522..3d0765bb0855 100644 --- a/location/java/android/location/LocationManager.java +++ b/location/java/android/location/LocationManager.java @@ -251,7 +251,7 @@ public class LocationManager { * @hide */ public static final String HIGH_POWER_REQUEST_CHANGE_ACTION = - "android.location.HIGH_POWER_REQUEST_CHANGE"; + "android.location.HIGH_POWER_REQUEST_CHANGE"; /** * Broadcast intent action for Settings app to inject a footer at the bottom of location @@ -310,6 +310,8 @@ public class LocationManager { new GnssMeasurementsListenerManager(); private final GnssNavigationMessageListenerManager mGnssNavigationMessageListenerTransport = new GnssNavigationMessageListenerManager(); + private final GnssAntennaInfoListenerManager mGnssAntennaInfoListenerManager = + new GnssAntennaInfoListenerManager(); /** * @hide @@ -2261,6 +2263,41 @@ public class LocationManager { } /** + * Registers a Gnss Antenna Info callback. + * + * @param executor the executor that the callback runs on. + * @param callback a {@link GnssAntennaInfo.Callback} object to register. + * @return {@code true} if the callback was added successfully, {@code false} otherwise. + * + * @throws IllegalArgumentException if executor is null + * @throws IllegalArgumentException if callback is null + * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present + */ + @RequiresPermission(ACCESS_FINE_LOCATION) + public boolean registerAntennaInfoCallback( + @NonNull @CallbackExecutor Executor executor, + @NonNull GnssAntennaInfo.Callback callback) { + try { + return mGnssAntennaInfoListenerManager.addListener(callback, executor); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Unregisters a GNSS Antenna Info callback. + * + * @param callback a {@link GnssAntennaInfo.Callback} object to remove. + */ + public void unregisterAntennaInfoCallback(@NonNull GnssAntennaInfo.Callback callback) { + try { + mGnssAntennaInfoListenerManager.removeListener(callback); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** * No-op method to keep backward-compatibility. * * @hide @@ -2989,6 +3026,48 @@ public class LocationManager { } } + private class GnssAntennaInfoListenerManager extends + AbstractListenerManager<Void, GnssAntennaInfo.Callback> { + + @Nullable + private IGnssAntennaInfoListener mListenerTransport; + + @Override + protected boolean registerService(Void ignored) throws RemoteException { + Preconditions.checkState(mListenerTransport == null); + + GnssAntennaInfoListener transport = new GnssAntennaInfoListener(); + if (mService.addGnssAntennaInfoListener(transport, mContext.getPackageName(), + mContext.getFeatureId(), "gnss antenna info callback")) { + mListenerTransport = transport; + return true; + } else { + return false; + } + } + + @Override + protected void unregisterService() throws RemoteException { + Preconditions.checkState(mListenerTransport != null); + + mService.removeGnssAntennaInfoListener(mListenerTransport); + mListenerTransport = null; + } + + private class GnssAntennaInfoListener extends IGnssAntennaInfoListener.Stub { + @Override + public void onGnssAntennaInfoReceived(final List<GnssAntennaInfo> gnssAntennaInfos) { + execute((callback) -> callback.onGnssAntennaInfoReceived(gnssAntennaInfos)); + } + + @Override + public void onStatusChanged(int status) { + execute((listener) -> listener.onStatusChanged(status)); + } + } + + } + private class BatchedLocationCallbackManager extends AbstractListenerManager<Void, BatchedLocationCallback> { @@ -3001,7 +3080,7 @@ public class LocationManager { BatchedLocationCallback transport = new BatchedLocationCallback(); if (mService.addGnssBatchingCallback(transport, mContext.getPackageName(), - mContext.getFeatureId(), "batched location callback")) { + mContext.getFeatureId(), "batched location callback")) { mListenerTransport = transport; return true; } else { |