1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.location.gnss.hal;
18 
19 import static com.android.server.location.gnss.GnssManagerService.TAG;
20 
21 import android.annotation.CallbackExecutor;
22 import android.annotation.IntDef;
23 import android.annotation.NonNull;
24 import android.annotation.Nullable;
25 import android.location.GnssAntennaInfo;
26 import android.location.GnssCapabilities;
27 import android.location.GnssMeasurementCorrections;
28 import android.location.GnssMeasurementsEvent;
29 import android.location.GnssNavigationMessage;
30 import android.location.GnssSignalType;
31 import android.location.GnssStatus;
32 import android.location.Location;
33 import android.os.Binder;
34 import android.os.Handler;
35 import android.os.SystemClock;
36 import android.util.Log;
37 
38 import com.android.internal.annotations.GuardedBy;
39 import com.android.internal.annotations.VisibleForTesting;
40 import com.android.internal.util.ArrayUtils;
41 import com.android.internal.util.Preconditions;
42 import com.android.server.FgThread;
43 import com.android.server.location.gnss.GnssConfiguration;
44 import com.android.server.location.gnss.GnssPowerStats;
45 import com.android.server.location.injector.EmergencyHelper;
46 import com.android.server.location.injector.Injector;
47 
48 import java.lang.annotation.ElementType;
49 import java.lang.annotation.Retention;
50 import java.lang.annotation.RetentionPolicy;
51 import java.lang.annotation.Target;
52 import java.util.ArrayList;
53 import java.util.List;
54 import java.util.Objects;
55 import java.util.concurrent.CountDownLatch;
56 import java.util.concurrent.Executor;
57 import java.util.concurrent.TimeUnit;
58 import java.util.concurrent.atomic.AtomicReference;
59 
60 /**
61  * Entry point for most GNSS HAL commands and callbacks.
62  */
63 public class GnssNative {
64 
65     // IMPORTANT - must match GnssPositionMode enum in IGnss.hal
66     public static final int GNSS_POSITION_MODE_STANDALONE = 0;
67     public static final int GNSS_POSITION_MODE_MS_BASED = 1;
68     public static final int GNSS_POSITION_MODE_MS_ASSISTED = 2;
69 
70     @IntDef(prefix = "GNSS_POSITION_MODE_", value = {GNSS_POSITION_MODE_STANDALONE,
71             GNSS_POSITION_MODE_MS_BASED, GNSS_POSITION_MODE_MS_ASSISTED})
72     @Retention(RetentionPolicy.SOURCE)
73     public @interface GnssPositionMode {}
74 
75     // IMPORTANT - must match GnssPositionRecurrence enum in IGnss.hal
76     public static final int GNSS_POSITION_RECURRENCE_PERIODIC = 0;
77     public static final int GNSS_POSITION_RECURRENCE_SINGLE = 1;
78 
79     @IntDef(prefix = "GNSS_POSITION_RECURRENCE_", value = {GNSS_POSITION_RECURRENCE_PERIODIC,
80             GNSS_POSITION_RECURRENCE_SINGLE})
81     @Retention(RetentionPolicy.SOURCE)
82     public @interface GnssPositionRecurrence {}
83 
84     // IMPORTANT - must match the GnssLocationFlags enum in types.hal
85     public static final int GNSS_LOCATION_HAS_LAT_LONG = 1;
86     public static final int GNSS_LOCATION_HAS_ALTITUDE = 2;
87     public static final int GNSS_LOCATION_HAS_SPEED = 4;
88     public static final int GNSS_LOCATION_HAS_BEARING = 8;
89     public static final int GNSS_LOCATION_HAS_HORIZONTAL_ACCURACY = 16;
90     public static final int GNSS_LOCATION_HAS_VERTICAL_ACCURACY = 32;
91     public static final int GNSS_LOCATION_HAS_SPEED_ACCURACY = 64;
92     public static final int GNSS_LOCATION_HAS_BEARING_ACCURACY = 128;
93 
94     @IntDef(flag = true, prefix = "GNSS_LOCATION_", value = {GNSS_LOCATION_HAS_LAT_LONG,
95             GNSS_LOCATION_HAS_ALTITUDE, GNSS_LOCATION_HAS_SPEED, GNSS_LOCATION_HAS_BEARING,
96             GNSS_LOCATION_HAS_HORIZONTAL_ACCURACY, GNSS_LOCATION_HAS_VERTICAL_ACCURACY,
97             GNSS_LOCATION_HAS_SPEED_ACCURACY, GNSS_LOCATION_HAS_BEARING_ACCURACY})
98     @Retention(RetentionPolicy.SOURCE)
99     public @interface GnssLocationFlags {}
100 
101     // IMPORTANT - must match the ElapsedRealtimeFlags enum in types.hal
102     public static final int GNSS_REALTIME_HAS_TIMESTAMP_NS = 1;
103     public static final int GNSS_REALTIME_HAS_TIME_UNCERTAINTY_NS = 2;
104 
105     @IntDef(flag = true, value = {GNSS_REALTIME_HAS_TIMESTAMP_NS,
106             GNSS_REALTIME_HAS_TIME_UNCERTAINTY_NS})
107     @Retention(RetentionPolicy.SOURCE)
108     public @interface GnssRealtimeFlags {}
109 
110     // IMPORTANT - must match the GnssAidingData enum in IGnss.hal
111     public static final int GNSS_AIDING_TYPE_EPHEMERIS = 0x0001;
112     public static final int GNSS_AIDING_TYPE_ALMANAC = 0x0002;
113     public static final int GNSS_AIDING_TYPE_POSITION = 0x0004;
114     public static final int GNSS_AIDING_TYPE_TIME = 0x0008;
115     public static final int GNSS_AIDING_TYPE_IONO = 0x0010;
116     public static final int GNSS_AIDING_TYPE_UTC = 0x0020;
117     public static final int GNSS_AIDING_TYPE_HEALTH = 0x0040;
118     public static final int GNSS_AIDING_TYPE_SVDIR = 0x0080;
119     public static final int GNSS_AIDING_TYPE_SVSTEER = 0x0100;
120     public static final int GNSS_AIDING_TYPE_SADATA = 0x0200;
121     public static final int GNSS_AIDING_TYPE_RTI = 0x0400;
122     public static final int GNSS_AIDING_TYPE_CELLDB_INFO = 0x8000;
123     public static final int GNSS_AIDING_TYPE_ALL = 0xFFFF;
124 
125     @IntDef(flag = true, prefix = "GNSS_AIDING_", value = {GNSS_AIDING_TYPE_EPHEMERIS,
126             GNSS_AIDING_TYPE_ALMANAC, GNSS_AIDING_TYPE_POSITION, GNSS_AIDING_TYPE_TIME,
127             GNSS_AIDING_TYPE_IONO, GNSS_AIDING_TYPE_UTC, GNSS_AIDING_TYPE_HEALTH,
128             GNSS_AIDING_TYPE_SVDIR, GNSS_AIDING_TYPE_SVSTEER, GNSS_AIDING_TYPE_SADATA,
129             GNSS_AIDING_TYPE_RTI, GNSS_AIDING_TYPE_CELLDB_INFO, GNSS_AIDING_TYPE_ALL})
130     @Retention(RetentionPolicy.SOURCE)
131     public @interface GnssAidingTypeFlags {}
132 
133     // IMPORTANT - must match OEM definitions, this isn't part of a hal for some reason
134     public static final int AGPS_REF_LOCATION_TYPE_GSM_CELLID = 1;
135     public static final int AGPS_REF_LOCATION_TYPE_UMTS_CELLID = 2;
136     public static final int AGPS_REF_LOCATION_TYPE_LTE_CELLID = 4;
137     public static final int AGPS_REF_LOCATION_TYPE_NR_CELLID = 8;
138 
139     @IntDef(prefix = "AGPS_REF_LOCATION_TYPE_", value = {AGPS_REF_LOCATION_TYPE_GSM_CELLID,
140             AGPS_REF_LOCATION_TYPE_UMTS_CELLID, AGPS_REF_LOCATION_TYPE_LTE_CELLID,
141             AGPS_REF_LOCATION_TYPE_NR_CELLID})
142     @Retention(RetentionPolicy.SOURCE)
143     public @interface AgpsReferenceLocationType {}
144 
145     // IMPORTANT - must match OEM definitions, this isn't part of a hal for some reason
146     public static final int AGPS_SETID_TYPE_NONE = 0;
147     public static final int AGPS_SETID_TYPE_IMSI = 1;
148     public static final int AGPS_SETID_TYPE_MSISDN = 2;
149 
150     private static final int POWER_STATS_REQUEST_TIMEOUT_MILLIS = 100;
151 
152     @IntDef(prefix = "AGPS_SETID_TYPE_", value = {AGPS_SETID_TYPE_NONE, AGPS_SETID_TYPE_IMSI,
153             AGPS_SETID_TYPE_MSISDN})
154     @Retention(RetentionPolicy.SOURCE)
155     public @interface AgpsSetIdType {}
156 
157     /** Callbacks relevant to the entire HAL. */
158     public interface BaseCallbacks {
onHalStarted()159         default void onHalStarted() {}
onHalRestarted()160         void onHalRestarted();
onCapabilitiesChanged(GnssCapabilities oldCapabilities, GnssCapabilities newCapabilities)161         default void onCapabilitiesChanged(GnssCapabilities oldCapabilities,
162                 GnssCapabilities newCapabilities) {}
163     }
164 
165     /** Callbacks for status events. */
166     public interface StatusCallbacks {
167 
168         // IMPORTANT - must match GnssStatusValue enum in IGnssCallback.hal
169         int GNSS_STATUS_NONE = 0;
170         int GNSS_STATUS_SESSION_BEGIN = 1;
171         int GNSS_STATUS_SESSION_END = 2;
172         int GNSS_STATUS_ENGINE_ON = 3;
173         int GNSS_STATUS_ENGINE_OFF = 4;
174 
175         @IntDef(prefix = "GNSS_STATUS_", value = {GNSS_STATUS_NONE, GNSS_STATUS_SESSION_BEGIN,
176                 GNSS_STATUS_SESSION_END, GNSS_STATUS_ENGINE_ON, GNSS_STATUS_ENGINE_OFF})
177         @Retention(RetentionPolicy.SOURCE)
178         @interface GnssStatusValue {}
179 
onReportStatus(@nssStatusValue int status)180         void onReportStatus(@GnssStatusValue int status);
onReportFirstFix(int ttff)181         void onReportFirstFix(int ttff);
182     }
183 
184     /** Callbacks for SV status events. */
185     public interface SvStatusCallbacks {
onReportSvStatus(GnssStatus gnssStatus)186         void onReportSvStatus(GnssStatus gnssStatus);
187     }
188 
189     /** Callbacks for NMEA events. */
190     public interface NmeaCallbacks {
onReportNmea(long timestamp)191         void onReportNmea(long timestamp);
192     }
193 
194     /** Callbacks for location events. */
195     public interface LocationCallbacks {
onReportLocation(boolean hasLatLong, Location location)196         void onReportLocation(boolean hasLatLong, Location location);
onReportLocations(Location[] locations)197         void onReportLocations(Location[] locations);
198     }
199 
200     /** Callbacks for measurement events. */
201     public interface MeasurementCallbacks {
onReportMeasurements(GnssMeasurementsEvent event)202         void onReportMeasurements(GnssMeasurementsEvent event);
203     }
204 
205     /** Callbacks for antenna info events. */
206     public interface AntennaInfoCallbacks {
onReportAntennaInfo(List<GnssAntennaInfo> antennaInfos)207         void onReportAntennaInfo(List<GnssAntennaInfo> antennaInfos);
208     }
209 
210     /** Callbacks for navigation message events. */
211     public interface NavigationMessageCallbacks {
onReportNavigationMessage(GnssNavigationMessage event)212         void onReportNavigationMessage(GnssNavigationMessage event);
213     }
214 
215     /** Callbacks for geofence events. */
216     public interface GeofenceCallbacks {
217 
218         // IMPORTANT - must match GeofenceTransition enum in IGnssGeofenceCallback.hal
219         int GEOFENCE_TRANSITION_ENTERED = 1 << 0L;
220         int GEOFENCE_TRANSITION_EXITED = 1 << 1L;
221         int GEOFENCE_TRANSITION_UNCERTAIN = 1 << 2L;
222 
223         @IntDef(prefix = "GEOFENCE_TRANSITION_", value = {GEOFENCE_TRANSITION_ENTERED,
224                 GEOFENCE_TRANSITION_EXITED, GEOFENCE_TRANSITION_UNCERTAIN})
225         @Retention(RetentionPolicy.SOURCE)
226         @interface GeofenceTransition {}
227 
228         // IMPORTANT - must match GeofenceAvailability enum in IGnssGeofenceCallback.hal
229         int GEOFENCE_AVAILABILITY_UNAVAILABLE = 1 << 0L;
230         int GEOFENCE_AVAILABILITY_AVAILABLE = 1 << 1L;
231 
232         @IntDef(prefix = "GEOFENCE_AVAILABILITY_", value = {GEOFENCE_AVAILABILITY_UNAVAILABLE,
233                 GEOFENCE_AVAILABILITY_AVAILABLE})
234         @Retention(RetentionPolicy.SOURCE)
235         @interface GeofenceAvailability {}
236 
237         // IMPORTANT - must match GeofenceStatus enum in IGnssGeofenceCallback.hal
238         int GEOFENCE_STATUS_OPERATION_SUCCESS = 0;
239         int GEOFENCE_STATUS_ERROR_TOO_MANY_GEOFENCES = 100;
240         int GEOFENCE_STATUS_ERROR_ID_EXISTS = -101;
241         int GEOFENCE_STATUS_ERROR_ID_UNKNOWN = -102;
242         int GEOFENCE_STATUS_ERROR_INVALID_TRANSITION = -103;
243         int GEOFENCE_STATUS_ERROR_GENERIC = -149;
244 
245         @IntDef(prefix = "GEOFENCE_STATUS_", value = {GEOFENCE_STATUS_OPERATION_SUCCESS,
246                 GEOFENCE_STATUS_ERROR_TOO_MANY_GEOFENCES, GEOFENCE_STATUS_ERROR_ID_EXISTS,
247                 GEOFENCE_STATUS_ERROR_ID_UNKNOWN, GEOFENCE_STATUS_ERROR_INVALID_TRANSITION,
248                 GEOFENCE_STATUS_ERROR_GENERIC})
249         @Retention(RetentionPolicy.SOURCE)
250         @interface GeofenceStatus {}
251 
onReportGeofenceTransition(int geofenceId, Location location, @GeofenceTransition int transition, long timestamp)252         void onReportGeofenceTransition(int geofenceId, Location location,
253                 @GeofenceTransition int transition, long timestamp);
onReportGeofenceStatus(@eofenceAvailability int availabilityStatus, Location location)254         void onReportGeofenceStatus(@GeofenceAvailability int availabilityStatus,
255                 Location location);
onReportGeofenceAddStatus(int geofenceId, @GeofenceStatus int status)256         void onReportGeofenceAddStatus(int geofenceId, @GeofenceStatus int status);
onReportGeofenceRemoveStatus(int geofenceId, @GeofenceStatus int status)257         void onReportGeofenceRemoveStatus(int geofenceId, @GeofenceStatus int status);
onReportGeofencePauseStatus(int geofenceId, @GeofenceStatus int status)258         void onReportGeofencePauseStatus(int geofenceId, @GeofenceStatus int status);
onReportGeofenceResumeStatus(int geofenceId, @GeofenceStatus int status)259         void onReportGeofenceResumeStatus(int geofenceId, @GeofenceStatus int status);
260     }
261 
262     /** Callbacks for the HAL requesting time. */
263     public interface TimeCallbacks {
onRequestUtcTime()264         void onRequestUtcTime();
265     }
266 
267     /** Callbacks for the HAL requesting locations. */
268     public interface LocationRequestCallbacks {
onRequestLocation(boolean independentFromGnss, boolean isUserEmergency)269         void onRequestLocation(boolean independentFromGnss, boolean isUserEmergency);
onRequestRefLocation()270         void onRequestRefLocation();
271     }
272 
273     /** Callbacks for HAL requesting PSDS download. */
274     public interface PsdsCallbacks {
onRequestPsdsDownload(int psdsType)275         void onRequestPsdsDownload(int psdsType);
276     }
277 
278     /** Callbacks for AGPS functionality. */
279     public interface AGpsCallbacks {
280 
281         // IMPORTANT - must match OEM definitions, this isn't part of a hal for some reason
282         int AGPS_REQUEST_SETID_IMSI = 1 << 0L;
283         int AGPS_REQUEST_SETID_MSISDN = 1 << 1L;
284 
285         @IntDef(flag = true, prefix = "AGPS_REQUEST_SETID_", value = {AGPS_REQUEST_SETID_IMSI,
286                 AGPS_REQUEST_SETID_MSISDN})
287         @Retention(RetentionPolicy.SOURCE)
288         @interface AgpsSetIdFlags {}
289 
onReportAGpsStatus(int agpsType, int agpsStatus, byte[] suplIpAddr)290         void onReportAGpsStatus(int agpsType, int agpsStatus, byte[] suplIpAddr);
onRequestSetID(@gpsSetIdFlags int flags)291         void onRequestSetID(@AgpsSetIdFlags int flags);
292     }
293 
294     /** Callbacks for notifications. */
295     public interface NotificationCallbacks {
onReportNfwNotification(String proxyAppPackageName, byte protocolStack, String otherProtocolStackName, byte requestor, String requestorId, byte responseType, boolean inEmergencyMode, boolean isCachedLocation)296         void onReportNfwNotification(String proxyAppPackageName, byte protocolStack,
297                 String otherProtocolStackName, byte requestor, String requestorId,
298                 byte responseType, boolean inEmergencyMode, boolean isCachedLocation);
299     }
300 
301     /** Callback for reporting {@link GnssPowerStats} */
302     public interface PowerStatsCallback {
303         /**
304          * Called when power stats are reported.
305          * @param powerStats non-null value when power stats are available, {@code null} otherwise.
306          */
onReportPowerStats(@ullable GnssPowerStats powerStats)307         void onReportPowerStats(@Nullable GnssPowerStats powerStats);
308     }
309 
310     // set lower than the current ITAR limit of 600m/s to allow this to trigger even if GPS HAL
311     // stops output right at 600m/s, depriving this of the information of a device that reaches
312     // greater than 600m/s, and higher than the speed of sound to avoid impacting most use cases.
313     private static final float ITAR_SPEED_LIMIT_METERS_PER_SECOND = 400.0f;
314 
315     /**
316      * Indicates that this method is a native entry point. Useful purely for IDEs which can
317      * understand entry points, and thus eliminate incorrect warnings about methods not used.
318      */
319     @Target(ElementType.METHOD)
320     @Retention(RetentionPolicy.SOURCE)
321     private @interface NativeEntryPoint {}
322 
323     @GuardedBy("GnssNative.class")
324     private static GnssHal sGnssHal;
325 
326     @GuardedBy("GnssNative.class")
327     private static boolean sGnssHalInitialized;
328 
329     @GuardedBy("GnssNative.class")
330     private static GnssNative sInstance;
331 
332     private final Handler mHandler;
333 
334     /**
335      * Sets GnssHal instance to use for testing.
336      */
337     @VisibleForTesting
setGnssHalForTest(GnssHal gnssHal)338     public static synchronized void setGnssHalForTest(GnssHal gnssHal) {
339         sGnssHal = Objects.requireNonNull(gnssHal);
340         sGnssHalInitialized = false;
341         sInstance = null;
342     }
343 
initializeHal()344     private static synchronized void initializeHal() {
345         if (!sGnssHalInitialized) {
346             if (sGnssHal == null) {
347                 sGnssHal = new GnssHal();
348             }
349             sGnssHal.classInitOnce();
350             sGnssHalInitialized = true;
351         }
352     }
353 
354     /**
355      * Returns true if GNSS is supported on this device. If true, then
356      * {@link #create(Injector, GnssConfiguration)} may be invoked.
357      */
isSupported()358     public static synchronized boolean isSupported() {
359         initializeHal();
360         return sGnssHal.isSupported();
361     }
362 
363     /**
364      * Creates a new instance of GnssNative. Should only be invoked if {@link #isSupported()} is
365      * true. May only be invoked once.
366      */
create(Injector injector, GnssConfiguration configuration)367     public static synchronized GnssNative create(Injector injector,
368             GnssConfiguration configuration) {
369         // side effect - ensures initialization
370         Preconditions.checkState(isSupported());
371         Preconditions.checkState(sInstance == null);
372         return (sInstance = new GnssNative(sGnssHal, injector, configuration));
373     }
374 
375     private final GnssHal mGnssHal;
376     private final EmergencyHelper mEmergencyHelper;
377     private final GnssConfiguration mConfiguration;
378 
379     // these callbacks may have multiple implementations
380     private BaseCallbacks[] mBaseCallbacks = new BaseCallbacks[0];
381     private StatusCallbacks[] mStatusCallbacks = new StatusCallbacks[0];
382     private SvStatusCallbacks[] mSvStatusCallbacks = new SvStatusCallbacks[0];
383     private NmeaCallbacks[] mNmeaCallbacks = new NmeaCallbacks[0];
384     private LocationCallbacks[] mLocationCallbacks = new LocationCallbacks[0];
385     private MeasurementCallbacks[] mMeasurementCallbacks = new MeasurementCallbacks[0];
386     private AntennaInfoCallbacks[] mAntennaInfoCallbacks = new AntennaInfoCallbacks[0];
387     private NavigationMessageCallbacks[] mNavigationMessageCallbacks =
388             new NavigationMessageCallbacks[0];
389 
390     private @Nullable GnssPowerStats mLastKnownPowerStats = null;
391     private final Object mPowerStatsLock = new Object();
392     private final Runnable mPowerStatsTimeoutCallback = () -> {
393         Log.d(TAG, "Request for power stats timed out");
394         reportGnssPowerStats(null);
395     };
396     private final List<PowerStatsCallback> mPendingPowerStatsCallbacks = new ArrayList<>();
397 
398     // these callbacks may only have a single implementation
399     private GeofenceCallbacks mGeofenceCallbacks;
400     private TimeCallbacks mTimeCallbacks;
401     private LocationRequestCallbacks mLocationRequestCallbacks;
402     private PsdsCallbacks mPsdsCallbacks;
403     private AGpsCallbacks mAGpsCallbacks;
404     private NotificationCallbacks mNotificationCallbacks;
405 
406     private boolean mRegistered;
407 
408     private volatile boolean mItarSpeedLimitExceeded;
409 
410     private GnssCapabilities mCapabilities = new GnssCapabilities.Builder().build();
411     private @GnssCapabilities.TopHalCapabilityFlags int mTopFlags;
412     private int mHardwareYear = 0;
413     private @Nullable String mHardwareModelName = null;
414     private long mStartRealtimeMs = 0;
415     private boolean mHasFirstFix = false;
416 
GnssNative(GnssHal gnssHal, Injector injector, GnssConfiguration configuration)417     private GnssNative(GnssHal gnssHal, Injector injector, GnssConfiguration configuration) {
418         mGnssHal = Objects.requireNonNull(gnssHal);
419         mEmergencyHelper = injector.getEmergencyHelper();
420         mConfiguration = configuration;
421         mHandler = FgThread.getHandler();
422     }
423 
addBaseCallbacks(BaseCallbacks callbacks)424     public void addBaseCallbacks(BaseCallbacks callbacks) {
425         Preconditions.checkState(!mRegistered);
426         mBaseCallbacks = ArrayUtils.appendElement(BaseCallbacks.class, mBaseCallbacks, callbacks);
427     }
428 
addStatusCallbacks(StatusCallbacks callbacks)429     public void addStatusCallbacks(StatusCallbacks callbacks) {
430         Preconditions.checkState(!mRegistered);
431         mStatusCallbacks = ArrayUtils.appendElement(StatusCallbacks.class, mStatusCallbacks,
432                 callbacks);
433     }
434 
addSvStatusCallbacks(SvStatusCallbacks callbacks)435     public void addSvStatusCallbacks(SvStatusCallbacks callbacks) {
436         Preconditions.checkState(!mRegistered);
437         mSvStatusCallbacks = ArrayUtils.appendElement(SvStatusCallbacks.class, mSvStatusCallbacks,
438                 callbacks);
439     }
440 
addNmeaCallbacks(NmeaCallbacks callbacks)441     public void addNmeaCallbacks(NmeaCallbacks callbacks) {
442         Preconditions.checkState(!mRegistered);
443         mNmeaCallbacks = ArrayUtils.appendElement(NmeaCallbacks.class, mNmeaCallbacks,
444                 callbacks);
445     }
446 
addLocationCallbacks(LocationCallbacks callbacks)447     public void addLocationCallbacks(LocationCallbacks callbacks) {
448         Preconditions.checkState(!mRegistered);
449         mLocationCallbacks = ArrayUtils.appendElement(LocationCallbacks.class, mLocationCallbacks,
450                 callbacks);
451     }
452 
addMeasurementCallbacks(MeasurementCallbacks callbacks)453     public void addMeasurementCallbacks(MeasurementCallbacks callbacks) {
454         Preconditions.checkState(!mRegistered);
455         mMeasurementCallbacks = ArrayUtils.appendElement(MeasurementCallbacks.class,
456                 mMeasurementCallbacks, callbacks);
457     }
458 
addAntennaInfoCallbacks(AntennaInfoCallbacks callbacks)459     public void addAntennaInfoCallbacks(AntennaInfoCallbacks callbacks) {
460         Preconditions.checkState(!mRegistered);
461         mAntennaInfoCallbacks = ArrayUtils.appendElement(AntennaInfoCallbacks.class,
462                 mAntennaInfoCallbacks, callbacks);
463     }
464 
addNavigationMessageCallbacks(NavigationMessageCallbacks callbacks)465     public void addNavigationMessageCallbacks(NavigationMessageCallbacks callbacks) {
466         Preconditions.checkState(!mRegistered);
467         mNavigationMessageCallbacks = ArrayUtils.appendElement(NavigationMessageCallbacks.class,
468                 mNavigationMessageCallbacks, callbacks);
469     }
470 
setGeofenceCallbacks(GeofenceCallbacks callbacks)471     public void setGeofenceCallbacks(GeofenceCallbacks callbacks) {
472         Preconditions.checkState(!mRegistered);
473         Preconditions.checkState(mGeofenceCallbacks == null);
474         mGeofenceCallbacks = Objects.requireNonNull(callbacks);
475     }
476 
setTimeCallbacks(TimeCallbacks callbacks)477     public void setTimeCallbacks(TimeCallbacks callbacks) {
478         Preconditions.checkState(!mRegistered);
479         Preconditions.checkState(mTimeCallbacks == null);
480         mTimeCallbacks = Objects.requireNonNull(callbacks);
481     }
482 
setLocationRequestCallbacks(LocationRequestCallbacks callbacks)483     public void setLocationRequestCallbacks(LocationRequestCallbacks callbacks) {
484         Preconditions.checkState(!mRegistered);
485         Preconditions.checkState(mLocationRequestCallbacks == null);
486         mLocationRequestCallbacks = Objects.requireNonNull(callbacks);
487     }
488 
setPsdsCallbacks(PsdsCallbacks callbacks)489     public void setPsdsCallbacks(PsdsCallbacks callbacks) {
490         Preconditions.checkState(!mRegistered);
491         Preconditions.checkState(mPsdsCallbacks == null);
492         mPsdsCallbacks = Objects.requireNonNull(callbacks);
493     }
494 
setAGpsCallbacks(AGpsCallbacks callbacks)495     public void setAGpsCallbacks(AGpsCallbacks callbacks) {
496         Preconditions.checkState(!mRegistered);
497         Preconditions.checkState(mAGpsCallbacks == null);
498         mAGpsCallbacks = Objects.requireNonNull(callbacks);
499     }
500 
setNotificationCallbacks(NotificationCallbacks callbacks)501     public void setNotificationCallbacks(NotificationCallbacks callbacks) {
502         Preconditions.checkState(!mRegistered);
503         Preconditions.checkState(mNotificationCallbacks == null);
504         mNotificationCallbacks = Objects.requireNonNull(callbacks);
505     }
506 
507     /**
508      * Registers with the HAL and allows callbacks to begin. Once registered with the native HAL,
509      * no more callbacks can be added or set. Must only be called once.
510      */
register()511     public void register() {
512         Preconditions.checkState(!mRegistered);
513         mRegistered = true;
514 
515         initializeGnss(false);
516         Log.i(TAG, "gnss hal started");
517 
518         for (int i = 0; i < mBaseCallbacks.length; i++) {
519             mBaseCallbacks[i].onHalStarted();
520         }
521     }
522 
initializeGnss(boolean restart)523     private void initializeGnss(boolean restart) {
524         Preconditions.checkState(mRegistered);
525         mTopFlags = 0;
526         mGnssHal.initOnce(GnssNative.this, restart);
527 
528         // gnss chipset appears to require an init/cleanup cycle on startup in order to properly
529         // initialize - undocumented and no idea why this is the case
530         if (mGnssHal.init()) {
531             mGnssHal.cleanup();
532             Log.i(TAG, "gnss hal initialized");
533         } else {
534             Log.e(TAG, "gnss hal initialization failed");
535         }
536     }
537 
getConfiguration()538     public GnssConfiguration getConfiguration() {
539         return mConfiguration;
540     }
541 
542     /**
543      * Starts up GNSS HAL, and has undocumented side effect of informing HAL that location is
544      * allowed by settings.
545      */
init()546     public boolean init() {
547         Preconditions.checkState(mRegistered);
548         return mGnssHal.init();
549     }
550 
551     /**
552      * Shuts down GNSS HAL, and has undocumented side effect of informing HAL that location is not
553      * allowed by settings.
554      */
cleanup()555     public void cleanup() {
556         Preconditions.checkState(mRegistered);
557         mGnssHal.cleanup();
558     }
559 
560     /**
561      * Returns the latest power stats from the GNSS HAL.
562      */
getLastKnownPowerStats()563     public @Nullable GnssPowerStats getLastKnownPowerStats() {
564         return mLastKnownPowerStats;
565     }
566 
567     /**
568      * Returns current capabilities of the GNSS HAL.
569      */
getCapabilities()570     public GnssCapabilities getCapabilities() {
571         return mCapabilities;
572     }
573 
574     /**
575      * Returns hardware year of GNSS chipset.
576      */
getHardwareYear()577     public int getHardwareYear() {
578         return mHardwareYear;
579     }
580 
581     /**
582      * Returns hardware model name of GNSS chipset.
583      */
getHardwareModelName()584     public @Nullable String getHardwareModelName() {
585         return mHardwareModelName;
586     }
587 
588     /**
589      * Returns true if the ITAR speed limit is currently being exceeded, and thus location
590      * information may be blocked.
591      */
isItarSpeedLimitExceeded()592     public boolean isItarSpeedLimitExceeded() {
593         return mItarSpeedLimitExceeded;
594     }
595 
596     /**
597      * Starts the GNSS HAL.
598      */
start()599     public boolean start() {
600         Preconditions.checkState(mRegistered);
601         mStartRealtimeMs = SystemClock.elapsedRealtime();
602         mHasFirstFix = false;
603         return mGnssHal.start();
604     }
605 
606     /**
607      * Stops the GNSS HAL.
608      */
stop()609     public boolean stop() {
610         Preconditions.checkState(mRegistered);
611         return mGnssHal.stop();
612     }
613 
614     /**
615      * Sets the position mode.
616      */
setPositionMode(@nssPositionMode int mode, @GnssPositionRecurrence int recurrence, int minInterval, int preferredAccuracy, int preferredTime, boolean lowPowerMode)617     public boolean setPositionMode(@GnssPositionMode int mode,
618             @GnssPositionRecurrence int recurrence, int minInterval, int preferredAccuracy,
619             int preferredTime, boolean lowPowerMode) {
620         Preconditions.checkState(mRegistered);
621         return mGnssHal.setPositionMode(mode, recurrence, minInterval, preferredAccuracy,
622                 preferredTime, lowPowerMode);
623     }
624 
625     /**
626      * Returns a debug string from the GNSS HAL.
627      */
getInternalState()628     public String getInternalState() {
629         Preconditions.checkState(mRegistered);
630         return mGnssHal.getInternalState();
631     }
632 
633     /**
634      * Deletes any aiding data specified by the given flags.
635      */
deleteAidingData(@nssAidingTypeFlags int flags)636     public void deleteAidingData(@GnssAidingTypeFlags int flags) {
637         Preconditions.checkState(mRegistered);
638         mGnssHal.deleteAidingData(flags);
639     }
640 
641     /**
642      * Reads an NMEA message into the given buffer, returning the number of bytes loaded into the
643      * buffer.
644      */
readNmea(byte[] buffer, int bufferSize)645     public int readNmea(byte[] buffer, int bufferSize) {
646         Preconditions.checkState(mRegistered);
647         return mGnssHal.readNmea(buffer, bufferSize);
648     }
649 
650     /**
651      * Injects location information into the GNSS HAL.
652      */
injectLocation(Location location)653     public void injectLocation(Location location) {
654         Preconditions.checkState(mRegistered);
655         if (location.hasAccuracy()) {
656 
657             int gnssLocationFlags = GNSS_LOCATION_HAS_LAT_LONG
658                     | (location.hasAltitude() ? GNSS_LOCATION_HAS_ALTITUDE : 0)
659                     | (location.hasSpeed() ? GNSS_LOCATION_HAS_SPEED : 0)
660                     | (location.hasBearing() ? GNSS_LOCATION_HAS_BEARING : 0)
661                     | (location.hasAccuracy() ? GNSS_LOCATION_HAS_HORIZONTAL_ACCURACY : 0)
662                     | (location.hasVerticalAccuracy() ? GNSS_LOCATION_HAS_VERTICAL_ACCURACY : 0)
663                     | (location.hasSpeedAccuracy() ? GNSS_LOCATION_HAS_SPEED_ACCURACY : 0)
664                     | (location.hasBearingAccuracy() ? GNSS_LOCATION_HAS_BEARING_ACCURACY : 0);
665 
666             double latitudeDegrees = location.getLatitude();
667             double longitudeDegrees = location.getLongitude();
668             double altitudeMeters = location.getAltitude();
669             float speedMetersPerSec = location.getSpeed();
670             float bearingDegrees = location.getBearing();
671             float horizontalAccuracyMeters = location.getAccuracy();
672             float verticalAccuracyMeters = location.getVerticalAccuracyMeters();
673             float speedAccuracyMetersPerSecond = location.getSpeedAccuracyMetersPerSecond();
674             float bearingAccuracyDegrees = location.getBearingAccuracyDegrees();
675             long timestamp = location.getTime();
676 
677             int elapsedRealtimeFlags = GNSS_REALTIME_HAS_TIMESTAMP_NS
678                     | (location.hasElapsedRealtimeUncertaintyNanos()
679                     ? GNSS_REALTIME_HAS_TIME_UNCERTAINTY_NS : 0);
680             long elapsedRealtimeNanos = location.getElapsedRealtimeNanos();
681             double elapsedRealtimeUncertaintyNanos = location.getElapsedRealtimeUncertaintyNanos();
682 
683             mGnssHal.injectLocation(gnssLocationFlags, latitudeDegrees, longitudeDegrees,
684                     altitudeMeters, speedMetersPerSec, bearingDegrees, horizontalAccuracyMeters,
685                     verticalAccuracyMeters, speedAccuracyMetersPerSecond, bearingAccuracyDegrees,
686                     timestamp, elapsedRealtimeFlags, elapsedRealtimeNanos,
687                     elapsedRealtimeUncertaintyNanos);
688         }
689     }
690 
691     /**
692      * Injects a location into the GNSS HAL in response to a HAL request for location.
693      */
injectBestLocation(Location location)694     public void injectBestLocation(Location location) {
695         Preconditions.checkState(mRegistered);
696 
697         int gnssLocationFlags = GNSS_LOCATION_HAS_LAT_LONG
698                 | (location.hasAltitude() ? GNSS_LOCATION_HAS_ALTITUDE : 0)
699                 | (location.hasSpeed() ? GNSS_LOCATION_HAS_SPEED : 0)
700                 | (location.hasBearing() ? GNSS_LOCATION_HAS_BEARING : 0)
701                 | (location.hasAccuracy() ? GNSS_LOCATION_HAS_HORIZONTAL_ACCURACY : 0)
702                 | (location.hasVerticalAccuracy() ? GNSS_LOCATION_HAS_VERTICAL_ACCURACY : 0)
703                 | (location.hasSpeedAccuracy() ? GNSS_LOCATION_HAS_SPEED_ACCURACY : 0)
704                 | (location.hasBearingAccuracy() ? GNSS_LOCATION_HAS_BEARING_ACCURACY : 0);
705 
706         double latitudeDegrees = location.getLatitude();
707         double longitudeDegrees = location.getLongitude();
708         double altitudeMeters = location.getAltitude();
709         float speedMetersPerSec = location.getSpeed();
710         float bearingDegrees = location.getBearing();
711         float horizontalAccuracyMeters = location.getAccuracy();
712         float verticalAccuracyMeters = location.getVerticalAccuracyMeters();
713         float speedAccuracyMetersPerSecond = location.getSpeedAccuracyMetersPerSecond();
714         float bearingAccuracyDegrees = location.getBearingAccuracyDegrees();
715         long timestamp = location.getTime();
716 
717         int elapsedRealtimeFlags = GNSS_REALTIME_HAS_TIMESTAMP_NS
718                 | (location.hasElapsedRealtimeUncertaintyNanos()
719                 ? GNSS_REALTIME_HAS_TIME_UNCERTAINTY_NS : 0);
720         long elapsedRealtimeNanos = location.getElapsedRealtimeNanos();
721         double elapsedRealtimeUncertaintyNanos = location.getElapsedRealtimeUncertaintyNanos();
722 
723         mGnssHal.injectBestLocation(gnssLocationFlags, latitudeDegrees, longitudeDegrees,
724                 altitudeMeters, speedMetersPerSec, bearingDegrees, horizontalAccuracyMeters,
725                 verticalAccuracyMeters, speedAccuracyMetersPerSecond, bearingAccuracyDegrees,
726                 timestamp, elapsedRealtimeFlags, elapsedRealtimeNanos,
727                 elapsedRealtimeUncertaintyNanos);
728     }
729 
730     /**
731      * Injects time information into the GNSS HAL.
732      */
injectTime(long time, long timeReference, int uncertainty)733     public void injectTime(long time, long timeReference, int uncertainty) {
734         Preconditions.checkState(mRegistered);
735         mGnssHal.injectTime(time, timeReference, uncertainty);
736     }
737 
738     /**
739      * Returns true if navigation message collection is supported.
740      */
isNavigationMessageCollectionSupported()741     public boolean isNavigationMessageCollectionSupported() {
742         Preconditions.checkState(mRegistered);
743         return mGnssHal.isNavigationMessageCollectionSupported();
744     }
745 
746     /**
747      * Starts navigation message collection.
748      */
startNavigationMessageCollection()749     public boolean startNavigationMessageCollection() {
750         Preconditions.checkState(mRegistered);
751         return mGnssHal.startNavigationMessageCollection();
752     }
753 
754     /**
755      * Stops navigation message collection.
756      */
stopNavigationMessageCollection()757     public boolean stopNavigationMessageCollection() {
758         Preconditions.checkState(mRegistered);
759         return mGnssHal.stopNavigationMessageCollection();
760     }
761 
762     /**
763      * Returns true if antenna info is supported.
764      */
isAntennaInfoSupported()765     public boolean isAntennaInfoSupported() {
766         Preconditions.checkState(mRegistered);
767         return mGnssHal.isAntennaInfoSupported();
768     }
769 
770     /**
771      * Starts antenna info listening.
772      */
startAntennaInfoListening()773     public boolean startAntennaInfoListening() {
774         Preconditions.checkState(mRegistered);
775         return mGnssHal.startAntennaInfoListening();
776     }
777 
778     /**
779      * Stops antenna info listening.
780      */
stopAntennaInfoListening()781     public boolean stopAntennaInfoListening() {
782         Preconditions.checkState(mRegistered);
783         return mGnssHal.stopAntennaInfoListening();
784     }
785 
786     /**
787      * Returns true if measurement collection is supported.
788      */
isMeasurementSupported()789     public boolean isMeasurementSupported() {
790         Preconditions.checkState(mRegistered);
791         return mGnssHal.isMeasurementSupported();
792     }
793 
794     /**
795      * Starts measurement collection.
796      */
startMeasurementCollection(boolean enableFullTracking, boolean enableCorrVecOutputs, int intervalMillis)797     public boolean startMeasurementCollection(boolean enableFullTracking,
798             boolean enableCorrVecOutputs, int intervalMillis) {
799         Preconditions.checkState(mRegistered);
800         return mGnssHal.startMeasurementCollection(enableFullTracking, enableCorrVecOutputs,
801                 intervalMillis);
802     }
803 
804     /**
805      * Stops measurement collection.
806      */
stopMeasurementCollection()807     public boolean stopMeasurementCollection() {
808         Preconditions.checkState(mRegistered);
809         return mGnssHal.stopMeasurementCollection();
810     }
811 
812     /**
813      * Starts sv status collection.
814      */
startSvStatusCollection()815     public boolean startSvStatusCollection() {
816         Preconditions.checkState(mRegistered);
817         return mGnssHal.startSvStatusCollection();
818     }
819 
820     /**
821      * Stops sv status collection.
822      */
stopSvStatusCollection()823     public boolean stopSvStatusCollection() {
824         Preconditions.checkState(mRegistered);
825         return mGnssHal.stopSvStatusCollection();
826     }
827 
828     /**
829      * Starts NMEA message collection.
830      */
startNmeaMessageCollection()831     public boolean startNmeaMessageCollection() {
832         Preconditions.checkState(mRegistered);
833         return mGnssHal.startNmeaMessageCollection();
834     }
835 
836     /**
837      * Stops NMEA message collection.
838      */
stopNmeaMessageCollection()839     public boolean stopNmeaMessageCollection() {
840         Preconditions.checkState(mRegistered);
841         return mGnssHal.stopNmeaMessageCollection();
842     }
843 
844     /**
845      * Returns true if measurement corrections are supported.
846      */
isMeasurementCorrectionsSupported()847     public boolean isMeasurementCorrectionsSupported() {
848         Preconditions.checkState(mRegistered);
849         return mGnssHal.isMeasurementCorrectionsSupported();
850     }
851 
852     /**
853      * Injects measurement corrections into the GNSS HAL.
854      */
injectMeasurementCorrections(GnssMeasurementCorrections corrections)855     public boolean injectMeasurementCorrections(GnssMeasurementCorrections corrections) {
856         Preconditions.checkState(mRegistered);
857         return mGnssHal.injectMeasurementCorrections(corrections);
858     }
859 
860     /**
861      * Initialize batching.
862      */
initBatching()863     public boolean initBatching() {
864         Preconditions.checkState(mRegistered);
865         return mGnssHal.initBatching();
866     }
867 
868     /**
869      * Cleanup batching.
870      */
cleanupBatching()871     public void cleanupBatching() {
872         Preconditions.checkState(mRegistered);
873         mGnssHal.cleanupBatching();
874     }
875 
876     /**
877      * Start batching.
878      */
startBatch(long periodNanos, float minUpdateDistanceMeters, boolean wakeOnFifoFull)879     public boolean startBatch(long periodNanos, float minUpdateDistanceMeters,
880             boolean wakeOnFifoFull) {
881         Preconditions.checkState(mRegistered);
882         return mGnssHal.startBatch(periodNanos, minUpdateDistanceMeters, wakeOnFifoFull);
883     }
884 
885     /**
886      * Flush batching.
887      */
flushBatch()888     public void flushBatch() {
889         Preconditions.checkState(mRegistered);
890         mGnssHal.flushBatch();
891     }
892 
893     /**
894      * Stop batching.
895      */
stopBatch()896     public void stopBatch() {
897         Preconditions.checkState(mRegistered);
898         mGnssHal.stopBatch();
899     }
900 
901     /**
902      * Get current batching size.
903      */
getBatchSize()904     public int getBatchSize() {
905         Preconditions.checkState(mRegistered);
906         return mGnssHal.getBatchSize();
907     }
908 
909     /**
910      * Check if GNSS geofencing is supported.
911      */
isGeofencingSupported()912     public boolean isGeofencingSupported() {
913         Preconditions.checkState(mRegistered);
914         return mGnssHal.isGeofencingSupported();
915     }
916 
917     /**
918      * Add geofence.
919      */
addGeofence(int geofenceId, double latitude, double longitude, double radius, int lastTransition, int monitorTransitions, int notificationResponsiveness, int unknownTimer)920     public boolean addGeofence(int geofenceId, double latitude, double longitude, double radius,
921             int lastTransition, int monitorTransitions, int notificationResponsiveness,
922             int unknownTimer) {
923         Preconditions.checkState(mRegistered);
924         return mGnssHal.addGeofence(geofenceId, latitude, longitude, radius, lastTransition,
925                 monitorTransitions, notificationResponsiveness, unknownTimer);
926     }
927 
928     /**
929      * Resume geofence.
930      */
resumeGeofence(int geofenceId, int monitorTransitions)931     public boolean resumeGeofence(int geofenceId, int monitorTransitions) {
932         Preconditions.checkState(mRegistered);
933         return mGnssHal.resumeGeofence(geofenceId, monitorTransitions);
934     }
935 
936     /**
937      * Pause geofence.
938      */
pauseGeofence(int geofenceId)939     public boolean pauseGeofence(int geofenceId) {
940         Preconditions.checkState(mRegistered);
941         return mGnssHal.pauseGeofence(geofenceId);
942     }
943 
944     /**
945      * Remove geofence.
946      */
removeGeofence(int geofenceId)947     public boolean removeGeofence(int geofenceId) {
948         Preconditions.checkState(mRegistered);
949         return mGnssHal.removeGeofence(geofenceId);
950     }
951 
952     /**
953      * Returns true if visibility control is supported.
954      */
isGnssVisibilityControlSupported()955     public boolean isGnssVisibilityControlSupported() {
956         Preconditions.checkState(mRegistered);
957         return mGnssHal.isGnssVisibilityControlSupported();
958     }
959 
960     /**
961      * Request an eventual update of GNSS power statistics.
962      *
963      * @param executor Executor that will run {@code callback}
964      * @param callback Called with non-null power stats if they were obtained in time, called with
965      *                 {@code null} if stats could not be obtained in time.
966      */
requestPowerStats( @onNull @allbackExecutor Executor executor, @NonNull PowerStatsCallback callback)967     public void requestPowerStats(
968             @NonNull @CallbackExecutor Executor executor,
969             @NonNull PowerStatsCallback callback) {
970         Preconditions.checkState(mRegistered);
971         synchronized (mPowerStatsLock) {
972             mPendingPowerStatsCallbacks.add(powerStats -> {
973                 Binder.withCleanCallingIdentity(
974                         () -> executor.execute(() -> callback.onReportPowerStats(powerStats)));
975             });
976             if (mPendingPowerStatsCallbacks.size() == 1) {
977                 mGnssHal.requestPowerStats();
978                 mHandler.postDelayed(mPowerStatsTimeoutCallback,
979                         POWER_STATS_REQUEST_TIMEOUT_MILLIS);
980             }
981         }
982     }
983 
984     /**
985      * Request GNSS power statistics and blocks for a short time waiting for the result.
986      *
987      * @return non-null power stats, or {@code null} if stats could not be obtained in time.
988      */
requestPowerStatsBlocking()989     public @Nullable GnssPowerStats requestPowerStatsBlocking() {
990         AtomicReference<GnssPowerStats> statsWrapper = new AtomicReference<>();
991         CountDownLatch latch = new CountDownLatch(1);
992         requestPowerStats(Runnable::run, powerStats -> {
993             statsWrapper.set(powerStats);
994             latch.countDown();
995         });
996 
997         try {
998             latch.await(POWER_STATS_REQUEST_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
999         } catch (InterruptedException e) {
1000             Log.d(TAG, "Interrupted while waiting for power stats");
1001             Thread.currentThread().interrupt();
1002         }
1003 
1004         return statsWrapper.get();
1005     }
1006 
1007     /**
1008      * Sets AGPS server information.
1009      */
setAgpsServer(int type, String hostname, int port)1010     public void setAgpsServer(int type, String hostname, int port) {
1011         Preconditions.checkState(mRegistered);
1012         mGnssHal.setAgpsServer(type, hostname, port);
1013     }
1014 
1015     /**
1016      * Sets AGPS set id.
1017      */
setAgpsSetId(@gpsSetIdType int type, String setId)1018     public void setAgpsSetId(@AgpsSetIdType int type, String setId) {
1019         Preconditions.checkState(mRegistered);
1020         mGnssHal.setAgpsSetId(type, setId);
1021     }
1022 
1023     /**
1024      * Sets AGPS reference cell id location.
1025      */
setAgpsReferenceLocationCellId(@gpsReferenceLocationType int type, int mcc, int mnc, int lac, long cid, int tac, int pcid, int arfcn)1026     public void setAgpsReferenceLocationCellId(@AgpsReferenceLocationType int type, int mcc,
1027             int mnc, int lac, long cid, int tac, int pcid, int arfcn) {
1028         Preconditions.checkState(mRegistered);
1029         mGnssHal.setAgpsReferenceLocationCellId(type, mcc, mnc, lac, cid, tac, pcid, arfcn);
1030     }
1031 
1032     /**
1033      * Returns true if Predicted Satellite Data Service APIs are supported.
1034      */
isPsdsSupported()1035     public boolean isPsdsSupported() {
1036         Preconditions.checkState(mRegistered);
1037         return mGnssHal.isPsdsSupported();
1038     }
1039 
1040     /**
1041      * Injects Predicited Satellite Data Service data into the GNSS HAL.
1042      */
injectPsdsData(byte[] data, int length, int psdsType)1043     public void injectPsdsData(byte[] data, int length, int psdsType) {
1044         Preconditions.checkState(mRegistered);
1045         mGnssHal.injectPsdsData(data, length, psdsType);
1046     }
1047 
1048     /**
1049      * Injects NI SUPL message data into the GNSS HAL.
1050      */
injectNiSuplMessageData(byte[] data, int length, int slotIndex)1051     public void injectNiSuplMessageData(byte[] data, int length, int slotIndex) {
1052         Preconditions.checkState(mRegistered);
1053         mGnssHal.injectNiSuplMessageData(data, length, slotIndex);
1054     }
1055 
1056     @NativeEntryPoint
reportGnssServiceDied()1057     void reportGnssServiceDied() {
1058         // Not necessary to clear (and restore) binder identity since it runs on another thread.
1059         Log.e(TAG, "gnss hal died - restarting shortly...");
1060 
1061         // move to another thread just in case there is some awkward gnss thread dependency with
1062         // the death notification. there shouldn't be, but you never know with gnss...
1063         FgThread.getExecutor().execute(this::restartHal);
1064     }
1065 
1066     @VisibleForTesting
restartHal()1067     void restartHal() {
1068         initializeGnss(true);
1069         Log.e(TAG, "gnss hal restarted");
1070 
1071         for (int i = 0; i < mBaseCallbacks.length; i++) {
1072             mBaseCallbacks[i].onHalRestarted();
1073         }
1074     }
1075 
1076     @NativeEntryPoint
reportLocation(boolean hasLatLong, Location location)1077     void reportLocation(boolean hasLatLong, Location location) {
1078         Binder.withCleanCallingIdentity(() -> {
1079             if (hasLatLong && !mHasFirstFix) {
1080                 mHasFirstFix = true;
1081 
1082                 // notify status listeners
1083                 int ttff = (int) (SystemClock.elapsedRealtime() - mStartRealtimeMs);
1084                 for (int i = 0; i < mStatusCallbacks.length; i++) {
1085                     mStatusCallbacks[i].onReportFirstFix(ttff);
1086                 }
1087             }
1088 
1089             if (location.hasSpeed()) {
1090                 boolean exceeded = location.getSpeed() > ITAR_SPEED_LIMIT_METERS_PER_SECOND;
1091                 if (!mItarSpeedLimitExceeded && exceeded) {
1092                     Log.w(TAG, "speed nearing ITAR threshold - blocking further GNSS output");
1093                 } else if (mItarSpeedLimitExceeded && !exceeded) {
1094                     Log.w(TAG, "speed leaving ITAR threshold - allowing further GNSS output");
1095                 }
1096                 mItarSpeedLimitExceeded = exceeded;
1097             }
1098 
1099             if (mItarSpeedLimitExceeded) {
1100                 return;
1101             }
1102 
1103             for (int i = 0; i < mLocationCallbacks.length; i++) {
1104                 mLocationCallbacks[i].onReportLocation(hasLatLong, location);
1105             }
1106         });
1107     }
1108 
1109     @NativeEntryPoint
reportStatus(@tatusCallbacks.GnssStatusValue int gnssStatus)1110     void reportStatus(@StatusCallbacks.GnssStatusValue int gnssStatus) {
1111         Binder.withCleanCallingIdentity(() -> {
1112             for (int i = 0; i < mStatusCallbacks.length; i++) {
1113                 mStatusCallbacks[i].onReportStatus(gnssStatus);
1114             }
1115         });
1116     }
1117 
1118     @NativeEntryPoint
reportSvStatus(int svCount, int[] svidWithFlags, float[] cn0DbHzs, float[] elevations, float[] azimuths, float[] carrierFrequencies, float[] basebandCn0DbHzs)1119     void reportSvStatus(int svCount, int[] svidWithFlags, float[] cn0DbHzs,
1120             float[] elevations, float[] azimuths, float[] carrierFrequencies,
1121             float[] basebandCn0DbHzs) {
1122         Binder.withCleanCallingIdentity(() -> {
1123             GnssStatus gnssStatus = GnssStatus.wrap(svCount, svidWithFlags, cn0DbHzs, elevations,
1124                     azimuths, carrierFrequencies, basebandCn0DbHzs);
1125             for (int i = 0; i < mSvStatusCallbacks.length; i++) {
1126                 mSvStatusCallbacks[i].onReportSvStatus(gnssStatus);
1127             }
1128         });
1129     }
1130 
1131     @NativeEntryPoint
reportAGpsStatus(int agpsType, int agpsStatus, byte[] suplIpAddr)1132     void reportAGpsStatus(int agpsType, int agpsStatus, byte[] suplIpAddr) {
1133         Binder.withCleanCallingIdentity(
1134                 () -> mAGpsCallbacks.onReportAGpsStatus(agpsType, agpsStatus, suplIpAddr));
1135     }
1136 
1137     @NativeEntryPoint
reportNmea(long timestamp)1138     void reportNmea(long timestamp) {
1139         Binder.withCleanCallingIdentity(() -> {
1140             if (mItarSpeedLimitExceeded) {
1141                 return;
1142             }
1143 
1144             for (int i = 0; i < mNmeaCallbacks.length; i++) {
1145                 mNmeaCallbacks[i].onReportNmea(timestamp);
1146             }
1147         });
1148     }
1149 
1150     @NativeEntryPoint
reportMeasurementData(GnssMeasurementsEvent event)1151     void reportMeasurementData(GnssMeasurementsEvent event) {
1152         Binder.withCleanCallingIdentity(() -> {
1153             if (mItarSpeedLimitExceeded) {
1154                 return;
1155             }
1156 
1157             for (int i = 0; i < mMeasurementCallbacks.length; i++) {
1158                 mMeasurementCallbacks[i].onReportMeasurements(event);
1159             }
1160         });
1161     }
1162 
1163     @NativeEntryPoint
reportAntennaInfo(List<GnssAntennaInfo> antennaInfos)1164     void reportAntennaInfo(List<GnssAntennaInfo> antennaInfos) {
1165         Binder.withCleanCallingIdentity(() -> {
1166             for (int i = 0; i < mAntennaInfoCallbacks.length; i++) {
1167                 mAntennaInfoCallbacks[i].onReportAntennaInfo(antennaInfos);
1168             }
1169         });
1170     }
1171 
1172     @NativeEntryPoint
reportNavigationMessage(GnssNavigationMessage event)1173     void reportNavigationMessage(GnssNavigationMessage event) {
1174         Binder.withCleanCallingIdentity(() -> {
1175             if (mItarSpeedLimitExceeded) {
1176                 return;
1177             }
1178 
1179             for (int i = 0; i < mNavigationMessageCallbacks.length; i++) {
1180                 mNavigationMessageCallbacks[i].onReportNavigationMessage(event);
1181             }
1182         });
1183     }
1184 
1185     @NativeEntryPoint
setTopHalCapabilities(@nssCapabilities.TopHalCapabilityFlags int capabilities, boolean isAdrCapabilityKnown)1186     void setTopHalCapabilities(@GnssCapabilities.TopHalCapabilityFlags int capabilities,
1187             boolean isAdrCapabilityKnown) {
1188         // Here the bits specified by 'capabilities' are turned on. It is handled differently from
1189         // sub hal because top hal capabilities could be set by HIDL HAL and/or AIDL HAL. Each of
1190         // them possesses a different set of capabilities.
1191         mTopFlags |= capabilities;
1192         GnssCapabilities oldCapabilities = mCapabilities;
1193         mCapabilities = oldCapabilities.withTopHalFlags(mTopFlags, isAdrCapabilityKnown);
1194         onCapabilitiesChanged(oldCapabilities, mCapabilities);
1195     }
1196 
1197     @NativeEntryPoint
setSubHalMeasurementCorrectionsCapabilities( @nssCapabilities.SubHalMeasurementCorrectionsCapabilityFlags int capabilities)1198     void setSubHalMeasurementCorrectionsCapabilities(
1199             @GnssCapabilities.SubHalMeasurementCorrectionsCapabilityFlags int capabilities) {
1200         GnssCapabilities oldCapabilities = mCapabilities;
1201         mCapabilities = oldCapabilities.withSubHalMeasurementCorrectionsFlags(capabilities);
1202         onCapabilitiesChanged(oldCapabilities, mCapabilities);
1203     }
1204 
1205     @NativeEntryPoint
setSubHalPowerIndicationCapabilities( @nssCapabilities.SubHalPowerCapabilityFlags int capabilities)1206     void setSubHalPowerIndicationCapabilities(
1207             @GnssCapabilities.SubHalPowerCapabilityFlags int capabilities) {
1208         GnssCapabilities oldCapabilities = mCapabilities;
1209         mCapabilities = oldCapabilities.withSubHalPowerFlags(capabilities);
1210         onCapabilitiesChanged(oldCapabilities, mCapabilities);
1211     }
1212 
1213     @NativeEntryPoint
setSignalTypeCapabilities(List<GnssSignalType> signalTypes)1214     void setSignalTypeCapabilities(List<GnssSignalType> signalTypes) {
1215         GnssCapabilities oldCapabilities = mCapabilities;
1216         mCapabilities = oldCapabilities.withSignalTypes(signalTypes);
1217         onCapabilitiesChanged(oldCapabilities, mCapabilities);
1218     }
1219 
onCapabilitiesChanged(GnssCapabilities oldCapabilities, GnssCapabilities newCapabilities)1220     private void onCapabilitiesChanged(GnssCapabilities oldCapabilities,
1221             GnssCapabilities newCapabilities) {
1222         Binder.withCleanCallingIdentity(() -> {
1223             if (newCapabilities.equals(oldCapabilities)) {
1224                 return;
1225             }
1226 
1227             Log.i(TAG, "gnss capabilities changed to " + newCapabilities);
1228 
1229             for (int i = 0; i < mBaseCallbacks.length; i++) {
1230                 mBaseCallbacks[i].onCapabilitiesChanged(oldCapabilities, newCapabilities);
1231             }
1232         });
1233     }
1234 
1235     @NativeEntryPoint
reportGnssPowerStats(GnssPowerStats powerStats)1236     void reportGnssPowerStats(GnssPowerStats powerStats) {
1237         synchronized (mPowerStatsLock) {
1238             mHandler.removeCallbacks(mPowerStatsTimeoutCallback);
1239             if (powerStats != null) {
1240                 mLastKnownPowerStats = powerStats;
1241             }
1242             mPendingPowerStatsCallbacks.forEach(cb -> cb.onReportPowerStats(powerStats));
1243             mPendingPowerStatsCallbacks.clear();
1244         }
1245     }
1246 
1247     @NativeEntryPoint
setGnssYearOfHardware(int year)1248     void setGnssYearOfHardware(int year) {
1249         mHardwareYear = year;
1250     }
1251 
1252     @NativeEntryPoint
setGnssHardwareModelName(String modelName)1253     private void setGnssHardwareModelName(String modelName) {
1254         mHardwareModelName = modelName;
1255     }
1256 
1257     @NativeEntryPoint
reportLocationBatch(Location[] locations)1258     void reportLocationBatch(Location[] locations) {
1259         Binder.withCleanCallingIdentity(() -> {
1260             for (int i = 0; i < mLocationCallbacks.length; i++) {
1261                 mLocationCallbacks[i].onReportLocations(locations);
1262             }
1263         });
1264     }
1265 
1266     @NativeEntryPoint
psdsDownloadRequest(int psdsType)1267     void psdsDownloadRequest(int psdsType) {
1268         Binder.withCleanCallingIdentity(() -> mPsdsCallbacks.onRequestPsdsDownload(psdsType));
1269     }
1270 
1271     @NativeEntryPoint
reportGeofenceTransition(int geofenceId, Location location, int transition, long transitionTimestamp)1272     void reportGeofenceTransition(int geofenceId, Location location, int transition,
1273             long transitionTimestamp) {
1274         Binder.withCleanCallingIdentity(
1275                 () -> mGeofenceCallbacks.onReportGeofenceTransition(geofenceId, location,
1276                         transition, transitionTimestamp));
1277     }
1278 
1279     @NativeEntryPoint
reportGeofenceStatus(int status, Location location)1280     void reportGeofenceStatus(int status, Location location) {
1281         Binder.withCleanCallingIdentity(
1282                 () -> mGeofenceCallbacks.onReportGeofenceStatus(status, location));
1283     }
1284 
1285     @NativeEntryPoint
reportGeofenceAddStatus(int geofenceId, @GeofenceCallbacks.GeofenceStatus int status)1286     void reportGeofenceAddStatus(int geofenceId, @GeofenceCallbacks.GeofenceStatus int status) {
1287         Binder.withCleanCallingIdentity(
1288                 () -> mGeofenceCallbacks.onReportGeofenceAddStatus(geofenceId, status));
1289     }
1290 
1291     @NativeEntryPoint
reportGeofenceRemoveStatus(int geofenceId, @GeofenceCallbacks.GeofenceStatus int status)1292     void reportGeofenceRemoveStatus(int geofenceId, @GeofenceCallbacks.GeofenceStatus int status) {
1293         Binder.withCleanCallingIdentity(
1294                 () -> mGeofenceCallbacks.onReportGeofenceRemoveStatus(geofenceId, status));
1295     }
1296 
1297     @NativeEntryPoint
reportGeofencePauseStatus(int geofenceId, @GeofenceCallbacks.GeofenceStatus int status)1298     void reportGeofencePauseStatus(int geofenceId, @GeofenceCallbacks.GeofenceStatus int status) {
1299         Binder.withCleanCallingIdentity(
1300                 () -> mGeofenceCallbacks.onReportGeofencePauseStatus(geofenceId, status));
1301     }
1302 
1303     @NativeEntryPoint
reportGeofenceResumeStatus(int geofenceId, @GeofenceCallbacks.GeofenceStatus int status)1304     void reportGeofenceResumeStatus(int geofenceId, @GeofenceCallbacks.GeofenceStatus int status) {
1305         Binder.withCleanCallingIdentity(
1306                 () -> mGeofenceCallbacks.onReportGeofenceResumeStatus(geofenceId, status));
1307     }
1308 
1309     @NativeEntryPoint
requestSetID(int flags)1310     void requestSetID(int flags) {
1311         Binder.withCleanCallingIdentity(() -> mAGpsCallbacks.onRequestSetID(flags));
1312     }
1313 
1314     @NativeEntryPoint
requestLocation(boolean independentFromGnss, boolean isUserEmergency)1315     void requestLocation(boolean independentFromGnss, boolean isUserEmergency) {
1316         Binder.withCleanCallingIdentity(
1317                 () -> mLocationRequestCallbacks.onRequestLocation(independentFromGnss,
1318                         isUserEmergency));
1319     }
1320 
1321     @NativeEntryPoint
requestUtcTime()1322     void requestUtcTime() {
1323         Binder.withCleanCallingIdentity(() -> mTimeCallbacks.onRequestUtcTime());
1324     }
1325 
1326     @NativeEntryPoint
requestRefLocation()1327     void requestRefLocation() {
1328         Binder.withCleanCallingIdentity(
1329                 () -> mLocationRequestCallbacks.onRequestRefLocation());
1330     }
1331 
1332     @NativeEntryPoint
reportNfwNotification(String proxyAppPackageName, byte protocolStack, String otherProtocolStackName, byte requestor, String requestorId, byte responseType, boolean inEmergencyMode, boolean isCachedLocation)1333     void reportNfwNotification(String proxyAppPackageName, byte protocolStack,
1334             String otherProtocolStackName, byte requestor, String requestorId,
1335             byte responseType, boolean inEmergencyMode, boolean isCachedLocation) {
1336         Binder.withCleanCallingIdentity(
1337                 () -> mNotificationCallbacks.onReportNfwNotification(proxyAppPackageName,
1338                         protocolStack, otherProtocolStackName, requestor, requestorId, responseType,
1339                         inEmergencyMode, isCachedLocation));
1340     }
1341 
1342     @NativeEntryPoint
isInEmergencySession()1343     public boolean isInEmergencySession() {
1344         return Binder.withCleanCallingIdentity(
1345                 () -> mEmergencyHelper.isInEmergency(
1346                         TimeUnit.SECONDS.toMillis(mConfiguration.getEsExtensionSec())));
1347     }
1348 
1349     /**
1350      * Encapsulates actual HAL methods for testing purposes.
1351      */
1352     @VisibleForTesting
1353     public static class GnssHal {
1354 
GnssHal()1355         protected GnssHal() {}
1356 
classInitOnce()1357         protected void classInitOnce() {
1358             native_class_init_once();
1359         }
1360 
isSupported()1361         protected boolean isSupported() {
1362             return native_is_supported();
1363         }
1364 
initOnce(GnssNative gnssNative, boolean reinitializeGnssServiceHandle)1365         protected void initOnce(GnssNative gnssNative, boolean reinitializeGnssServiceHandle) {
1366             gnssNative.native_init_once(reinitializeGnssServiceHandle);
1367         }
1368 
init()1369         protected boolean init() {
1370             return native_init();
1371         }
1372 
cleanup()1373         protected void cleanup() {
1374             native_cleanup();
1375         }
1376 
start()1377         protected boolean start() {
1378             return native_start();
1379         }
1380 
stop()1381         protected boolean stop() {
1382             return native_stop();
1383         }
1384 
setPositionMode(@nssPositionMode int mode, @GnssPositionRecurrence int recurrence, int minInterval, int preferredAccuracy, int preferredTime, boolean lowPowerMode)1385         protected boolean setPositionMode(@GnssPositionMode int mode,
1386                 @GnssPositionRecurrence int recurrence, int minInterval, int preferredAccuracy,
1387                 int preferredTime, boolean lowPowerMode) {
1388             return native_set_position_mode(mode, recurrence, minInterval, preferredAccuracy,
1389                     preferredTime, lowPowerMode);
1390         }
1391 
getInternalState()1392         protected String getInternalState() {
1393             return native_get_internal_state();
1394         }
1395 
deleteAidingData(@nssAidingTypeFlags int flags)1396         protected void deleteAidingData(@GnssAidingTypeFlags int flags) {
1397             native_delete_aiding_data(flags);
1398         }
1399 
readNmea(byte[] buffer, int bufferSize)1400         protected int readNmea(byte[] buffer, int bufferSize) {
1401             return native_read_nmea(buffer, bufferSize);
1402         }
1403 
injectLocation(@nssLocationFlags 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)1404         protected void injectLocation(@GnssLocationFlags int gnssLocationFlags, double latitude,
1405                 double longitude, double altitude, float speed, float bearing,
1406                 float horizontalAccuracy, float verticalAccuracy, float speedAccuracy,
1407                 float bearingAccuracy, long timestamp, @GnssRealtimeFlags int elapsedRealtimeFlags,
1408                 long elapsedRealtimeNanos, double elapsedRealtimeUncertaintyNanos) {
1409             native_inject_location(gnssLocationFlags, latitude, longitude, altitude, speed,
1410                     bearing, horizontalAccuracy, verticalAccuracy, speedAccuracy, bearingAccuracy,
1411                     timestamp, elapsedRealtimeFlags, elapsedRealtimeNanos,
1412                     elapsedRealtimeUncertaintyNanos);
1413         }
1414 
injectBestLocation(@nssLocationFlags 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)1415         protected void injectBestLocation(@GnssLocationFlags int gnssLocationFlags, double latitude,
1416                 double longitude, double altitude, float speed, float bearing,
1417                 float horizontalAccuracy, float verticalAccuracy, float speedAccuracy,
1418                 float bearingAccuracy, long timestamp, @GnssRealtimeFlags int elapsedRealtimeFlags,
1419                 long elapsedRealtimeNanos, double elapsedRealtimeUncertaintyNanos) {
1420             native_inject_best_location(gnssLocationFlags, latitude, longitude, altitude, speed,
1421                     bearing, horizontalAccuracy, verticalAccuracy, speedAccuracy, bearingAccuracy,
1422                     timestamp, elapsedRealtimeFlags, elapsedRealtimeNanos,
1423                     elapsedRealtimeUncertaintyNanos);
1424         }
1425 
injectTime(long time, long timeReference, int uncertainty)1426         protected void injectTime(long time, long timeReference, int uncertainty) {
1427             native_inject_time(time, timeReference, uncertainty);
1428         }
1429 
isNavigationMessageCollectionSupported()1430         protected boolean isNavigationMessageCollectionSupported() {
1431             return native_is_navigation_message_supported();
1432         }
1433 
startNavigationMessageCollection()1434         protected boolean startNavigationMessageCollection() {
1435             return native_start_navigation_message_collection();
1436         }
1437 
stopNavigationMessageCollection()1438         protected boolean stopNavigationMessageCollection() {
1439             return native_stop_navigation_message_collection();
1440         }
1441 
isAntennaInfoSupported()1442         protected boolean isAntennaInfoSupported() {
1443             return native_is_antenna_info_supported();
1444         }
1445 
startAntennaInfoListening()1446         protected boolean startAntennaInfoListening() {
1447             return native_start_antenna_info_listening();
1448         }
1449 
stopAntennaInfoListening()1450         protected boolean stopAntennaInfoListening() {
1451             return native_stop_antenna_info_listening();
1452         }
1453 
isMeasurementSupported()1454         protected boolean isMeasurementSupported() {
1455             return native_is_measurement_supported();
1456         }
1457 
startMeasurementCollection(boolean enableFullTracking, boolean enableCorrVecOutputs, int intervalMillis)1458         protected boolean startMeasurementCollection(boolean enableFullTracking,
1459                 boolean enableCorrVecOutputs, int intervalMillis) {
1460             return native_start_measurement_collection(enableFullTracking, enableCorrVecOutputs,
1461                     intervalMillis);
1462         }
1463 
stopMeasurementCollection()1464         protected boolean stopMeasurementCollection() {
1465             return native_stop_measurement_collection();
1466         }
1467 
isMeasurementCorrectionsSupported()1468         protected boolean isMeasurementCorrectionsSupported() {
1469             return native_is_measurement_corrections_supported();
1470         }
1471 
injectMeasurementCorrections(GnssMeasurementCorrections corrections)1472         protected boolean injectMeasurementCorrections(GnssMeasurementCorrections corrections) {
1473             return native_inject_measurement_corrections(corrections);
1474         }
1475 
startSvStatusCollection()1476         protected boolean startSvStatusCollection() {
1477             return native_start_sv_status_collection();
1478         }
1479 
stopSvStatusCollection()1480         protected boolean stopSvStatusCollection() {
1481             return native_stop_sv_status_collection();
1482         }
1483 
startNmeaMessageCollection()1484         protected boolean startNmeaMessageCollection() {
1485             return native_start_nmea_message_collection();
1486         }
1487 
stopNmeaMessageCollection()1488         protected boolean stopNmeaMessageCollection() {
1489             return native_stop_nmea_message_collection();
1490         }
1491 
getBatchSize()1492         protected int getBatchSize() {
1493             return native_get_batch_size();
1494         }
1495 
initBatching()1496         protected boolean initBatching() {
1497             return native_init_batching();
1498         }
1499 
cleanupBatching()1500         protected void cleanupBatching() {
1501             native_cleanup_batching();
1502         }
1503 
startBatch(long periodNanos, float minUpdateDistanceMeters, boolean wakeOnFifoFull)1504         protected boolean startBatch(long periodNanos, float minUpdateDistanceMeters,
1505                 boolean wakeOnFifoFull) {
1506             return native_start_batch(periodNanos, minUpdateDistanceMeters, wakeOnFifoFull);
1507         }
1508 
flushBatch()1509         protected void flushBatch() {
1510             native_flush_batch();
1511         }
1512 
stopBatch()1513         protected void stopBatch() {
1514             native_stop_batch();
1515         }
1516 
isGeofencingSupported()1517         protected boolean isGeofencingSupported() {
1518             return native_is_geofence_supported();
1519         }
1520 
addGeofence(int geofenceId, double latitude, double longitude, double radius, int lastTransition, int monitorTransitions, int notificationResponsiveness, int unknownTimer)1521         protected boolean addGeofence(int geofenceId, double latitude, double longitude,
1522                 double radius, int lastTransition, int monitorTransitions,
1523                 int notificationResponsiveness, int unknownTimer) {
1524             return native_add_geofence(geofenceId, latitude, longitude, radius, lastTransition,
1525                     monitorTransitions, notificationResponsiveness, unknownTimer);
1526         }
1527 
resumeGeofence(int geofenceId, int monitorTransitions)1528         protected boolean resumeGeofence(int geofenceId, int monitorTransitions) {
1529             return native_resume_geofence(geofenceId, monitorTransitions);
1530         }
1531 
pauseGeofence(int geofenceId)1532         protected boolean pauseGeofence(int geofenceId) {
1533             return native_pause_geofence(geofenceId);
1534         }
1535 
removeGeofence(int geofenceId)1536         protected boolean removeGeofence(int geofenceId) {
1537             return native_remove_geofence(geofenceId);
1538         }
1539 
isGnssVisibilityControlSupported()1540         protected boolean isGnssVisibilityControlSupported() {
1541             return native_is_gnss_visibility_control_supported();
1542         }
1543 
requestPowerStats()1544         protected void requestPowerStats() {
1545             native_request_power_stats();
1546         }
1547 
setAgpsServer(int type, String hostname, int port)1548         protected void setAgpsServer(int type, String hostname, int port) {
1549             native_set_agps_server(type, hostname, port);
1550         }
1551 
setAgpsSetId(@gpsSetIdType int type, String setId)1552         protected void setAgpsSetId(@AgpsSetIdType int type, String setId) {
1553             native_agps_set_id(type, setId);
1554         }
1555 
setAgpsReferenceLocationCellId(@gpsReferenceLocationType int type, int mcc, int mnc, int lac, long cid, int tac, int pcid, int arfcn)1556         protected void setAgpsReferenceLocationCellId(@AgpsReferenceLocationType int type, int mcc,
1557                 int mnc, int lac, long cid, int tac, int pcid, int arfcn) {
1558             native_agps_set_ref_location_cellid(type, mcc, mnc, lac, cid, tac, pcid, arfcn);
1559         }
1560 
isPsdsSupported()1561         protected boolean isPsdsSupported() {
1562             return native_supports_psds();
1563         }
1564 
injectPsdsData(byte[] data, int length, int psdsType)1565         protected void injectPsdsData(byte[] data, int length, int psdsType) {
1566             native_inject_psds_data(data, length, psdsType);
1567         }
1568 
injectNiSuplMessageData(byte[] data, int length, int slotIndex)1569         protected void injectNiSuplMessageData(byte[] data, int length, int slotIndex) {
1570             native_inject_ni_supl_message_data(data, length, slotIndex);
1571         }
1572     }
1573 
1574     // basic APIs
1575 
native_class_init_once()1576     private static native void native_class_init_once();
1577 
native_is_supported()1578     private static native boolean native_is_supported();
1579 
native_init_once(boolean reinitializeGnssServiceHandle)1580     private native void native_init_once(boolean reinitializeGnssServiceHandle);
1581 
native_init()1582     private static native boolean native_init();
1583 
native_cleanup()1584     private static native void native_cleanup();
1585 
native_start()1586     private static native boolean native_start();
1587 
native_stop()1588     private static native boolean native_stop();
1589 
native_set_position_mode(int mode, int recurrence, int minInterval, int preferredAccuracy, int preferredTime, boolean lowPowerMode)1590     private static native boolean native_set_position_mode(int mode, int recurrence,
1591             int minInterval, int preferredAccuracy, int preferredTime, boolean lowPowerMode);
1592 
native_get_internal_state()1593     private static native String native_get_internal_state();
1594 
native_delete_aiding_data(int flags)1595     private static native void native_delete_aiding_data(int flags);
1596 
1597     // NMEA APIs
1598 
native_read_nmea(byte[] buffer, int bufferSize)1599     private static native int native_read_nmea(byte[] buffer, int bufferSize);
1600 
native_start_nmea_message_collection()1601     private static native boolean native_start_nmea_message_collection();
1602 
native_stop_nmea_message_collection()1603     private static native boolean native_stop_nmea_message_collection();
1604 
1605     // location injection APIs
1606 
native_inject_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)1607     private static native void native_inject_location(
1608             int gnssLocationFlags, double latitudeDegrees, double longitudeDegrees,
1609             double altitudeMeters, float speedMetersPerSec, float bearingDegrees,
1610             float horizontalAccuracyMeters, float verticalAccuracyMeters,
1611             float speedAccuracyMetersPerSecond, float bearingAccuracyDegrees,
1612             long timestamp, int elapsedRealtimeFlags, long elapsedRealtimeNanos,
1613             double elapsedRealtimeUncertaintyNanos);
1614 
1615 
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)1616     private static native void native_inject_best_location(
1617             int gnssLocationFlags, double latitudeDegrees, double longitudeDegrees,
1618             double altitudeMeters, float speedMetersPerSec, float bearingDegrees,
1619             float horizontalAccuracyMeters, float verticalAccuracyMeters,
1620             float speedAccuracyMetersPerSecond, float bearingAccuracyDegrees,
1621             long timestamp, int elapsedRealtimeFlags, long elapsedRealtimeNanos,
1622             double elapsedRealtimeUncertaintyNanos);
1623 
1624     // time injection APIs
1625 
native_inject_time(long time, long timeReference, int uncertainty)1626     private static native void native_inject_time(long time, long timeReference, int uncertainty);
1627 
1628     // sv status APIs
native_start_sv_status_collection()1629     private static native boolean native_start_sv_status_collection();
1630 
native_stop_sv_status_collection()1631     private static native boolean native_stop_sv_status_collection();
1632 
1633     // navigation message APIs
1634 
native_is_navigation_message_supported()1635     private static native boolean native_is_navigation_message_supported();
1636 
native_start_navigation_message_collection()1637     private static native boolean native_start_navigation_message_collection();
1638 
native_stop_navigation_message_collection()1639     private static native boolean native_stop_navigation_message_collection();
1640 
1641     // antenna info APIS
1642     // TODO: in a next version of the HAL, consider removing the necessity for listening to antenna
1643     //   info changes, and simply report them always, same as capabilities.
1644 
native_is_antenna_info_supported()1645     private static native boolean native_is_antenna_info_supported();
1646 
native_start_antenna_info_listening()1647     private static native boolean native_start_antenna_info_listening();
1648 
native_stop_antenna_info_listening()1649     private static native boolean native_stop_antenna_info_listening();
1650 
1651     // measurement APIs
1652 
native_is_measurement_supported()1653     private static native boolean native_is_measurement_supported();
1654 
native_start_measurement_collection(boolean enableFullTracking, boolean enableCorrVecOutputs, int intervalMillis)1655     private static native boolean native_start_measurement_collection(boolean enableFullTracking,
1656             boolean enableCorrVecOutputs, int intervalMillis);
1657 
native_stop_measurement_collection()1658     private static native boolean native_stop_measurement_collection();
1659 
1660     // measurement corrections APIs
1661 
native_is_measurement_corrections_supported()1662     private static native boolean native_is_measurement_corrections_supported();
1663 
native_inject_measurement_corrections( GnssMeasurementCorrections corrections)1664     private static native boolean native_inject_measurement_corrections(
1665             GnssMeasurementCorrections corrections);
1666 
1667     // batching APIs
1668 
native_init_batching()1669     private static native boolean native_init_batching();
1670 
native_cleanup_batching()1671     private static native void native_cleanup_batching();
1672 
native_start_batch(long periodNanos, float minUpdateDistanceMeters, boolean wakeOnFifoFull)1673     private static native boolean native_start_batch(long periodNanos,
1674             float minUpdateDistanceMeters, boolean wakeOnFifoFull);
1675 
native_flush_batch()1676     private static native void native_flush_batch();
1677 
native_stop_batch()1678     private static native boolean native_stop_batch();
1679 
native_get_batch_size()1680     private static native int native_get_batch_size();
1681 
1682     // geofence APIs
1683 
native_is_geofence_supported()1684     private static native boolean native_is_geofence_supported();
1685 
native_add_geofence(int geofenceId, double latitude, double longitude, double radius, int lastTransition, int monitorTransitions, int notificationResponsivenes, int unknownTimer)1686     private static native boolean native_add_geofence(int geofenceId, double latitude,
1687             double longitude, double radius, int lastTransition, int monitorTransitions,
1688             int notificationResponsivenes, int unknownTimer);
1689 
native_resume_geofence(int geofenceId, int monitorTransitions)1690     private static native boolean native_resume_geofence(int geofenceId, int monitorTransitions);
1691 
native_pause_geofence(int geofenceId)1692     private static native boolean native_pause_geofence(int geofenceId);
1693 
native_remove_geofence(int geofenceId)1694     private static native boolean native_remove_geofence(int geofenceId);
1695 
1696     // network initiated (NI) APIs
1697 
native_is_gnss_visibility_control_supported()1698     private static native boolean native_is_gnss_visibility_control_supported();
1699 
1700     // power stats APIs
1701 
native_request_power_stats()1702     private static native void native_request_power_stats();
1703 
1704     // AGPS APIs
1705 
native_set_agps_server(int type, String hostname, int port)1706     private static native void native_set_agps_server(int type, String hostname, int port);
1707 
native_agps_set_id(int type, String setid)1708     private static native void native_agps_set_id(int type, String setid);
1709 
native_agps_set_ref_location_cellid(int type, int mcc, int mnc, int lac, long cid, int tac, int pcid, int arfcn)1710     private static native void native_agps_set_ref_location_cellid(int type, int mcc, int mnc,
1711             int lac, long cid, int tac, int pcid, int arfcn);
1712 
native_inject_ni_supl_message_data(byte[] data, int length, int slotIndex)1713     private static native void native_inject_ni_supl_message_data(byte[] data, int length,
1714             int slotIndex);
1715 
1716     // PSDS APIs
1717 
native_supports_psds()1718     private static native boolean native_supports_psds();
1719 
native_inject_psds_data(byte[] data, int length, int psdsType)1720     private static native void native_inject_psds_data(byte[] data, int length, int psdsType);
1721 }
1722