• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.hal.GnssNative.GNSS_LOCATION_HAS_ALTITUDE;
20 import static com.android.server.location.gnss.hal.GnssNative.GNSS_LOCATION_HAS_BEARING;
21 import static com.android.server.location.gnss.hal.GnssNative.GNSS_LOCATION_HAS_BEARING_ACCURACY;
22 import static com.android.server.location.gnss.hal.GnssNative.GNSS_LOCATION_HAS_HORIZONTAL_ACCURACY;
23 import static com.android.server.location.gnss.hal.GnssNative.GNSS_LOCATION_HAS_LAT_LONG;
24 import static com.android.server.location.gnss.hal.GnssNative.GNSS_LOCATION_HAS_SPEED;
25 import static com.android.server.location.gnss.hal.GnssNative.GNSS_LOCATION_HAS_SPEED_ACCURACY;
26 import static com.android.server.location.gnss.hal.GnssNative.GNSS_LOCATION_HAS_VERTICAL_ACCURACY;
27 import static com.android.server.location.gnss.hal.GnssNative.GNSS_REALTIME_HAS_TIMESTAMP_NS;
28 import static com.android.server.location.gnss.hal.GnssNative.GNSS_REALTIME_HAS_TIME_UNCERTAINTY_NS;
29 import static com.android.server.location.gnss.hal.GnssNative.GeofenceCallbacks.GEOFENCE_STATUS_ERROR_ID_EXISTS;
30 import static com.android.server.location.gnss.hal.GnssNative.GeofenceCallbacks.GEOFENCE_STATUS_ERROR_ID_UNKNOWN;
31 import static com.android.server.location.gnss.hal.GnssNative.GeofenceCallbacks.GEOFENCE_STATUS_OPERATION_SUCCESS;
32 import static com.android.server.location.gnss.hal.GnssNative.GeofenceCallbacks.GEOFENCE_TRANSITION_ENTERED;
33 import static com.android.server.location.gnss.hal.GnssNative.GeofenceCallbacks.GEOFENCE_TRANSITION_EXITED;
34 
35 import android.annotation.Nullable;
36 import android.location.GnssAntennaInfo;
37 import android.location.GnssMeasurementCorrections;
38 import android.location.GnssMeasurementsEvent;
39 import android.location.GnssNavigationMessage;
40 import android.location.Location;
41 
42 import com.android.server.location.gnss.GnssPowerStats;
43 import com.android.server.location.gnss.hal.GnssNative.GnssLocationFlags;
44 import com.android.server.location.gnss.hal.GnssNative.GnssRealtimeFlags;
45 
46 import java.util.ArrayList;
47 import java.util.Collection;
48 import java.util.HashMap;
49 import java.util.List;
50 import java.util.Objects;
51 
52 /**
53  * Fake GNSS HAL for testing.
54  */
55 public final class FakeGnssHal extends GnssNative.GnssHal {
56 
57     public static class GnssHalPositionMode {
58 
59         public final int Mode;
60         public final int Recurrence;
61         public final int MinInterval;
62         public final int PreferredAccuracy;
63         public final int PreferredTime;
64         public final boolean LowPowerMode;
65 
GnssHalPositionMode()66         GnssHalPositionMode() {
67             Mode = 0;
68             Recurrence = 0;
69             MinInterval = 0;
70             PreferredAccuracy = 0;
71             PreferredTime = 0;
72             LowPowerMode = false;
73         }
74 
GnssHalPositionMode(int mode, int recurrence, int minInterval, int preferredAccuracy, int preferredTime, boolean lowPowerMode)75         public GnssHalPositionMode(int mode, int recurrence, int minInterval, int preferredAccuracy,
76                 int preferredTime, boolean lowPowerMode) {
77             Mode = mode;
78             Recurrence = recurrence;
79             MinInterval = minInterval;
80             PreferredAccuracy = preferredAccuracy;
81             PreferredTime = preferredTime;
82             LowPowerMode = lowPowerMode;
83         }
84 
85         @Override
equals(Object o)86         public boolean equals(Object o) {
87             if (this == o) {
88                 return true;
89             }
90             if (o == null || getClass() != o.getClass()) {
91                 return false;
92             }
93 
94             GnssHalPositionMode that = (GnssHalPositionMode) o;
95             return Mode == that.Mode
96                     && Recurrence == that.Recurrence
97                     && MinInterval == that.MinInterval
98                     && PreferredAccuracy == that.PreferredAccuracy
99                     && PreferredTime == that.PreferredTime
100                     && LowPowerMode == that.LowPowerMode;
101         }
102 
103         @Override
hashCode()104         public int hashCode() {
105             return Objects.hash(Recurrence, MinInterval);
106         }
107     }
108 
109     public static class GnssHalBatchingMode {
110 
111         public final long PeriodNanos;
112         public final float MinUpdateDistanceMeters;
113         public final boolean WakeOnFifoFull;
114 
GnssHalBatchingMode()115         GnssHalBatchingMode() {
116             PeriodNanos = 0;
117             MinUpdateDistanceMeters = 0.0f;
118             WakeOnFifoFull = false;
119         }
120 
GnssHalBatchingMode(long periodNanos, float minUpdateDistanceMeters, boolean wakeOnFifoFull)121         public GnssHalBatchingMode(long periodNanos, float minUpdateDistanceMeters,
122                 boolean wakeOnFifoFull) {
123             PeriodNanos = periodNanos;
124             MinUpdateDistanceMeters = minUpdateDistanceMeters;
125             WakeOnFifoFull = wakeOnFifoFull;
126         }
127 
128         @Override
equals(Object o)129         public boolean equals(Object o) {
130             if (this == o) {
131                 return true;
132             }
133             if (o == null || getClass() != o.getClass()) {
134                 return false;
135             }
136 
137             GnssHalBatchingMode that = (GnssHalBatchingMode) o;
138             return PeriodNanos == that.PeriodNanos
139                     && MinUpdateDistanceMeters == that.MinUpdateDistanceMeters
140                     && WakeOnFifoFull == that.WakeOnFifoFull;
141         }
142 
143         @Override
hashCode()144         public int hashCode() {
145             return Objects.hash(PeriodNanos, MinUpdateDistanceMeters, WakeOnFifoFull);
146         }
147     }
148 
149     public static class GnssHalInjectedTime {
150 
151         public final long Time;
152         public final long TimeReference;
153         public final int Uncertainty;
154 
GnssHalInjectedTime(long time, long timeReference, int uncertainty)155         public GnssHalInjectedTime(long time, long timeReference, int uncertainty) {
156             Time = time;
157             TimeReference = timeReference;
158             Uncertainty = uncertainty;
159         }
160 
161         @Override
equals(Object o)162         public boolean equals(Object o) {
163             if (this == o) {
164                 return true;
165             }
166             if (o == null || getClass() != o.getClass()) {
167                 return false;
168             }
169 
170             GnssHalInjectedTime that = (GnssHalInjectedTime) o;
171             return Time == that.Time
172                     && TimeReference == that.TimeReference
173                     && Uncertainty == that.Uncertainty;
174         }
175 
176         @Override
hashCode()177         public int hashCode() {
178             return Objects.hash(Time);
179         }
180     }
181 
182     public static class GnssHalGeofence {
183 
184         public final int GeofenceId;
185         public final Location Center;
186         public final double Radius;
187         public int LastTransition;
188         public int MonitorTransitions;
189         public final int NotificationResponsiveness;
190         public final int UnknownTimer;
191         public boolean Paused;
192 
GnssHalGeofence(int geofenceId, double latitude, double longitude, double radius, int lastTransition, int monitorTransitions, int notificationResponsiveness, int unknownTimer, boolean paused)193         public GnssHalGeofence(int geofenceId, double latitude, double longitude, double radius,
194                 int lastTransition, int monitorTransitions, int notificationResponsiveness,
195                 int unknownTimer, boolean paused) {
196             GeofenceId = geofenceId;
197             Center = new Location("");
198             Center.setLatitude(latitude);
199             Center.setLongitude(longitude);
200             Radius = radius;
201             LastTransition = lastTransition;
202             MonitorTransitions = monitorTransitions;
203             NotificationResponsiveness = notificationResponsiveness;
204             UnknownTimer = unknownTimer;
205             Paused = paused;
206         }
207 
208         @Override
equals(Object o)209         public boolean equals(Object o) {
210             if (this == o) {
211                 return true;
212             }
213             if (o == null || getClass() != o.getClass()) {
214                 return false;
215             }
216 
217             GnssHalGeofence that = (GnssHalGeofence) o;
218             return GeofenceId == that.GeofenceId
219                     && Double.compare(that.Radius, Radius) == 0
220                     && LastTransition == that.LastTransition
221                     && MonitorTransitions == that.MonitorTransitions
222                     && NotificationResponsiveness == that.NotificationResponsiveness
223                     && UnknownTimer == that.UnknownTimer
224                     && Paused == that.Paused
225                     && Center.equals(that.Center);
226         }
227 
228         @Override
hashCode()229         public int hashCode() {
230             return Objects.hash(GeofenceId);
231         }
232     }
233 
234     private static class HalState {
235         private boolean mStarted = false;
236         private boolean mBatchingStarted = false;
237         private boolean mNavigationMessagesStarted = false;
238         private boolean mAntennaInfoListeningStarted = false;
239         private boolean mMeasurementCollectionStarted = false;
240         private boolean mMeasurementCollectionFullTracking = false;
241         private boolean mMeasurementCollectionCorrVecOutputsEnabled = false;
242         private int mMeasurementCollectionIntervalMillis = 0;
243         private GnssHalPositionMode mPositionMode = new GnssHalPositionMode();
244         private GnssHalBatchingMode mBatchingMode = new GnssHalBatchingMode();
245         private final ArrayList<Location> mBatchedLocations = new ArrayList<>();
246         private Location mInjectedLocation = null;
247         private Location mInjectedBestLocation = null;
248         private GnssHalInjectedTime mInjectedTime = null;
249         private GnssMeasurementCorrections mInjectedMeasurementCorrections = null;
250         private final HashMap<Integer, GnssHalGeofence> mGeofences = new HashMap<>();
251         private GnssPowerStats mPowerStats = new GnssPowerStats(0, 0, 0, 0, 0, 0, 0, 0,
252                 new double[0]);
253     }
254 
255     private @Nullable GnssNative mGnssNative;
256     private HalState mState = new HalState();
257 
258     private boolean mIsNavigationMessageCollectionSupported = true;
259     private boolean mIsAntennaInfoListeningSupported = true;
260     private boolean mIsMeasurementSupported = true;
261     private boolean mIsMeasurementCorrectionsSupported = true;
262     private int mBatchSize = 0;
263     private boolean mIsGeofencingSupported = true;
264     private boolean mIsVisibilityControlSupported = true;
265 
FakeGnssHal()266     public FakeGnssHal() {}
267 
restartHal()268     public void restartHal() {
269         mState = new HalState();
270         Objects.requireNonNull(mGnssNative).restartHal();
271     }
272 
setIsNavigationMessageCollectionSupported(boolean supported)273     public void setIsNavigationMessageCollectionSupported(boolean supported) {
274         mIsNavigationMessageCollectionSupported = supported;
275     }
276 
setIsAntennaInfoListeningSupported(boolean supported)277     public void setIsAntennaInfoListeningSupported(boolean supported) {
278         mIsAntennaInfoListeningSupported = supported;
279     }
280 
setIsMeasurementSupported(boolean supported)281     public void setIsMeasurementSupported(boolean supported) {
282         mIsMeasurementSupported = supported;
283     }
284 
setIsMeasurementCorrectionsSupported(boolean supported)285     public void setIsMeasurementCorrectionsSupported(boolean supported) {
286         mIsMeasurementCorrectionsSupported = supported;
287     }
288 
setBatchSize(int batchSize)289     public void setBatchSize(int batchSize) {
290         mBatchSize = batchSize;
291     }
292 
setIsGeofencingSupported(boolean supported)293     public void setIsGeofencingSupported(boolean supported) {
294         mIsGeofencingSupported = supported;
295     }
296 
setPowerStats(GnssPowerStats powerStats)297     public void setPowerStats(GnssPowerStats powerStats) {
298         mState.mPowerStats = powerStats;
299     }
300 
setIsVisibilityControlSupported(boolean supported)301     public void setIsVisibilityControlSupported(boolean supported) {
302         mIsVisibilityControlSupported = supported;
303     }
304 
getPositionMode()305     public GnssHalPositionMode getPositionMode() {
306         return mState.mPositionMode;
307     }
308 
reportLocation(Location location)309     public void reportLocation(Location location) {
310         if (mState.mStarted) {
311             Objects.requireNonNull(mGnssNative).reportLocation(true, location);
312         }
313         if (mState.mBatchingStarted) {
314             mState.mBatchedLocations.add(location);
315             if (mState.mBatchedLocations.size() >= mBatchSize) {
316                 if (mState.mBatchingMode.WakeOnFifoFull) {
317                     flushBatch();
318                 } else {
319                     mState.mBatchedLocations.remove(0);
320                 }
321             }
322         }
323         for (GnssHalGeofence geofence : mState.mGeofences.values()) {
324             if (!geofence.Paused) {
325                 if (geofence.Center.distanceTo(location) > geofence.Radius) {
326                     if (geofence.LastTransition != GEOFENCE_TRANSITION_EXITED) {
327                         geofence.LastTransition = GEOFENCE_TRANSITION_EXITED;
328                         if ((geofence.MonitorTransitions & GEOFENCE_TRANSITION_EXITED) != 0) {
329                             Objects.requireNonNull(mGnssNative).reportGeofenceTransition(
330                                     geofence.GeofenceId, location, GEOFENCE_TRANSITION_EXITED,
331                                     location.getTime());
332                         }
333                     }
334                 } else {
335                     if (geofence.LastTransition != GEOFENCE_TRANSITION_ENTERED) {
336                         geofence.LastTransition = GEOFENCE_TRANSITION_ENTERED;
337                         if ((geofence.MonitorTransitions & GEOFENCE_TRANSITION_ENTERED) != 0) {
338                             Objects.requireNonNull(mGnssNative).reportGeofenceTransition(
339                                     geofence.GeofenceId, location, GEOFENCE_TRANSITION_ENTERED,
340                                     location.getTime());
341                         }
342                     }
343                 }
344             }
345         }
346     }
347 
reportNavigationMessage(GnssNavigationMessage message)348     public void reportNavigationMessage(GnssNavigationMessage message) {
349         if (mState.mNavigationMessagesStarted) {
350             Objects.requireNonNull(mGnssNative).reportNavigationMessage(message);
351         }
352     }
353 
reportAntennaInfo(List<GnssAntennaInfo> antennaInfos)354     public void reportAntennaInfo(List<GnssAntennaInfo> antennaInfos) {
355         if (mState.mAntennaInfoListeningStarted) {
356             Objects.requireNonNull(mGnssNative).reportAntennaInfo(antennaInfos);
357         }
358     }
359 
isMeasurementCollectionFullTracking()360     public boolean isMeasurementCollectionFullTracking() {
361         return mState.mMeasurementCollectionFullTracking;
362     }
363 
reportMeasurement(GnssMeasurementsEvent event)364     public void reportMeasurement(GnssMeasurementsEvent event) {
365         if (mState.mMeasurementCollectionStarted) {
366             Objects.requireNonNull(mGnssNative).reportMeasurementData(event);
367         }
368     }
369 
getLastInjectedTime()370     public GnssHalInjectedTime getLastInjectedTime() {
371         return mState.mInjectedTime;
372     }
373 
getLastInjectedCorrections()374     public GnssMeasurementCorrections getLastInjectedCorrections() {
375         return mState.mInjectedMeasurementCorrections;
376     }
377 
getGeofences()378     public Collection<GnssHalGeofence> getGeofences() {
379         return mState.mGeofences.values();
380     }
381 
382     @Override
classInitOnce()383     protected void classInitOnce() {}
384 
385     @Override
isSupported()386     protected boolean isSupported() {
387         return true;
388     }
389 
390     @Override
initOnce(GnssNative gnssNative, boolean reinitializeGnssServiceHandle)391     protected void initOnce(GnssNative gnssNative, boolean reinitializeGnssServiceHandle) {
392         mGnssNative = Objects.requireNonNull(gnssNative);
393     }
394 
395     @Override
init()396     protected boolean init() {
397         return true;
398     }
399 
400     @Override
cleanup()401     protected void cleanup() {}
402 
403     @Override
start()404     protected boolean start() {
405         mState.mStarted = true;
406         return true;
407     }
408 
409     @Override
stop()410     protected boolean stop() {
411         mState.mStarted = false;
412         return true;
413     }
414 
415     @Override
setPositionMode(int mode, int recurrence, int minInterval, int preferredAccuracy, int preferredTime, boolean lowPowerMode)416     protected boolean setPositionMode(int mode, int recurrence, int minInterval,
417             int preferredAccuracy, int preferredTime, boolean lowPowerMode) {
418         mState.mPositionMode = new GnssHalPositionMode(mode, recurrence, minInterval,
419                 preferredAccuracy, preferredTime, lowPowerMode);
420         return true;
421     }
422 
423     @Override
getInternalState()424     protected String getInternalState() {
425         return "DebugState";
426     }
427 
428     @Override
deleteAidingData(int flags)429     protected void deleteAidingData(int flags) {}
430 
431     @Override
readNmea(byte[] buffer, int bufferSize)432     protected int readNmea(byte[] buffer, int bufferSize) {
433         return 0;
434     }
435 
436     @Override
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)437     protected void injectLocation(@GnssLocationFlags int gnssLocationFlags, double latitude,
438             double longitude, double altitude, float speed, float bearing, float horizontalAccuracy,
439             float verticalAccuracy, float speedAccuracy, float bearingAccuracy, long timestamp,
440             @GnssRealtimeFlags int elapsedRealtimeFlags, long elapsedRealtimeNanos,
441             double elapsedRealtimeUncertaintyNanos) {
442         mState.mInjectedLocation = new Location("injected");
443         mState.mInjectedLocation.setLatitude(latitude);
444         mState.mInjectedLocation.setLongitude(longitude);
445         mState.mInjectedLocation.setAccuracy(horizontalAccuracy);
446     }
447 
448     @Override
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)449     protected void injectBestLocation(@GnssLocationFlags int gnssLocationFlags, double latitude,
450             double longitude, double altitude, float speed, float bearing, float horizontalAccuracy,
451             float verticalAccuracy, float speedAccuracy, float bearingAccuracy, long timestamp,
452             @GnssRealtimeFlags int elapsedRealtimeFlags, long elapsedRealtimeNanos,
453             double elapsedRealtimeUncertaintyNanos) {
454         mState.mInjectedBestLocation = new Location("injectedBest");
455         if ((gnssLocationFlags & GNSS_LOCATION_HAS_LAT_LONG) != 0) {
456             mState.mInjectedBestLocation.setLatitude(latitude);
457             mState.mInjectedBestLocation.setLongitude(longitude);
458         }
459         if ((gnssLocationFlags & GNSS_LOCATION_HAS_ALTITUDE) != 0) {
460             mState.mInjectedBestLocation.setAltitude(altitude);
461         }
462         if ((gnssLocationFlags & GNSS_LOCATION_HAS_SPEED) != 0) {
463             mState.mInjectedBestLocation.setSpeed(speed);
464         }
465         if ((gnssLocationFlags & GNSS_LOCATION_HAS_BEARING) != 0) {
466             mState.mInjectedBestLocation.setBearing(bearing);
467         }
468         if ((gnssLocationFlags & GNSS_LOCATION_HAS_HORIZONTAL_ACCURACY) != 0) {
469             mState.mInjectedBestLocation.setAccuracy(horizontalAccuracy);
470         }
471         if ((gnssLocationFlags & GNSS_LOCATION_HAS_VERTICAL_ACCURACY) != 0) {
472             mState.mInjectedBestLocation.setVerticalAccuracyMeters(verticalAccuracy);
473         }
474         if ((gnssLocationFlags & GNSS_LOCATION_HAS_SPEED_ACCURACY) != 0) {
475             mState.mInjectedBestLocation.setSpeedAccuracyMetersPerSecond(speedAccuracy);
476         }
477         if ((gnssLocationFlags & GNSS_LOCATION_HAS_BEARING_ACCURACY) != 0) {
478             mState.mInjectedBestLocation.setBearingAccuracyDegrees(bearingAccuracy);
479         }
480         mState.mInjectedBestLocation.setTime(timestamp);
481         if ((elapsedRealtimeFlags & GNSS_REALTIME_HAS_TIMESTAMP_NS) != 0) {
482             mState.mInjectedBestLocation.setElapsedRealtimeNanos(elapsedRealtimeNanos);
483         }
484         if ((elapsedRealtimeFlags & GNSS_REALTIME_HAS_TIME_UNCERTAINTY_NS) != 0) {
485             mState.mInjectedBestLocation.setElapsedRealtimeUncertaintyNanos(
486                     elapsedRealtimeUncertaintyNanos);
487         }
488     }
489 
490     @Override
injectTime(long time, long timeReference, int uncertainty)491     protected void injectTime(long time, long timeReference, int uncertainty) {
492         mState.mInjectedTime = new GnssHalInjectedTime(time, timeReference, uncertainty);
493     }
494 
495     @Override
isNavigationMessageCollectionSupported()496     protected boolean isNavigationMessageCollectionSupported() {
497         return mIsNavigationMessageCollectionSupported;
498     }
499 
500     @Override
startNavigationMessageCollection()501     protected boolean startNavigationMessageCollection() {
502         mState.mNavigationMessagesStarted = true;
503         return true;
504     }
505 
506     @Override
stopNavigationMessageCollection()507     protected boolean stopNavigationMessageCollection() {
508         mState.mNavigationMessagesStarted = false;
509         return true;
510     }
511 
512     @Override
isAntennaInfoSupported()513     protected boolean isAntennaInfoSupported() {
514         return mIsAntennaInfoListeningSupported;
515     }
516 
517     @Override
startAntennaInfoListening()518     protected boolean startAntennaInfoListening() {
519         mState.mAntennaInfoListeningStarted = true;
520         return true;
521     }
522 
523     @Override
stopAntennaInfoListening()524     protected boolean stopAntennaInfoListening() {
525         mState.mAntennaInfoListeningStarted = false;
526         return true;
527     }
528 
529     @Override
isMeasurementSupported()530     protected boolean isMeasurementSupported() {
531         return mIsMeasurementSupported;
532     }
533 
534     @Override
startMeasurementCollection(boolean enableFullTracking, boolean enableCorrVecOutputs, int intervalMillis)535     protected boolean startMeasurementCollection(boolean enableFullTracking,
536             boolean enableCorrVecOutputs, int intervalMillis) {
537         mState.mMeasurementCollectionStarted = true;
538         mState.mMeasurementCollectionFullTracking = enableFullTracking;
539         mState.mMeasurementCollectionCorrVecOutputsEnabled = enableCorrVecOutputs;
540         mState.mMeasurementCollectionIntervalMillis = intervalMillis;
541         return true;
542     }
543 
544     @Override
stopMeasurementCollection()545     protected boolean stopMeasurementCollection() {
546         mState.mMeasurementCollectionStarted = false;
547         mState.mMeasurementCollectionFullTracking = false;
548         mState.mMeasurementCollectionCorrVecOutputsEnabled = false;
549         mState.mMeasurementCollectionIntervalMillis = 0;
550         return true;
551     }
552 
553     @Override
isMeasurementCorrectionsSupported()554     protected boolean isMeasurementCorrectionsSupported() {
555         return mIsMeasurementCorrectionsSupported;
556     }
557 
558     @Override
injectMeasurementCorrections(GnssMeasurementCorrections corrections)559     protected boolean injectMeasurementCorrections(GnssMeasurementCorrections corrections) {
560         mState.mInjectedMeasurementCorrections = corrections;
561         return true;
562     }
563 
564     @Override
getBatchSize()565     protected int getBatchSize() {
566         return mBatchSize;
567     }
568 
569     @Override
initBatching()570     protected boolean initBatching() {
571         return true;
572     }
573 
574     @Override
cleanupBatching()575     protected void cleanupBatching() {}
576 
577     @Override
startBatch(long periodNanos, float minUpdateDistanceMeters, boolean wakeOnFifoFull)578     protected boolean startBatch(long periodNanos, float minUpdateDistanceMeters,
579             boolean wakeOnFifoFull) {
580         mState.mBatchingStarted = true;
581         mState.mBatchingMode = new GnssHalBatchingMode(periodNanos, minUpdateDistanceMeters,
582                 wakeOnFifoFull);
583         return true;
584     }
585 
586     @Override
flushBatch()587     protected void flushBatch() {
588         Location[] locations = mState.mBatchedLocations.toArray(new Location[0]);
589         mState.mBatchedLocations.clear();
590         Objects.requireNonNull(mGnssNative).reportLocationBatch(locations);
591     }
592 
593     @Override
stopBatch()594     protected void stopBatch() {
595         mState.mBatchingStarted = false;
596         mState.mBatchingMode = new GnssHalBatchingMode();
597         mState.mBatchedLocations.clear();
598     }
599 
600     @Override
isGeofencingSupported()601     protected boolean isGeofencingSupported() {
602         return mIsGeofencingSupported;
603     }
604 
605     @Override
addGeofence(int geofenceId, double latitude, double longitude, double radius, int lastTransition, int monitorTransitions, int notificationResponsiveness, int unknownTimer)606     protected boolean addGeofence(int geofenceId, double latitude, double longitude, double radius,
607             int lastTransition, int monitorTransitions, int notificationResponsiveness,
608             int unknownTimer) {
609         if (mState.mGeofences.containsKey(geofenceId)) {
610             Objects.requireNonNull(mGnssNative).reportGeofenceAddStatus(geofenceId,
611                     GEOFENCE_STATUS_ERROR_ID_EXISTS);
612         } else {
613             mState.mGeofences.put(geofenceId,
614                     new GnssHalGeofence(geofenceId, latitude, longitude, radius, lastTransition,
615                             monitorTransitions, notificationResponsiveness, unknownTimer, false));
616             Objects.requireNonNull(mGnssNative).reportGeofenceAddStatus(geofenceId,
617                     GEOFENCE_STATUS_OPERATION_SUCCESS);
618         }
619         return true;
620     }
621 
622     @Override
resumeGeofence(int geofenceId, int monitorTransitions)623     protected boolean resumeGeofence(int geofenceId, int monitorTransitions) {
624         GnssHalGeofence geofence = mState.mGeofences.get(geofenceId);
625         if (geofence != null) {
626             geofence.Paused = false;
627             geofence.MonitorTransitions = monitorTransitions;
628             Objects.requireNonNull(mGnssNative).reportGeofenceAddStatus(geofenceId,
629                     GEOFENCE_STATUS_OPERATION_SUCCESS);
630         } else {
631             Objects.requireNonNull(mGnssNative).reportGeofenceAddStatus(geofenceId,
632                     GEOFENCE_STATUS_ERROR_ID_UNKNOWN);
633         }
634         return true;
635     }
636 
637     @Override
pauseGeofence(int geofenceId)638     protected boolean pauseGeofence(int geofenceId) {
639         GnssHalGeofence geofence = mState.mGeofences.get(geofenceId);
640         if (geofence != null) {
641             geofence.Paused = true;
642             Objects.requireNonNull(mGnssNative).reportGeofenceAddStatus(geofenceId,
643                     GEOFENCE_STATUS_OPERATION_SUCCESS);
644         } else {
645             Objects.requireNonNull(mGnssNative).reportGeofenceAddStatus(geofenceId,
646                     GEOFENCE_STATUS_ERROR_ID_UNKNOWN);
647         }
648         return true;
649     }
650 
651     @Override
removeGeofence(int geofenceId)652     protected boolean removeGeofence(int geofenceId) {
653         if (mState.mGeofences.remove(geofenceId) != null) {
654             Objects.requireNonNull(mGnssNative).reportGeofenceRemoveStatus(geofenceId,
655                     GEOFENCE_STATUS_OPERATION_SUCCESS);
656         } else {
657             Objects.requireNonNull(mGnssNative).reportGeofenceRemoveStatus(geofenceId,
658                     GEOFENCE_STATUS_ERROR_ID_UNKNOWN);
659         }
660         return true;
661     }
662 
663     @Override
isGnssVisibilityControlSupported()664     protected boolean isGnssVisibilityControlSupported() {
665         return mIsVisibilityControlSupported;
666     }
667 
668     @Override
sendNiResponse(int notificationId, int userResponse)669     protected void sendNiResponse(int notificationId, int userResponse) {}
670 
671     @Override
requestPowerStats()672     protected void requestPowerStats() {
673         Objects.requireNonNull(mGnssNative).reportGnssPowerStats(mState.mPowerStats);
674     }
675 
676     @Override
setAgpsServer(int type, String hostname, int port)677     protected void setAgpsServer(int type, String hostname, int port) {}
678 
679     @Override
setAgpsSetId(int type, String setId)680     protected void setAgpsSetId(int type, String setId) {}
681 
682     @Override
setAgpsReferenceLocationCellId(int type, int mcc, int mnc, int lac, long cid, int tac, int pcid, int arfcn)683     protected void setAgpsReferenceLocationCellId(int type, int mcc, int mnc, int lac, long cid,
684             int tac, int pcid, int arfcn) {}
685 
686     @Override
isPsdsSupported()687     protected boolean isPsdsSupported() {
688         return true;
689     }
690 
691     @Override
injectPsdsData(byte[] data, int length, int psdsType)692     protected void injectPsdsData(byte[] data, int length, int psdsType) {}
693 }
694