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