diff options
| author | 2021-01-07 23:05:01 +0000 | |
|---|---|---|
| committer | 2021-01-07 23:05:01 +0000 | |
| commit | 9f053e5fb849bbca6f960f03f463fb2d29f9f6c7 (patch) | |
| tree | 7683aac74f22b212fbec712e1df060fbd3a3b7d0 /location/java | |
| parent | 805d08aeec9dda2237cf032b59642d8571305508 (diff) | |
| parent | 7a46eda83ee043d516467182bf49a3d55106e58f (diff) | |
Merge "Add GNSS capabilities and antenna broadcasts"
Diffstat (limited to 'location/java')
7 files changed, 277 insertions, 145 deletions
diff --git a/location/java/android/location/GnssAntennaInfo.java b/location/java/android/location/GnssAntennaInfo.java index 23977f18f749..f1eb8fccdd3c 100644 --- a/location/java/android/location/GnssAntennaInfo.java +++ b/location/java/android/location/GnssAntennaInfo.java @@ -34,17 +34,19 @@ import java.util.Objects; public final class GnssAntennaInfo implements Parcelable { private final double mCarrierFrequencyMHz; private final PhaseCenterOffset mPhaseCenterOffset; - private final SphericalCorrections mPhaseCenterVariationCorrections; - private final SphericalCorrections mSignalGainCorrections; + private final @Nullable SphericalCorrections mPhaseCenterVariationCorrections; + private final @Nullable SphericalCorrections mSignalGainCorrections; /** - * Used for receiving GNSS antenna info from the GNSS engine. You can implement this interface - * and call {@link LocationManager#registerAntennaInfoListener}; + * Used for receiving GNSS antenna info from the GNSS engine. + * + * @deprecated Prefer to use a broadcast receiver for + * {@link LocationManager#ACTION_GNSS_ANTENNA_INFOS_CHANGED}. */ + @Deprecated public interface Listener { /** - * Returns the latest GNSS antenna info. This event is triggered when a listener is - * registered, and whenever the antenna info changes (due to a device configuration change). + * Invoked on a change to GNSS antenna info. */ void onGnssAntennaInfoReceived(@NonNull List<GnssAntennaInfo> gnssAntennaInfos); } @@ -172,6 +174,28 @@ public final class GnssAntennaInfo implements Parcelable { + ", OffsetZMm=" + mOffsetZMm + " +/-" + mOffsetZUncertaintyMm + '}'; } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof PhaseCenterOffset)) { + return false; + } + PhaseCenterOffset that = (PhaseCenterOffset) o; + return Double.compare(that.mOffsetXMm, mOffsetXMm) == 0 + && Double.compare(that.mOffsetXUncertaintyMm, mOffsetXUncertaintyMm) == 0 + && Double.compare(that.mOffsetYMm, mOffsetYMm) == 0 + && Double.compare(that.mOffsetYUncertaintyMm, mOffsetYUncertaintyMm) == 0 + && Double.compare(that.mOffsetZMm, mOffsetZMm) == 0 + && Double.compare(that.mOffsetZUncertaintyMm, mOffsetZUncertaintyMm) == 0; + } + + @Override + public int hashCode() { + return Objects.hash(mOffsetXMm, mOffsetYMm, mOffsetZMm); + } } /** @@ -190,38 +214,34 @@ public final class GnssAntennaInfo implements Parcelable { * i.e., deltaPhi = 180 / (number of columns - 1). */ public static final 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; + private final double[][] mCorrections; + private final double[][] mCorrectionUncertainties; public 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."); + if (corrections.length != correctionUncertainties.length || corrections.length < 1) { + throw new IllegalArgumentException("correction and uncertainty arrays must have " + + "the same (non-zero) 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."); + for (int i = 0; i < corrections.length; i++) { + if (corrections[i].length != mNumColumns + || correctionUncertainties[i].length != mNumColumns || mNumColumns < 2) { + throw new IllegalArgumentException("correction and uncertainty arrays must all " + + " have the same (greater than 2) number of columns"); + } } mCorrections = corrections; mCorrectionUncertainties = correctionUncertainties; - mDeltaTheta = 360.0d / mNumRows; - mDeltaPhi = 180.0d / (mNumColumns - 1); } - SphericalCorrections(Parcel in) { + private SphericalCorrections(Parcel in) { int numRows = in.readInt(); int numColumns = in.readInt(); @@ -231,19 +251,16 @@ public final class GnssAntennaInfo implements Parcelable { 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]); + for (int col = 0; col < numColumns; col++) { + corrections[row][col] = in.readDouble(); + correctionUncertainties[row][col] = in.readDouble(); + } } mNumRows = numRows; mNumColumns = numColumns; mCorrections = corrections; mCorrectionUncertainties = correctionUncertainties; - mDeltaTheta = 360.0d / mNumRows; - mDeltaPhi = 180.0d / (mNumColumns - 1); } /** @@ -286,7 +303,7 @@ public final class GnssAntennaInfo implements Parcelable { */ @FloatRange(from = 0.0f, to = 360.0f) public double getDeltaTheta() { - return mDeltaTheta; + return 360.0D / mNumRows; } /** @@ -294,7 +311,7 @@ public final class GnssAntennaInfo implements Parcelable { */ @FloatRange(from = 0.0f, to = 180.0f) public double getDeltaPhi() { - return mDeltaPhi; + return 180.0D / (mNumColumns - 1); } @@ -320,11 +337,11 @@ public final class GnssAntennaInfo implements Parcelable { 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); + for (int row = 0; row < mNumRows; row++) { + for (int col = 0; col < mNumColumns; col++) { + dest.writeDouble(mCorrections[row][col]); + dest.writeDouble(mCorrectionUncertainties[row][col]); + } } } @@ -333,22 +350,41 @@ public final class GnssAntennaInfo implements Parcelable { return "SphericalCorrections{" + "Corrections=" + Arrays.toString(mCorrections) + ", CorrectionUncertainties=" + Arrays.toString(mCorrectionUncertainties) - + ", DeltaTheta=" + mDeltaTheta - + ", DeltaPhi=" + mDeltaPhi + + ", DeltaTheta=" + getDeltaTheta() + + ", DeltaPhi=" + getDeltaPhi() + '}'; } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof SphericalCorrections)) { + return false; + } + SphericalCorrections that = (SphericalCorrections) o; + return mNumRows == that.mNumRows + && mNumColumns == that.mNumColumns + && Arrays.deepEquals(mCorrections, that.mCorrections) + && Arrays.deepEquals(mCorrectionUncertainties, that.mCorrectionUncertainties); + } + + @Override + public int hashCode() { + int result = Arrays.deepHashCode(mCorrections); + result = 31 * result + Arrays.deepHashCode(mCorrectionUncertainties); + return result; + } } private GnssAntennaInfo( double carrierFrequencyMHz, - @NonNull PhaseCenterOffset phaseCenterOffset, + PhaseCenterOffset phaseCenterOffset, @Nullable SphericalCorrections phaseCenterVariationCorrections, @Nullable SphericalCorrections signalGainCorrectionDbi) { - if (phaseCenterOffset == null) { - throw new IllegalArgumentException("Phase Center Offset Coordinates cannot be null."); - } mCarrierFrequencyMHz = carrierFrequencyMHz; - mPhaseCenterOffset = phaseCenterOffset; + mPhaseCenterOffset = Objects.requireNonNull(phaseCenterOffset); mPhaseCenterVariationCorrections = phaseCenterVariationCorrections; mSignalGainCorrections = signalGainCorrectionDbi; } @@ -359,8 +395,28 @@ public final class GnssAntennaInfo implements Parcelable { public static class Builder { private double mCarrierFrequencyMHz; private PhaseCenterOffset mPhaseCenterOffset; - private SphericalCorrections mPhaseCenterVariationCorrections; - private SphericalCorrections mSignalGainCorrections; + private @Nullable SphericalCorrections mPhaseCenterVariationCorrections; + private @Nullable SphericalCorrections mSignalGainCorrections; + + /** + * @deprecated Prefer {@link #Builder(double, PhaseCenterOffset)}. + */ + @Deprecated + public Builder() { + this(0, new PhaseCenterOffset(0, 0, 0, 0, 0, 0)); + } + + public Builder(double carrierFrequencyMHz, @NonNull PhaseCenterOffset phaseCenterOffset) { + mCarrierFrequencyMHz = carrierFrequencyMHz; + mPhaseCenterOffset = Objects.requireNonNull(phaseCenterOffset); + } + + public Builder(@NonNull GnssAntennaInfo antennaInfo) { + mCarrierFrequencyMHz = antennaInfo.mCarrierFrequencyMHz; + mPhaseCenterOffset = antennaInfo.mPhaseCenterOffset; + mPhaseCenterVariationCorrections = antennaInfo.mPhaseCenterVariationCorrections; + mSignalGainCorrections = antennaInfo.mSignalGainCorrections; + } /** * Set antenna carrier frequency (MHz). @@ -462,32 +518,29 @@ public final class GnssAntennaInfo implements Parcelable { 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(); - PhaseCenterOffset phaseCenterOffset = - in.readParcelable(classLoader); - SphericalCorrections phaseCenterVariationCorrections = - in.readParcelable(classLoader); - SphericalCorrections signalGainCorrections = - in.readParcelable(classLoader); - - return new GnssAntennaInfo( - carrierFrequencyMHz, - phaseCenterOffset, - phaseCenterVariationCorrections, - signalGainCorrections); - } + public static final @NonNull Creator<GnssAntennaInfo> CREATOR = new Creator<GnssAntennaInfo>() { + @Override + public GnssAntennaInfo createFromParcel(Parcel in) { + double carrierFrequencyMHz = in.readDouble(); + PhaseCenterOffset phaseCenterOffset = + in.readTypedObject(PhaseCenterOffset.CREATOR); + SphericalCorrections phaseCenterVariationCorrections = + in.readTypedObject(SphericalCorrections.CREATOR); + SphericalCorrections signalGainCorrections = + in.readTypedObject(SphericalCorrections.CREATOR); + + return new GnssAntennaInfo( + carrierFrequencyMHz, + phaseCenterOffset, + phaseCenterVariationCorrections, + signalGainCorrections); + } - @Override - public GnssAntennaInfo[] newArray(int size) { - return new GnssAntennaInfo[size]; - } - }; + @Override + public GnssAntennaInfo[] newArray(int size) { + return new GnssAntennaInfo[size]; + } + }; @Override public int describeContents() { @@ -497,9 +550,9 @@ public final class GnssAntennaInfo implements Parcelable { @Override public void writeToParcel(@NonNull Parcel parcel, int flags) { parcel.writeDouble(mCarrierFrequencyMHz); - parcel.writeParcelable(mPhaseCenterOffset, flags); - parcel.writeParcelable(mPhaseCenterVariationCorrections, flags); - parcel.writeParcelable(mSignalGainCorrections, flags); + parcel.writeTypedObject(mPhaseCenterOffset, flags); + parcel.writeTypedObject(mPhaseCenterVariationCorrections, flags); + parcel.writeTypedObject(mSignalGainCorrections, flags); } @Override @@ -511,4 +564,26 @@ public final class GnssAntennaInfo implements Parcelable { + ", SignalGainCorrections=" + mSignalGainCorrections + '}'; } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof GnssAntennaInfo)) { + return false; + } + GnssAntennaInfo that = (GnssAntennaInfo) o; + return Double.compare(that.mCarrierFrequencyMHz, mCarrierFrequencyMHz) == 0 + && mPhaseCenterOffset.equals(that.mPhaseCenterOffset) + && Objects.equals(mPhaseCenterVariationCorrections, + that.mPhaseCenterVariationCorrections) + && Objects.equals(mSignalGainCorrections, that.mSignalGainCorrections); + } + + @Override + public int hashCode() { + return Objects.hash(mCarrierFrequencyMHz, mPhaseCenterOffset, + mPhaseCenterVariationCorrections, mSignalGainCorrections); + } } diff --git a/location/java/android/location/GnssMeasurementsEvent.java b/location/java/android/location/GnssMeasurementsEvent.java index 98ef2d4a6c9f..a07a64acb6e6 100644 --- a/location/java/android/location/GnssMeasurementsEvent.java +++ b/location/java/android/location/GnssMeasurementsEvent.java @@ -16,9 +16,9 @@ package android.location; -import android.annotation.TestApi; import android.annotation.IntDef; import android.annotation.NonNull; +import android.annotation.TestApi; import android.os.Parcel; import android.os.Parcelable; @@ -46,8 +46,10 @@ public final class GnssMeasurementsEvent implements Parcelable { public static abstract class Callback { /** * The status of the GNSS measurements event. + * @deprecated Do not use. * @hide */ + @Deprecated @Retention(RetentionPolicy.SOURCE) @IntDef({STATUS_NOT_SUPPORTED, STATUS_READY, STATUS_LOCATION_DISABLED, STATUS_NOT_ALLOWED}) public @interface GnssMeasurementsStatus {} @@ -56,19 +58,28 @@ public final class GnssMeasurementsEvent implements Parcelable { * The system does not support tracking of GNSS Measurements. * * <p>This status will not change in the future. + * + * @deprecated Do not use. */ + @Deprecated public static final int STATUS_NOT_SUPPORTED = 0; /** * GNSS Measurements are successfully being tracked, it will receive updates once they are * available. + * + * @deprecated Do not use. */ + @Deprecated public static final int STATUS_READY = 1; /** * GPS provider or Location is disabled, updates will not be received until they are * enabled. + * + * @deprecated Do not use. */ + @Deprecated public static final int STATUS_LOCATION_DISABLED = 2; /** @@ -81,7 +92,10 @@ public final class GnssMeasurementsEvent implements Parcelable { * * <p>If such a status is received, one would try again at a later time point where no * other client is having a conflicting request. + * + * @deprecated Do not use. */ + @Deprecated public static final int STATUS_NOT_ALLOWED = 3; /** @@ -91,7 +105,13 @@ public final class GnssMeasurementsEvent implements Parcelable { /** * Reports the latest status of the GNSS Measurements sub-system. + * + * @deprecated Do not rely on this callback. From Android S onwards this callback will be + * invoked once with {@link #STATUS_READY} in all cases for backwards compatibility, and + * then never invoked again. Use LocationManager APIs if you need to determine if + * GNSS measurements are supported or if location is off, etc... */ + @Deprecated public void onStatusChanged(@GnssMeasurementsStatus int status) {} } diff --git a/location/java/android/location/GnssNavigationMessage.java b/location/java/android/location/GnssNavigationMessage.java index aade5ac63317..84a363d25c63 100644 --- a/location/java/android/location/GnssNavigationMessage.java +++ b/location/java/android/location/GnssNavigationMessage.java @@ -110,6 +110,7 @@ public final class GnssNavigationMessage implements Parcelable { public static abstract class Callback { /** * The status of GNSS Navigation Message event. + * @deprecated Do not use. * @hide */ @Retention(RetentionPolicy.SOURCE) @@ -120,19 +121,28 @@ public final class GnssNavigationMessage implements Parcelable { * The system does not support tracking of GNSS Navigation Messages. * * This status will not change in the future. + * + * @deprecated Do not use. */ + @Deprecated public static final int STATUS_NOT_SUPPORTED = 0; /** * GNSS Navigation Messages are successfully being tracked, it will receive updates once * they are available. + * + * @deprecated Do not use. */ + @Deprecated public static final int STATUS_READY = 1; /** * GNSS provider or Location is disabled, updated will not be received until they are * enabled. + * + * @deprecated Do not use. */ + @Deprecated public static final int STATUS_LOCATION_DISABLED = 2; /** @@ -142,7 +152,13 @@ public final class GnssNavigationMessage implements Parcelable { /** * Returns the latest status of the GNSS Navigation Messages sub-system. + * + * @deprecated Do not rely on this callback. From Android S onwards this callback will be + * invoked once with {@link #STATUS_READY} in all cases for backwards compatibility, and + * then never invoked again. Use LocationManager APIs if you need to determine if + * GNSS navigation messages are supported or if location is off, etc... */ + @Deprecated public void onStatusChanged(@GnssNavigationMessageStatus int status) {} } diff --git a/location/java/android/location/GnssStatus.java b/location/java/android/location/GnssStatus.java index c5b4c1667831..b46e8ce2f605 100644 --- a/location/java/android/location/GnssStatus.java +++ b/location/java/android/location/GnssStatus.java @@ -391,20 +391,10 @@ public final class GnssStatus implements Parcelable { float[] basebandCn0DbHzs = new float[svCount]; for (int i = 0; i < svCount; i++) { svidWithFlags[i] = in.readInt(); - } - for (int i = 0; i < svCount; i++) { cn0DbHzs[i] = in.readFloat(); - } - for (int i = 0; i < svCount; i++) { elevations[i] = in.readFloat(); - } - for (int i = 0; i < svCount; i++) { azimuths[i] = in.readFloat(); - } - for (int i = 0; i < svCount; i++) { carrierFrequencies[i] = in.readFloat(); - } - for (int i = 0; i < svCount; i++) { basebandCn0DbHzs[i] = in.readFloat(); } @@ -428,20 +418,10 @@ public final class GnssStatus implements Parcelable { parcel.writeInt(mSvCount); for (int i = 0; i < mSvCount; i++) { parcel.writeInt(mSvidWithFlags[i]); - } - for (int i = 0; i < mSvCount; i++) { parcel.writeFloat(mCn0DbHzs[i]); - } - for (int i = 0; i < mSvCount; i++) { parcel.writeFloat(mElevations[i]); - } - for (int i = 0; i < mSvCount; i++) { parcel.writeFloat(mAzimuths[i]); - } - for (int i = 0; i < mSvCount; i++) { parcel.writeFloat(mCarrierFrequencies[i]); - } - for (int i = 0; i < mSvCount; i++) { parcel.writeFloat(mBasebandCn0DbHzs[i]); } } diff --git a/location/java/android/location/IGnssAntennaInfoListener.aidl b/location/java/android/location/IGnssAntennaInfoListener.aidl deleted file mode 100644 index 603ed6a2614e..000000000000 --- a/location/java/android/location/IGnssAntennaInfoListener.aidl +++ /dev/null @@ -1,26 +0,0 @@ -/* - * 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); -}
\ No newline at end of file diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl index 621fe1ba1432..c50904cad4e2 100644 --- a/location/java/android/location/ILocationManager.aidl +++ b/location/java/android/location/ILocationManager.aidl @@ -21,11 +21,11 @@ import android.location.Address; import android.location.Criteria; import android.location.GeocoderParams; import android.location.Geofence; +import android.location.GnssAntennaInfo; import android.location.GnssCapabilities; import android.location.GnssMeasurementCorrections; import android.location.GnssMeasurementRequest; import android.location.IGeocodeListener; -import android.location.IGnssAntennaInfoListener; import android.location.IGnssMeasurementsListener; import android.location.IGnssStatusListener; import android.location.IGnssNavigationMessageListener; @@ -76,6 +76,8 @@ interface ILocationManager int getGnssYearOfHardware(); String getGnssHardwareModelName(); + @nullable List<GnssAntennaInfo> getGnssAntennaInfos(); + void registerGnssStatusCallback(in IGnssStatusListener callback, String packageName, String attributionTag); void unregisterGnssStatusCallback(in IGnssStatusListener callback); @@ -86,9 +88,6 @@ interface ILocationManager void removeGnssMeasurementsListener(in IGnssMeasurementsListener listener); void injectGnssMeasurementCorrections(in GnssMeasurementCorrections corrections); - void addGnssAntennaInfoListener(in IGnssAntennaInfoListener listener, String packageName, String attributionTag); - void removeGnssAntennaInfoListener(in IGnssAntennaInfoListener listener); - void addGnssNavigationMessageListener(in IGnssNavigationMessageListener listener, String packageName, String attributionTag); void removeGnssNavigationMessageListener(in IGnssNavigationMessageListener listener); diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java index 00381a68a2a2..1d3e8ebaa0ab 100644 --- a/location/java/android/location/LocationManager.java +++ b/location/java/android/location/LocationManager.java @@ -44,7 +44,10 @@ import android.compat.Compatibility; import android.compat.annotation.ChangeId; import android.compat.annotation.EnabledAfter; import android.compat.annotation.UnsupportedAppUsage; +import android.content.BroadcastReceiver; import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; import android.content.pm.PackageManager; import android.os.Build; import android.os.Bundle; @@ -64,6 +67,7 @@ import com.android.internal.listeners.ListenerTransportMultiplexer; import com.android.internal.util.Preconditions; import java.lang.ref.WeakReference; +import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; @@ -312,6 +316,48 @@ public class LocationManager { "android.location.HIGH_POWER_REQUEST_CHANGE"; /** + * Broadcast intent action when GNSS capabilities change. This is most common at boot time as + * GNSS capabilities are queried from the chipset. Includes an intent extra, + * {@link #EXTRA_GNSS_CAPABILITIES}, with the new {@link GnssCapabilities}. + * + * @see #EXTRA_GNSS_CAPABILITIES + * @see #getGnssCapabilities() + */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_GNSS_CAPABILITIES_CHANGED = + "android.location.action.GNSS_CAPABILITIES_CHANGED"; + + /** + * Intent extra included with {@link #ACTION_GNSS_CAPABILITIES_CHANGED} broadcasts, containing + * the new {@link GnssCapabilities}. + * + * @see #ACTION_GNSS_CAPABILITIES_CHANGED + */ + public static final String EXTRA_GNSS_CAPABILITIES = "android.location.extra.GNSS_CAPABILITIES"; + + /** + * Broadcast intent action when GNSS antenna infos change. Includes an intent extra, + * {@link #EXTRA_GNSS_ANTENNA_INFOS}, with an ArrayList of the new {@link GnssAntennaInfo}. This + * may be read via {@link android.content.Intent#getParcelableArrayListExtra(String)}. + * + * @see #EXTRA_GNSS_ANTENNA_INFOS + * @see #getGnssAntennaInfos() + */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_GNSS_ANTENNA_INFOS_CHANGED = + "android.location.action.GNSS_ANTENNA_INFOS_CHANGED"; + + /** + * Intent extra included with {@link #ACTION_GNSS_ANTENNA_INFOS_CHANGED} broadcasts, containing + * the new ArrayList of {@link GnssAntennaInfo}. This may be read via + * {@link android.content.Intent#getParcelableArrayListExtra(String)}. + * + * @see #ACTION_GNSS_ANTENNA_INFOS_CHANGED + */ + public static final String EXTRA_GNSS_ANTENNA_INFOS = + "android.location.extra.GNSS_ANTENNA_INFOS"; + + /** * Broadcast intent action for Settings app to inject a footer at the bottom of location * settings. This is for use only by apps that are included in the system image. * @@ -2137,6 +2183,20 @@ public class LocationManager { } /** + * Returns the current list of GNSS antenna infos, or null if unknown or unsupported. + * + * @see #getGnssCapabilities() + */ + @Nullable + public List<GnssAntennaInfo> getGnssAntennaInfos() { + try { + return mService.getGnssAntennaInfos(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** * Retrieves information about the current status of the GPS engine. This should only be called * from within the {@link GpsStatus.Listener#onGpsStatusChanged} callback to ensure that the * data is copied atomically. @@ -2559,15 +2619,19 @@ public class LocationManager { * * <p>Not all GNSS chipsets support antenna info updates, see {@link #getGnssCapabilities()}. * + * <p>Prior to Android S, this requires the {@link Manifest.permission#ACCESS_FINE_LOCATION} + * permission. + * * @param executor the executor that the listener runs on * @param listener the listener to register * @return {@code true} always * * @throws IllegalArgumentException if executor is null * @throws IllegalArgumentException if listener is null - * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present + * + * @deprecated Prefer to use a receiver for {@link #ACTION_GNSS_ANTENNA_INFOS_CHANGED}. */ - @RequiresPermission(ACCESS_FINE_LOCATION) + @Deprecated public boolean registerAntennaInfoListener( @NonNull @CallbackExecutor Executor executor, @NonNull GnssAntennaInfo.Listener listener) { @@ -2579,7 +2643,10 @@ public class LocationManager { * Unregisters a GNSS Antenna Info listener. * * @param listener a {@link GnssAntennaInfo.Listener} object to remove + * + * @deprecated Prefer to use a receiver for {@link #ACTION_GNSS_ANTENNA_INFOS_CHANGED}. */ + @Deprecated public void unregisterAntennaInfoListener(@NonNull GnssAntennaInfo.Listener listener) { getGnssAntennaInfoTransportMultiplexer().removeListener(listener); } @@ -3153,40 +3220,41 @@ public class LocationManager { private class GnssAntennaInfoTransportMultiplexer extends ListenerTransportMultiplexer<Void, GnssAntennaInfo.Listener> { - private @Nullable IGnssAntennaInfoListener mListenerTransport; + private @Nullable BroadcastReceiver mListenerTransport; GnssAntennaInfoTransportMultiplexer() {} @Override - protected void registerWithServer(Void ignored) throws RemoteException { - IGnssAntennaInfoListener transport = mListenerTransport; - if (transport == null) { - transport = new GnssAntennaInfoListener(); + protected void registerWithServer(Void ignored) { + if (mListenerTransport == null) { + // if an exception is thrown the transport should not be set + BroadcastReceiver transport = new GnssAntennaInfoReceiver(); + mContext.registerReceiver(transport, + new IntentFilter(ACTION_GNSS_ANTENNA_INFOS_CHANGED)); + mListenerTransport = transport; } - - // if a remote exception is thrown the transport should not be set - mListenerTransport = null; - mService.addGnssAntennaInfoListener(transport, mContext.getPackageName(), - mContext.getAttributionTag()); - mListenerTransport = transport; } @Override - protected void unregisterWithServer() throws RemoteException { + protected void unregisterWithServer() { if (mListenerTransport != null) { - IGnssAntennaInfoListener transport = mListenerTransport; + BroadcastReceiver transport = mListenerTransport; mListenerTransport = null; - mService.removeGnssAntennaInfoListener(transport); + mContext.unregisterReceiver(transport); } } - private class GnssAntennaInfoListener extends IGnssAntennaInfoListener.Stub { + private class GnssAntennaInfoReceiver extends BroadcastReceiver { - GnssAntennaInfoListener() {} + GnssAntennaInfoReceiver() {} @Override - public void onGnssAntennaInfoReceived(List<GnssAntennaInfo> infos) { - deliverToListeners(callback -> callback.onGnssAntennaInfoReceived(infos)); + public void onReceive(Context context, Intent intent) { + ArrayList<GnssAntennaInfo> infos = intent.getParcelableArrayListExtra( + EXTRA_GNSS_ANTENNA_INFOS); + if (infos != null) { + deliverToListeners(callback -> callback.onGnssAntennaInfoReceived(infos)); + } } } } |