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; 18 19 import static android.location.LocationManager.GPS_PROVIDER; 20 21 import android.Manifest; 22 import android.annotation.Nullable; 23 import android.content.Context; 24 import android.location.GnssMeasurementCorrections; 25 import android.location.GnssRequest; 26 import android.location.IBatchedLocationCallback; 27 import android.location.IGnssAntennaInfoListener; 28 import android.location.IGnssMeasurementsListener; 29 import android.location.IGnssNavigationMessageListener; 30 import android.location.IGnssStatusListener; 31 import android.location.IGpsGeofenceHardware; 32 import android.location.INetInitiatedListener; 33 import android.location.Location; 34 import android.location.LocationManagerInternal; 35 import android.os.Binder; 36 import android.os.IBinder; 37 import android.os.IInterface; 38 import android.os.Process; 39 import android.os.RemoteException; 40 import android.stats.location.LocationStatsEnums; 41 import android.util.ArrayMap; 42 import android.util.Log; 43 44 import com.android.internal.annotations.GuardedBy; 45 import com.android.internal.annotations.VisibleForTesting; 46 import com.android.internal.util.IndentingPrintWriter; 47 import com.android.internal.util.Preconditions; 48 import com.android.server.LocalServices; 49 import com.android.server.location.AppForegroundHelper; 50 import com.android.server.location.AppOpsHelper; 51 import com.android.server.location.CallerIdentity; 52 import com.android.server.location.LocationManagerServiceUtils.LinkedListener; 53 import com.android.server.location.LocationManagerServiceUtils.LinkedListenerBase; 54 import com.android.server.location.LocationUsageLogger; 55 import com.android.server.location.RemoteListenerHelper; 56 import com.android.server.location.SettingsHelper; 57 58 import java.io.FileDescriptor; 59 import java.io.PrintWriter; 60 import java.util.List; 61 import java.util.Map; 62 import java.util.function.Consumer; 63 import java.util.function.Function; 64 65 /** Manages Gnss providers and related Gnss functions for LocationManagerService. */ 66 public class GnssManagerService { 67 68 private static final String TAG = "GnssManagerService"; 69 isGnssSupported()70 public static boolean isGnssSupported() { 71 return GnssLocationProvider.isSupported(); 72 } 73 74 private final Context mContext; 75 private final AppOpsHelper mAppOpsHelper; 76 private final SettingsHelper mSettingsHelper; 77 private final AppForegroundHelper mAppForegroundHelper; 78 private final LocationUsageLogger mLocationUsageLogger; 79 80 private final GnssLocationProvider mGnssLocationProvider; 81 private final GnssStatusListenerHelper mGnssStatusProvider; 82 private final GnssMeasurementsProvider mGnssMeasurementsProvider; 83 private final GnssMeasurementCorrectionsProvider mGnssMeasurementCorrectionsProvider; 84 private final GnssAntennaInfoProvider mGnssAntennaInfoProvider; 85 private final GnssNavigationMessageProvider mGnssNavigationMessageProvider; 86 private final GnssLocationProvider.GnssSystemInfoProvider mGnssSystemInfoProvider; 87 private final GnssLocationProvider.GnssMetricsProvider mGnssMetricsProvider; 88 private final GnssCapabilitiesProvider mGnssCapabilitiesProvider; 89 private final GnssBatchingProvider mGnssBatchingProvider; 90 private final INetInitiatedListener mNetInitiatedListener; 91 private final IGpsGeofenceHardware mGpsGeofenceProxy; 92 93 @GuardedBy("mGnssMeasurementsListeners") 94 private final ArrayMap<IBinder, LinkedListener<GnssRequest, IGnssMeasurementsListener>> 95 mGnssMeasurementsListeners = new ArrayMap<>(); 96 97 @GuardedBy("mGnssAntennaInfoListeners") 98 private final ArrayMap<IBinder, 99 LinkedListener<Void, IGnssAntennaInfoListener>> 100 mGnssAntennaInfoListeners = new ArrayMap<>(); 101 102 @GuardedBy("mGnssNavigationMessageListeners") 103 private final ArrayMap<IBinder, LinkedListener<Void, IGnssNavigationMessageListener>> 104 mGnssNavigationMessageListeners = new ArrayMap<>(); 105 106 @GuardedBy("mGnssStatusListeners") 107 private final ArrayMap<IBinder, LinkedListener<Void, IGnssStatusListener>> 108 mGnssStatusListeners = new ArrayMap<>(); 109 110 @GuardedBy("this") 111 @Nullable private LocationManagerInternal mLocationManagerInternal; 112 113 private final Object mGnssBatchingLock = new Object(); 114 115 @GuardedBy("mGnssBatchingLock") 116 @Nullable private IBatchedLocationCallback mGnssBatchingCallback; 117 118 @GuardedBy("mGnssBatchingLock") 119 @Nullable 120 private LinkedListener<Void, IBatchedLocationCallback> mGnssBatchingDeathCallback; 121 122 @GuardedBy("mGnssBatchingLock") 123 private boolean mGnssBatchingInProgress = false; 124 GnssManagerService(Context context, AppOpsHelper appOpsHelper, SettingsHelper settingsHelper, AppForegroundHelper appForegroundHelper, LocationUsageLogger locationUsageLogger)125 public GnssManagerService(Context context, AppOpsHelper appOpsHelper, 126 SettingsHelper settingsHelper, AppForegroundHelper appForegroundHelper, 127 LocationUsageLogger locationUsageLogger) { 128 this(context, appOpsHelper, settingsHelper, appForegroundHelper, locationUsageLogger, null); 129 } 130 131 // Can use this constructor to inject GnssLocationProvider for testing 132 @VisibleForTesting GnssManagerService(Context context, AppOpsHelper appOpsHelper, SettingsHelper settingsHelper, AppForegroundHelper appForegroundHelper, LocationUsageLogger locationUsageLogger, GnssLocationProvider gnssLocationProvider)133 GnssManagerService(Context context, AppOpsHelper appOpsHelper, SettingsHelper settingsHelper, 134 AppForegroundHelper appForegroundHelper, LocationUsageLogger locationUsageLogger, 135 GnssLocationProvider gnssLocationProvider) { 136 Preconditions.checkState(isGnssSupported()); 137 138 mContext = context; 139 mAppOpsHelper = appOpsHelper; 140 mSettingsHelper = settingsHelper; 141 mAppForegroundHelper = appForegroundHelper; 142 mLocationUsageLogger = locationUsageLogger; 143 144 if (gnssLocationProvider == null) { 145 gnssLocationProvider = new GnssLocationProvider(mContext); 146 } 147 148 mGnssLocationProvider = gnssLocationProvider; 149 mGnssStatusProvider = mGnssLocationProvider.getGnssStatusProvider(); 150 mGnssMeasurementsProvider = mGnssLocationProvider.getGnssMeasurementsProvider(); 151 mGnssAntennaInfoProvider = mGnssLocationProvider.getGnssAntennaInfoProvider(); 152 mGnssMeasurementCorrectionsProvider = 153 mGnssLocationProvider.getGnssMeasurementCorrectionsProvider(); 154 mGnssNavigationMessageProvider = mGnssLocationProvider.getGnssNavigationMessageProvider(); 155 mGnssSystemInfoProvider = mGnssLocationProvider.getGnssSystemInfoProvider(); 156 mGnssMetricsProvider = mGnssLocationProvider.getGnssMetricsProvider(); 157 mGnssCapabilitiesProvider = mGnssLocationProvider.getGnssCapabilitiesProvider(); 158 mGnssBatchingProvider = mGnssLocationProvider.getGnssBatchingProvider(); 159 mNetInitiatedListener = mGnssLocationProvider.getNetInitiatedListener(); 160 mGpsGeofenceProxy = mGnssLocationProvider.getGpsGeofenceProxy(); 161 } 162 163 /** Called when system is ready. */ onSystemReady()164 public synchronized void onSystemReady() { 165 if (mLocationManagerInternal != null) { 166 return; 167 } 168 169 mAppOpsHelper.onSystemReady(); 170 mSettingsHelper.onSystemReady(); 171 mAppForegroundHelper.onSystemReady(); 172 173 mLocationManagerInternal = LocalServices.getService(LocationManagerInternal.class); 174 175 mAppForegroundHelper.addListener(this::onAppForegroundChanged); 176 } 177 178 /** Retrieve the GnssLocationProvider. */ getGnssLocationProvider()179 public GnssLocationProvider getGnssLocationProvider() { 180 return mGnssLocationProvider; 181 } 182 183 /** Retrieve the IGpsGeofenceHardware. */ getGpsGeofenceProxy()184 public IGpsGeofenceHardware getGpsGeofenceProxy() { 185 return mGpsGeofenceProxy; 186 } 187 188 /** 189 * Get year of GNSS hardware. 190 */ getGnssYearOfHardware()191 public int getGnssYearOfHardware() { 192 return mGnssSystemInfoProvider.getGnssYearOfHardware(); 193 } 194 195 /** 196 * Get model name of GNSS hardware. 197 */ 198 @Nullable getGnssHardwareModelName()199 public String getGnssHardwareModelName() { 200 return mGnssSystemInfoProvider.getGnssHardwareModelName(); 201 } 202 203 /** 204 * Get GNSS hardware capabilities. The capabilities returned are a bitfield as described in 205 * {@link android.location.GnssCapabilities}. 206 */ getGnssCapabilities()207 public long getGnssCapabilities() { 208 return mGnssCapabilitiesProvider.getGnssCapabilities(); 209 } 210 211 /** 212 * Get size of GNSS batch (GNSS location results are batched together for power savings). 213 */ getGnssBatchSize(String packageName)214 public int getGnssBatchSize(String packageName) { 215 mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE, null); 216 mContext.enforceCallingPermission(Manifest.permission.ACCESS_FINE_LOCATION, null); 217 218 synchronized (mGnssBatchingLock) { 219 return mGnssBatchingProvider.getBatchSize(); 220 } 221 } 222 223 /** 224 * Starts GNSS batch collection. GNSS positions are collected in a batch before being delivered 225 * as a collection. 226 */ startGnssBatch(long periodNanos, boolean wakeOnFifoFull, String packageName, String featureId)227 public boolean startGnssBatch(long periodNanos, boolean wakeOnFifoFull, String packageName, 228 String featureId) { 229 mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE, null); 230 mContext.enforceCallingPermission(Manifest.permission.ACCESS_FINE_LOCATION, null); 231 232 CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, featureId); 233 if (!mAppOpsHelper.checkLocationAccess(identity)) { 234 return false; 235 } 236 237 synchronized (mGnssBatchingLock) { 238 if (mGnssBatchingInProgress) { 239 // Current design does not expect multiple starts to be called repeatedly 240 Log.e(TAG, "startGnssBatch unexpectedly called w/o stopping prior batch"); 241 stopGnssBatch(); 242 } 243 244 mGnssBatchingInProgress = true; 245 return mGnssBatchingProvider.start(periodNanos, wakeOnFifoFull); 246 } 247 } 248 249 /** 250 * Adds a GNSS batching callback for delivering GNSS location batch results. 251 */ addGnssBatchingCallback(IBatchedLocationCallback callback, String packageName, @Nullable String featureId)252 public boolean addGnssBatchingCallback(IBatchedLocationCallback callback, String packageName, 253 @Nullable String featureId) { 254 mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE, null); 255 mContext.enforceCallingPermission(Manifest.permission.ACCESS_FINE_LOCATION, null); 256 257 CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, featureId); 258 259 synchronized (mGnssBatchingLock) { 260 mGnssBatchingCallback = callback; 261 mGnssBatchingDeathCallback = 262 new LinkedListener<>( 263 /* request= */ null, 264 callback, 265 identity, 266 (IBatchedLocationCallback listener) -> { 267 stopGnssBatch(); 268 removeGnssBatchingCallback(); 269 }); 270 271 return mGnssBatchingDeathCallback.linkToListenerDeathNotificationLocked( 272 callback.asBinder()); 273 } 274 } 275 276 /** 277 * Force flush GNSS location results from batch. 278 * 279 * @param packageName name of requesting package 280 */ flushGnssBatch(String packageName)281 public void flushGnssBatch(String packageName) { 282 mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE, null); 283 mContext.enforceCallingPermission(Manifest.permission.ACCESS_FINE_LOCATION, null); 284 285 synchronized (mGnssBatchingLock) { 286 mGnssBatchingProvider.flush(); 287 } 288 } 289 290 /** 291 * Removes GNSS batching callback. 292 */ removeGnssBatchingCallback()293 public void removeGnssBatchingCallback() { 294 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE, null); 295 296 synchronized (mGnssBatchingLock) { 297 mGnssBatchingDeathCallback.unlinkFromListenerDeathNotificationLocked( 298 mGnssBatchingCallback.asBinder()); 299 mGnssBatchingCallback = null; 300 mGnssBatchingDeathCallback = null; 301 } 302 } 303 304 /** 305 * Stop GNSS batch collection. 306 */ stopGnssBatch()307 public boolean stopGnssBatch() { 308 mContext.enforceCallingPermission(android.Manifest.permission.LOCATION_HARDWARE, null); 309 310 synchronized (mGnssBatchingLock) { 311 mGnssBatchingInProgress = false; 312 return mGnssBatchingProvider.stop(); 313 } 314 } 315 onAppForegroundChanged(int uid, boolean foreground)316 private void onAppForegroundChanged(int uid, boolean foreground) { 317 synchronized (mGnssMeasurementsListeners) { 318 updateListenersOnForegroundChangedLocked( 319 mGnssMeasurementsListeners, 320 mGnssMeasurementsProvider, 321 IGnssMeasurementsListener.Stub::asInterface, 322 uid, 323 foreground); 324 } 325 synchronized (mGnssNavigationMessageListeners) { 326 updateListenersOnForegroundChangedLocked( 327 mGnssNavigationMessageListeners, 328 mGnssNavigationMessageProvider, 329 IGnssNavigationMessageListener.Stub::asInterface, 330 uid, 331 foreground); 332 } 333 synchronized (mGnssStatusListeners) { 334 updateListenersOnForegroundChangedLocked( 335 mGnssStatusListeners, 336 mGnssStatusProvider, 337 IGnssStatusListener.Stub::asInterface, 338 uid, 339 foreground); 340 } 341 synchronized (mGnssAntennaInfoListeners) { 342 updateListenersOnForegroundChangedLocked( 343 mGnssAntennaInfoListeners, 344 mGnssAntennaInfoProvider, 345 IGnssAntennaInfoListener.Stub::asInterface, 346 uid, 347 foreground); 348 } 349 } 350 updateListenersOnForegroundChangedLocked( Map<IBinder, LinkedListener<TRequest, TListener>> gnssDataListeners, RemoteListenerHelper<TRequest, TListener> gnssDataProvider, Function<IBinder, TListener> mapBinderToListener, int uid, boolean foreground)351 private <TRequest, TListener extends IInterface> void updateListenersOnForegroundChangedLocked( 352 Map<IBinder, LinkedListener<TRequest, TListener>> gnssDataListeners, 353 RemoteListenerHelper<TRequest, TListener> gnssDataProvider, 354 Function<IBinder, TListener> mapBinderToListener, 355 int uid, 356 boolean foreground) { 357 for (Map.Entry<IBinder, LinkedListener<TRequest, TListener>> entry : 358 gnssDataListeners.entrySet()) { 359 LinkedListener<TRequest, TListener> linkedListener = entry.getValue(); 360 CallerIdentity callerIdentity = linkedListener.getCallerIdentity(); 361 TRequest request = linkedListener.getRequest(); 362 if (callerIdentity.uid != uid) { 363 continue; 364 } 365 366 TListener listener = mapBinderToListener.apply(entry.getKey()); 367 if (foreground || isThrottlingExempt(callerIdentity)) { 368 gnssDataProvider.addListener(request, listener, callerIdentity); 369 } else { 370 gnssDataProvider.removeListener(listener); 371 } 372 } 373 } 374 addGnssDataListenerLocked( @ullable TRequest request, TListener listener, String packageName, @Nullable String featureId, RemoteListenerHelper<TRequest, TListener> gnssDataProvider, ArrayMap<IBinder, LinkedListener<TRequest, TListener>> gnssDataListeners, Consumer<TListener> binderDeathCallback)375 private <TListener extends IInterface, TRequest> boolean addGnssDataListenerLocked( 376 @Nullable TRequest request, 377 TListener listener, 378 String packageName, 379 @Nullable String featureId, 380 RemoteListenerHelper<TRequest, TListener> gnssDataProvider, 381 ArrayMap<IBinder, 382 LinkedListener<TRequest, TListener>> gnssDataListeners, 383 Consumer<TListener> binderDeathCallback) { 384 mContext.enforceCallingPermission(Manifest.permission.ACCESS_FINE_LOCATION, null); 385 386 CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, featureId); 387 if (!mAppOpsHelper.checkLocationAccess(identity)) { 388 return false; 389 } 390 391 LinkedListener<TRequest, TListener> linkedListener = new LinkedListener<>(request, listener, 392 identity, binderDeathCallback); 393 IBinder binder = listener.asBinder(); 394 if (!linkedListener.linkToListenerDeathNotificationLocked(binder)) { 395 return false; 396 } 397 398 gnssDataListeners.put(binder, linkedListener); 399 if (gnssDataProvider == mGnssMeasurementsProvider 400 || gnssDataProvider == mGnssStatusProvider) { 401 mLocationUsageLogger.logLocationApiUsage( 402 LocationStatsEnums.USAGE_STARTED, 403 gnssDataProvider == mGnssMeasurementsProvider 404 ? LocationStatsEnums.API_ADD_GNSS_MEASUREMENTS_LISTENER 405 : LocationStatsEnums.API_REGISTER_GNSS_STATUS_CALLBACK, 406 packageName, 407 /* LocationRequest= */ null, 408 /* hasListener= */ true, 409 /* hasIntent= */ false, 410 /* geofence= */ null, 411 mAppForegroundHelper.getImportance(identity.uid)); 412 } 413 if (mAppForegroundHelper.isAppForeground(identity.uid) 414 || isThrottlingExempt(identity)) { 415 gnssDataProvider.addListener(request, listener, identity); 416 } 417 return true; 418 } 419 removeGnssDataListenerLocked( TListener listener, RemoteListenerHelper<TRequest, TListener> gnssDataProvider, ArrayMap<IBinder, LinkedListener<TRequest, TListener>> gnssDataListeners)420 private <TRequest, TListener extends IInterface> void removeGnssDataListenerLocked( 421 TListener listener, 422 RemoteListenerHelper<TRequest, TListener> gnssDataProvider, 423 ArrayMap<IBinder, LinkedListener<TRequest, TListener>> gnssDataListeners) { 424 if (gnssDataProvider == null) { 425 Log.e( 426 TAG, 427 "Can not remove GNSS data listener. GNSS data provider " 428 + "not available."); 429 return; 430 } 431 432 IBinder binder = listener.asBinder(); 433 LinkedListener<TRequest, TListener> linkedListener = 434 gnssDataListeners.remove(binder); 435 if (linkedListener == null) { 436 return; 437 } 438 if (gnssDataProvider == mGnssMeasurementsProvider 439 || gnssDataProvider == mGnssStatusProvider) { 440 mLocationUsageLogger.logLocationApiUsage( 441 LocationStatsEnums.USAGE_ENDED, 442 gnssDataProvider == mGnssMeasurementsProvider 443 ? LocationStatsEnums.API_ADD_GNSS_MEASUREMENTS_LISTENER 444 : LocationStatsEnums.API_REGISTER_GNSS_STATUS_CALLBACK, 445 linkedListener.getCallerIdentity().packageName, 446 /* LocationRequest= */ null, 447 /* hasListener= */ true, 448 /* hasIntent= */ false, 449 /* geofence= */ null, 450 mAppForegroundHelper.getImportance(Binder.getCallingUid())); 451 } 452 linkedListener.unlinkFromListenerDeathNotificationLocked(binder); 453 gnssDataProvider.removeListener(listener); 454 } 455 456 /** 457 * Registers listener for GNSS status changes. 458 */ registerGnssStatusCallback(IGnssStatusListener listener, String packageName, @Nullable String featureId)459 public boolean registerGnssStatusCallback(IGnssStatusListener listener, String packageName, 460 @Nullable String featureId) { 461 synchronized (mGnssStatusListeners) { 462 return addGnssDataListenerLocked( 463 /* request= */ null, 464 listener, 465 packageName, 466 featureId, 467 mGnssStatusProvider, 468 mGnssStatusListeners, 469 this::unregisterGnssStatusCallback); 470 } 471 } 472 473 /** 474 * Unregisters listener for GNSS status changes. 475 */ unregisterGnssStatusCallback(IGnssStatusListener listener)476 public void unregisterGnssStatusCallback(IGnssStatusListener listener) { 477 synchronized (mGnssStatusListeners) { 478 removeGnssDataListenerLocked(listener, mGnssStatusProvider, mGnssStatusListeners); 479 } 480 } 481 482 /** 483 * Adds a GNSS measurements listener. 484 */ addGnssMeasurementsListener(@ullable GnssRequest request, IGnssMeasurementsListener listener, String packageName, @Nullable String featureId)485 public boolean addGnssMeasurementsListener(@Nullable GnssRequest request, 486 IGnssMeasurementsListener listener, String packageName, 487 @Nullable String featureId) { 488 if (request != null && request.isFullTracking()) { 489 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.LOCATION_HARDWARE, 490 null); 491 } 492 synchronized (mGnssMeasurementsListeners) { 493 return addGnssDataListenerLocked( 494 request, 495 listener, 496 packageName, 497 featureId, 498 mGnssMeasurementsProvider, 499 mGnssMeasurementsListeners, 500 this::removeGnssMeasurementsListener); 501 } 502 } 503 504 /** 505 * Injects GNSS measurement corrections. 506 */ injectGnssMeasurementCorrections( GnssMeasurementCorrections measurementCorrections, String packageName)507 public void injectGnssMeasurementCorrections( 508 GnssMeasurementCorrections measurementCorrections, String packageName) { 509 mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE, null); 510 mContext.enforceCallingPermission(Manifest.permission.ACCESS_FINE_LOCATION, null); 511 512 mGnssMeasurementCorrectionsProvider.injectGnssMeasurementCorrections( 513 measurementCorrections); 514 } 515 516 /** 517 * Removes a GNSS measurements listener. 518 */ removeGnssMeasurementsListener(IGnssMeasurementsListener listener)519 public void removeGnssMeasurementsListener(IGnssMeasurementsListener listener) { 520 synchronized (mGnssMeasurementsListeners) { 521 removeGnssDataListenerLocked(listener, mGnssMeasurementsProvider, 522 mGnssMeasurementsListeners); 523 } 524 } 525 526 /** 527 * Adds a GNSS Antenna Info listener. 528 * 529 * @param listener called when GNSS antenna info is received 530 * @param packageName name of requesting package 531 */ addGnssAntennaInfoListener( IGnssAntennaInfoListener listener, String packageName, @Nullable String featureId)532 public boolean addGnssAntennaInfoListener( 533 IGnssAntennaInfoListener listener, String packageName, 534 @Nullable String featureId) { 535 synchronized (mGnssAntennaInfoListeners) { 536 return addGnssDataListenerLocked( 537 /* request= */ null, 538 listener, 539 packageName, 540 featureId, 541 mGnssAntennaInfoProvider, 542 mGnssAntennaInfoListeners, 543 this::removeGnssAntennaInfoListener); 544 } 545 } 546 547 /** 548 * Removes a GNSS Antenna Info listener. 549 * 550 * @param listener called when GNSS antenna info is received 551 */ removeGnssAntennaInfoListener(IGnssAntennaInfoListener listener)552 public void removeGnssAntennaInfoListener(IGnssAntennaInfoListener listener) { 553 synchronized (mGnssAntennaInfoListeners) { 554 removeGnssDataListenerLocked( 555 listener, mGnssAntennaInfoProvider, mGnssAntennaInfoListeners); 556 } 557 } 558 559 /** 560 * Adds a GNSS navigation message listener. 561 */ addGnssNavigationMessageListener( IGnssNavigationMessageListener listener, String packageName, @Nullable String featureId)562 public boolean addGnssNavigationMessageListener( 563 IGnssNavigationMessageListener listener, String packageName, 564 @Nullable String featureId) { 565 synchronized (mGnssNavigationMessageListeners) { 566 return addGnssDataListenerLocked( 567 /* request= */ null, 568 listener, 569 packageName, 570 featureId, 571 mGnssNavigationMessageProvider, 572 mGnssNavigationMessageListeners, 573 this::removeGnssNavigationMessageListener); 574 } 575 } 576 577 /** 578 * Removes a GNSS navigation message listener. 579 */ removeGnssNavigationMessageListener(IGnssNavigationMessageListener listener)580 public void removeGnssNavigationMessageListener(IGnssNavigationMessageListener listener) { 581 synchronized (mGnssNavigationMessageListeners) { 582 removeGnssDataListenerLocked( 583 listener, mGnssNavigationMessageProvider, mGnssNavigationMessageListeners); 584 } 585 } 586 587 /** 588 * Send Ni Response, indicating a location request initiated by a network carrier. 589 */ sendNiResponse(int notifId, int userResponse)590 public void sendNiResponse(int notifId, int userResponse) { 591 try { 592 mNetInitiatedListener.sendNiResponse(notifId, userResponse); 593 } catch (RemoteException e) { 594 Log.e(TAG, "RemoteException in LocationManagerService.sendNiResponse"); 595 } 596 } 597 598 /** 599 * Report location results to GNSS batching listener. 600 */ onReportLocation(List<Location> locations)601 public void onReportLocation(List<Location> locations) { 602 IBatchedLocationCallback gnssBatchingCallback; 603 LinkedListener<Void, IBatchedLocationCallback> gnssBatchingDeathCallback; 604 synchronized (mGnssBatchingLock) { 605 gnssBatchingCallback = mGnssBatchingCallback; 606 gnssBatchingDeathCallback = mGnssBatchingDeathCallback; 607 } 608 609 if (gnssBatchingCallback == null || gnssBatchingDeathCallback == null) { 610 return; 611 } 612 613 int userId = gnssBatchingDeathCallback.getCallerIdentity().userId; 614 if (!mLocationManagerInternal.isProviderEnabledForUser(GPS_PROVIDER, userId)) { 615 Log.w(TAG, "reportLocationBatch() called without user permission"); 616 return; 617 } 618 619 try { 620 gnssBatchingCallback.onLocationBatch(locations); 621 } catch (RemoteException e) { 622 Log.e(TAG, "reportLocationBatch() failed", e); 623 } 624 } 625 isThrottlingExempt(CallerIdentity callerIdentity)626 private boolean isThrottlingExempt(CallerIdentity callerIdentity) { 627 if (callerIdentity.uid == Process.SYSTEM_UID) { 628 return true; 629 } 630 631 if (mSettingsHelper.getBackgroundThrottlePackageWhitelist().contains( 632 callerIdentity.packageName)) { 633 return true; 634 } 635 636 synchronized (this) { 637 Preconditions.checkState(mLocationManagerInternal != null); 638 } 639 return mLocationManagerInternal.isProviderPackage(callerIdentity.packageName); 640 } 641 642 /** 643 * Dump info for debugging. 644 */ dump(FileDescriptor fd, PrintWriter pw, String[] args)645 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 646 IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " "); 647 648 if (args.length > 0 && args[0].equals("--gnssmetrics")) { 649 if (mGnssMetricsProvider != null) { 650 pw.append(mGnssMetricsProvider.getGnssMetricsAsProtoString()); 651 } 652 return; 653 } 654 655 ipw.println("GnssMeasurement Listeners:"); 656 ipw.increaseIndent(); 657 synchronized (mGnssMeasurementsListeners) { 658 for (LinkedListenerBase listener : mGnssMeasurementsListeners.values()) { 659 ipw.println(listener); 660 } 661 } 662 ipw.decreaseIndent(); 663 664 ipw.println("GnssNavigationMessage Listeners:"); 665 ipw.increaseIndent(); 666 synchronized (mGnssNavigationMessageListeners) { 667 for (LinkedListenerBase listener : mGnssNavigationMessageListeners.values()) { 668 ipw.println(listener); 669 } 670 } 671 ipw.decreaseIndent(); 672 673 ipw.println("GnssStatus Listeners:"); 674 ipw.increaseIndent(); 675 synchronized (mGnssStatusListeners) { 676 for (LinkedListenerBase listener : mGnssStatusListeners.values()) { 677 ipw.println(listener); 678 } 679 } 680 ipw.decreaseIndent(); 681 682 synchronized (mGnssBatchingLock) { 683 if (mGnssBatchingInProgress) { 684 ipw.println("GNSS batching in progress"); 685 } 686 } 687 } 688 } 689