blob: 1eef0de3a05dbb91d3b369149dcf92df71c735db [file] [log] [blame]
/*
* 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.gnss.hal;
import static com.android.server.location.gnss.GnssManagerService.TAG;
import android.annotation.IntDef;
import android.annotation.Nullable;
import android.location.GnssAntennaInfo;
import android.location.GnssCapabilities;
import android.location.GnssMeasurementCorrections;
import android.location.GnssMeasurementsEvent;
import android.location.GnssNavigationMessage;
import android.location.GnssStatus;
import android.location.Location;
import android.os.Binder;
import android.os.SystemClock;
import android.util.Log;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.Preconditions;
import com.android.server.FgThread;
import com.android.server.location.gnss.GnssConfiguration;
import com.android.server.location.gnss.GnssPowerStats;
import com.android.server.location.injector.EmergencyHelper;
import com.android.server.location.injector.Injector;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.List;
import java.util.Objects;
/**
* Entry point for most GNSS HAL commands and callbacks.
*/
public class GnssNative {
// IMPORTANT - must match GnssPositionMode enum in IGnss.hal
public static final int GNSS_POSITION_MODE_STANDALONE = 0;
public static final int GNSS_POSITION_MODE_MS_BASED = 1;
public static final int GNSS_POSITION_MODE_MS_ASSISTED = 2;
@IntDef(prefix = "GNSS_POSITION_MODE_", value = {GNSS_POSITION_MODE_STANDALONE,
GNSS_POSITION_MODE_MS_BASED, GNSS_POSITION_MODE_MS_ASSISTED})
@Retention(RetentionPolicy.SOURCE)
public @interface GnssPositionMode {}
// IMPORTANT - must match GnssPositionRecurrence enum in IGnss.hal
public static final int GNSS_POSITION_RECURRENCE_PERIODIC = 0;
public static final int GNSS_POSITION_RECURRENCE_SINGLE = 1;
@IntDef(prefix = "GNSS_POSITION_RECURRENCE_", value = {GNSS_POSITION_RECURRENCE_PERIODIC,
GNSS_POSITION_RECURRENCE_SINGLE})
@Retention(RetentionPolicy.SOURCE)
public @interface GnssPositionRecurrence {}
// IMPORTANT - must match the GnssLocationFlags enum in types.hal
public static final int GNSS_LOCATION_HAS_LAT_LONG = 1;
public static final int GNSS_LOCATION_HAS_ALTITUDE = 2;
public static final int GNSS_LOCATION_HAS_SPEED = 4;
public static final int GNSS_LOCATION_HAS_BEARING = 8;
public static final int GNSS_LOCATION_HAS_HORIZONTAL_ACCURACY = 16;
public static final int GNSS_LOCATION_HAS_VERTICAL_ACCURACY = 32;
public static final int GNSS_LOCATION_HAS_SPEED_ACCURACY = 64;
public static final int GNSS_LOCATION_HAS_BEARING_ACCURACY = 128;
@IntDef(flag = true, prefix = "GNSS_LOCATION_", value = {GNSS_LOCATION_HAS_LAT_LONG,
GNSS_LOCATION_HAS_ALTITUDE, GNSS_LOCATION_HAS_SPEED, GNSS_LOCATION_HAS_BEARING,
GNSS_LOCATION_HAS_HORIZONTAL_ACCURACY, GNSS_LOCATION_HAS_VERTICAL_ACCURACY,
GNSS_LOCATION_HAS_SPEED_ACCURACY, GNSS_LOCATION_HAS_BEARING_ACCURACY})
@Retention(RetentionPolicy.SOURCE)
public @interface GnssLocationFlags {}
// IMPORTANT - must match the ElapsedRealtimeFlags enum in types.hal
public static final int GNSS_REALTIME_HAS_TIMESTAMP_NS = 1;
public static final int GNSS_REALTIME_HAS_TIME_UNCERTAINTY_NS = 2;
@IntDef(flag = true, value = {GNSS_REALTIME_HAS_TIMESTAMP_NS,
GNSS_REALTIME_HAS_TIME_UNCERTAINTY_NS})
@Retention(RetentionPolicy.SOURCE)
public @interface GnssRealtimeFlags {}
// IMPORTANT - must match the GnssAidingData enum in IGnss.hal
public static final int GNSS_AIDING_TYPE_EPHEMERIS = 0x0001;
public static final int GNSS_AIDING_TYPE_ALMANAC = 0x0002;
public static final int GNSS_AIDING_TYPE_POSITION = 0x0004;
public static final int GNSS_AIDING_TYPE_TIME = 0x0008;
public static final int GNSS_AIDING_TYPE_IONO = 0x0010;
public static final int GNSS_AIDING_TYPE_UTC = 0x0020;
public static final int GNSS_AIDING_TYPE_HEALTH = 0x0040;
public static final int GNSS_AIDING_TYPE_SVDIR = 0x0080;
public static final int GNSS_AIDING_TYPE_SVSTEER = 0x0100;
public static final int GNSS_AIDING_TYPE_SADATA = 0x0200;
public static final int GNSS_AIDING_TYPE_RTI = 0x0400;
public static final int GNSS_AIDING_TYPE_CELLDB_INFO = 0x8000;
public static final int GNSS_AIDING_TYPE_ALL = 0xFFFF;
@IntDef(flag = true, prefix = "GNSS_AIDING_", value = {GNSS_AIDING_TYPE_EPHEMERIS,
GNSS_AIDING_TYPE_ALMANAC, GNSS_AIDING_TYPE_POSITION, GNSS_AIDING_TYPE_TIME,
GNSS_AIDING_TYPE_IONO, GNSS_AIDING_TYPE_UTC, GNSS_AIDING_TYPE_HEALTH,
GNSS_AIDING_TYPE_SVDIR, GNSS_AIDING_TYPE_SVSTEER, GNSS_AIDING_TYPE_SADATA,
GNSS_AIDING_TYPE_RTI, GNSS_AIDING_TYPE_CELLDB_INFO, GNSS_AIDING_TYPE_ALL})
@Retention(RetentionPolicy.SOURCE)
public @interface GnssAidingTypeFlags {}
// IMPORTANT - must match OEM definitions, this isn't part of a hal for some reason
public static final int AGPS_REF_LOCATION_TYPE_GSM_CELLID = 1;
public static final int AGPS_REF_LOCATION_TYPE_UMTS_CELLID = 2;
@IntDef(prefix = "AGPS_REF_LOCATION_TYPE_", value = {AGPS_REF_LOCATION_TYPE_GSM_CELLID,
AGPS_REF_LOCATION_TYPE_UMTS_CELLID})
@Retention(RetentionPolicy.SOURCE)
public @interface AgpsReferenceLocationType {}
// IMPORTANT - must match OEM definitions, this isn't part of a hal for some reason
public static final int AGPS_SETID_TYPE_NONE = 0;
public static final int AGPS_SETID_TYPE_IMSI = 1;
public static final int AGPS_SETID_TYPE_MSISDN = 2;
@IntDef(prefix = "AGPS_SETID_TYPE_", value = {AGPS_SETID_TYPE_NONE, AGPS_SETID_TYPE_IMSI,
AGPS_SETID_TYPE_MSISDN})
@Retention(RetentionPolicy.SOURCE)
public @interface AgpsSetIdType {}
/** Callbacks relevant to the entire HAL. */
public interface BaseCallbacks {
default void onHalStarted() {}
void onHalRestarted();
default void onCapabilitiesChanged(GnssCapabilities oldCapabilities,
GnssCapabilities newCapabilities) {}
}
/** Callbacks for status events. */
public interface StatusCallbacks {
// IMPORTANT - must match GnssStatusValue enum in IGnssCallback.hal
int GNSS_STATUS_NONE = 0;
int GNSS_STATUS_SESSION_BEGIN = 1;
int GNSS_STATUS_SESSION_END = 2;
int GNSS_STATUS_ENGINE_ON = 3;
int GNSS_STATUS_ENGINE_OFF = 4;
@IntDef(prefix = "GNSS_STATUS_", value = {GNSS_STATUS_NONE, GNSS_STATUS_SESSION_BEGIN,
GNSS_STATUS_SESSION_END, GNSS_STATUS_ENGINE_ON, GNSS_STATUS_ENGINE_OFF})
@Retention(RetentionPolicy.SOURCE)
@interface GnssStatusValue {}
void onReportStatus(@GnssStatusValue int status);
void onReportFirstFix(int ttff);
}
/** Callbacks for SV status events. */
public interface SvStatusCallbacks {
void onReportSvStatus(GnssStatus gnssStatus);
}
/** Callbacks for NMEA events. */
public interface NmeaCallbacks {
void onReportNmea(long timestamp);
}
/** Callbacks for location events. */
public interface LocationCallbacks {
void onReportLocation(boolean hasLatLong, Location location);
void onReportLocations(Location[] locations);
}
/** Callbacks for measurement events. */
public interface MeasurementCallbacks {
void onReportMeasurements(GnssMeasurementsEvent event);
}
/** Callbacks for antenna info events. */
public interface AntennaInfoCallbacks {
void onReportAntennaInfo(List<GnssAntennaInfo> antennaInfos);
}
/** Callbacks for navigation message events. */
public interface NavigationMessageCallbacks {
void onReportNavigationMessage(GnssNavigationMessage event);
}
/** Callbacks for geofence events. */
public interface GeofenceCallbacks {
// IMPORTANT - must match GeofenceTransition enum in IGnssGeofenceCallback.hal
int GEOFENCE_TRANSITION_ENTERED = 1 << 0L;
int GEOFENCE_TRANSITION_EXITED = 1 << 1L;
int GEOFENCE_TRANSITION_UNCERTAIN = 1 << 2L;
@IntDef(prefix = "GEOFENCE_TRANSITION_", value = {GEOFENCE_TRANSITION_ENTERED,
GEOFENCE_TRANSITION_EXITED, GEOFENCE_TRANSITION_UNCERTAIN})
@Retention(RetentionPolicy.SOURCE)
@interface GeofenceTransition {}
// IMPORTANT - must match GeofenceAvailability enum in IGnssGeofenceCallback.hal
int GEOFENCE_AVAILABILITY_UNAVAILABLE = 1 << 0L;
int GEOFENCE_AVAILABILITY_AVAILABLE = 1 << 1L;
@IntDef(prefix = "GEOFENCE_AVAILABILITY_", value = {GEOFENCE_AVAILABILITY_UNAVAILABLE,
GEOFENCE_AVAILABILITY_AVAILABLE})
@Retention(RetentionPolicy.SOURCE)
@interface GeofenceAvailability {}
// IMPORTANT - must match GeofenceStatus enum in IGnssGeofenceCallback.hal
int GEOFENCE_STATUS_OPERATION_SUCCESS = 0;
int GEOFENCE_STATUS_ERROR_TOO_MANY_GEOFENCES = 100;
int GEOFENCE_STATUS_ERROR_ID_EXISTS = -101;
int GEOFENCE_STATUS_ERROR_ID_UNKNOWN = -102;
int GEOFENCE_STATUS_ERROR_INVALID_TRANSITION = -103;
int GEOFENCE_STATUS_ERROR_GENERIC = -149;
@IntDef(prefix = "GEOFENCE_STATUS_", value = {GEOFENCE_STATUS_OPERATION_SUCCESS,
GEOFENCE_STATUS_ERROR_TOO_MANY_GEOFENCES, GEOFENCE_STATUS_ERROR_ID_EXISTS,
GEOFENCE_STATUS_ERROR_ID_UNKNOWN, GEOFENCE_STATUS_ERROR_INVALID_TRANSITION,
GEOFENCE_STATUS_ERROR_GENERIC})
@Retention(RetentionPolicy.SOURCE)
@interface GeofenceStatus {}
void onReportGeofenceTransition(int geofenceId, Location location,
@GeofenceTransition int transition, long timestamp);
void onReportGeofenceStatus(@GeofenceAvailability int availabilityStatus,
Location location);
void onReportGeofenceAddStatus(int geofenceId, @GeofenceStatus int status);
void onReportGeofenceRemoveStatus(int geofenceId, @GeofenceStatus int status);
void onReportGeofencePauseStatus(int geofenceId, @GeofenceStatus int status);
void onReportGeofenceResumeStatus(int geofenceId, @GeofenceStatus int status);
}
/** Callbacks for the HAL requesting time. */
public interface TimeCallbacks {
void onRequestUtcTime();
}
/** Callbacks for the HAL requesting locations. */
public interface LocationRequestCallbacks {
void onRequestLocation(boolean independentFromGnss, boolean isUserEmergency);
void onRequestRefLocation();
}
/** Callbacks for HAL requesting PSDS download. */
public interface PsdsCallbacks {
void onRequestPsdsDownload(int psdsType);
}
/** Callbacks for AGPS functionality. */
public interface AGpsCallbacks {
// IMPORTANT - must match OEM definitions, this isn't part of a hal for some reason
int AGPS_REQUEST_SETID_IMSI = 1 << 0L;
int AGPS_REQUEST_SETID_MSISDN = 1 << 1L;
@IntDef(flag = true, prefix = "AGPS_REQUEST_SETID_", value = {AGPS_REQUEST_SETID_IMSI,
AGPS_REQUEST_SETID_MSISDN})
@Retention(RetentionPolicy.SOURCE)
@interface AgpsSetIdFlags {}
void onReportAGpsStatus(int agpsType, int agpsStatus, byte[] suplIpAddr);
void onRequestSetID(@AgpsSetIdFlags int flags);
}
/** Callbacks for notifications. */
public interface NotificationCallbacks {
void onReportNiNotification(int notificationId, int niType, int notifyFlags,
int timeout, int defaultResponse, String requestorId, String text,
int requestorIdEncoding, int textEncoding);
void onReportNfwNotification(String proxyAppPackageName, byte protocolStack,
String otherProtocolStackName, byte requestor, String requestorId,
byte responseType, boolean inEmergencyMode, boolean isCachedLocation);
}
// set lower than the current ITAR limit of 600m/s to allow this to trigger even if GPS HAL
// stops output right at 600m/s, depriving this of the information of a device that reaches
// greater than 600m/s, and higher than the speed of sound to avoid impacting most use cases.
private static final float ITAR_SPEED_LIMIT_METERS_PER_SECOND = 400.0f;
/**
* Indicates that this method is a native entry point. Useful purely for IDEs which can
* understand entry points, and thus eliminate incorrect warnings about methods not used.
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
private @interface NativeEntryPoint {}
@GuardedBy("GnssNative.class")
private static GnssHal sGnssHal;
@GuardedBy("GnssNative.class")
private static boolean sGnssHalInitialized;
@GuardedBy("GnssNative.class")
private static GnssNative sInstance;
/**
* Sets GnssHal instance to use for testing.
*/
@VisibleForTesting
public static synchronized void setGnssHalForTest(GnssHal gnssHal) {
sGnssHal = Objects.requireNonNull(gnssHal);
sGnssHalInitialized = false;
sInstance = null;
}
private static synchronized void initializeHal() {
if (!sGnssHalInitialized) {
if (sGnssHal == null) {
sGnssHal = new GnssHal();
}
sGnssHal.classInitOnce();
sGnssHalInitialized = true;
}
}
/**
* Returns true if GNSS is supported on this device. If true, then
* {@link #create(Injector, GnssConfiguration)} may be invoked.
*/
public static synchronized boolean isSupported() {
initializeHal();
return sGnssHal.isSupported();
}
/**
* Creates a new instance of GnssNative. Should only be invoked if {@link #isSupported()} is
* true. May only be invoked once.
*/
public static synchronized GnssNative create(Injector injector,
GnssConfiguration configuration) {
// side effect - ensures initialization
Preconditions.checkState(isSupported());
Preconditions.checkState(sInstance == null);
return (sInstance = new GnssNative(sGnssHal, injector, configuration));
}
private final GnssHal mGnssHal;
private final EmergencyHelper mEmergencyHelper;
private final GnssConfiguration mConfiguration;
// these callbacks may have multiple implementations
private BaseCallbacks[] mBaseCallbacks = new BaseCallbacks[0];
private StatusCallbacks[] mStatusCallbacks = new StatusCallbacks[0];
private SvStatusCallbacks[] mSvStatusCallbacks = new SvStatusCallbacks[0];
private NmeaCallbacks[] mNmeaCallbacks = new NmeaCallbacks[0];
private LocationCallbacks[] mLocationCallbacks = new LocationCallbacks[0];
private MeasurementCallbacks[] mMeasurementCallbacks = new MeasurementCallbacks[0];
private AntennaInfoCallbacks[] mAntennaInfoCallbacks = new AntennaInfoCallbacks[0];
private NavigationMessageCallbacks[] mNavigationMessageCallbacks =
new NavigationMessageCallbacks[0];
// these callbacks may only have a single implementation
private GeofenceCallbacks mGeofenceCallbacks;
private TimeCallbacks mTimeCallbacks;
private LocationRequestCallbacks mLocationRequestCallbacks;
private PsdsCallbacks mPsdsCallbacks;
private AGpsCallbacks mAGpsCallbacks;
private NotificationCallbacks mNotificationCallbacks;
private boolean mRegistered;
private volatile boolean mItarSpeedLimitExceeded;
private GnssCapabilities mCapabilities = new GnssCapabilities.Builder().build();
private @GnssCapabilities.TopHalCapabilityFlags int mTopFlags;
private @Nullable GnssPowerStats mPowerStats = null;
private int mHardwareYear = 0;
private @Nullable String mHardwareModelName = null;
private long mStartRealtimeMs = 0;
private boolean mHasFirstFix = false;
private GnssNative(GnssHal gnssHal, Injector injector, GnssConfiguration configuration) {
mGnssHal = Objects.requireNonNull(gnssHal);
mEmergencyHelper = injector.getEmergencyHelper();
mConfiguration = configuration;
}
public void addBaseCallbacks(BaseCallbacks callbacks) {
Preconditions.checkState(!mRegistered);
mBaseCallbacks = ArrayUtils.appendElement(BaseCallbacks.class, mBaseCallbacks, callbacks);
}
public void addStatusCallbacks(StatusCallbacks callbacks) {
Preconditions.checkState(!mRegistered);
mStatusCallbacks = ArrayUtils.appendElement(StatusCallbacks.class, mStatusCallbacks,
callbacks);
}
public void addSvStatusCallbacks(SvStatusCallbacks callbacks) {
Preconditions.checkState(!mRegistered);
mSvStatusCallbacks = ArrayUtils.appendElement(SvStatusCallbacks.class, mSvStatusCallbacks,
callbacks);
}
public void addNmeaCallbacks(NmeaCallbacks callbacks) {
Preconditions.checkState(!mRegistered);
mNmeaCallbacks = ArrayUtils.appendElement(NmeaCallbacks.class, mNmeaCallbacks,
callbacks);
}
public void addLocationCallbacks(LocationCallbacks callbacks) {
Preconditions.checkState(!mRegistered);
mLocationCallbacks = ArrayUtils.appendElement(LocationCallbacks.class, mLocationCallbacks,
callbacks);
}
public void addMeasurementCallbacks(MeasurementCallbacks callbacks) {
Preconditions.checkState(!mRegistered);
mMeasurementCallbacks = ArrayUtils.appendElement(MeasurementCallbacks.class,
mMeasurementCallbacks, callbacks);
}
public void addAntennaInfoCallbacks(AntennaInfoCallbacks callbacks) {
Preconditions.checkState(!mRegistered);
mAntennaInfoCallbacks = ArrayUtils.appendElement(AntennaInfoCallbacks.class,
mAntennaInfoCallbacks, callbacks);
}
public void addNavigationMessageCallbacks(NavigationMessageCallbacks callbacks) {
Preconditions.checkState(!mRegistered);
mNavigationMessageCallbacks = ArrayUtils.appendElement(NavigationMessageCallbacks.class,
mNavigationMessageCallbacks, callbacks);
}
public void setGeofenceCallbacks(GeofenceCallbacks callbacks) {
Preconditions.checkState(!mRegistered);
Preconditions.checkState(mGeofenceCallbacks == null);
mGeofenceCallbacks = Objects.requireNonNull(callbacks);
}
public void setTimeCallbacks(TimeCallbacks callbacks) {
Preconditions.checkState(!mRegistered);
Preconditions.checkState(mTimeCallbacks == null);
mTimeCallbacks = Objects.requireNonNull(callbacks);
}
public void setLocationRequestCallbacks(LocationRequestCallbacks callbacks) {
Preconditions.checkState(!mRegistered);
Preconditions.checkState(mLocationRequestCallbacks == null);
mLocationRequestCallbacks = Objects.requireNonNull(callbacks);
}
public void setPsdsCallbacks(PsdsCallbacks callbacks) {
Preconditions.checkState(!mRegistered);
Preconditions.checkState(mPsdsCallbacks == null);
mPsdsCallbacks = Objects.requireNonNull(callbacks);
}
public void setAGpsCallbacks(AGpsCallbacks callbacks) {
Preconditions.checkState(!mRegistered);
Preconditions.checkState(mAGpsCallbacks == null);
mAGpsCallbacks = Objects.requireNonNull(callbacks);
}
public void setNotificationCallbacks(NotificationCallbacks callbacks) {
Preconditions.checkState(!mRegistered);
Preconditions.checkState(mNotificationCallbacks == null);
mNotificationCallbacks = Objects.requireNonNull(callbacks);
}
/**
* Registers with the HAL and allows callbacks to begin. Once registered with the native HAL,
* no more callbacks can be added or set. Must only be called once.
*/
public void register() {
Preconditions.checkState(!mRegistered);
mRegistered = true;
initializeGnss(false);
Log.i(TAG, "gnss hal started");
for (int i = 0; i < mBaseCallbacks.length; i++) {
mBaseCallbacks[i].onHalStarted();
}
}
private void initializeGnss(boolean restart) {
Preconditions.checkState(mRegistered);
mTopFlags = 0;
mGnssHal.initOnce(GnssNative.this, restart);
// gnss chipset appears to require an init/cleanup cycle on startup in order to properly
// initialize - undocumented and no idea why this is the case
if (mGnssHal.init()) {
mGnssHal.cleanup();
Log.i(TAG, "gnss hal initialized");
} else {
Log.e(TAG, "gnss hal initialization failed");
}
}
public GnssConfiguration getConfiguration() {
return mConfiguration;
}
/**
* Starts up GNSS HAL, and has undocumented side effect of informing HAL that location is
* allowed by settings.
*/
public boolean init() {
Preconditions.checkState(mRegistered);
return mGnssHal.init();
}
/**
* Shuts down GNSS HAL, and has undocumented side effect of informing HAL that location is not
* allowed by settings.
*/
public void cleanup() {
Preconditions.checkState(mRegistered);
mGnssHal.cleanup();
}
/**
* Returns the latest power stats from the GNSS HAL.
*/
public @Nullable GnssPowerStats getPowerStats() {
return mPowerStats;
}
/**
* Returns current capabilities of the GNSS HAL.
*/
public GnssCapabilities getCapabilities() {
return mCapabilities;
}
/**
* Returns hardware year of GNSS chipset.
*/
public int getHardwareYear() {
return mHardwareYear;
}
/**
* Returns hardware model name of GNSS chipset.
*/
public @Nullable String getHardwareModelName() {
return mHardwareModelName;
}
/**
* Returns true if the ITAR speed limit is currently being exceeded, and thus location
* information may be blocked.
*/
public boolean isItarSpeedLimitExceeded() {
return mItarSpeedLimitExceeded;
}
/**
* Starts the GNSS HAL.
*/
public boolean start() {
Preconditions.checkState(mRegistered);
mStartRealtimeMs = SystemClock.elapsedRealtime();
mHasFirstFix = false;
return mGnssHal.start();
}
/**
* Stops the GNSS HAL.
*/
public boolean stop() {
Preconditions.checkState(mRegistered);
return mGnssHal.stop();
}
/**
* Sets the position mode.
*/
public boolean setPositionMode(@GnssPositionMode int mode,
@GnssPositionRecurrence int recurrence, int minInterval, int preferredAccuracy,
int preferredTime, boolean lowPowerMode) {
Preconditions.checkState(mRegistered);
return mGnssHal.setPositionMode(mode, recurrence, minInterval, preferredAccuracy,
preferredTime, lowPowerMode);
}
/**
* Returns a debug string from the GNSS HAL.
*/
public String getInternalState() {
Preconditions.checkState(mRegistered);
return mGnssHal.getInternalState();
}
/**
* Deletes any aiding data specified by the given flags.
*/
public void deleteAidingData(@GnssAidingTypeFlags int flags) {
Preconditions.checkState(mRegistered);
mGnssHal.deleteAidingData(flags);
}
/**
* Reads an NMEA message into the given buffer, returning the number of bytes loaded into the
* buffer.
*/
public int readNmea(byte[] buffer, int bufferSize) {
Preconditions.checkState(mRegistered);
return mGnssHal.readNmea(buffer, bufferSize);
}
/**
* Injects location information into the GNSS HAL.
*/
public void injectLocation(Location location) {
Preconditions.checkState(mRegistered);
if (location.hasAccuracy()) {
mGnssHal.injectLocation(location.getLatitude(), location.getLongitude(),
location.getAccuracy());
}
}
/**
* Injects a location into the GNSS HAL in response to a HAL request for location.
*/
public void injectBestLocation(Location location) {
Preconditions.checkState(mRegistered);
int gnssLocationFlags = GNSS_LOCATION_HAS_LAT_LONG
| (location.hasAltitude() ? GNSS_LOCATION_HAS_ALTITUDE : 0)
| (location.hasSpeed() ? GNSS_LOCATION_HAS_SPEED : 0)
| (location.hasBearing() ? GNSS_LOCATION_HAS_BEARING : 0)
| (location.hasAccuracy() ? GNSS_LOCATION_HAS_HORIZONTAL_ACCURACY : 0)
| (location.hasVerticalAccuracy() ? GNSS_LOCATION_HAS_VERTICAL_ACCURACY : 0)
| (location.hasSpeedAccuracy() ? GNSS_LOCATION_HAS_SPEED_ACCURACY : 0)
| (location.hasBearingAccuracy() ? GNSS_LOCATION_HAS_BEARING_ACCURACY : 0);
double latitudeDegrees = location.getLatitude();
double longitudeDegrees = location.getLongitude();
double altitudeMeters = location.getAltitude();
float speedMetersPerSec = location.getSpeed();
float bearingDegrees = location.getBearing();
float horizontalAccuracyMeters = location.getAccuracy();
float verticalAccuracyMeters = location.getVerticalAccuracyMeters();
float speedAccuracyMetersPerSecond = location.getSpeedAccuracyMetersPerSecond();
float bearingAccuracyDegrees = location.getBearingAccuracyDegrees();
long timestamp = location.getTime();
int elapsedRealtimeFlags = GNSS_REALTIME_HAS_TIMESTAMP_NS
| (location.hasElapsedRealtimeUncertaintyNanos()
? GNSS_REALTIME_HAS_TIME_UNCERTAINTY_NS : 0);
long elapsedRealtimeNanos = location.getElapsedRealtimeNanos();
double elapsedRealtimeUncertaintyNanos = location.getElapsedRealtimeUncertaintyNanos();
mGnssHal.injectBestLocation(gnssLocationFlags, latitudeDegrees, longitudeDegrees,
altitudeMeters, speedMetersPerSec, bearingDegrees, horizontalAccuracyMeters,
verticalAccuracyMeters, speedAccuracyMetersPerSecond, bearingAccuracyDegrees,
timestamp, elapsedRealtimeFlags, elapsedRealtimeNanos,
elapsedRealtimeUncertaintyNanos);
}
/**
* Injects time information into the GNSS HAL.
*/
public void injectTime(long time, long timeReference, int uncertainty) {
Preconditions.checkState(mRegistered);
mGnssHal.injectTime(time, timeReference, uncertainty);
}
/**
* Returns true if navigation message collection is supported.
*/
public boolean isNavigationMessageCollectionSupported() {
Preconditions.checkState(mRegistered);
return mGnssHal.isNavigationMessageCollectionSupported();
}
/**
* Starts navigation message collection.
*/
public boolean startNavigationMessageCollection() {
Preconditions.checkState(mRegistered);
return mGnssHal.startNavigationMessageCollection();
}
/**
* Stops navigation message collection.
*/
public boolean stopNavigationMessageCollection() {
Preconditions.checkState(mRegistered);
return mGnssHal.stopNavigationMessageCollection();
}
/**
* Returns true if antenna info is supported.
*/
public boolean isAntennaInfoSupported() {
Preconditions.checkState(mRegistered);
return mGnssHal.isAntennaInfoSupported();
}
/**
* Starts antenna info listening.
*/
public boolean startAntennaInfoListening() {
Preconditions.checkState(mRegistered);
return mGnssHal.startAntennaInfoListening();
}
/**
* Stops antenna info listening.
*/
public boolean stopAntennaInfoListening() {
Preconditions.checkState(mRegistered);
return mGnssHal.stopAntennaInfoListening();
}
/**
* Returns true if measurement collection is supported.
*/
public boolean isMeasurementSupported() {
Preconditions.checkState(mRegistered);
return mGnssHal.isMeasurementSupported();
}
/**
* Starts measurement collection.
*/
public boolean startMeasurementCollection(boolean enableFullTracking,
boolean enableCorrVecOutputs) {
Preconditions.checkState(mRegistered);
return mGnssHal.startMeasurementCollection(enableFullTracking, enableCorrVecOutputs);
}
/**
* Stops measurement collection.
*/
public boolean stopMeasurementCollection() {
Preconditions.checkState(mRegistered);
return mGnssHal.stopMeasurementCollection();
}
/**
* Returns true if measurement corrections are supported.
*/
public boolean isMeasurementCorrectionsSupported() {
Preconditions.checkState(mRegistered);
return mGnssHal.isMeasurementCorrectionsSupported();
}
/**
* Injects measurement corrections into the GNSS HAL.
*/
public boolean injectMeasurementCorrections(GnssMeasurementCorrections corrections) {
Preconditions.checkState(mRegistered);
return mGnssHal.injectMeasurementCorrections(corrections);
}
/**
* Initialize batching.
*/
public boolean initBatching() {
Preconditions.checkState(mRegistered);
return mGnssHal.initBatching();
}
/**
* Cleanup batching.
*/
public void cleanupBatching() {
Preconditions.checkState(mRegistered);
mGnssHal.cleanupBatching();
}
/**
* Start batching.
*/
public boolean startBatch(long periodNanos, boolean wakeOnFifoFull) {
Preconditions.checkState(mRegistered);
return mGnssHal.startBatch(periodNanos, wakeOnFifoFull);
}
/**
* Flush batching.
*/
public void flushBatch() {
Preconditions.checkState(mRegistered);
mGnssHal.flushBatch();
}
/**
* Stop batching.
*/
public void stopBatch() {
Preconditions.checkState(mRegistered);
mGnssHal.stopBatch();
}
/**
* Get current batching size.
*/
public int getBatchSize() {
Preconditions.checkState(mRegistered);
return mGnssHal.getBatchSize();
}
/**
* Check if GNSS geofencing is supported.
*/
public boolean isGeofencingSupported() {
Preconditions.checkState(mRegistered);
return mGnssHal.isGeofencingSupported();
}
/**
* Add geofence.
*/
public boolean addGeofence(int geofenceId, double latitude, double longitude, double radius,
int lastTransition, int monitorTransitions, int notificationResponsiveness,
int unknownTimer) {
Preconditions.checkState(mRegistered);
return mGnssHal.addGeofence(geofenceId, latitude, longitude, radius, lastTransition,
monitorTransitions, notificationResponsiveness, unknownTimer);
}
/**
* Resume geofence.
*/
public boolean resumeGeofence(int geofenceId, int monitorTransitions) {
Preconditions.checkState(mRegistered);
return mGnssHal.resumeGeofence(geofenceId, monitorTransitions);
}
/**
* Pause geofence.
*/
public boolean pauseGeofence(int geofenceId) {
Preconditions.checkState(mRegistered);
return mGnssHal.pauseGeofence(geofenceId);
}
/**
* Remove geofence.
*/
public boolean removeGeofence(int geofenceId) {
Preconditions.checkState(mRegistered);
return mGnssHal.removeGeofence(geofenceId);
}
/**
* Returns true if visibility control is supported.
*/
public boolean isGnssVisibilityControlSupported() {
Preconditions.checkState(mRegistered);
return mGnssHal.isGnssVisibilityControlSupported();
}
/**
* Send a network initiated respnse.
*/
public void sendNiResponse(int notificationId, int userResponse) {
Preconditions.checkState(mRegistered);
mGnssHal.sendNiResponse(notificationId, userResponse);
}
/**
* Request an eventual update of GNSS power statistics.
*/
public void requestPowerStats() {
Preconditions.checkState(mRegistered);
mGnssHal.requestPowerStats();
}
/**
* Sets AGPS server information.
*/
public void setAgpsServer(int type, String hostname, int port) {
Preconditions.checkState(mRegistered);
mGnssHal.setAgpsServer(type, hostname, port);
}
/**
* Sets AGPS set id.
*/
public void setAgpsSetId(@AgpsSetIdType int type, String setId) {
Preconditions.checkState(mRegistered);
mGnssHal.setAgpsSetId(type, setId);
}
/**
* Sets AGPS reference cell id location.
*/
public void setAgpsReferenceLocationCellId(@AgpsReferenceLocationType int type, int mcc,
int mnc, int lac, int cid) {
Preconditions.checkState(mRegistered);
mGnssHal.setAgpsReferenceLocationCellId(type, mcc, mnc, lac, cid);
}
/**
* Returns true if Predicted Satellite Data Service APIs are supported.
*/
public boolean isPsdsSupported() {
Preconditions.checkState(mRegistered);
return mGnssHal.isPsdsSupported();
}
/**
* Injects Predicited Satellite Data Service data into the GNSS HAL.
*/
public void injectPsdsData(byte[] data, int length, int psdsType) {
Preconditions.checkState(mRegistered);
mGnssHal.injectPsdsData(data, length, psdsType);
}
@NativeEntryPoint
void reportGnssServiceDied() {
// Not necessary to clear (and restore) binder identity since it runs on another thread.
Log.e(TAG, "gnss hal died - restarting shortly...");
// move to another thread just in case there is some awkward gnss thread dependency with
// the death notification. there shouldn't be, but you never know with gnss...
FgThread.getExecutor().execute(this::restartHal);
}
@VisibleForTesting
void restartHal() {
initializeGnss(true);
Log.e(TAG, "gnss hal restarted");
for (int i = 0; i < mBaseCallbacks.length; i++) {
mBaseCallbacks[i].onHalRestarted();
}
}
@NativeEntryPoint
void reportLocation(boolean hasLatLong, Location location) {
Binder.withCleanCallingIdentity(() -> {
if (hasLatLong && !mHasFirstFix) {
mHasFirstFix = true;
// notify status listeners
int ttff = (int) (SystemClock.elapsedRealtime() - mStartRealtimeMs);
for (int i = 0; i < mStatusCallbacks.length; i++) {
mStatusCallbacks[i].onReportFirstFix(ttff);
}
}
if (location.hasSpeed()) {
boolean exceeded = location.getSpeed() > ITAR_SPEED_LIMIT_METERS_PER_SECOND;
if (!mItarSpeedLimitExceeded && exceeded) {
Log.w(TAG, "speed nearing ITAR threshold - blocking further GNSS output");
} else if (mItarSpeedLimitExceeded && !exceeded) {
Log.w(TAG, "speed leaving ITAR threshold - allowing further GNSS output");
}
mItarSpeedLimitExceeded = exceeded;
}
if (mItarSpeedLimitExceeded) {
return;
}
for (int i = 0; i < mLocationCallbacks.length; i++) {
mLocationCallbacks[i].onReportLocation(hasLatLong, location);
}
});
}
@NativeEntryPoint
void reportStatus(@StatusCallbacks.GnssStatusValue int gnssStatus) {
Binder.withCleanCallingIdentity(() -> {
for (int i = 0; i < mStatusCallbacks.length; i++) {
mStatusCallbacks[i].onReportStatus(gnssStatus);
}
});
}
@NativeEntryPoint
void reportSvStatus(int svCount, int[] svidWithFlags, float[] cn0DbHzs,
float[] elevations, float[] azimuths, float[] carrierFrequencies,
float[] basebandCn0DbHzs) {
Binder.withCleanCallingIdentity(() -> {
GnssStatus gnssStatus = GnssStatus.wrap(svCount, svidWithFlags, cn0DbHzs, elevations,
azimuths, carrierFrequencies, basebandCn0DbHzs);
for (int i = 0; i < mSvStatusCallbacks.length; i++) {
mSvStatusCallbacks[i].onReportSvStatus(gnssStatus);
}
});
}
@NativeEntryPoint
void reportAGpsStatus(int agpsType, int agpsStatus, byte[] suplIpAddr) {
Binder.withCleanCallingIdentity(
() -> mAGpsCallbacks.onReportAGpsStatus(agpsType, agpsStatus, suplIpAddr));
}
@NativeEntryPoint
void reportNmea(long timestamp) {
Binder.withCleanCallingIdentity(() -> {
if (mItarSpeedLimitExceeded) {
return;
}
for (int i = 0; i < mNmeaCallbacks.length; i++) {
mNmeaCallbacks[i].onReportNmea(timestamp);
}
});
}
@NativeEntryPoint
void reportMeasurementData(GnssMeasurementsEvent event) {
Binder.withCleanCallingIdentity(() -> {
if (mItarSpeedLimitExceeded) {
return;
}
for (int i = 0; i < mMeasurementCallbacks.length; i++) {
mMeasurementCallbacks[i].onReportMeasurements(event);
}
});
}
@NativeEntryPoint
void reportAntennaInfo(List<GnssAntennaInfo> antennaInfos) {
Binder.withCleanCallingIdentity(() -> {
for (int i = 0; i < mAntennaInfoCallbacks.length; i++) {
mAntennaInfoCallbacks[i].onReportAntennaInfo(antennaInfos);
}
});
}
@NativeEntryPoint
void reportNavigationMessage(GnssNavigationMessage event) {
Binder.withCleanCallingIdentity(() -> {
if (mItarSpeedLimitExceeded) {
return;
}
for (int i = 0; i < mNavigationMessageCallbacks.length; i++) {
mNavigationMessageCallbacks[i].onReportNavigationMessage(event);
}
});
}
@NativeEntryPoint
void setTopHalCapabilities(@GnssCapabilities.TopHalCapabilityFlags int capabilities) {
// Here the bits specified by 'capabilities' are turned on. It is handled differently from
// sub hal because top hal capabilities could be set by HIDL HAL and/or AIDL HAL. Each of
// them possesses a different set of capabilities.
mTopFlags |= capabilities;
GnssCapabilities oldCapabilities = mCapabilities;
mCapabilities = oldCapabilities.withTopHalFlags(mTopFlags);
onCapabilitiesChanged(oldCapabilities, mCapabilities);
}
@NativeEntryPoint
void setSubHalMeasurementCorrectionsCapabilities(
@GnssCapabilities.SubHalMeasurementCorrectionsCapabilityFlags int capabilities) {
GnssCapabilities oldCapabilities = mCapabilities;
mCapabilities = oldCapabilities.withSubHalMeasurementCorrectionsFlags(capabilities);
onCapabilitiesChanged(oldCapabilities, mCapabilities);
}
@NativeEntryPoint
void setSubHalPowerIndicationCapabilities(
@GnssCapabilities.SubHalPowerCapabilityFlags int capabilities) {
GnssCapabilities oldCapabilities = mCapabilities;
mCapabilities = oldCapabilities.withSubHalPowerFlags(capabilities);
onCapabilitiesChanged(oldCapabilities, mCapabilities);
}
private void onCapabilitiesChanged(GnssCapabilities oldCapabilities,
GnssCapabilities newCapabilities) {
Binder.withCleanCallingIdentity(() -> {
if (newCapabilities.equals(oldCapabilities)) {
return;
}
Log.i(TAG, "gnss capabilities changed to " + newCapabilities);
for (int i = 0; i < mBaseCallbacks.length; i++) {
mBaseCallbacks[i].onCapabilitiesChanged(oldCapabilities, newCapabilities);
}
});
}
@NativeEntryPoint
void reportGnssPowerStats(GnssPowerStats powerStats) {
mPowerStats = powerStats;
}
@NativeEntryPoint
void setGnssYearOfHardware(int year) {
mHardwareYear = year;
}
@NativeEntryPoint
private void setGnssHardwareModelName(String modelName) {
mHardwareModelName = modelName;
}
@NativeEntryPoint
void reportLocationBatch(Location[] locations) {
Binder.withCleanCallingIdentity(() -> {
for (int i = 0; i < mLocationCallbacks.length; i++) {
mLocationCallbacks[i].onReportLocations(locations);
}
});
}
@NativeEntryPoint
void psdsDownloadRequest(int psdsType) {
Binder.withCleanCallingIdentity(() -> mPsdsCallbacks.onRequestPsdsDownload(psdsType));
}
@NativeEntryPoint
void reportGeofenceTransition(int geofenceId, Location location, int transition,
long transitionTimestamp) {
Binder.withCleanCallingIdentity(
() -> mGeofenceCallbacks.onReportGeofenceTransition(geofenceId, location,
transition, transitionTimestamp));
}
@NativeEntryPoint
void reportGeofenceStatus(int status, Location location) {
Binder.withCleanCallingIdentity(
() -> mGeofenceCallbacks.onReportGeofenceStatus(status, location));
}
@NativeEntryPoint
void reportGeofenceAddStatus(int geofenceId, @GeofenceCallbacks.GeofenceStatus int status) {
Binder.withCleanCallingIdentity(
() -> mGeofenceCallbacks.onReportGeofenceAddStatus(geofenceId, status));
}
@NativeEntryPoint
void reportGeofenceRemoveStatus(int geofenceId, @GeofenceCallbacks.GeofenceStatus int status) {
Binder.withCleanCallingIdentity(
() -> mGeofenceCallbacks.onReportGeofenceRemoveStatus(geofenceId, status));
}
@NativeEntryPoint
void reportGeofencePauseStatus(int geofenceId, @GeofenceCallbacks.GeofenceStatus int status) {
Binder.withCleanCallingIdentity(
() -> mGeofenceCallbacks.onReportGeofencePauseStatus(geofenceId, status));
}
@NativeEntryPoint
void reportGeofenceResumeStatus(int geofenceId, @GeofenceCallbacks.GeofenceStatus int status) {
Binder.withCleanCallingIdentity(
() -> mGeofenceCallbacks.onReportGeofenceResumeStatus(geofenceId, status));
}
@NativeEntryPoint
void reportNiNotification(int notificationId, int niType, int notifyFlags,
int timeout, int defaultResponse, String requestorId, String text,
int requestorIdEncoding, int textEncoding) {
Binder.withCleanCallingIdentity(
() -> mNotificationCallbacks.onReportNiNotification(notificationId, niType,
notifyFlags, timeout, defaultResponse, requestorId, text,
requestorIdEncoding, textEncoding));
}
@NativeEntryPoint
void requestSetID(int flags) {
Binder.withCleanCallingIdentity(() -> mAGpsCallbacks.onRequestSetID(flags));
}
@NativeEntryPoint
void requestLocation(boolean independentFromGnss, boolean isUserEmergency) {
Binder.withCleanCallingIdentity(
() -> mLocationRequestCallbacks.onRequestLocation(independentFromGnss,
isUserEmergency));
}
@NativeEntryPoint
void requestUtcTime() {
Binder.withCleanCallingIdentity(() -> mTimeCallbacks.onRequestUtcTime());
}
@NativeEntryPoint
void requestRefLocation() {
Binder.withCleanCallingIdentity(
() -> mLocationRequestCallbacks.onRequestRefLocation());
}
@NativeEntryPoint
void reportNfwNotification(String proxyAppPackageName, byte protocolStack,
String otherProtocolStackName, byte requestor, String requestorId,
byte responseType, boolean inEmergencyMode, boolean isCachedLocation) {
Binder.withCleanCallingIdentity(
() -> mNotificationCallbacks.onReportNfwNotification(proxyAppPackageName,
protocolStack, otherProtocolStackName, requestor, requestorId, responseType,
inEmergencyMode, isCachedLocation));
}
@NativeEntryPoint
boolean isInEmergencySession() {
return Binder.withCleanCallingIdentity(
() -> mEmergencyHelper.isInEmergency(mConfiguration.getEsExtensionSec()));
}
/**
* Encapsulates actual HAL methods for testing purposes.
*/
@VisibleForTesting
public static class GnssHal {
protected GnssHal() {}
protected void classInitOnce() {
native_class_init_once();
}
protected boolean isSupported() {
return native_is_supported();
}
protected void initOnce(GnssNative gnssNative, boolean reinitializeGnssServiceHandle) {
gnssNative.native_init_once(reinitializeGnssServiceHandle);
}
protected boolean init() {
return native_init();
}
protected void cleanup() {
native_cleanup();
}
protected boolean start() {
return native_start();
}
protected boolean stop() {
return native_stop();
}
protected boolean setPositionMode(@GnssPositionMode int mode,
@GnssPositionRecurrence int recurrence, int minInterval, int preferredAccuracy,
int preferredTime, boolean lowPowerMode) {
return native_set_position_mode(mode, recurrence, minInterval, preferredAccuracy,
preferredTime, lowPowerMode);
}
protected String getInternalState() {
return native_get_internal_state();
}
protected void deleteAidingData(@GnssAidingTypeFlags int flags) {
native_delete_aiding_data(flags);
}
protected int readNmea(byte[] buffer, int bufferSize) {
return native_read_nmea(buffer, bufferSize);
}
protected void injectLocation(double latitude, double longitude, float accuracy) {
native_inject_location(latitude, longitude, accuracy);
}
protected void injectBestLocation(@GnssLocationFlags int gnssLocationFlags, double latitude,
double longitude, double altitude, float speed, float bearing,
float horizontalAccuracy, float verticalAccuracy, float speedAccuracy,
float bearingAccuracy, long timestamp, @GnssRealtimeFlags int elapsedRealtimeFlags,
long elapsedRealtimeNanos, double elapsedRealtimeUncertaintyNanos) {
native_inject_best_location(gnssLocationFlags, latitude, longitude, altitude, speed,
bearing, horizontalAccuracy, verticalAccuracy, speedAccuracy, bearingAccuracy,
timestamp, elapsedRealtimeFlags, elapsedRealtimeNanos,
elapsedRealtimeUncertaintyNanos);
}
protected void injectTime(long time, long timeReference, int uncertainty) {
native_inject_time(time, timeReference, uncertainty);
}
protected boolean isNavigationMessageCollectionSupported() {
return native_is_navigation_message_supported();
}
protected boolean startNavigationMessageCollection() {
return native_start_navigation_message_collection();
}
protected boolean stopNavigationMessageCollection() {
return native_stop_navigation_message_collection();
}
protected boolean isAntennaInfoSupported() {
return native_is_antenna_info_supported();
}
protected boolean startAntennaInfoListening() {
return native_start_antenna_info_listening();
}
protected boolean stopAntennaInfoListening() {
return native_stop_antenna_info_listening();
}
protected boolean isMeasurementSupported() {
return native_is_measurement_supported();
}
protected boolean startMeasurementCollection(boolean enableFullTracking,
boolean enableCorrVecOutputs) {
return native_start_measurement_collection(enableFullTracking, enableCorrVecOutputs);
}
protected boolean stopMeasurementCollection() {
return native_stop_measurement_collection();
}
protected boolean isMeasurementCorrectionsSupported() {
return native_is_measurement_corrections_supported();
}
protected boolean injectMeasurementCorrections(GnssMeasurementCorrections corrections) {
return native_inject_measurement_corrections(corrections);
}
protected int getBatchSize() {
return native_get_batch_size();
}
protected boolean initBatching() {
return native_init_batching();
}
protected void cleanupBatching() {
native_cleanup_batching();
}
protected boolean startBatch(long periodNanos, boolean wakeOnFifoFull) {
return native_start_batch(periodNanos, wakeOnFifoFull);
}
protected void flushBatch() {
native_flush_batch();
}
protected void stopBatch() {
native_stop_batch();
}
protected boolean isGeofencingSupported() {
return native_is_geofence_supported();
}
protected boolean addGeofence(int geofenceId, double latitude, double longitude,
double radius, int lastTransition, int monitorTransitions,
int notificationResponsiveness, int unknownTimer) {
return native_add_geofence(geofenceId, latitude, longitude, radius, lastTransition,
monitorTransitions, notificationResponsiveness, unknownTimer);
}
protected boolean resumeGeofence(int geofenceId, int monitorTransitions) {
return native_resume_geofence(geofenceId, monitorTransitions);
}
protected boolean pauseGeofence(int geofenceId) {
return native_pause_geofence(geofenceId);
}
protected boolean removeGeofence(int geofenceId) {
return native_remove_geofence(geofenceId);
}
protected boolean isGnssVisibilityControlSupported() {
return native_is_gnss_visibility_control_supported();
}
protected void sendNiResponse(int notificationId, int userResponse) {
native_send_ni_response(notificationId, userResponse);
}
protected void requestPowerStats() {
native_request_power_stats();
}
protected void setAgpsServer(int type, String hostname, int port) {
native_set_agps_server(type, hostname, port);
}
protected void setAgpsSetId(@AgpsSetIdType int type, String setId) {
native_agps_set_id(type, setId);
}
protected void setAgpsReferenceLocationCellId(@AgpsReferenceLocationType int type, int mcc,
int mnc, int lac, int cid) {
native_agps_set_ref_location_cellid(type, mcc, mnc, lac, cid);
}
protected boolean isPsdsSupported() {
return native_supports_psds();
}
protected void injectPsdsData(byte[] data, int length, int psdsType) {
native_inject_psds_data(data, length, psdsType);
}
}
// basic APIs
private static native void native_class_init_once();
private static native boolean native_is_supported();
private native void native_init_once(boolean reinitializeGnssServiceHandle);
private static native boolean native_init();
private static native void native_cleanup();
private static native boolean native_start();
private static native boolean native_stop();
private static native boolean native_set_position_mode(int mode, int recurrence,
int minInterval, int preferredAccuracy, int preferredTime, boolean lowPowerMode);
private static native String native_get_internal_state();
private static native void native_delete_aiding_data(int flags);
// NMEA APIs
private static native int native_read_nmea(byte[] buffer, int bufferSize);
// location injection APIs
private static native void native_inject_location(double latitude, double longitude,
float accuracy);
private static native void native_inject_best_location(
int gnssLocationFlags, double latitudeDegrees, double longitudeDegrees,
double altitudeMeters, float speedMetersPerSec, float bearingDegrees,
float horizontalAccuracyMeters, float verticalAccuracyMeters,
float speedAccuracyMetersPerSecond, float bearingAccuracyDegrees,
long timestamp, int elapsedRealtimeFlags, long elapsedRealtimeNanos,
double elapsedRealtimeUncertaintyNanos);
// time injection APIs
private static native void native_inject_time(long time, long timeReference, int uncertainty);
// navigation message APIs
private static native boolean native_is_navigation_message_supported();
private static native boolean native_start_navigation_message_collection();
private static native boolean native_stop_navigation_message_collection();
// antenna info APIS
// TODO: in a next version of the HAL, consider removing the necessity for listening to antenna
// info changes, and simply report them always, same as capabilities.
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();
// measurement APIs
private static native boolean native_is_measurement_supported();
private static native boolean native_start_measurement_collection(boolean enableFullTracking,
boolean enableCorrVecOutputs);
private static native boolean native_stop_measurement_collection();
// measurement corrections APIs
private static native boolean native_is_measurement_corrections_supported();
private static native boolean native_inject_measurement_corrections(
GnssMeasurementCorrections corrections);
// batching APIs
private static native boolean native_init_batching();
private static native void native_cleanup_batching();
private static native boolean native_start_batch(long periodNanos, boolean wakeOnFifoFull);
private static native void native_flush_batch();
private static native boolean native_stop_batch();
private static native int native_get_batch_size();
// geofence APIs
private static native boolean native_is_geofence_supported();
private static native boolean native_add_geofence(int geofenceId, double latitude,
double longitude, double radius, int lastTransition, int monitorTransitions,
int notificationResponsivenes, int unknownTimer);
private static native boolean native_resume_geofence(int geofenceId, int monitorTransitions);
private static native boolean native_pause_geofence(int geofenceId);
private static native boolean native_remove_geofence(int geofenceId);
// network initiated (NI) APIs
private static native boolean native_is_gnss_visibility_control_supported();
private static native void native_send_ni_response(int notificationId, int userResponse);
// power stats APIs
private static native void native_request_power_stats();
// AGPS APIs
private static native void native_set_agps_server(int type, String hostname, int port);
private static native void native_agps_set_id(int type, String setid);
private static native void native_agps_set_ref_location_cellid(int type, int mcc, int mnc,
int lac, int cid);
// PSDS APIs
private static native boolean native_supports_psds();
private static native void native_inject_psds_data(byte[] data, int length, int psdsType);
}