Add GnssAntennaInfo framework APIs
Test: End to end test: run "atest GnssAntennaInfoRegistrationTest" on cuttlefish and watch "adb logcat | grep -i GnssAntennaInfo". Other tests: atest GnssAntennaInfoTest, atest GnssAntennaInfoProviderTest, atest GnssManagerServiceTest, atest VtsHalGnssV2_1TargetTest, atest LocationManagerFineTest. Bug:124556515 Change-Id: I70e4014dd3959b0570c35bd2aa8bb839ef167d70
This commit is contained in:
@@ -23465,6 +23465,69 @@ package android.location {
|
||||
method public static boolean isPresent();
|
||||
}
|
||||
|
||||
public final class GnssAntennaInfo implements android.os.Parcelable {
|
||||
ctor public GnssAntennaInfo(double, @NonNull android.location.GnssAntennaInfo.PhaseCenterOffsetCoordinates, @Nullable android.location.GnssAntennaInfo.PhaseCenterVariationCorrections, @Nullable android.location.GnssAntennaInfo.SignalGainCorrections);
|
||||
method public int describeContents();
|
||||
method public double getCarrierFrequencyMHz();
|
||||
method @NonNull public android.location.GnssAntennaInfo.PhaseCenterOffsetCoordinates getPhaseCenterOffsetCoordinates();
|
||||
method @Nullable public android.location.GnssAntennaInfo.PhaseCenterVariationCorrections getPhaseCenterVariationCorrections();
|
||||
method @Nullable public android.location.GnssAntennaInfo.SignalGainCorrections getSignalGainCorrections();
|
||||
method public void writeToParcel(@NonNull android.os.Parcel, int);
|
||||
field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssAntennaInfo> CREATOR;
|
||||
}
|
||||
|
||||
public abstract static class GnssAntennaInfo.Callback {
|
||||
ctor public GnssAntennaInfo.Callback();
|
||||
method public void onGnssAntennaInfoReceived(@NonNull java.util.List<android.location.GnssAntennaInfo>);
|
||||
method public void onStatusChanged(int);
|
||||
field public static final int STATUS_LOCATION_DISABLED = 2; // 0x2
|
||||
field public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
|
||||
field public static final int STATUS_READY = 1; // 0x1
|
||||
}
|
||||
|
||||
public static final class GnssAntennaInfo.PhaseCenterOffsetCoordinates implements android.os.Parcelable {
|
||||
ctor public GnssAntennaInfo.PhaseCenterOffsetCoordinates(double, double, double, double, double, double);
|
||||
method public int describeContents();
|
||||
method public double getXCoordMillimeters();
|
||||
method public double getXCoordUncertaintyMillimeters();
|
||||
method public double getYCoordMillimeters();
|
||||
method public double getYCoordUncertaintyMillimeters();
|
||||
method public double getZCoordMillimeters();
|
||||
method public double getZCoordUncertaintyMillimeters();
|
||||
method public void writeToParcel(@NonNull android.os.Parcel, int);
|
||||
field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssAntennaInfo.PhaseCenterOffsetCoordinates> CREATOR;
|
||||
}
|
||||
|
||||
public static final class GnssAntennaInfo.PhaseCenterVariationCorrections implements android.os.Parcelable {
|
||||
ctor public GnssAntennaInfo.PhaseCenterVariationCorrections(@NonNull double[][], @NonNull double[][]);
|
||||
method public int describeContents();
|
||||
method public double getDeltaPhi();
|
||||
method public double getDeltaTheta();
|
||||
method public int getNumColumns();
|
||||
method public int getNumRows();
|
||||
method public double getPhaseCenterVariationCorrectionMillimetersAt(int, int);
|
||||
method public double getPhaseCenterVariationCorrectionUncertaintyMillimetersAt(int, int);
|
||||
method @NonNull public double[][] getRawCorrectionUncertaintiesArray();
|
||||
method @NonNull public double[][] getRawCorrectionsArray();
|
||||
method public void writeToParcel(@NonNull android.os.Parcel, int);
|
||||
field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssAntennaInfo.PhaseCenterVariationCorrections> CREATOR;
|
||||
}
|
||||
|
||||
public static final class GnssAntennaInfo.SignalGainCorrections implements android.os.Parcelable {
|
||||
ctor public GnssAntennaInfo.SignalGainCorrections(@NonNull double[][], @NonNull double[][]);
|
||||
method public int describeContents();
|
||||
method public double getDeltaPhi();
|
||||
method public double getDeltaTheta();
|
||||
method public int getNumColumns();
|
||||
method public int getNumRows();
|
||||
method @NonNull public double[][] getRawCorrectionUncertaintiesArray();
|
||||
method @NonNull public double[][] getRawCorrectionsArray();
|
||||
method public double getSignalGainCorrectionDbiAt(int, int);
|
||||
method public double getSignalGainCorrectionUncertaintyDbiAt(int, int);
|
||||
method public void writeToParcel(@NonNull android.os.Parcel, int);
|
||||
field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssAntennaInfo.SignalGainCorrections> CREATOR;
|
||||
}
|
||||
|
||||
public final class GnssClock implements android.os.Parcelable {
|
||||
method public int describeContents();
|
||||
method public double getBiasNanos();
|
||||
@@ -23782,6 +23845,7 @@ package android.location {
|
||||
method @NonNull public java.util.List<java.lang.String> getProviders(@NonNull android.location.Criteria, boolean);
|
||||
method public boolean isLocationEnabled();
|
||||
method public boolean isProviderEnabled(@NonNull String);
|
||||
method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerAntennaInfoCallback(@NonNull java.util.concurrent.Executor, @NonNull android.location.GnssAntennaInfo.Callback);
|
||||
method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssMeasurementsCallback(@NonNull android.location.GnssMeasurementsEvent.Callback);
|
||||
method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssMeasurementsCallback(@NonNull android.location.GnssMeasurementsEvent.Callback, @Nullable android.os.Handler);
|
||||
method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssMeasurementsCallback(@NonNull java.util.concurrent.Executor, @NonNull android.location.GnssMeasurementsEvent.Callback);
|
||||
@@ -23813,6 +23877,7 @@ package android.location {
|
||||
method public void setTestProviderEnabled(@NonNull String, boolean);
|
||||
method public void setTestProviderLocation(@NonNull String, @NonNull android.location.Location);
|
||||
method @Deprecated public void setTestProviderStatus(@NonNull String, int, @Nullable android.os.Bundle, long);
|
||||
method public void unregisterAntennaInfoCallback(@NonNull android.location.GnssAntennaInfo.Callback);
|
||||
method public void unregisterGnssMeasurementsCallback(@NonNull android.location.GnssMeasurementsEvent.Callback);
|
||||
method public void unregisterGnssNavigationMessageCallback(@NonNull android.location.GnssNavigationMessage.Callback);
|
||||
method public void unregisterGnssStatusCallback(@NonNull android.location.GnssStatus.Callback);
|
||||
|
||||
@@ -3806,6 +3806,7 @@ package android.location {
|
||||
|
||||
public final class GnssCapabilities {
|
||||
method public boolean hasGeofencing();
|
||||
method public boolean hasGnssAntennaInfo();
|
||||
method public boolean hasLowPowerMode();
|
||||
method public boolean hasMeasurementCorrections();
|
||||
method public boolean hasMeasurementCorrectionsExcessPathLength();
|
||||
|
||||
19
location/java/android/location/GnssAntennaInfo.aidl
Normal file
19
location/java/android/location/GnssAntennaInfo.aidl
Normal file
@@ -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;
|
||||
654
location/java/android/location/GnssAntennaInfo.java
Normal file
654
location/java/android/location/GnssAntennaInfo.java
Normal file
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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 ");
|
||||
|
||||
27
location/java/android/location/IGnssAntennaInfoListener.aidl
Normal file
27
location/java/android/location/IGnssAntennaInfoListener.aidl
Normal file
@@ -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);
|
||||
}
|
||||
@@ -23,6 +23,7 @@ import android.location.GeocoderParams;
|
||||
import android.location.Geofence;
|
||||
import android.location.GnssMeasurementCorrections;
|
||||
import android.location.IBatchedLocationCallback;
|
||||
import android.location.IGnssAntennaInfoListener;
|
||||
import android.location.IGnssMeasurementsListener;
|
||||
import android.location.IGnssStatusListener;
|
||||
import android.location.IGnssNavigationMessageListener;
|
||||
@@ -76,6 +77,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);
|
||||
|
||||
@@ -278,6 +278,8 @@ public class LocationManager {
|
||||
new GnssMeasurementsListenerManager();
|
||||
private final GnssNavigationMessageListenerManager mGnssNavigationMessageListenerTransport =
|
||||
new GnssNavigationMessageListenerManager();
|
||||
private final GnssAntennaInfoListenerManager mGnssAntennaInfoListenerManager =
|
||||
new GnssAntennaInfoListenerManager();
|
||||
|
||||
/**
|
||||
* @hide
|
||||
@@ -2198,6 +2200,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.
|
||||
*
|
||||
@@ -2929,6 +2966,48 @@ public class LocationManager {
|
||||
}
|
||||
}
|
||||
|
||||
private class GnssAntennaInfoListenerManager extends
|
||||
AbstractListenerManager<GnssAntennaInfo.Callback> {
|
||||
|
||||
@Nullable
|
||||
private IGnssAntennaInfoListener mListenerTransport;
|
||||
|
||||
@Override
|
||||
protected boolean registerService() 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<BatchedLocationCallback> {
|
||||
|
||||
@@ -2941,7 +3020,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 {
|
||||
|
||||
@@ -43,6 +43,7 @@ import android.location.GeocoderParams;
|
||||
import android.location.Geofence;
|
||||
import android.location.GnssMeasurementCorrections;
|
||||
import android.location.IBatchedLocationCallback;
|
||||
import android.location.IGnssAntennaInfoListener;
|
||||
import android.location.IGnssMeasurementsListener;
|
||||
import android.location.IGnssNavigationMessageListener;
|
||||
import android.location.IGnssStatusListener;
|
||||
@@ -2317,6 +2318,22 @@ public class LocationManagerService extends ILocationManager.Stub {
|
||||
packageName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addGnssAntennaInfoListener(IGnssAntennaInfoListener listener,
|
||||
String packageName, String featureId, String listenerIdentifier) {
|
||||
Objects.requireNonNull(listenerIdentifier);
|
||||
|
||||
return mGnssManagerService != null && mGnssManagerService.addGnssAntennaInfoListener(
|
||||
listener, packageName, featureId, listenerIdentifier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeGnssAntennaInfoListener(IGnssAntennaInfoListener listener) {
|
||||
if (mGnssManagerService != null) {
|
||||
mGnssManagerService.removeGnssAntennaInfoListener(listener);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addGnssNavigationMessageListener(IGnssNavigationMessageListener listener,
|
||||
String packageName, String featureId, String listenerIdentifier) {
|
||||
|
||||
@@ -0,0 +1,178 @@
|
||||
/*
|
||||
* 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 com.android.server.location;
|
||||
|
||||
import android.content.Context;
|
||||
import android.location.GnssAntennaInfo;
|
||||
import android.location.IGnssAntennaInfoListener;
|
||||
import android.os.Handler;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* An base implementation for GNSS antenna info provider. It abstracts out the responsibility of
|
||||
* handling listeners, while still allowing technology specific implementations to be built.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public abstract class GnssAntennaInfoProvider
|
||||
extends RemoteListenerHelper<IGnssAntennaInfoListener> {
|
||||
private static final String TAG = "GnssAntennaInfoProvider";
|
||||
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
|
||||
|
||||
private final GnssAntennaInfoProviderNative mNative;
|
||||
|
||||
private boolean mIsListeningStarted;
|
||||
|
||||
protected GnssAntennaInfoProvider(Context context, Handler handler) {
|
||||
this(context, handler, new GnssAntennaInfoProviderNative());
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public GnssAntennaInfoProvider(
|
||||
Context context, Handler handler, GnssAntennaInfoProviderNative aNative) {
|
||||
super(context, handler, TAG);
|
||||
mNative = aNative;
|
||||
}
|
||||
|
||||
void resumeIfStarted() {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "resumeIfStarted");
|
||||
}
|
||||
if (mIsListeningStarted) {
|
||||
mNative.startAntennaInfoListening();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isAvailableInPlatform() {
|
||||
return mNative.isAntennaInfoSupported();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int registerWithService() {
|
||||
boolean started = mNative.startAntennaInfoListening();
|
||||
if (started) {
|
||||
mIsListeningStarted = true;
|
||||
return RemoteListenerHelper.RESULT_SUCCESS;
|
||||
}
|
||||
return RemoteListenerHelper.RESULT_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void unregisterFromService() {
|
||||
boolean stopped = mNative.stopAntennaInfoListening();
|
||||
if (stopped) {
|
||||
mIsListeningStarted = false;
|
||||
}
|
||||
}
|
||||
|
||||
/** Handle GNSS capabilities update from the GNSS HAL implementation. */
|
||||
public void onCapabilitiesUpdated(boolean isAntennaInfoSupported) {
|
||||
setSupported(isAntennaInfoSupported);
|
||||
updateResult();
|
||||
}
|
||||
|
||||
/** Handle GNSS enabled changes.*/
|
||||
public void onGpsEnabledChanged() {
|
||||
tryUpdateRegistrationWithService();
|
||||
updateResult();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ListenerOperation<IGnssAntennaInfoListener> getHandlerOperation(int result) {
|
||||
int status;
|
||||
switch (result) {
|
||||
case RESULT_SUCCESS:
|
||||
status = GnssAntennaInfo.Callback.STATUS_READY;
|
||||
break;
|
||||
case RESULT_NOT_AVAILABLE:
|
||||
case RESULT_NOT_SUPPORTED:
|
||||
case RESULT_INTERNAL_ERROR:
|
||||
status = GnssAntennaInfo.Callback.STATUS_NOT_SUPPORTED;
|
||||
break;
|
||||
case RESULT_GPS_LOCATION_DISABLED:
|
||||
status = GnssAntennaInfo.Callback.STATUS_LOCATION_DISABLED;
|
||||
break;
|
||||
case RESULT_UNKNOWN:
|
||||
return null;
|
||||
default:
|
||||
Log.v(TAG, "Unhandled addListener result: " + result);
|
||||
return null;
|
||||
}
|
||||
return new StatusChangedOperation(status);
|
||||
}
|
||||
|
||||
private static class StatusChangedOperation
|
||||
implements ListenerOperation<IGnssAntennaInfoListener> {
|
||||
private final int mStatus;
|
||||
|
||||
StatusChangedOperation(int status) {
|
||||
mStatus = status;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(IGnssAntennaInfoListener listener,
|
||||
CallerIdentity callerIdentity) throws RemoteException {
|
||||
listener.onStatusChanged(mStatus);
|
||||
}
|
||||
}
|
||||
|
||||
/** Handle Gnss Antenna Info report. */
|
||||
public void onGnssAntennaInfoAvailable(final List<GnssAntennaInfo> gnssAntennaInfos) {
|
||||
foreach((IGnssAntennaInfoListener listener, CallerIdentity callerIdentity) -> {
|
||||
if (!hasPermission(mContext, callerIdentity)) {
|
||||
logPermissionDisabledEventNotReported(
|
||||
TAG, callerIdentity.mPackageName, "GNSS antenna info");
|
||||
return;
|
||||
}
|
||||
listener.onGnssAntennaInfoReceived(gnssAntennaInfos);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper class for native methods. This is mocked for testing.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
public static class GnssAntennaInfoProviderNative {
|
||||
|
||||
public boolean isAntennaInfoSupported() {
|
||||
return native_is_antenna_info_supported();
|
||||
}
|
||||
|
||||
/** Start antenna info listening. */
|
||||
public boolean startAntennaInfoListening() {
|
||||
return native_start_antenna_info_listening();
|
||||
}
|
||||
|
||||
/** Stop antenna info listening. */
|
||||
public boolean stopAntennaInfoListening() {
|
||||
return native_stop_antenna_info_listening();
|
||||
}
|
||||
}
|
||||
|
||||
private static native boolean native_is_antenna_info_supported();
|
||||
|
||||
private static native boolean native_start_antenna_info_listening();
|
||||
|
||||
private static native boolean native_stop_antenna_info_listening();
|
||||
}
|
||||
@@ -77,6 +77,9 @@ public class GnssCapabilitiesProvider {
|
||||
if (hasCapability(topHalCapabilities, GnssLocationProvider.GPS_CAPABILITY_NAV_MESSAGES)) {
|
||||
gnssCapabilities |= GnssCapabilities.NAV_MESSAGES;
|
||||
}
|
||||
if (hasCapability(topHalCapabilities, GnssLocationProvider.GPS_CAPABILITY_ANTENNA_INFO)) {
|
||||
gnssCapabilities |= GnssCapabilities.ANTENNA_INFO;
|
||||
}
|
||||
|
||||
synchronized (this) {
|
||||
mGnssCapabilities &= ~GNSS_CAPABILITIES_TOP_HAL;
|
||||
|
||||
@@ -29,6 +29,7 @@ import android.hardware.location.GeofenceHardware;
|
||||
import android.hardware.location.GeofenceHardwareImpl;
|
||||
import android.location.Criteria;
|
||||
import android.location.FusedBatchOptions;
|
||||
import android.location.GnssAntennaInfo;
|
||||
import android.location.GnssMeasurementsEvent;
|
||||
import android.location.GnssNavigationMessage;
|
||||
import android.location.GnssStatus;
|
||||
@@ -182,6 +183,7 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
|
||||
public static final int GPS_CAPABILITY_LOW_POWER_MODE = 0x0000100;
|
||||
public static final int GPS_CAPABILITY_SATELLITE_BLACKLIST = 0x0000200;
|
||||
public static final int GPS_CAPABILITY_MEASUREMENT_CORRECTIONS = 0x0000400;
|
||||
public static final int GPS_CAPABILITY_ANTENNA_INFO = 0x0000800;
|
||||
|
||||
// The AGPS SUPL mode
|
||||
private static final int AGPS_SUPL_MODE_MSA = 0x02;
|
||||
@@ -397,6 +399,7 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
|
||||
private final GnssStatusListenerHelper mGnssStatusListenerHelper;
|
||||
private final GnssMeasurementsProvider mGnssMeasurementsProvider;
|
||||
private final GnssMeasurementCorrectionsProvider mGnssMeasurementCorrectionsProvider;
|
||||
private final GnssAntennaInfoProvider mGnssAntennaInfoProvider;
|
||||
private final GnssNavigationMessageProvider mGnssNavigationMessageProvider;
|
||||
private final LocationChangeListener mNetworkLocationListener = new NetworkLocationListener();
|
||||
private final LocationChangeListener mFusedLocationListener = new FusedLocationListener();
|
||||
@@ -469,6 +472,10 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
|
||||
return mGnssMeasurementCorrectionsProvider;
|
||||
}
|
||||
|
||||
public GnssAntennaInfoProvider getGnssAntennaInfoProvider() {
|
||||
return mGnssAntennaInfoProvider;
|
||||
}
|
||||
|
||||
public GnssNavigationMessageProvider getGnssNavigationMessageProvider() {
|
||||
return mGnssNavigationMessageProvider;
|
||||
}
|
||||
@@ -693,6 +700,13 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
|
||||
|
||||
mGnssMeasurementCorrectionsProvider = new GnssMeasurementCorrectionsProvider(mHandler);
|
||||
|
||||
mGnssAntennaInfoProvider = new GnssAntennaInfoProvider(mContext, mHandler) {
|
||||
@Override
|
||||
protected boolean isGpsEnabled() {
|
||||
return GnssLocationProvider.this.isGpsEnabled();
|
||||
}
|
||||
};
|
||||
|
||||
mGnssNavigationMessageProvider = new GnssNavigationMessageProvider(mContext, mHandler) {
|
||||
@Override
|
||||
protected boolean isGpsEnabled() {
|
||||
@@ -992,6 +1006,7 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
|
||||
|
||||
mGnssMeasurementsProvider.onGpsEnabledChanged();
|
||||
mGnssNavigationMessageProvider.onGpsEnabledChanged();
|
||||
mGnssAntennaInfoProvider.onGpsEnabledChanged();
|
||||
mGnssBatchingProvider.enable();
|
||||
if (mGnssVisibilityControl != null) {
|
||||
mGnssVisibilityControl.onGpsEnabledChanged(/* isEnabled= */ true);
|
||||
@@ -1018,6 +1033,7 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
|
||||
// do this before releasing wakelock
|
||||
native_cleanup();
|
||||
|
||||
mGnssAntennaInfoProvider.onGpsEnabledChanged();
|
||||
mGnssMeasurementsProvider.onGpsEnabledChanged();
|
||||
mGnssNavigationMessageProvider.onGpsEnabledChanged();
|
||||
}
|
||||
@@ -1562,6 +1578,11 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
|
||||
}
|
||||
}
|
||||
|
||||
@NativeEntryPoint
|
||||
private void reportAntennaInfo(List<GnssAntennaInfo> antennaInfos) {
|
||||
mHandler.post(() -> mGnssAntennaInfoProvider.onGnssAntennaInfoAvailable(antennaInfos));
|
||||
}
|
||||
|
||||
@NativeEntryPoint
|
||||
private void reportNavigationMessage(GnssNavigationMessage event) {
|
||||
if (!mItarSpeedLimitExceeded) {
|
||||
@@ -1585,6 +1606,8 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
|
||||
mGnssNavigationMessageProvider.onCapabilitiesUpdated(
|
||||
hasCapability(GPS_CAPABILITY_NAV_MESSAGES));
|
||||
restartRequests();
|
||||
mGnssAntennaInfoProvider.onCapabilitiesUpdated(
|
||||
hasCapability(GPS_CAPABILITY_ANTENNA_INFO));
|
||||
|
||||
mGnssCapabilitiesProvider.setTopHalCapabilities(mTopHalCapabilities);
|
||||
});
|
||||
@@ -1606,6 +1629,7 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
|
||||
Log.i(TAG, "restartRequests");
|
||||
|
||||
restartLocationRequest();
|
||||
mGnssAntennaInfoProvider.resumeIfStarted();
|
||||
mGnssMeasurementsProvider.resumeIfStarted();
|
||||
mGnssNavigationMessageProvider.resumeIfStarted();
|
||||
mGnssBatchingProvider.resumeIfStarted();
|
||||
@@ -2198,6 +2222,8 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
|
||||
s.append(" ago)").append('\n');
|
||||
s.append("mFixInterval=").append(mFixInterval).append('\n');
|
||||
s.append("mLowPowerMode=").append(mLowPowerMode).append('\n');
|
||||
s.append("mGnssAntennaInfoProvider.isRegistered()=")
|
||||
.append(mGnssAntennaInfoProvider.isRegistered()).append('\n');
|
||||
s.append("mGnssMeasurementsProvider.isRegistered()=")
|
||||
.append(mGnssMeasurementsProvider.isRegistered()).append('\n');
|
||||
s.append("mGnssNavigationMessageProvider.isRegistered()=")
|
||||
|
||||
@@ -26,6 +26,7 @@ import android.content.Context;
|
||||
import android.location.GnssCapabilities;
|
||||
import android.location.GnssMeasurementCorrections;
|
||||
import android.location.IBatchedLocationCallback;
|
||||
import android.location.IGnssAntennaInfoListener;
|
||||
import android.location.IGnssMeasurementsListener;
|
||||
import android.location.IGnssNavigationMessageListener;
|
||||
import android.location.IGnssStatusListener;
|
||||
@@ -51,6 +52,7 @@ import com.android.server.LocationManagerServiceUtils.LinkedListener;
|
||||
import com.android.server.LocationManagerServiceUtils.LinkedListenerBase;
|
||||
import com.android.server.location.AppForegroundHelper;
|
||||
import com.android.server.location.CallerIdentity;
|
||||
import com.android.server.location.GnssAntennaInfoProvider;
|
||||
import com.android.server.location.GnssBatchingProvider;
|
||||
import com.android.server.location.GnssCapabilitiesProvider;
|
||||
import com.android.server.location.GnssLocationProvider;
|
||||
@@ -87,6 +89,7 @@ public class GnssManagerService {
|
||||
private final GnssStatusListenerHelper mGnssStatusProvider;
|
||||
private final GnssMeasurementsProvider mGnssMeasurementsProvider;
|
||||
private final GnssMeasurementCorrectionsProvider mGnssMeasurementCorrectionsProvider;
|
||||
private final GnssAntennaInfoProvider mGnssAntennaInfoProvider;
|
||||
private final GnssNavigationMessageProvider mGnssNavigationMessageProvider;
|
||||
private final GnssLocationProvider.GnssSystemInfoProvider mGnssSystemInfoProvider;
|
||||
private final GnssLocationProvider.GnssMetricsProvider mGnssMetricsProvider;
|
||||
@@ -99,6 +102,11 @@ public class GnssManagerService {
|
||||
private final ArrayMap<IBinder, LinkedListener<IGnssMeasurementsListener>>
|
||||
mGnssMeasurementsListeners = new ArrayMap<>();
|
||||
|
||||
@GuardedBy("mGnssAntennaInfoListeners")
|
||||
private final ArrayMap<IBinder,
|
||||
LinkedListener<IGnssAntennaInfoListener>>
|
||||
mGnssAntennaInfoListeners = new ArrayMap<>();
|
||||
|
||||
@GuardedBy("mGnssNavigationMessageListeners")
|
||||
private final ArrayMap<IBinder, LinkedListener<IGnssNavigationMessageListener>>
|
||||
mGnssNavigationMessageListeners = new ArrayMap<>();
|
||||
@@ -147,6 +155,7 @@ public class GnssManagerService {
|
||||
mGnssLocationProvider = gnssLocationProvider;
|
||||
mGnssStatusProvider = mGnssLocationProvider.getGnssStatusProvider();
|
||||
mGnssMeasurementsProvider = mGnssLocationProvider.getGnssMeasurementsProvider();
|
||||
mGnssAntennaInfoProvider = mGnssLocationProvider.getGnssAntennaInfoProvider();
|
||||
mGnssMeasurementCorrectionsProvider =
|
||||
mGnssLocationProvider.getGnssMeasurementCorrectionsProvider();
|
||||
mGnssNavigationMessageProvider = mGnssLocationProvider.getGnssNavigationMessageProvider();
|
||||
@@ -354,6 +363,14 @@ public class GnssManagerService {
|
||||
uid,
|
||||
foreground);
|
||||
}
|
||||
synchronized (mGnssAntennaInfoListeners) {
|
||||
updateListenersOnForegroundChangedLocked(
|
||||
mGnssAntennaInfoListeners,
|
||||
mGnssAntennaInfoProvider,
|
||||
IGnssAntennaInfoListener.Stub::asInterface,
|
||||
uid,
|
||||
foreground);
|
||||
}
|
||||
}
|
||||
|
||||
private <TListener extends IInterface> void updateListenersOnForegroundChangedLocked(
|
||||
@@ -530,6 +547,40 @@ public class GnssManagerService {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a GNSS Antenna Info listener.
|
||||
*
|
||||
* @param listener called when GNSS antenna info is received
|
||||
* @param packageName name of requesting package
|
||||
* @return true if listener is successfully added, false otherwise
|
||||
*/
|
||||
public boolean addGnssAntennaInfoListener(
|
||||
IGnssAntennaInfoListener listener, String packageName,
|
||||
@Nullable String featureId, @NonNull String listenerIdentifier) {
|
||||
synchronized (mGnssAntennaInfoListeners) {
|
||||
return addGnssDataListenerLocked(
|
||||
listener,
|
||||
packageName,
|
||||
featureId,
|
||||
listenerIdentifier,
|
||||
mGnssAntennaInfoProvider,
|
||||
mGnssAntennaInfoListeners,
|
||||
this::removeGnssAntennaInfoListener);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a GNSS Antenna Info listener.
|
||||
*
|
||||
* @param listener called when GNSS antenna info is received
|
||||
*/
|
||||
public void removeGnssAntennaInfoListener(IGnssAntennaInfoListener listener) {
|
||||
synchronized (mGnssAntennaInfoListeners) {
|
||||
removeGnssDataListenerLocked(
|
||||
listener, mGnssAntennaInfoProvider, mGnssAntennaInfoListeners);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a GNSS navigation message listener.
|
||||
*/
|
||||
|
||||
@@ -26,17 +26,18 @@
|
||||
#include <android/hardware/gnss/1.0/IGnssMeasurement.h>
|
||||
#include <android/hardware/gnss/1.1/IGnssMeasurement.h>
|
||||
#include <android/hardware/gnss/2.0/IGnssMeasurement.h>
|
||||
#include <android/hardware/gnss/2.1/IGnssAntennaInfo.h>
|
||||
#include <android/hardware/gnss/2.1/IGnssMeasurement.h>
|
||||
#include <android/hardware/gnss/measurement_corrections/1.0/IMeasurementCorrections.h>
|
||||
#include <android/hardware/gnss/measurement_corrections/1.1/IMeasurementCorrections.h>
|
||||
#include <android/hardware/gnss/visibility_control/1.0/IGnssVisibilityControl.h>
|
||||
#include <nativehelper/JNIHelp.h>
|
||||
#include "jni.h"
|
||||
#include "hardware_legacy/power.h"
|
||||
#include "utils/Log.h"
|
||||
#include "utils/misc.h"
|
||||
#include "android_runtime/AndroidRuntime.h"
|
||||
#include "android_runtime/Log.h"
|
||||
#include "hardware_legacy/power.h"
|
||||
#include "jni.h"
|
||||
#include "utils/Log.h"
|
||||
#include "utils/misc.h"
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <cinttypes>
|
||||
@@ -54,6 +55,12 @@ static jclass class_location;
|
||||
static jclass class_gnssNavigationMessage;
|
||||
static jclass class_gnssClock;
|
||||
static jclass class_gnssConfiguration_halInterfaceVersion;
|
||||
static jclass class_gnssAntennaInfo;
|
||||
static jclass class_phaseCenterOffsetCoordinates;
|
||||
static jclass class_phaseCenterVariationCorrections;
|
||||
static jclass class_signalGainCorrections;
|
||||
static jclass class_arrayList;
|
||||
static jclass class_doubleArray;
|
||||
|
||||
static jobject mCallbacksObj = nullptr;
|
||||
|
||||
@@ -78,6 +85,7 @@ static jmethodID method_reportGeofenceRemoveStatus;
|
||||
static jmethodID method_reportGeofencePauseStatus;
|
||||
static jmethodID method_reportGeofenceResumeStatus;
|
||||
static jmethodID method_reportMeasurementData;
|
||||
static jmethodID method_reportAntennaInfo;
|
||||
static jmethodID method_reportNavigationMessages;
|
||||
static jmethodID method_reportLocationBatch;
|
||||
static jmethodID method_reportGnssServiceDied;
|
||||
@@ -114,6 +122,12 @@ static jmethodID method_gnssNavigationMessageCtor;
|
||||
static jmethodID method_gnssClockCtor;
|
||||
static jmethodID method_gnssMeasurementCtor;
|
||||
static jmethodID method_halInterfaceVersionCtor;
|
||||
static jmethodID method_gnssAntennaInfoCtor;
|
||||
static jmethodID method_phaseCenterOffsetCoordinatesCtor;
|
||||
static jmethodID method_phaseCenterVariationCorrectionsCtor;
|
||||
static jmethodID method_signalGainCorrectionsCtor;
|
||||
static jmethodID method_arrayListCtor;
|
||||
static jmethodID method_arrayListAdd;
|
||||
|
||||
/*
|
||||
* Save a pointer to JavaVm to attach/detach threads executing
|
||||
@@ -171,6 +185,8 @@ using IGnssConfiguration_V2_0 = android::hardware::gnss::V2_0::IGnssConfiguratio
|
||||
using IGnssConfiguration_V2_1 = android::hardware::gnss::V2_1::IGnssConfiguration;
|
||||
using IGnssDebug_V1_0 = android::hardware::gnss::V1_0::IGnssDebug;
|
||||
using IGnssDebug_V2_0 = android::hardware::gnss::V2_0::IGnssDebug;
|
||||
using IGnssAntennaInfo = android::hardware::gnss::V2_1::IGnssAntennaInfo;
|
||||
using IGnssAntennaInfoCallback = android::hardware::gnss::V2_1::IGnssAntennaInfoCallback;
|
||||
using IGnssMeasurement_V1_0 = android::hardware::gnss::V1_0::IGnssMeasurement;
|
||||
using IGnssMeasurement_V1_1 = android::hardware::gnss::V1_1::IGnssMeasurement;
|
||||
using IGnssMeasurement_V2_0 = android::hardware::gnss::V2_0::IGnssMeasurement;
|
||||
@@ -241,6 +257,7 @@ sp<IGnssNavigationMessage> gnssNavigationMessageIface = nullptr;
|
||||
sp<IMeasurementCorrections_V1_0> gnssCorrectionsIface_V1_0 = nullptr;
|
||||
sp<IMeasurementCorrections_V1_1> gnssCorrectionsIface_V1_1 = nullptr;
|
||||
sp<IGnssVisibilityControl> gnssVisibilityControlIface = nullptr;
|
||||
sp<IGnssAntennaInfo> gnssAntennaInfoIface = nullptr;
|
||||
|
||||
#define WAKE_LOCK_NAME "GPS"
|
||||
|
||||
@@ -1050,6 +1067,195 @@ Return<void> GnssNavigationMessageCallback::gnssNavigationMessageCb(
|
||||
return Void();
|
||||
}
|
||||
|
||||
/*
|
||||
* GnssAntennaInfoCallback implements the callback methods required for the
|
||||
* GnssAntennaInfo interface.
|
||||
*/
|
||||
struct GnssAntennaInfoCallback : public IGnssAntennaInfoCallback {
|
||||
// Methods from V2_1::GnssAntennaInfoCallback follow.
|
||||
Return<void> gnssAntennaInfoCb(
|
||||
const hidl_vec<IGnssAntennaInfoCallback::GnssAntennaInfo>& gnssAntennaInfos);
|
||||
|
||||
private:
|
||||
jobject translateAllGnssAntennaInfos(
|
||||
JNIEnv* env,
|
||||
const hidl_vec<IGnssAntennaInfoCallback::GnssAntennaInfo>& gnssAntennaInfos);
|
||||
jobject translateSingleGnssAntennaInfo(
|
||||
JNIEnv* env, const IGnssAntennaInfoCallback::GnssAntennaInfo& gnssAntennaInfo);
|
||||
jobject translatePhaseCenterOffsetCoordinates(
|
||||
JNIEnv* env, const IGnssAntennaInfoCallback::GnssAntennaInfo& gnssAntennaInfo);
|
||||
jobject translatePhaseCenterVariationCorrections(
|
||||
JNIEnv* env, const IGnssAntennaInfoCallback::GnssAntennaInfo& gnssAntennaInfo);
|
||||
jobject translateSignalGainCorrections(
|
||||
JNIEnv* env, const IGnssAntennaInfoCallback::GnssAntennaInfo& gnssAntennaInfo);
|
||||
jobjectArray translate2dDoubleArray(JNIEnv* env,
|
||||
const hidl_vec<IGnssAntennaInfoCallback::Row>& array);
|
||||
void translateAndReportGnssAntennaInfo(
|
||||
const hidl_vec<IGnssAntennaInfoCallback::GnssAntennaInfo>& gnssAntennaInfos);
|
||||
void reportAntennaInfo(JNIEnv* env, const jobject antennaInfosArray);
|
||||
};
|
||||
|
||||
Return<void> GnssAntennaInfoCallback::gnssAntennaInfoCb(
|
||||
const hidl_vec<IGnssAntennaInfoCallback::GnssAntennaInfo>& gnssAntennaInfos) {
|
||||
translateAndReportGnssAntennaInfo(gnssAntennaInfos);
|
||||
return Void();
|
||||
}
|
||||
|
||||
jobjectArray GnssAntennaInfoCallback::translate2dDoubleArray(
|
||||
JNIEnv* env, const hidl_vec<IGnssAntennaInfoCallback::Row>& array) {
|
||||
jsize numRows = array.size();
|
||||
if (numRows == 0) {
|
||||
// Empty array
|
||||
return NULL;
|
||||
}
|
||||
jsize numCols = array[0].row.size();
|
||||
if (numCols <= 1) {
|
||||
// phi angle separation is computed as 180.0 / (numColumns - 1), so can't be < 2.
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Allocate array of double arrays
|
||||
jobjectArray returnArray = env->NewObjectArray(numRows, class_doubleArray, NULL);
|
||||
|
||||
// Create each double array
|
||||
for (uint8_t i = 0; i < numRows; i++) {
|
||||
jdoubleArray doubleArray = env->NewDoubleArray(numCols);
|
||||
env->SetDoubleArrayRegion(doubleArray, (jsize)0, numCols, array[i].row.data());
|
||||
env->SetObjectArrayElement(returnArray, (jsize)i, doubleArray);
|
||||
env->DeleteLocalRef(doubleArray);
|
||||
}
|
||||
return returnArray;
|
||||
}
|
||||
|
||||
jobject GnssAntennaInfoCallback::translateAllGnssAntennaInfos(
|
||||
JNIEnv* env, const hidl_vec<IGnssAntennaInfoCallback::GnssAntennaInfo>& gnssAntennaInfos) {
|
||||
jobject arrayList = env->NewObject(class_arrayList,
|
||||
method_arrayListCtor); // Create new ArrayList instance
|
||||
|
||||
for (auto gnssAntennaInfo : gnssAntennaInfos) {
|
||||
jobject gnssAntennaInfoObject = translateSingleGnssAntennaInfo(env, gnssAntennaInfo);
|
||||
|
||||
env->CallBooleanMethod(arrayList, method_arrayListAdd,
|
||||
gnssAntennaInfoObject); // Add the antennaInfo to the ArrayList
|
||||
|
||||
// Delete Local Refs
|
||||
env->DeleteLocalRef(gnssAntennaInfoObject);
|
||||
}
|
||||
return arrayList;
|
||||
}
|
||||
|
||||
jobject GnssAntennaInfoCallback::translatePhaseCenterOffsetCoordinates(
|
||||
JNIEnv* env, const IGnssAntennaInfoCallback::GnssAntennaInfo& gnssAntennaInfo) {
|
||||
jobject phaseCenterOffsetCoordinates =
|
||||
env->NewObject(class_phaseCenterOffsetCoordinates,
|
||||
method_phaseCenterOffsetCoordinatesCtor,
|
||||
gnssAntennaInfo.phaseCenterOffsetCoordinateMillimeters.x,
|
||||
gnssAntennaInfo.phaseCenterOffsetCoordinateMillimeters.xUncertainty,
|
||||
gnssAntennaInfo.phaseCenterOffsetCoordinateMillimeters.y,
|
||||
gnssAntennaInfo.phaseCenterOffsetCoordinateMillimeters.yUncertainty,
|
||||
gnssAntennaInfo.phaseCenterOffsetCoordinateMillimeters.z,
|
||||
gnssAntennaInfo.phaseCenterOffsetCoordinateMillimeters.zUncertainty);
|
||||
|
||||
return phaseCenterOffsetCoordinates;
|
||||
}
|
||||
|
||||
jobject GnssAntennaInfoCallback::translatePhaseCenterVariationCorrections(
|
||||
JNIEnv* env, const IGnssAntennaInfoCallback::GnssAntennaInfo& gnssAntennaInfo) {
|
||||
if (gnssAntennaInfo.phaseCenterVariationCorrectionMillimeters == NULL ||
|
||||
gnssAntennaInfo.phaseCenterVariationCorrectionUncertaintyMillimeters == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
jobjectArray phaseCenterVariationCorrectionsArray =
|
||||
translate2dDoubleArray(env, gnssAntennaInfo.phaseCenterVariationCorrectionMillimeters);
|
||||
jobjectArray phaseCenterVariationCorrectionsUncertaintiesArray =
|
||||
translate2dDoubleArray(env,
|
||||
gnssAntennaInfo
|
||||
.phaseCenterVariationCorrectionUncertaintyMillimeters);
|
||||
|
||||
if (phaseCenterVariationCorrectionsArray == NULL ||
|
||||
phaseCenterVariationCorrectionsUncertaintiesArray == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
jobject phaseCenterVariationCorrections =
|
||||
env->NewObject(class_phaseCenterVariationCorrections,
|
||||
method_phaseCenterVariationCorrectionsCtor,
|
||||
phaseCenterVariationCorrectionsArray,
|
||||
phaseCenterVariationCorrectionsUncertaintiesArray);
|
||||
|
||||
env->DeleteLocalRef(phaseCenterVariationCorrectionsArray);
|
||||
env->DeleteLocalRef(phaseCenterVariationCorrectionsUncertaintiesArray);
|
||||
|
||||
return phaseCenterVariationCorrections;
|
||||
}
|
||||
|
||||
jobject GnssAntennaInfoCallback::translateSignalGainCorrections(
|
||||
JNIEnv* env, const IGnssAntennaInfoCallback::GnssAntennaInfo& gnssAntennaInfo) {
|
||||
if (gnssAntennaInfo.signalGainCorrectionDbi == NULL ||
|
||||
gnssAntennaInfo.signalGainCorrectionUncertaintyDbi == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
jobjectArray signalGainCorrectionsArray =
|
||||
translate2dDoubleArray(env, gnssAntennaInfo.signalGainCorrectionDbi);
|
||||
jobjectArray signalGainCorrectionsUncertaintiesArray =
|
||||
translate2dDoubleArray(env, gnssAntennaInfo.signalGainCorrectionUncertaintyDbi);
|
||||
|
||||
if (signalGainCorrectionsArray == NULL || signalGainCorrectionsUncertaintiesArray == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
jobject signalGainCorrections =
|
||||
env->NewObject(class_signalGainCorrections, method_signalGainCorrectionsCtor,
|
||||
signalGainCorrectionsArray, signalGainCorrectionsUncertaintiesArray);
|
||||
|
||||
env->DeleteLocalRef(signalGainCorrectionsArray);
|
||||
env->DeleteLocalRef(signalGainCorrectionsUncertaintiesArray);
|
||||
|
||||
return signalGainCorrections;
|
||||
}
|
||||
|
||||
jobject GnssAntennaInfoCallback::translateSingleGnssAntennaInfo(
|
||||
JNIEnv* env, const IGnssAntennaInfoCallback::GnssAntennaInfo& gnssAntennaInfo) {
|
||||
jobject phaseCenterOffsetCoordinates =
|
||||
translatePhaseCenterOffsetCoordinates(env, gnssAntennaInfo);
|
||||
|
||||
// Nullable
|
||||
jobject phaseCenterVariationCorrections =
|
||||
translatePhaseCenterVariationCorrections(env, gnssAntennaInfo);
|
||||
|
||||
// Nullable
|
||||
jobject signalGainCorrections = translateSignalGainCorrections(env, gnssAntennaInfo);
|
||||
|
||||
jobject gnssAntennaInfoObject =
|
||||
env->NewObject(class_gnssAntennaInfo, method_gnssAntennaInfoCtor,
|
||||
gnssAntennaInfo.carrierFrequencyMHz, phaseCenterOffsetCoordinates,
|
||||
phaseCenterVariationCorrections, signalGainCorrections);
|
||||
|
||||
// Delete Local Refs
|
||||
env->DeleteLocalRef(phaseCenterOffsetCoordinates);
|
||||
env->DeleteLocalRef(phaseCenterVariationCorrections);
|
||||
env->DeleteLocalRef(signalGainCorrections);
|
||||
|
||||
return gnssAntennaInfoObject;
|
||||
}
|
||||
|
||||
void GnssAntennaInfoCallback::translateAndReportGnssAntennaInfo(
|
||||
const hidl_vec<IGnssAntennaInfoCallback::GnssAntennaInfo>& gnssAntennaInfos) {
|
||||
JNIEnv* env = getJniEnv();
|
||||
|
||||
jobject arrayList = translateAllGnssAntennaInfos(env, gnssAntennaInfos);
|
||||
|
||||
reportAntennaInfo(env, arrayList);
|
||||
|
||||
env->DeleteLocalRef(arrayList);
|
||||
}
|
||||
|
||||
void GnssAntennaInfoCallback::reportAntennaInfo(JNIEnv* env, const jobject antennaInfosArray) {
|
||||
env->CallVoidMethod(mCallbacksObj, method_reportAntennaInfo, antennaInfosArray);
|
||||
checkAndClearExceptionFromCallback(env, __FUNCTION__);
|
||||
}
|
||||
|
||||
/*
|
||||
* GnssMeasurementCallback implements the callback methods required for the
|
||||
* GnssMeasurement interface.
|
||||
@@ -1708,6 +1914,7 @@ static void android_location_GnssLocationProvider_class_init_native(JNIEnv* env,
|
||||
"(II)V");
|
||||
method_reportGeofencePauseStatus = env->GetMethodID(clazz, "reportGeofencePauseStatus",
|
||||
"(II)V");
|
||||
method_reportAntennaInfo = env->GetMethodID(clazz, "reportAntennaInfo", "(Ljava/util/List;)V");
|
||||
method_reportMeasurementData = env->GetMethodID(
|
||||
clazz,
|
||||
"reportMeasurementData",
|
||||
@@ -1791,6 +1998,36 @@ static void android_location_GnssLocationProvider_class_init_native(JNIEnv* env,
|
||||
class_gnssMeasurement = (jclass) env->NewGlobalRef(gnssMeasurementClass);
|
||||
method_gnssMeasurementCtor = env->GetMethodID(class_gnssMeasurement, "<init>", "()V");
|
||||
|
||||
jclass gnssAntennaInfoClass = env->FindClass("android/location/GnssAntennaInfo");
|
||||
class_gnssAntennaInfo = (jclass)env->NewGlobalRef(gnssAntennaInfoClass);
|
||||
method_gnssAntennaInfoCtor =
|
||||
env->GetMethodID(class_gnssAntennaInfo, "<init>",
|
||||
"(D"
|
||||
"Landroid/location/GnssAntennaInfo$PhaseCenterOffsetCoordinates;"
|
||||
"Landroid/location/GnssAntennaInfo$PhaseCenterVariationCorrections;"
|
||||
"Landroid/location/GnssAntennaInfo$SignalGainCorrections;"
|
||||
")V");
|
||||
|
||||
jclass phaseCenterOffsetCoordinatesClass =
|
||||
env->FindClass("android/location/GnssAntennaInfo$PhaseCenterOffsetCoordinates");
|
||||
class_phaseCenterOffsetCoordinates =
|
||||
(jclass)env->NewGlobalRef(phaseCenterOffsetCoordinatesClass);
|
||||
method_phaseCenterOffsetCoordinatesCtor =
|
||||
env->GetMethodID(class_phaseCenterOffsetCoordinates, "<init>", "(DDDDDD)V");
|
||||
|
||||
jclass phaseCenterVariationCorrectionsClass =
|
||||
env->FindClass("android/location/GnssAntennaInfo$PhaseCenterVariationCorrections");
|
||||
class_phaseCenterVariationCorrections =
|
||||
(jclass)env->NewGlobalRef(phaseCenterVariationCorrectionsClass);
|
||||
method_phaseCenterVariationCorrectionsCtor =
|
||||
env->GetMethodID(class_phaseCenterVariationCorrections, "<init>", "([[D[[D)V");
|
||||
|
||||
jclass signalGainCorrectionsClass =
|
||||
env->FindClass("android/location/GnssAntennaInfo$SignalGainCorrections");
|
||||
class_signalGainCorrections = (jclass)env->NewGlobalRef(signalGainCorrectionsClass);
|
||||
method_signalGainCorrectionsCtor =
|
||||
env->GetMethodID(class_signalGainCorrections, "<init>", "([[D[[D)V");
|
||||
|
||||
jclass locationClass = env->FindClass("android/location/Location");
|
||||
class_location = (jclass) env->NewGlobalRef(locationClass);
|
||||
method_locationCtor = env->GetMethodID(class_location, "<init>", "(Ljava/lang/String;)V");
|
||||
@@ -1809,6 +2046,14 @@ static void android_location_GnssLocationProvider_class_init_native(JNIEnv* env,
|
||||
(jclass) env->NewGlobalRef(gnssConfiguration_halInterfaceVersionClass);
|
||||
method_halInterfaceVersionCtor =
|
||||
env->GetMethodID(class_gnssConfiguration_halInterfaceVersion, "<init>", "(II)V");
|
||||
|
||||
jclass arrayListClass = env->FindClass("java/util/ArrayList");
|
||||
class_arrayList = (jclass)env->NewGlobalRef(arrayListClass);
|
||||
method_arrayListCtor = env->GetMethodID(class_arrayList, "<init>", "()V");
|
||||
method_arrayListAdd = env->GetMethodID(class_arrayList, "add", "(Ljava/lang/Object;)Z");
|
||||
|
||||
jclass doubleArrayClass = env->FindClass("[D");
|
||||
class_doubleArray = (jclass)env->NewGlobalRef(doubleArrayClass);
|
||||
}
|
||||
|
||||
/* Initialization needed at system boot and whenever GNSS service dies. */
|
||||
@@ -1934,6 +2179,15 @@ static void android_location_GnssLocationProvider_init_once(JNIEnv* env, jclass
|
||||
}
|
||||
}
|
||||
|
||||
if (gnssHal_V2_1 != nullptr) {
|
||||
auto gnssAntennaInfo = gnssHal_V2_1->getExtensionGnssAntennaInfo();
|
||||
if (!gnssAntennaInfo.isOk()) {
|
||||
ALOGD("Unable to get a handle to GnssAntennaInfo");
|
||||
} else {
|
||||
gnssAntennaInfoIface = gnssAntennaInfo;
|
||||
}
|
||||
}
|
||||
|
||||
if (gnssHal_V2_1 != nullptr) {
|
||||
auto gnssCorrections = gnssHal_V2_1->getExtensionMeasurementCorrections_1_1();
|
||||
if (!gnssCorrections.isOk()) {
|
||||
@@ -2725,6 +2979,52 @@ static jboolean android_location_GnssGeofenceProvider_resume_geofence(JNIEnv* /*
|
||||
return checkHidlReturn(result, "IGnssGeofencing resumeGeofence() failed.");
|
||||
}
|
||||
|
||||
static jboolean android_location_GnssAntennaInfoProvider_is_antenna_info_supported(JNIEnv* env,
|
||||
jclass clazz) {
|
||||
if (gnssAntennaInfoIface != nullptr) {
|
||||
return JNI_TRUE;
|
||||
}
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
static jboolean android_location_GnssAntennaInfoProvider_start_antenna_info_listening(
|
||||
JNIEnv* /* env */, jobject /* obj */) {
|
||||
if (gnssAntennaInfoIface == nullptr) {
|
||||
ALOGE("%s: IGnssAntennaInfo interface not available.", __func__);
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
sp<GnssAntennaInfoCallback> cbIface = new GnssAntennaInfoCallback();
|
||||
|
||||
auto result = gnssAntennaInfoIface->setCallback(cbIface);
|
||||
|
||||
if (!checkHidlReturn(result, "IGnssAntennaInfo setCallback() failed.")) {
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
IGnssAntennaInfo::GnssAntennaInfoStatus initRet = result;
|
||||
if (initRet != IGnssAntennaInfo::GnssAntennaInfoStatus::SUCCESS) {
|
||||
ALOGE("An error has been found on GnssAntennaInfoInterface::init, status=%d",
|
||||
static_cast<int32_t>(initRet));
|
||||
return JNI_FALSE;
|
||||
} else {
|
||||
ALOGD("gnss antenna info has been enabled");
|
||||
}
|
||||
|
||||
return JNI_TRUE;
|
||||
}
|
||||
|
||||
static jboolean android_location_GnssAntennaInfoProvider_stop_antenna_info_listening(
|
||||
JNIEnv* /* env */, jobject /* obj */) {
|
||||
if (gnssAntennaInfoIface == nullptr) {
|
||||
ALOGE("%s: IGnssAntennaInfo interface not available.", __func__);
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
auto result = gnssAntennaInfoIface->close();
|
||||
return checkHidlReturn(result, "IGnssAntennaInfo close() failed.");
|
||||
}
|
||||
|
||||
static jboolean android_location_GnssMeasurementsProvider_is_measurement_supported(
|
||||
JNIEnv* env, jclass clazz) {
|
||||
if (gnssMeasurementIface != nullptr) {
|
||||
@@ -3286,6 +3586,19 @@ static const JNINativeMethod sMethodsBatching[] = {
|
||||
reinterpret_cast<void *>(android_location_GnssBatchingProvider_cleanup_batching)},
|
||||
};
|
||||
|
||||
static const JNINativeMethod sAntennaInfoMethods[] = {
|
||||
/* name, signature, funcPtr */
|
||||
{"native_is_antenna_info_supported", "()Z",
|
||||
reinterpret_cast<void*>(
|
||||
android_location_GnssAntennaInfoProvider_is_antenna_info_supported)},
|
||||
{"native_start_antenna_info_listening", "()Z",
|
||||
reinterpret_cast<void*>(
|
||||
android_location_GnssAntennaInfoProvider_start_antenna_info_listening)},
|
||||
{"native_stop_antenna_info_listening", "()Z",
|
||||
reinterpret_cast<void*>(
|
||||
android_location_GnssAntennaInfoProvider_stop_antenna_info_listening)},
|
||||
};
|
||||
|
||||
static const JNINativeMethod sGeofenceMethods[] = {
|
||||
/* name, signature, funcPtr */
|
||||
{"native_is_geofence_supported",
|
||||
@@ -3407,6 +3720,8 @@ static const JNINativeMethod sVisibilityControlMethods[] = {
|
||||
};
|
||||
|
||||
int register_android_server_location_GnssLocationProvider(JNIEnv* env) {
|
||||
jniRegisterNativeMethods(env, "com/android/server/location/GnssAntennaInfoProvider",
|
||||
sAntennaInfoMethods, NELEM(sAntennaInfoMethods));
|
||||
jniRegisterNativeMethods(
|
||||
env,
|
||||
"com/android/server/location/GnssBatchingProvider",
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* 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 com.android.server.location;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.platform.test.annotations.Presubmit;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link GnssAntennaInfoProvider}.
|
||||
*/
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Presubmit
|
||||
public class GnssAntennaInfoProviderTest {
|
||||
@Mock
|
||||
private GnssAntennaInfoProvider.GnssAntennaInfoProviderNative mMockNative;
|
||||
private GnssAntennaInfoProvider mTestProvider;
|
||||
|
||||
/** Setup. */
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
when(mMockNative.startAntennaInfoListening()).thenReturn(true);
|
||||
when(mMockNative.stopAntennaInfoListening()).thenReturn(true);
|
||||
|
||||
mTestProvider = new GnssAntennaInfoProvider(RuntimeEnvironment.application,
|
||||
new Handler(Looper.myLooper()), mMockNative) {
|
||||
@Override
|
||||
public boolean isGpsEnabled() {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that registerWithService calls the native startAntennaInfoListening method.
|
||||
*/
|
||||
@Test
|
||||
public void register_nativeStarted() {
|
||||
mTestProvider.registerWithService();
|
||||
verify(mMockNative, times(1)).startAntennaInfoListening();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that unregisterFromService calls the native stopAntennaInfoListening method.
|
||||
*/
|
||||
@Test
|
||||
public void unregister_nativeStopped() {
|
||||
mTestProvider.registerWithService();
|
||||
mTestProvider.unregisterFromService();
|
||||
verify(mMockNative, times(1)).stopAntennaInfoListening();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that GnssAntennaInfoProvider.isAntennaInfoSupported() returns the result of the
|
||||
* native isAntennaInfoSupported method.
|
||||
*/
|
||||
@Test
|
||||
public void isSupported_nativeIsSupported() {
|
||||
when(mMockNative.isAntennaInfoSupported()).thenReturn(true);
|
||||
assertThat(mTestProvider.isAvailableInPlatform()).isTrue();
|
||||
|
||||
when(mMockNative.isAntennaInfoSupported()).thenReturn(false);
|
||||
assertThat(mTestProvider.isAvailableInPlatform()).isFalse();
|
||||
}
|
||||
}
|
||||
@@ -35,12 +35,14 @@ import android.Manifest;
|
||||
import android.app.AppOpsManager;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.location.GnssAntennaInfo;
|
||||
import android.location.GnssClock;
|
||||
import android.location.GnssMeasurementCorrections;
|
||||
import android.location.GnssMeasurementsEvent;
|
||||
import android.location.GnssNavigationMessage;
|
||||
import android.location.GnssSingleSatCorrection;
|
||||
import android.location.IBatchedLocationCallback;
|
||||
import android.location.IGnssAntennaInfoListener;
|
||||
import android.location.IGnssMeasurementsListener;
|
||||
import android.location.IGnssNavigationMessageListener;
|
||||
import android.location.IGnssStatusListener;
|
||||
@@ -55,6 +57,8 @@ import android.os.RemoteException;
|
||||
|
||||
import com.android.server.LocalServices;
|
||||
import com.android.server.location.AppForegroundHelper;
|
||||
import com.android.server.location.GnssAntennaInfoProvider;
|
||||
import com.android.server.location.GnssAntennaInfoProvider.GnssAntennaInfoProviderNative;
|
||||
import com.android.server.location.GnssBatchingProvider;
|
||||
import com.android.server.location.GnssCapabilitiesProvider;
|
||||
import com.android.server.location.GnssLocationProvider;
|
||||
@@ -101,6 +105,7 @@ public class GnssManagerServiceTest {
|
||||
private GnssMeasurementsProvider mTestGnssMeasurementsProvider;
|
||||
private GnssStatusListenerHelper mTestGnssStatusProvider;
|
||||
private GnssNavigationMessageProvider mTestGnssNavigationMessageProvider;
|
||||
private GnssAntennaInfoProvider mTestGnssAntennaInfoProvider;
|
||||
|
||||
// Managers and services
|
||||
@Mock
|
||||
@@ -151,6 +156,8 @@ public class GnssManagerServiceTest {
|
||||
mMockContext, mMockHandler);
|
||||
mTestGnssNavigationMessageProvider = createGnssNavigationMessageProvider(
|
||||
mMockContext, mMockHandler);
|
||||
mTestGnssAntennaInfoProvider = createGnssAntennaInfoProvider(
|
||||
mMockContext, mMockHandler);
|
||||
|
||||
// Setup GnssLocationProvider to return providers
|
||||
when(mMockGnssLocationProvider.getGnssStatusProvider()).thenReturn(
|
||||
@@ -169,6 +176,8 @@ public class GnssManagerServiceTest {
|
||||
mTestGnssNavigationMessageProvider);
|
||||
when(mMockGnssLocationProvider.getNetInitiatedListener()).thenReturn(
|
||||
mNetInitiatedListener);
|
||||
when(mMockGnssLocationProvider.getGnssAntennaInfoProvider()).thenReturn(
|
||||
mTestGnssAntennaInfoProvider);
|
||||
|
||||
// Setup GnssBatching provider
|
||||
when(mMockGnssBatchingProvider.start(anyLong(), anyBoolean())).thenReturn(true);
|
||||
@@ -204,6 +213,12 @@ public class GnssManagerServiceTest {
|
||||
return mockListener;
|
||||
}
|
||||
|
||||
private IGnssAntennaInfoListener createMockGnssAntennaInfoListener() {
|
||||
IGnssAntennaInfoListener mockListener = mock(IGnssAntennaInfoListener.class);
|
||||
overrideAsBinder(mockListener);
|
||||
return mockListener;
|
||||
}
|
||||
|
||||
private IBatchedLocationCallback createMockBatchedLocationCallback() {
|
||||
IBatchedLocationCallback mockedCallback = mock(IBatchedLocationCallback.class);
|
||||
overrideAsBinder(mockedCallback);
|
||||
@@ -224,6 +239,39 @@ public class GnssManagerServiceTest {
|
||||
Arrays.asList(gnssSingleSatCorrection)).build();
|
||||
}
|
||||
|
||||
private static List<GnssAntennaInfo> createDummyGnssAntennaInfos() {
|
||||
double carrierFrequencyMHz = 13758.0;
|
||||
|
||||
GnssAntennaInfo.PhaseCenterOffsetCoordinates phaseCenterOffsetCoordinates = new
|
||||
GnssAntennaInfo.PhaseCenterOffsetCoordinates(
|
||||
4.3d,
|
||||
1.4d,
|
||||
2.10d,
|
||||
2.1d,
|
||||
3.12d,
|
||||
0.5d);
|
||||
|
||||
double[][] phaseCenterVariationCorrectionsMillimeters = new double[10][10];
|
||||
double[][] phaseCenterVariationCorrectionsUncertaintyMillimeters = new double[10][10];
|
||||
GnssAntennaInfo.PhaseCenterVariationCorrections
|
||||
phaseCenterVariationCorrections =
|
||||
new GnssAntennaInfo.PhaseCenterVariationCorrections(
|
||||
phaseCenterVariationCorrectionsMillimeters,
|
||||
phaseCenterVariationCorrectionsUncertaintyMillimeters);
|
||||
|
||||
double[][] signalGainCorrectionsDbi = new double[10][10];
|
||||
double[][] signalGainCorrectionsUncertaintyDbi = new double[10][10];
|
||||
GnssAntennaInfo.SignalGainCorrections signalGainCorrections = new
|
||||
GnssAntennaInfo.SignalGainCorrections(
|
||||
signalGainCorrectionsDbi,
|
||||
signalGainCorrectionsUncertaintyDbi);
|
||||
|
||||
List<GnssAntennaInfo> gnssAntennaInfos = new ArrayList();
|
||||
gnssAntennaInfos.add(new GnssAntennaInfo(carrierFrequencyMHz, phaseCenterOffsetCoordinates,
|
||||
phaseCenterVariationCorrections, signalGainCorrections));
|
||||
return gnssAntennaInfos;
|
||||
}
|
||||
|
||||
private void enableLocationPermissions() {
|
||||
Mockito.doThrow(new SecurityException()).when(
|
||||
mMockContext).enforceCallingPermission(
|
||||
@@ -298,6 +346,18 @@ public class GnssManagerServiceTest {
|
||||
};
|
||||
}
|
||||
|
||||
private GnssAntennaInfoProvider createGnssAntennaInfoProvider(Context context,
|
||||
Handler handler) {
|
||||
GnssAntennaInfoProviderNative mockGnssAntenaInfoProviderNative = mock(
|
||||
GnssAntennaInfoProviderNative.class);
|
||||
return new GnssAntennaInfoProvider(context, handler, mockGnssAntenaInfoProviderNative) {
|
||||
@Override
|
||||
protected boolean isGpsEnabled() {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getGnssYearOfHardwareTest() {
|
||||
final int gnssYearOfHardware = 2012;
|
||||
@@ -661,6 +721,82 @@ public class GnssManagerServiceTest {
|
||||
gnssMeasurementsEvent);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addGnssAntennaInfoListenerWithoutPermissionsTest() throws RemoteException {
|
||||
IGnssAntennaInfoListener mockGnssAntennaInfoListener =
|
||||
createMockGnssAntennaInfoListener();
|
||||
List<GnssAntennaInfo> gnssAntennaInfos = createDummyGnssAntennaInfos();
|
||||
|
||||
disableLocationPermissions();
|
||||
|
||||
assertThrows(SecurityException.class,
|
||||
() -> mGnssManagerService.addGnssAntennaInfoListener(
|
||||
mockGnssAntennaInfoListener,
|
||||
"com.android.server", "abcd123", "TestGnssAntennaInfoListener"));
|
||||
|
||||
mTestGnssAntennaInfoProvider.onGnssAntennaInfoAvailable(gnssAntennaInfos);
|
||||
verify(mockGnssAntennaInfoListener, times(0))
|
||||
.onGnssAntennaInfoReceived(gnssAntennaInfos);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addGnssAntennaInfoListenerWithPermissionsTest() throws RemoteException {
|
||||
IGnssAntennaInfoListener mockGnssAntennaInfoListener =
|
||||
createMockGnssAntennaInfoListener();
|
||||
List<GnssAntennaInfo> gnssAntennaInfos = createDummyGnssAntennaInfos();
|
||||
|
||||
enableLocationPermissions();
|
||||
|
||||
assertThat(mGnssManagerService.addGnssAntennaInfoListener(mockGnssAntennaInfoListener,
|
||||
"com.android.server", "abcd123", "TestGnssAntennaInfoListener")).isEqualTo(true);
|
||||
|
||||
mTestGnssAntennaInfoProvider.onGnssAntennaInfoAvailable(gnssAntennaInfos);
|
||||
verify(mockGnssAntennaInfoListener, times(1))
|
||||
.onGnssAntennaInfoReceived(gnssAntennaInfos);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void removeGnssAntennaInfoListenerWithoutPermissionsTest() throws RemoteException {
|
||||
IGnssAntennaInfoListener mockGnssAntennaInfoListener =
|
||||
createMockGnssAntennaInfoListener();
|
||||
List<GnssAntennaInfo> gnssAntennaInfos = createDummyGnssAntennaInfos();
|
||||
|
||||
enableLocationPermissions();
|
||||
|
||||
mGnssManagerService.addGnssAntennaInfoListener(
|
||||
mockGnssAntennaInfoListener,
|
||||
"com.android.server", "abcd123", "TestGnssAntennaInfoListener");
|
||||
|
||||
disableLocationPermissions();
|
||||
|
||||
mGnssManagerService.removeGnssAntennaInfoListener(
|
||||
mockGnssAntennaInfoListener);
|
||||
|
||||
mTestGnssAntennaInfoProvider.onGnssAntennaInfoAvailable(gnssAntennaInfos);
|
||||
verify(mockGnssAntennaInfoListener, times(0)).onGnssAntennaInfoReceived(
|
||||
gnssAntennaInfos);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void removeGnssAntennaInfoListenerWithPermissionsTest() throws RemoteException {
|
||||
IGnssAntennaInfoListener mockGnssAntennaInfoListener =
|
||||
createMockGnssAntennaInfoListener();
|
||||
List<GnssAntennaInfo> gnssAntennaInfos = createDummyGnssAntennaInfos();
|
||||
|
||||
enableLocationPermissions();
|
||||
|
||||
mGnssManagerService.addGnssAntennaInfoListener(
|
||||
mockGnssAntennaInfoListener,
|
||||
"com.android.server", "abcd123", "TestGnssAntennaInfoListener");
|
||||
|
||||
mGnssManagerService.removeGnssAntennaInfoListener(
|
||||
mockGnssAntennaInfoListener);
|
||||
|
||||
mTestGnssAntennaInfoProvider.onGnssAntennaInfoAvailable(gnssAntennaInfos);
|
||||
verify(mockGnssAntennaInfoListener, times(0)).onGnssAntennaInfoReceived(
|
||||
gnssAntennaInfos);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addGnssNavigationMessageListenerWithoutPermissionsTest() throws RemoteException {
|
||||
IGnssNavigationMessageListener mockGnssNavigationMessageListener =
|
||||
|
||||
Reference in New Issue
Block a user