1 /* 2 * Copyright (C) 2008 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; 18 19 import android.app.AlarmManager; 20 import android.app.AppOpsManager; 21 import android.app.PendingIntent; 22 import android.content.BroadcastReceiver; 23 import android.content.ContentResolver; 24 import android.content.Context; 25 import android.content.Intent; 26 import android.content.IntentFilter; 27 import android.database.ContentObserver; 28 import android.hardware.location.GeofenceHardware; 29 import android.hardware.location.GeofenceHardwareImpl; 30 import android.location.Criteria; 31 import android.location.FusedBatchOptions; 32 import android.location.GnssMeasurementsEvent; 33 import android.location.GnssNavigationMessage; 34 import android.location.GnssStatus; 35 import android.location.IGpsGeofenceHardware; 36 import android.location.INetInitiatedListener; 37 import android.location.Location; 38 import android.location.LocationListener; 39 import android.location.LocationManager; 40 import android.location.LocationProvider; 41 import android.location.LocationRequest; 42 import android.os.AsyncTask; 43 import android.os.BatteryStats; 44 import android.os.Binder; 45 import android.os.Bundle; 46 import android.os.Handler; 47 import android.os.Looper; 48 import android.os.Message; 49 import android.os.PersistableBundle; 50 import android.os.PowerManager; 51 import android.os.PowerManager.ServiceType; 52 import android.os.PowerSaveState; 53 import android.os.RemoteException; 54 import android.os.ServiceManager; 55 import android.os.SystemClock; 56 import android.os.SystemProperties; 57 import android.os.UserHandle; 58 import android.os.WorkSource; 59 import android.os.WorkSource.WorkChain; 60 import android.provider.Settings; 61 import android.telephony.CarrierConfigManager; 62 import android.telephony.SubscriptionManager; 63 import android.telephony.TelephonyManager; 64 import android.telephony.gsm.GsmCellLocation; 65 import android.text.TextUtils; 66 import android.util.Log; 67 import android.util.StatsLog; 68 import android.util.TimeUtils; 69 70 import com.android.internal.annotations.GuardedBy; 71 import com.android.internal.app.IBatteryStats; 72 import com.android.internal.location.GpsNetInitiatedHandler; 73 import com.android.internal.location.GpsNetInitiatedHandler.GpsNiNotification; 74 import com.android.internal.location.ProviderProperties; 75 import com.android.internal.location.ProviderRequest; 76 import com.android.internal.location.gnssmetrics.GnssMetrics; 77 import com.android.internal.telephony.TelephonyIntents; 78 import com.android.server.location.GnssSatelliteBlacklistHelper.GnssSatelliteBlacklistCallback; 79 import com.android.server.location.NtpTimeHelper.InjectNtpTimeCallback; 80 81 import java.io.FileDescriptor; 82 import java.io.PrintWriter; 83 import java.lang.annotation.ElementType; 84 import java.lang.annotation.Retention; 85 import java.lang.annotation.RetentionPolicy; 86 import java.lang.annotation.Target; 87 import java.util.ArrayList; 88 import java.util.Arrays; 89 import java.util.List; 90 91 /** 92 * A GNSS implementation of LocationProvider used by LocationManager. 93 * 94 * {@hide} 95 */ 96 public class GnssLocationProvider extends AbstractLocationProvider implements 97 InjectNtpTimeCallback, 98 GnssSatelliteBlacklistCallback { 99 100 /** 101 * Indicates that this method is a native entry point. Useful purely for IDEs which can 102 * understand entry points, and thus eliminate incorrect warnings about methods not used. 103 */ 104 @Target(ElementType.METHOD) 105 @Retention(RetentionPolicy.SOURCE) 106 private @interface NativeEntryPoint { 107 } 108 109 private static final String TAG = "GnssLocationProvider"; 110 111 private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); 112 private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE); 113 114 private static final ProviderProperties PROPERTIES = new ProviderProperties( 115 true, true, false, false, true, true, true, 116 Criteria.POWER_HIGH, Criteria.ACCURACY_FINE); 117 118 // these need to match GnssPositionMode enum in IGnss.hal 119 private static final int GPS_POSITION_MODE_STANDALONE = 0; 120 private static final int GPS_POSITION_MODE_MS_BASED = 1; 121 private static final int GPS_POSITION_MODE_MS_ASSISTED = 2; 122 123 // these need to match GnssPositionRecurrence enum in IGnss.hal 124 private static final int GPS_POSITION_RECURRENCE_PERIODIC = 0; 125 private static final int GPS_POSITION_RECURRENCE_SINGLE = 1; 126 127 // these need to match GnssStatusValue enum in IGnssCallback.hal 128 private static final int GPS_STATUS_NONE = 0; 129 private static final int GPS_STATUS_SESSION_BEGIN = 1; 130 private static final int GPS_STATUS_SESSION_END = 2; 131 private static final int GPS_STATUS_ENGINE_ON = 3; 132 private static final int GPS_STATUS_ENGINE_OFF = 4; 133 134 // these need to match GnssLocationFlags enum in types.hal 135 private static final int LOCATION_INVALID = 0; 136 private static final int LOCATION_HAS_LAT_LONG = 1; 137 private static final int LOCATION_HAS_ALTITUDE = 2; 138 private static final int LOCATION_HAS_SPEED = 4; 139 private static final int LOCATION_HAS_BEARING = 8; 140 private static final int LOCATION_HAS_HORIZONTAL_ACCURACY = 16; 141 private static final int LOCATION_HAS_VERTICAL_ACCURACY = 32; 142 private static final int LOCATION_HAS_SPEED_ACCURACY = 64; 143 private static final int LOCATION_HAS_BEARING_ACCURACY = 128; 144 145 // these need to match ElapsedRealtimeFlags enum in types.hal 146 private static final int ELAPSED_REALTIME_HAS_TIMESTAMP_NS = 1; 147 private static final int ELAPSED_REALTIME_HAS_TIME_UNCERTAINTY_NS = 2; 148 149 // IMPORTANT - the GPS_DELETE_* symbols here must match GnssAidingData enum in IGnss.hal 150 private static final int GPS_DELETE_EPHEMERIS = 0x0001; 151 private static final int GPS_DELETE_ALMANAC = 0x0002; 152 private static final int GPS_DELETE_POSITION = 0x0004; 153 private static final int GPS_DELETE_TIME = 0x0008; 154 private static final int GPS_DELETE_IONO = 0x0010; 155 private static final int GPS_DELETE_UTC = 0x0020; 156 private static final int GPS_DELETE_HEALTH = 0x0040; 157 private static final int GPS_DELETE_SVDIR = 0x0080; 158 private static final int GPS_DELETE_SVSTEER = 0x0100; 159 private static final int GPS_DELETE_SADATA = 0x0200; 160 private static final int GPS_DELETE_RTI = 0x0400; 161 private static final int GPS_DELETE_CELLDB_INFO = 0x8000; 162 private static final int GPS_DELETE_ALL = 0xFFFF; 163 164 // The GPS_CAPABILITY_* flags must match Capabilities enum in IGnssCallback.hal 165 private static final int GPS_CAPABILITY_SCHEDULING = 0x0000001; 166 private static final int GPS_CAPABILITY_MSB = 0x0000002; 167 private static final int GPS_CAPABILITY_MSA = 0x0000004; 168 private static final int GPS_CAPABILITY_SINGLE_SHOT = 0x0000008; 169 private static final int GPS_CAPABILITY_ON_DEMAND_TIME = 0x0000010; 170 public static final int GPS_CAPABILITY_GEOFENCING = 0x0000020; 171 public static final int GPS_CAPABILITY_MEASUREMENTS = 0x0000040; 172 public static final int GPS_CAPABILITY_NAV_MESSAGES = 0x0000080; 173 public static final int GPS_CAPABILITY_LOW_POWER_MODE = 0x0000100; 174 public static final int GPS_CAPABILITY_SATELLITE_BLACKLIST = 0x0000200; 175 public static final int GPS_CAPABILITY_MEASUREMENT_CORRECTIONS = 0x0000400; 176 177 // The AGPS SUPL mode 178 private static final int AGPS_SUPL_MODE_MSA = 0x02; 179 private static final int AGPS_SUPL_MODE_MSB = 0x01; 180 181 private static final int SET_REQUEST = 3; 182 private static final int INJECT_NTP_TIME = 5; 183 // PSDS stands for Predicted Satellite Data Service 184 private static final int DOWNLOAD_PSDS_DATA = 6; 185 private static final int UPDATE_LOCATION = 7; // Handle external location from network listener 186 private static final int DOWNLOAD_PSDS_DATA_FINISHED = 11; 187 private static final int INITIALIZE_HANDLER = 13; 188 private static final int REQUEST_LOCATION = 16; 189 private static final int REPORT_LOCATION = 17; // HAL reports location 190 private static final int REPORT_SV_STATUS = 18; // HAL reports SV status 191 192 // Request setid 193 private static final int AGPS_RIL_REQUEST_SETID_IMSI = 1; 194 private static final int AGPS_RIL_REQUEST_SETID_MSISDN = 2; 195 196 // ref. location info 197 private static final int AGPS_REF_LOCATION_TYPE_GSM_CELLID = 1; 198 private static final int AGPS_REF_LOCATION_TYPE_UMTS_CELLID = 2; 199 200 // set id info 201 private static final int AGPS_SETID_TYPE_NONE = 0; 202 private static final int AGPS_SETID_TYPE_IMSI = 1; 203 private static final int AGPS_SETID_TYPE_MSISDN = 2; 204 205 private static final int GPS_GEOFENCE_UNAVAILABLE = 1 << 0L; 206 private static final int GPS_GEOFENCE_AVAILABLE = 1 << 1L; 207 208 // GPS Geofence errors. Should match GeofenceStatus enum in IGnssGeofenceCallback.hal. 209 private static final int GPS_GEOFENCE_OPERATION_SUCCESS = 0; 210 private static final int GPS_GEOFENCE_ERROR_TOO_MANY_GEOFENCES = 100; 211 private static final int GPS_GEOFENCE_ERROR_ID_EXISTS = -101; 212 private static final int GPS_GEOFENCE_ERROR_ID_UNKNOWN = -102; 213 private static final int GPS_GEOFENCE_ERROR_INVALID_TRANSITION = -103; 214 private static final int GPS_GEOFENCE_ERROR_GENERIC = -149; 215 216 // TCP/IP constants. 217 // Valid TCP/UDP port range is (0, 65535]. 218 private static final int TCP_MIN_PORT = 0; 219 private static final int TCP_MAX_PORT = 0xffff; 220 221 // 1 second, or 1 Hz frequency. 222 private static final long LOCATION_UPDATE_MIN_TIME_INTERVAL_MILLIS = 1000; 223 // Default update duration in milliseconds for REQUEST_LOCATION. 224 private static final long LOCATION_UPDATE_DURATION_MILLIS = 10 * 1000; 225 // Update duration extension multiplier for emergency REQUEST_LOCATION. 226 private static final int EMERGENCY_LOCATION_UPDATE_DURATION_MULTIPLIER = 3; 227 228 /** simpler wrapper for ProviderRequest + Worksource */ 229 private static class GpsRequest { 230 public ProviderRequest request; 231 public WorkSource source; 232 GpsRequest(ProviderRequest request, WorkSource source)233 public GpsRequest(ProviderRequest request, WorkSource source) { 234 this.request = request; 235 this.source = source; 236 } 237 } 238 239 // Threadsafe class to hold stats reported in the Extras Bundle 240 private static class LocationExtras { 241 private int mSvCount; 242 private int mMeanCn0; 243 private int mMaxCn0; 244 private final Bundle mBundle; 245 LocationExtras()246 public LocationExtras() { 247 mBundle = new Bundle(); 248 } 249 set(int svCount, int meanCn0, int maxCn0)250 public void set(int svCount, int meanCn0, int maxCn0) { 251 synchronized (this) { 252 mSvCount = svCount; 253 mMeanCn0 = meanCn0; 254 mMaxCn0 = maxCn0; 255 } 256 setBundle(mBundle); 257 } 258 reset()259 public void reset() { 260 set(0, 0, 0); 261 } 262 263 // Also used by outside methods to add to other bundles setBundle(Bundle extras)264 public void setBundle(Bundle extras) { 265 if (extras != null) { 266 synchronized (this) { 267 extras.putInt("satellites", mSvCount); 268 extras.putInt("meanCn0", mMeanCn0); 269 extras.putInt("maxCn0", mMaxCn0); 270 } 271 } 272 } 273 getBundle()274 public Bundle getBundle() { 275 synchronized (this) { 276 return new Bundle(mBundle); 277 } 278 } 279 } 280 281 private final Object mLock = new Object(); 282 283 // current status 284 private int mStatus = LocationProvider.TEMPORARILY_UNAVAILABLE; 285 286 // time for last status update 287 private long mStatusUpdateTime = SystemClock.elapsedRealtime(); 288 289 // turn off GPS fix icon if we haven't received a fix in 10 seconds 290 private static final long RECENT_FIX_TIMEOUT = 10 * 1000; 291 292 // stop trying if we do not receive a fix within 60 seconds 293 private static final int NO_FIX_TIMEOUT = 60 * 1000; 294 295 // if the fix interval is below this we leave GPS on, 296 // if above then we cycle the GPS driver. 297 // Typical hot TTTF is ~5 seconds, so 10 seconds seems sane. 298 private static final int GPS_POLLING_THRESHOLD_INTERVAL = 10 * 1000; 299 300 // how long to wait if we have a network error in NTP or PSDS downloading 301 // the initial value of the exponential backoff 302 // current setting - 5 minutes 303 private static final long RETRY_INTERVAL = 5 * 60 * 1000; 304 // how long to wait if we have a network error in NTP or PSDS downloading 305 // the max value of the exponential backoff 306 // current setting - 4 hours 307 private static final long MAX_RETRY_INTERVAL = 4 * 60 * 60 * 1000; 308 309 // Timeout when holding wakelocks for downloading PSDS data. 310 private static final long DOWNLOAD_PSDS_DATA_TIMEOUT_MS = 60 * 1000; 311 312 private final ExponentialBackOff mPsdsBackOff = new ExponentialBackOff(RETRY_INTERVAL, 313 MAX_RETRY_INTERVAL); 314 315 // True if we are enabled 316 @GuardedBy("mLock") 317 private boolean mGpsEnabled; 318 319 private boolean mShutdown; 320 321 // states for injecting ntp and downloading psds data 322 private static final int STATE_PENDING_NETWORK = 0; 323 private static final int STATE_DOWNLOADING = 1; 324 private static final int STATE_IDLE = 2; 325 326 // flags to trigger NTP or PSDS data download when network becomes available 327 // initialized to true so we do NTP and PSDS when the network comes up after booting 328 private int mDownloadPsdsDataPending = STATE_PENDING_NETWORK; 329 330 // true if GPS is navigating 331 private boolean mNavigating; 332 333 // requested frequency of fixes, in milliseconds 334 private int mFixInterval = 1000; 335 336 // true if low power mode for the GNSS chipset is part of the latest request. 337 private boolean mLowPowerMode = false; 338 339 // true if we started navigation in the HAL, only change value of this in setStarted 340 private boolean mStarted; 341 342 // for logging of latest change, and warning of ongoing location after a stop 343 private long mStartedChangedElapsedRealtime; 344 345 // threshold for delay in GNSS engine turning off before warning & error 346 private static final long LOCATION_OFF_DELAY_THRESHOLD_WARN_MILLIS = 2 * 1000; 347 private static final long LOCATION_OFF_DELAY_THRESHOLD_ERROR_MILLIS = 15 * 1000; 348 349 // capabilities reported through the top level IGnssCallback.hal 350 private volatile int mTopHalCapabilities; 351 352 // true if PSDS is supported 353 private boolean mSupportsPsds; 354 355 // for calculating time to first fix 356 private long mFixRequestTime = 0; 357 // time to first fix for most recent session 358 private int mTimeToFirstFix = 0; 359 // time we received our last fix 360 private long mLastFixTime; 361 362 private int mPositionMode; 363 private GnssPositionMode mLastPositionMode; 364 365 // Current request from underlying location clients. 366 private ProviderRequest mProviderRequest; 367 // The WorkSource associated with the most recent client request (i.e, most recent call to 368 // setRequest). 369 private WorkSource mWorkSource = null; 370 // True if gps should be disabled because of PowerManager controls 371 private boolean mDisableGpsForPowerManager = false; 372 373 /** 374 * Properties loaded from PROPERTIES_FILE. 375 * It must be accessed only inside {@link #mHandler}. 376 */ 377 private GnssConfiguration mGnssConfiguration; 378 379 private String mSuplServerHost; 380 private int mSuplServerPort = TCP_MIN_PORT; 381 private String mC2KServerHost; 382 private int mC2KServerPort; 383 private boolean mSuplEsEnabled = false; 384 385 private final Looper mLooper; 386 private final LocationExtras mLocationExtras = new LocationExtras(); 387 private final GnssStatusListenerHelper mGnssStatusListenerHelper; 388 private final GnssMeasurementsProvider mGnssMeasurementsProvider; 389 private final GnssMeasurementCorrectionsProvider mGnssMeasurementCorrectionsProvider; 390 private final GnssNavigationMessageProvider mGnssNavigationMessageProvider; 391 private final LocationChangeListener mNetworkLocationListener = new NetworkLocationListener(); 392 private final LocationChangeListener mFusedLocationListener = new FusedLocationListener(); 393 private final NtpTimeHelper mNtpTimeHelper; 394 private final GnssBatchingProvider mGnssBatchingProvider; 395 private final GnssGeofenceProvider mGnssGeofenceProvider; 396 private final GnssCapabilitiesProvider mGnssCapabilitiesProvider; 397 398 // Available only on GNSS HAL 2.0 implementations and later. 399 private GnssVisibilityControl mGnssVisibilityControl; 400 401 // Handler for processing events 402 private Handler mHandler; 403 404 private final GnssNetworkConnectivityHandler mNetworkConnectivityHandler; 405 private final GpsNetInitiatedHandler mNIHandler; 406 407 // Wakelocks 408 private final static String WAKELOCK_KEY = "GnssLocationProvider"; 409 private final PowerManager.WakeLock mWakeLock; 410 private static final String DOWNLOAD_EXTRA_WAKELOCK_KEY = "GnssLocationProviderPsdsDownload"; 411 @GuardedBy("mLock") 412 private final PowerManager.WakeLock mDownloadPsdsWakeLock; 413 414 // Alarms 415 private final static String ALARM_WAKEUP = "com.android.internal.location.ALARM_WAKEUP"; 416 private final static String ALARM_TIMEOUT = "com.android.internal.location.ALARM_TIMEOUT"; 417 418 private final PowerManager mPowerManager; 419 private final AlarmManager mAlarmManager; 420 private final PendingIntent mWakeupIntent; 421 private final PendingIntent mTimeoutIntent; 422 423 private final AppOpsManager mAppOps; 424 private final IBatteryStats mBatteryStats; 425 426 // Current list of underlying location clients. 427 // only modified on handler thread 428 private WorkSource mClientSource = new WorkSource(); 429 430 private GeofenceHardwareImpl mGeofenceHardwareImpl; 431 432 // Volatile for simple inter-thread sync on these values. 433 private volatile int mHardwareYear = 0; 434 private volatile String mHardwareModelName; 435 436 // Set lower than the current ITAR limit of 600m/s to allow this to trigger even if GPS HAL 437 // stops output right at 600m/s, depriving this of the information of a device that reaches 438 // greater than 600m/s, and higher than the speed of sound to avoid impacting most use cases. 439 private static final float ITAR_SPEED_LIMIT_METERS_PER_SECOND = 400.0F; 440 441 private volatile boolean mItarSpeedLimitExceeded = false; 442 443 // GNSS Metrics 444 private GnssMetrics mGnssMetrics; 445 getGnssStatusProvider()446 public GnssStatusListenerHelper getGnssStatusProvider() { 447 return mGnssStatusListenerHelper; 448 } 449 getGpsGeofenceProxy()450 public IGpsGeofenceHardware getGpsGeofenceProxy() { 451 return mGnssGeofenceProvider; 452 } 453 getGnssMeasurementsProvider()454 public GnssMeasurementsProvider getGnssMeasurementsProvider() { 455 return mGnssMeasurementsProvider; 456 } 457 getGnssMeasurementCorrectionsProvider()458 public GnssMeasurementCorrectionsProvider getGnssMeasurementCorrectionsProvider() { 459 return mGnssMeasurementCorrectionsProvider; 460 } 461 getGnssNavigationMessageProvider()462 public GnssNavigationMessageProvider getGnssNavigationMessageProvider() { 463 return mGnssNavigationMessageProvider; 464 } 465 private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { 466 @Override 467 public void onReceive(Context context, Intent intent) { 468 String action = intent.getAction(); 469 if (DEBUG) Log.d(TAG, "receive broadcast intent, action: " + action); 470 if (action == null) { 471 return; 472 } 473 474 switch (action) { 475 case ALARM_WAKEUP: 476 startNavigating(); 477 break; 478 case ALARM_TIMEOUT: 479 hibernate(); 480 break; 481 case PowerManager.ACTION_POWER_SAVE_MODE_CHANGED: 482 case PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED: 483 case Intent.ACTION_SCREEN_OFF: 484 case Intent.ACTION_SCREEN_ON: 485 updateLowPowerMode(); 486 break; 487 case CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED: 488 case TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED: 489 subscriptionOrCarrierConfigChanged(context); 490 break; 491 } 492 } 493 }; 494 495 /** 496 * Implements {@link GnssSatelliteBlacklistCallback#onUpdateSatelliteBlacklist}. 497 */ 498 @Override onUpdateSatelliteBlacklist(int[] constellations, int[] svids)499 public void onUpdateSatelliteBlacklist(int[] constellations, int[] svids) { 500 mHandler.post(() -> mGnssConfiguration.setSatelliteBlacklist(constellations, svids)); 501 mGnssMetrics.resetConstellationTypes(); 502 } 503 subscriptionOrCarrierConfigChanged(Context context)504 private void subscriptionOrCarrierConfigChanged(Context context) { 505 if (DEBUG) Log.d(TAG, "received SIM related action: "); 506 TelephonyManager phone = (TelephonyManager) 507 mContext.getSystemService(Context.TELEPHONY_SERVICE); 508 CarrierConfigManager configManager = (CarrierConfigManager) 509 mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE); 510 int ddSubId = SubscriptionManager.getDefaultDataSubscriptionId(); 511 String mccMnc = SubscriptionManager.isValidSubscriptionId(ddSubId) 512 ? phone.getSimOperator(ddSubId) : phone.getSimOperator(); 513 boolean isKeepLppProfile = false; 514 if (!TextUtils.isEmpty(mccMnc)) { 515 if (DEBUG) Log.d(TAG, "SIM MCC/MNC is available: " + mccMnc); 516 if (configManager != null) { 517 PersistableBundle b = SubscriptionManager.isValidSubscriptionId(ddSubId) 518 ? configManager.getConfigForSubId(ddSubId) : null; 519 if (b != null) { 520 isKeepLppProfile = 521 b.getBoolean(CarrierConfigManager.Gps.KEY_PERSIST_LPP_MODE_BOOL); 522 } 523 } 524 if (isKeepLppProfile) { 525 // load current properties for the carrier 526 mGnssConfiguration.loadPropertiesFromCarrierConfig(); 527 String lpp_profile = mGnssConfiguration.getLppProfile(); 528 // set the persist property LPP_PROFILE for the value 529 if (lpp_profile != null) { 530 SystemProperties.set(GnssConfiguration.LPP_PROFILE, lpp_profile); 531 } 532 } else { 533 // reset the persist property 534 SystemProperties.set(GnssConfiguration.LPP_PROFILE, ""); 535 } 536 reloadGpsProperties(); 537 } else { 538 if (DEBUG) Log.d(TAG, "SIM MCC/MNC is still not available"); 539 } 540 } 541 updateLowPowerMode()542 private void updateLowPowerMode() { 543 // Disable GPS if we are in device idle mode. 544 boolean disableGpsForPowerManager = mPowerManager.isDeviceIdleMode(); 545 final PowerSaveState result = 546 mPowerManager.getPowerSaveState(ServiceType.LOCATION); 547 switch (result.locationMode) { 548 case PowerManager.LOCATION_MODE_GPS_DISABLED_WHEN_SCREEN_OFF: 549 case PowerManager.LOCATION_MODE_ALL_DISABLED_WHEN_SCREEN_OFF: 550 // If we are in battery saver mode and the screen is off, disable GPS. 551 disableGpsForPowerManager |= 552 result.batterySaverEnabled && !mPowerManager.isInteractive(); 553 break; 554 } 555 if (disableGpsForPowerManager != mDisableGpsForPowerManager) { 556 mDisableGpsForPowerManager = disableGpsForPowerManager; 557 updateEnabled(); 558 updateRequirements(); 559 } 560 } 561 isSupported()562 public static boolean isSupported() { 563 return native_is_supported(); 564 } 565 reloadGpsProperties()566 private void reloadGpsProperties() { 567 mGnssConfiguration.reloadGpsProperties(); 568 setSuplHostPort(); 569 // TODO: we should get rid of C2K specific setting. 570 mC2KServerHost = mGnssConfiguration.getC2KHost(); 571 mC2KServerPort = mGnssConfiguration.getC2KPort(TCP_MIN_PORT); 572 mNIHandler.setEmergencyExtensionSeconds(mGnssConfiguration.getEsExtensionSec()); 573 mSuplEsEnabled = mGnssConfiguration.getSuplEs(0) == 1; 574 mNIHandler.setSuplEsEnabled(mSuplEsEnabled); 575 if (mGnssVisibilityControl != null) { 576 mGnssVisibilityControl.onConfigurationUpdated(mGnssConfiguration); 577 } 578 } 579 GnssLocationProvider(Context context, LocationProviderManager locationProviderManager, Looper looper)580 public GnssLocationProvider(Context context, LocationProviderManager locationProviderManager, 581 Looper looper) { 582 super(context, locationProviderManager); 583 584 mLooper = looper; 585 586 // Create a wake lock 587 mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); 588 mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY); 589 mWakeLock.setReferenceCounted(true); 590 591 // Create a separate wake lock for psds downloader as it may be released due to timeout. 592 mDownloadPsdsWakeLock = mPowerManager.newWakeLock( 593 PowerManager.PARTIAL_WAKE_LOCK, DOWNLOAD_EXTRA_WAKELOCK_KEY); 594 mDownloadPsdsWakeLock.setReferenceCounted(true); 595 596 mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE); 597 mWakeupIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_WAKEUP), 0); 598 mTimeoutIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_TIMEOUT), 0); 599 600 mNetworkConnectivityHandler = new GnssNetworkConnectivityHandler(context, 601 GnssLocationProvider.this::onNetworkAvailable, looper); 602 603 // App ops service to keep track of who is accessing the GPS 604 mAppOps = mContext.getSystemService(AppOpsManager.class); 605 606 // Battery statistics service to be notified when GPS turns on or off 607 mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService( 608 BatteryStats.SERVICE_NAME)); 609 610 // Construct internal handler 611 mHandler = new ProviderHandler(looper); 612 613 // Load GPS configuration and register listeners in the background: 614 // some operations, such as opening files and registering broadcast receivers, can take a 615 // relative long time, so the ctor() is kept to create objects needed by this instance, 616 // while IO initialization and registration is delegated to our internal handler 617 // this approach is just fine because events are posted to our handler anyway 618 mGnssConfiguration = new GnssConfiguration(mContext); 619 mGnssCapabilitiesProvider = new GnssCapabilitiesProvider(); 620 // Create a GPS net-initiated handler (also needed by handleInitialize) 621 mNIHandler = new GpsNetInitiatedHandler(context, 622 mNetInitiatedListener, 623 mSuplEsEnabled); 624 sendMessage(INITIALIZE_HANDLER, 0, null); 625 626 mGnssStatusListenerHelper = new GnssStatusListenerHelper(mContext, mHandler) { 627 @Override 628 protected boolean isAvailableInPlatform() { 629 return isSupported(); 630 } 631 632 @Override 633 protected boolean isGpsEnabled() { 634 return GnssLocationProvider.this.isGpsEnabled(); 635 } 636 }; 637 638 mGnssMeasurementsProvider = new GnssMeasurementsProvider(mContext, mHandler) { 639 @Override 640 protected boolean isGpsEnabled() { 641 return GnssLocationProvider.this.isGpsEnabled(); 642 } 643 }; 644 645 mGnssMeasurementCorrectionsProvider = new GnssMeasurementCorrectionsProvider(mHandler); 646 647 mGnssNavigationMessageProvider = new GnssNavigationMessageProvider(mContext, mHandler) { 648 @Override 649 protected boolean isGpsEnabled() { 650 return GnssLocationProvider.this.isGpsEnabled(); 651 } 652 }; 653 654 mGnssMetrics = new GnssMetrics(mBatteryStats); 655 mNtpTimeHelper = new NtpTimeHelper(mContext, looper, this); 656 GnssSatelliteBlacklistHelper gnssSatelliteBlacklistHelper = 657 new GnssSatelliteBlacklistHelper(mContext, 658 looper, this); 659 mHandler.post(gnssSatelliteBlacklistHelper::updateSatelliteBlacklist); 660 mGnssBatchingProvider = new GnssBatchingProvider(); 661 mGnssGeofenceProvider = new GnssGeofenceProvider(); 662 663 mContext.registerReceiverAsUser(new BroadcastReceiver() { 664 @Override 665 public void onReceive(Context context, Intent intent) { 666 if (getSendingUserId() == UserHandle.USER_ALL) { 667 mShutdown = true; 668 updateEnabled(); 669 } 670 } 671 }, UserHandle.ALL, new IntentFilter(Intent.ACTION_SHUTDOWN), null, mHandler); 672 673 mContext.getContentResolver().registerContentObserver( 674 Settings.Secure.getUriFor(Settings.Secure.LOCATION_MODE), 675 true, 676 new ContentObserver(mHandler) { 677 @Override 678 public void onChange(boolean selfChange) { 679 updateEnabled(); 680 } 681 }, UserHandle.USER_ALL); 682 683 setProperties(PROPERTIES); 684 setEnabled(true); 685 } 686 687 /** 688 * Implements {@link InjectNtpTimeCallback#injectTime} 689 */ 690 @Override injectTime(long time, long timeReference, int uncertainty)691 public void injectTime(long time, long timeReference, int uncertainty) { 692 native_inject_time(time, timeReference, uncertainty); 693 } 694 695 /** 696 * Implements {@link GnssNetworkConnectivityHandler.GnssNetworkListener#onNetworkAvailable()} 697 */ onNetworkAvailable()698 private void onNetworkAvailable() { 699 mNtpTimeHelper.onNetworkAvailable(); 700 if (mDownloadPsdsDataPending == STATE_PENDING_NETWORK) { 701 if (mSupportsPsds) { 702 // Download only if supported, (prevents an unnecessary on-boot download) 703 psdsDownloadRequest(); 704 } 705 } 706 } 707 handleRequestLocation(boolean independentFromGnss, boolean isUserEmergency)708 private void handleRequestLocation(boolean independentFromGnss, boolean isUserEmergency) { 709 if (isRequestLocationRateLimited()) { 710 if (DEBUG) { 711 Log.d(TAG, "RequestLocation is denied due to too frequent requests."); 712 } 713 return; 714 } 715 ContentResolver resolver = mContext.getContentResolver(); 716 long durationMillis = Settings.Global.getLong( 717 resolver, 718 Settings.Global.GNSS_HAL_LOCATION_REQUEST_DURATION_MILLIS, 719 LOCATION_UPDATE_DURATION_MILLIS); 720 if (durationMillis == 0) { 721 Log.i(TAG, "GNSS HAL location request is disabled by Settings."); 722 return; 723 } 724 725 LocationManager locationManager = (LocationManager) mContext.getSystemService( 726 Context.LOCATION_SERVICE); 727 String provider; 728 LocationChangeListener locationListener; 729 LocationRequest locationRequest = new LocationRequest() 730 .setInterval(LOCATION_UPDATE_MIN_TIME_INTERVAL_MILLIS) 731 .setFastestInterval(LOCATION_UPDATE_MIN_TIME_INTERVAL_MILLIS); 732 733 if (independentFromGnss) { 734 // For fast GNSS TTFF 735 provider = LocationManager.NETWORK_PROVIDER; 736 locationListener = mNetworkLocationListener; 737 locationRequest.setQuality(LocationRequest.POWER_LOW); 738 } else { 739 // For Device-Based Hybrid (E911) 740 provider = LocationManager.FUSED_PROVIDER; 741 locationListener = mFusedLocationListener; 742 locationRequest.setQuality(LocationRequest.ACCURACY_FINE); 743 } 744 745 locationRequest.setProvider(provider); 746 747 // Ignore location settings if in emergency mode. 748 if (isUserEmergency && mNIHandler.getInEmergency()) { 749 locationRequest.setLocationSettingsIgnored(true); 750 durationMillis *= EMERGENCY_LOCATION_UPDATE_DURATION_MULTIPLIER; 751 } 752 753 Log.i(TAG, 754 String.format( 755 "GNSS HAL Requesting location updates from %s provider for %d millis.", 756 provider, durationMillis)); 757 758 try { 759 locationManager.requestLocationUpdates(locationRequest, 760 locationListener, mHandler.getLooper()); 761 locationListener.mNumLocationUpdateRequest++; 762 mHandler.postDelayed(() -> { 763 if (--locationListener.mNumLocationUpdateRequest == 0) { 764 Log.i(TAG, 765 String.format("Removing location updates from %s provider.", provider)); 766 locationManager.removeUpdates(locationListener); 767 } 768 }, durationMillis); 769 } catch (IllegalArgumentException e) { 770 Log.w(TAG, "Unable to request location.", e); 771 } 772 } 773 injectBestLocation(Location location)774 private void injectBestLocation(Location location) { 775 if (DEBUG) { 776 Log.d(TAG, "injectBestLocation: " + location); 777 } 778 int gnssLocationFlags = LOCATION_HAS_LAT_LONG | 779 (location.hasAltitude() ? LOCATION_HAS_ALTITUDE : 0) | 780 (location.hasSpeed() ? LOCATION_HAS_SPEED : 0) | 781 (location.hasBearing() ? LOCATION_HAS_BEARING : 0) | 782 (location.hasAccuracy() ? LOCATION_HAS_HORIZONTAL_ACCURACY : 0) | 783 (location.hasVerticalAccuracy() ? LOCATION_HAS_VERTICAL_ACCURACY : 0) | 784 (location.hasSpeedAccuracy() ? LOCATION_HAS_SPEED_ACCURACY : 0) | 785 (location.hasBearingAccuracy() ? LOCATION_HAS_BEARING_ACCURACY : 0); 786 787 double latitudeDegrees = location.getLatitude(); 788 double longitudeDegrees = location.getLongitude(); 789 double altitudeMeters = location.getAltitude(); 790 float speedMetersPerSec = location.getSpeed(); 791 float bearingDegrees = location.getBearing(); 792 float horizontalAccuracyMeters = location.getAccuracy(); 793 float verticalAccuracyMeters = location.getVerticalAccuracyMeters(); 794 float speedAccuracyMetersPerSecond = location.getSpeedAccuracyMetersPerSecond(); 795 float bearingAccuracyDegrees = location.getBearingAccuracyDegrees(); 796 long timestamp = location.getTime(); 797 798 int elapsedRealtimeFlags = ELAPSED_REALTIME_HAS_TIMESTAMP_NS 799 | (location.hasElapsedRealtimeUncertaintyNanos() 800 ? ELAPSED_REALTIME_HAS_TIME_UNCERTAINTY_NS : 0); 801 long elapsedRealtimeNanos = location.getElapsedRealtimeNanos(); 802 double elapsedRealtimeUncertaintyNanos = location.getElapsedRealtimeUncertaintyNanos(); 803 804 native_inject_best_location( 805 gnssLocationFlags, latitudeDegrees, longitudeDegrees, 806 altitudeMeters, speedMetersPerSec, bearingDegrees, 807 horizontalAccuracyMeters, verticalAccuracyMeters, 808 speedAccuracyMetersPerSecond, bearingAccuracyDegrees, timestamp, 809 elapsedRealtimeFlags, elapsedRealtimeNanos, elapsedRealtimeUncertaintyNanos); 810 } 811 812 /** Returns true if the location request is too frequent. */ isRequestLocationRateLimited()813 private boolean isRequestLocationRateLimited() { 814 // TODO: implement exponential backoff. 815 return false; 816 } 817 handleDownloadPsdsData()818 private void handleDownloadPsdsData() { 819 if (!mSupportsPsds) { 820 // native code reports psds not supported, don't try 821 Log.d(TAG, "handleDownloadPsdsData() called when PSDS not supported"); 822 return; 823 } 824 if (mDownloadPsdsDataPending == STATE_DOWNLOADING) { 825 // already downloading data 826 return; 827 } 828 if (!mNetworkConnectivityHandler.isDataNetworkConnected()) { 829 // try again when network is up 830 mDownloadPsdsDataPending = STATE_PENDING_NETWORK; 831 return; 832 } 833 mDownloadPsdsDataPending = STATE_DOWNLOADING; 834 835 synchronized (mLock) { 836 // hold wake lock while task runs 837 mDownloadPsdsWakeLock.acquire(DOWNLOAD_PSDS_DATA_TIMEOUT_MS); 838 } 839 Log.i(TAG, "WakeLock acquired by handleDownloadPsdsData()"); 840 AsyncTask.THREAD_POOL_EXECUTOR.execute(() -> { 841 GpsPsdsDownloader psdsDownloader = new GpsPsdsDownloader( 842 mGnssConfiguration.getProperties()); 843 byte[] data = psdsDownloader.downloadPsdsData(); 844 if (data != null) { 845 if (DEBUG) Log.d(TAG, "calling native_inject_psds_data"); 846 native_inject_psds_data(data, data.length); 847 mPsdsBackOff.reset(); 848 } 849 850 sendMessage(DOWNLOAD_PSDS_DATA_FINISHED, 0, null); 851 852 if (data == null) { 853 // try again later 854 // since this is delayed and not urgent we do not hold a wake lock here 855 mHandler.sendEmptyMessageDelayed(DOWNLOAD_PSDS_DATA, 856 mPsdsBackOff.nextBackoffMillis()); 857 } 858 859 // Release wake lock held by task, synchronize on mLock in case multiple 860 // download tasks overrun. 861 synchronized (mLock) { 862 if (mDownloadPsdsWakeLock.isHeld()) { 863 // This wakelock may have time-out, if a timeout was specified. 864 // Catch (and ignore) any timeout exceptions. 865 try { 866 mDownloadPsdsWakeLock.release(); 867 if (DEBUG) Log.d(TAG, "WakeLock released by handleDownloadPsdsData()"); 868 } catch (Exception e) { 869 Log.i(TAG, "Wakelock timeout & release race exception in " 870 + "handleDownloadPsdsData()", e); 871 } 872 } else { 873 Log.e(TAG, "WakeLock expired before release in " 874 + "handleDownloadPsdsData()"); 875 } 876 } 877 }); 878 } 879 handleUpdateLocation(Location location)880 private void handleUpdateLocation(Location location) { 881 if (location.hasAccuracy()) { 882 if (DEBUG) { 883 Log.d(TAG, "injectLocation: " + location); 884 } 885 native_inject_location(location.getLatitude(), location.getLongitude(), 886 location.getAccuracy()); 887 } 888 } 889 setSuplHostPort()890 private void setSuplHostPort() { 891 mSuplServerHost = mGnssConfiguration.getSuplHost(); 892 mSuplServerPort = mGnssConfiguration.getSuplPort(TCP_MIN_PORT); 893 if (mSuplServerHost != null 894 && mSuplServerPort > TCP_MIN_PORT 895 && mSuplServerPort <= TCP_MAX_PORT) { 896 native_set_agps_server(GnssNetworkConnectivityHandler.AGPS_TYPE_SUPL, 897 mSuplServerHost, mSuplServerPort); 898 } 899 } 900 901 /** 902 * Checks what SUPL mode to use, according to the AGPS mode as well as the 903 * allowed mode from properties. 904 * 905 * @param agpsEnabled whether AGPS is enabled by settings value 906 * @return SUPL mode (MSA vs MSB vs STANDALONE) 907 */ getSuplMode(boolean agpsEnabled)908 private int getSuplMode(boolean agpsEnabled) { 909 if (agpsEnabled) { 910 int suplMode = mGnssConfiguration.getSuplMode(0); 911 if (suplMode == 0) { 912 return GPS_POSITION_MODE_STANDALONE; 913 } 914 915 // MS-Based is the preferred mode for Assisted-GPS position computation, so we favor 916 // such mode when it is available 917 if (hasCapability(GPS_CAPABILITY_MSB) && (suplMode & AGPS_SUPL_MODE_MSB) != 0) { 918 return GPS_POSITION_MODE_MS_BASED; 919 } 920 } 921 return GPS_POSITION_MODE_STANDALONE; 922 } 923 setGpsEnabled(boolean enabled)924 private void setGpsEnabled(boolean enabled) { 925 synchronized (mLock) { 926 mGpsEnabled = enabled; 927 } 928 } 929 handleEnable()930 private void handleEnable() { 931 if (DEBUG) Log.d(TAG, "handleEnable"); 932 933 boolean inited = native_init(); 934 935 if (inited) { 936 setGpsEnabled(true); 937 mSupportsPsds = native_supports_psds(); 938 939 // TODO: remove the following native calls if we can make sure they are redundant. 940 if (mSuplServerHost != null) { 941 native_set_agps_server(GnssNetworkConnectivityHandler.AGPS_TYPE_SUPL, 942 mSuplServerHost, mSuplServerPort); 943 } 944 if (mC2KServerHost != null) { 945 native_set_agps_server(GnssNetworkConnectivityHandler.AGPS_TYPE_C2K, 946 mC2KServerHost, mC2KServerPort); 947 } 948 949 mGnssMeasurementsProvider.onGpsEnabledChanged(); 950 mGnssNavigationMessageProvider.onGpsEnabledChanged(); 951 mGnssBatchingProvider.enable(); 952 if (mGnssVisibilityControl != null) { 953 mGnssVisibilityControl.onGpsEnabledChanged(/* isEnabled= */ true); 954 } 955 } else { 956 setGpsEnabled(false); 957 Log.w(TAG, "Failed to enable location provider"); 958 } 959 } 960 handleDisable()961 private void handleDisable() { 962 if (DEBUG) Log.d(TAG, "handleDisable"); 963 964 setGpsEnabled(false); 965 updateClientUids(new WorkSource()); 966 stopNavigating(); 967 mAlarmManager.cancel(mWakeupIntent); 968 mAlarmManager.cancel(mTimeoutIntent); 969 970 if (mGnssVisibilityControl != null) { 971 mGnssVisibilityControl.onGpsEnabledChanged(/* isEnabled= */ false); 972 } 973 mGnssBatchingProvider.disable(); 974 // do this before releasing wakelock 975 native_cleanup(); 976 977 mGnssMeasurementsProvider.onGpsEnabledChanged(); 978 mGnssNavigationMessageProvider.onGpsEnabledChanged(); 979 } 980 updateEnabled()981 private void updateEnabled() { 982 // Generally follow location setting for current user 983 boolean enabled = mContext.getSystemService(LocationManager.class) 984 .isLocationEnabledForUser(UserHandle.CURRENT); 985 986 // ... but disable if PowerManager overrides 987 enabled &= !mDisableGpsForPowerManager; 988 989 // .. but enable anyway, if there's an active settings-ignored request (e.g. ELS) 990 enabled |= (mProviderRequest != null && mProviderRequest.reportLocation 991 && mProviderRequest.locationSettingsIgnored); 992 993 // ... and, finally, disable anyway, if device is being shut down 994 enabled &= !mShutdown; 995 996 if (enabled == isGpsEnabled()) { 997 return; 998 } 999 1000 if (enabled) { 1001 handleEnable(); 1002 } else { 1003 handleDisable(); 1004 } 1005 } 1006 isGpsEnabled()1007 private boolean isGpsEnabled() { 1008 synchronized (mLock) { 1009 return mGpsEnabled; 1010 } 1011 } 1012 1013 @Override getStatus(Bundle extras)1014 public int getStatus(Bundle extras) { 1015 mLocationExtras.setBundle(extras); 1016 return mStatus; 1017 } 1018 updateStatus(int status)1019 private void updateStatus(int status) { 1020 if (status != mStatus) { 1021 mStatus = status; 1022 mStatusUpdateTime = SystemClock.elapsedRealtime(); 1023 } 1024 } 1025 1026 @Override getStatusUpdateTime()1027 public long getStatusUpdateTime() { 1028 return mStatusUpdateTime; 1029 } 1030 1031 @Override setRequest(ProviderRequest request, WorkSource source)1032 public void setRequest(ProviderRequest request, WorkSource source) { 1033 sendMessage(SET_REQUEST, 0, new GpsRequest(request, source)); 1034 } 1035 handleSetRequest(ProviderRequest request, WorkSource source)1036 private void handleSetRequest(ProviderRequest request, WorkSource source) { 1037 mProviderRequest = request; 1038 mWorkSource = source; 1039 updateEnabled(); 1040 updateRequirements(); 1041 } 1042 1043 // Called when the requirements for GPS may have changed updateRequirements()1044 private void updateRequirements() { 1045 if (mProviderRequest == null || mWorkSource == null) { 1046 return; 1047 } 1048 1049 if (DEBUG) Log.d(TAG, "setRequest " + mProviderRequest); 1050 if (mProviderRequest.reportLocation && isGpsEnabled()) { 1051 // update client uids 1052 updateClientUids(mWorkSource); 1053 1054 mFixInterval = (int) mProviderRequest.interval; 1055 mLowPowerMode = mProviderRequest.lowPowerMode; 1056 // check for overflow 1057 if (mFixInterval != mProviderRequest.interval) { 1058 Log.w(TAG, "interval overflow: " + mProviderRequest.interval); 1059 mFixInterval = Integer.MAX_VALUE; 1060 } 1061 1062 // apply request to GPS engine 1063 if (mStarted && hasCapability(GPS_CAPABILITY_SCHEDULING)) { 1064 // change period and/or lowPowerMode 1065 if (!setPositionMode(mPositionMode, GPS_POSITION_RECURRENCE_PERIODIC, 1066 mFixInterval, 0, 0, mLowPowerMode)) { 1067 Log.e(TAG, "set_position_mode failed in updateRequirements"); 1068 } 1069 } else if (!mStarted) { 1070 // start GPS 1071 startNavigating(); 1072 } else { 1073 // GNSS Engine is already ON, but no GPS_CAPABILITY_SCHEDULING 1074 mAlarmManager.cancel(mTimeoutIntent); 1075 if (mFixInterval >= NO_FIX_TIMEOUT) { 1076 // set timer to give up if we do not receive a fix within NO_FIX_TIMEOUT 1077 // and our fix interval is not short 1078 mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, 1079 SystemClock.elapsedRealtime() + NO_FIX_TIMEOUT, mTimeoutIntent); 1080 } 1081 } 1082 } else { 1083 updateClientUids(new WorkSource()); 1084 1085 stopNavigating(); 1086 mAlarmManager.cancel(mWakeupIntent); 1087 mAlarmManager.cancel(mTimeoutIntent); 1088 } 1089 } 1090 setPositionMode(int mode, int recurrence, int minInterval, int preferredAccuracy, int preferredTime, boolean lowPowerMode)1091 private boolean setPositionMode(int mode, int recurrence, int minInterval, 1092 int preferredAccuracy, int preferredTime, boolean lowPowerMode) { 1093 GnssPositionMode positionMode = new GnssPositionMode(mode, recurrence, minInterval, 1094 preferredAccuracy, preferredTime, lowPowerMode); 1095 if (mLastPositionMode != null && mLastPositionMode.equals(positionMode)) { 1096 return true; 1097 } 1098 1099 boolean result = native_set_position_mode(mode, recurrence, minInterval, 1100 preferredAccuracy, preferredTime, lowPowerMode); 1101 if (result) { 1102 mLastPositionMode = positionMode; 1103 } else { 1104 mLastPositionMode = null; 1105 } 1106 return result; 1107 } 1108 updateClientUids(WorkSource source)1109 private void updateClientUids(WorkSource source) { 1110 if (source.equals(mClientSource)) { 1111 return; 1112 } 1113 1114 // (1) Inform BatteryStats that the list of IDs we're tracking changed. 1115 try { 1116 mBatteryStats.noteGpsChanged(mClientSource, source); 1117 } catch (RemoteException e) { 1118 Log.w(TAG, "RemoteException", e); 1119 } 1120 1121 // (2) Inform AppOps service about the list of changes to UIDs. 1122 1123 List<WorkChain>[] diffs = WorkSource.diffChains(mClientSource, source); 1124 if (diffs != null) { 1125 List<WorkChain> newChains = diffs[0]; 1126 List<WorkChain> goneChains = diffs[1]; 1127 1128 if (newChains != null) { 1129 for (WorkChain newChain : newChains) { 1130 mAppOps.startOpNoThrow(AppOpsManager.OP_GPS, newChain.getAttributionUid(), 1131 newChain.getAttributionTag()); 1132 } 1133 } 1134 1135 if (goneChains != null) { 1136 for (WorkChain goneChain : goneChains) { 1137 mAppOps.finishOp(AppOpsManager.OP_GPS, goneChain.getAttributionUid(), 1138 goneChain.getAttributionTag()); 1139 } 1140 } 1141 1142 mClientSource.transferWorkChains(source); 1143 } 1144 1145 // Update the flat UIDs and names list and inform app-ops of all changes. 1146 WorkSource[] changes = mClientSource.setReturningDiffs(source); 1147 if (changes != null) { 1148 WorkSource newWork = changes[0]; 1149 WorkSource goneWork = changes[1]; 1150 1151 // Update sources that were not previously tracked. 1152 if (newWork != null) { 1153 for (int i = 0; i < newWork.size(); i++) { 1154 mAppOps.startOpNoThrow(AppOpsManager.OP_GPS, 1155 newWork.get(i), newWork.getName(i)); 1156 } 1157 } 1158 1159 // Update sources that are no longer tracked. 1160 if (goneWork != null) { 1161 for (int i = 0; i < goneWork.size(); i++) { 1162 mAppOps.finishOp(AppOpsManager.OP_GPS, goneWork.get(i), goneWork.getName(i)); 1163 } 1164 } 1165 } 1166 } 1167 1168 @Override sendExtraCommand(String command, Bundle extras)1169 public void sendExtraCommand(String command, Bundle extras) { 1170 1171 long identity = Binder.clearCallingIdentity(); 1172 try { 1173 if ("delete_aiding_data".equals(command)) { 1174 deleteAidingData(extras); 1175 } else if ("force_time_injection".equals(command)) { 1176 requestUtcTime(); 1177 } else if ("force_psds_injection".equals(command)) { 1178 if (mSupportsPsds) { 1179 psdsDownloadRequest(); 1180 } 1181 } else { 1182 Log.w(TAG, "sendExtraCommand: unknown command " + command); 1183 } 1184 } finally { 1185 Binder.restoreCallingIdentity(identity); 1186 } 1187 } 1188 deleteAidingData(Bundle extras)1189 private void deleteAidingData(Bundle extras) { 1190 int flags; 1191 1192 if (extras == null) { 1193 flags = GPS_DELETE_ALL; 1194 } else { 1195 flags = 0; 1196 if (extras.getBoolean("ephemeris")) flags |= GPS_DELETE_EPHEMERIS; 1197 if (extras.getBoolean("almanac")) flags |= GPS_DELETE_ALMANAC; 1198 if (extras.getBoolean("position")) flags |= GPS_DELETE_POSITION; 1199 if (extras.getBoolean("time")) flags |= GPS_DELETE_TIME; 1200 if (extras.getBoolean("iono")) flags |= GPS_DELETE_IONO; 1201 if (extras.getBoolean("utc")) flags |= GPS_DELETE_UTC; 1202 if (extras.getBoolean("health")) flags |= GPS_DELETE_HEALTH; 1203 if (extras.getBoolean("svdir")) flags |= GPS_DELETE_SVDIR; 1204 if (extras.getBoolean("svsteer")) flags |= GPS_DELETE_SVSTEER; 1205 if (extras.getBoolean("sadata")) flags |= GPS_DELETE_SADATA; 1206 if (extras.getBoolean("rti")) flags |= GPS_DELETE_RTI; 1207 if (extras.getBoolean("celldb-info")) flags |= GPS_DELETE_CELLDB_INFO; 1208 if (extras.getBoolean("all")) flags |= GPS_DELETE_ALL; 1209 } 1210 1211 if (flags != 0) { 1212 native_delete_aiding_data(flags); 1213 } 1214 } 1215 startNavigating()1216 private void startNavigating() { 1217 if (!mStarted) { 1218 if (DEBUG) Log.d(TAG, "startNavigating"); 1219 mTimeToFirstFix = 0; 1220 mLastFixTime = 0; 1221 setStarted(true); 1222 mPositionMode = GPS_POSITION_MODE_STANDALONE; 1223 // Notify about suppressed output, if speed limit was previously exceeded. 1224 // Elsewhere, we check again with every speed output reported. 1225 if (mItarSpeedLimitExceeded) { 1226 Log.i(TAG, "startNavigating with ITAR limit in place. Output limited " + 1227 "until slow enough speed reported."); 1228 } 1229 1230 boolean agpsEnabled = 1231 (Settings.Global.getInt(mContext.getContentResolver(), 1232 Settings.Global.ASSISTED_GPS_ENABLED, 1) != 0); 1233 mPositionMode = getSuplMode(agpsEnabled); 1234 1235 if (DEBUG) { 1236 String mode; 1237 1238 switch (mPositionMode) { 1239 case GPS_POSITION_MODE_STANDALONE: 1240 mode = "standalone"; 1241 break; 1242 case GPS_POSITION_MODE_MS_ASSISTED: 1243 mode = "MS_ASSISTED"; 1244 break; 1245 case GPS_POSITION_MODE_MS_BASED: 1246 mode = "MS_BASED"; 1247 break; 1248 default: 1249 mode = "unknown"; 1250 break; 1251 } 1252 Log.d(TAG, "setting position_mode to " + mode); 1253 } 1254 1255 int interval = (hasCapability(GPS_CAPABILITY_SCHEDULING) ? mFixInterval : 1000); 1256 mLowPowerMode = mProviderRequest.lowPowerMode; 1257 if (!setPositionMode(mPositionMode, GPS_POSITION_RECURRENCE_PERIODIC, 1258 interval, 0, 0, mLowPowerMode)) { 1259 setStarted(false); 1260 Log.e(TAG, "set_position_mode failed in startNavigating()"); 1261 return; 1262 } 1263 if (!native_start()) { 1264 setStarted(false); 1265 Log.e(TAG, "native_start failed in startNavigating()"); 1266 return; 1267 } 1268 1269 // reset SV count to zero 1270 updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE); 1271 mLocationExtras.reset(); 1272 mFixRequestTime = SystemClock.elapsedRealtime(); 1273 if (!hasCapability(GPS_CAPABILITY_SCHEDULING)) { 1274 // set timer to give up if we do not receive a fix within NO_FIX_TIMEOUT 1275 // and our fix interval is not short 1276 if (mFixInterval >= NO_FIX_TIMEOUT) { 1277 mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, 1278 SystemClock.elapsedRealtime() + NO_FIX_TIMEOUT, mTimeoutIntent); 1279 } 1280 } 1281 } 1282 } 1283 stopNavigating()1284 private void stopNavigating() { 1285 if (DEBUG) Log.d(TAG, "stopNavigating"); 1286 if (mStarted) { 1287 setStarted(false); 1288 native_stop(); 1289 mLastFixTime = 0; 1290 // native_stop() may reset the position mode in hardware. 1291 mLastPositionMode = null; 1292 1293 // reset SV count to zero 1294 updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE); 1295 mLocationExtras.reset(); 1296 } 1297 } 1298 setStarted(boolean started)1299 private void setStarted(boolean started) { 1300 if (mStarted != started) { 1301 mStarted = started; 1302 mStartedChangedElapsedRealtime = SystemClock.elapsedRealtime(); 1303 } 1304 } 1305 hibernate()1306 private void hibernate() { 1307 // stop GPS until our next fix interval arrives 1308 stopNavigating(); 1309 mAlarmManager.cancel(mTimeoutIntent); 1310 mAlarmManager.cancel(mWakeupIntent); 1311 long now = SystemClock.elapsedRealtime(); 1312 mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, now + mFixInterval, mWakeupIntent); 1313 } 1314 hasCapability(int capability)1315 private boolean hasCapability(int capability) { 1316 return (mTopHalCapabilities & capability) != 0; 1317 } 1318 1319 @NativeEntryPoint reportLocation(boolean hasLatLong, Location location)1320 private void reportLocation(boolean hasLatLong, Location location) { 1321 sendMessage(REPORT_LOCATION, hasLatLong ? 1 : 0, location); 1322 } 1323 handleReportLocation(boolean hasLatLong, Location location)1324 private void handleReportLocation(boolean hasLatLong, Location location) { 1325 if (location.hasSpeed()) { 1326 mItarSpeedLimitExceeded = location.getSpeed() > ITAR_SPEED_LIMIT_METERS_PER_SECOND; 1327 } 1328 1329 if (mItarSpeedLimitExceeded) { 1330 Log.i(TAG, "Hal reported a speed in excess of ITAR limit." + 1331 " GPS/GNSS Navigation output blocked."); 1332 if (mStarted) { 1333 mGnssMetrics.logReceivedLocationStatus(false); 1334 } 1335 return; // No output of location allowed 1336 } 1337 1338 if (VERBOSE) Log.v(TAG, "reportLocation " + location.toString()); 1339 1340 location.setExtras(mLocationExtras.getBundle()); 1341 1342 reportLocation(location); 1343 1344 if (mStarted) { 1345 mGnssMetrics.logReceivedLocationStatus(hasLatLong); 1346 if (hasLatLong) { 1347 if (location.hasAccuracy()) { 1348 mGnssMetrics.logPositionAccuracyMeters(location.getAccuracy()); 1349 } 1350 if (mTimeToFirstFix > 0) { 1351 int timeBetweenFixes = (int) (SystemClock.elapsedRealtime() - mLastFixTime); 1352 mGnssMetrics.logMissedReports(mFixInterval, timeBetweenFixes); 1353 } 1354 } 1355 } else { 1356 // Warn or error about long delayed GNSS engine shutdown as this generally wastes 1357 // power and sends location when not expected. 1358 long locationAfterStartedFalseMillis = 1359 SystemClock.elapsedRealtime() - mStartedChangedElapsedRealtime; 1360 if (locationAfterStartedFalseMillis > LOCATION_OFF_DELAY_THRESHOLD_WARN_MILLIS) { 1361 String logMessage = "Unexpected GNSS Location report " 1362 + TimeUtils.formatDuration(locationAfterStartedFalseMillis) 1363 + " after location turned off"; 1364 if (locationAfterStartedFalseMillis > LOCATION_OFF_DELAY_THRESHOLD_ERROR_MILLIS) { 1365 Log.e(TAG, logMessage); 1366 } else { 1367 Log.w(TAG, logMessage); 1368 } 1369 } 1370 } 1371 1372 mLastFixTime = SystemClock.elapsedRealtime(); 1373 // report time to first fix 1374 if (mTimeToFirstFix == 0 && hasLatLong) { 1375 mTimeToFirstFix = (int) (mLastFixTime - mFixRequestTime); 1376 if (DEBUG) Log.d(TAG, "TTFF: " + mTimeToFirstFix); 1377 if (mStarted) { 1378 mGnssMetrics.logTimeToFirstFixMilliSecs(mTimeToFirstFix); 1379 } 1380 1381 // notify status listeners 1382 mGnssStatusListenerHelper.onFirstFix(mTimeToFirstFix); 1383 } 1384 1385 if (mStarted && mStatus != LocationProvider.AVAILABLE) { 1386 // For devices that use framework scheduling, a timer may be set to ensure we don't 1387 // spend too much power searching for a location, when the requested update rate is 1388 // slow. 1389 // As we just recievied a location, we'll cancel that timer. 1390 if (!hasCapability(GPS_CAPABILITY_SCHEDULING) && mFixInterval < NO_FIX_TIMEOUT) { 1391 mAlarmManager.cancel(mTimeoutIntent); 1392 } 1393 1394 updateStatus(LocationProvider.AVAILABLE); 1395 } 1396 1397 if (!hasCapability(GPS_CAPABILITY_SCHEDULING) && mStarted && 1398 mFixInterval > GPS_POLLING_THRESHOLD_INTERVAL) { 1399 if (DEBUG) Log.d(TAG, "got fix, hibernating"); 1400 hibernate(); 1401 } 1402 } 1403 1404 @NativeEntryPoint reportStatus(int status)1405 private void reportStatus(int status) { 1406 if (DEBUG) Log.v(TAG, "reportStatus status: " + status); 1407 1408 boolean wasNavigating = mNavigating; 1409 switch (status) { 1410 case GPS_STATUS_SESSION_BEGIN: 1411 mNavigating = true; 1412 break; 1413 case GPS_STATUS_SESSION_END: 1414 mNavigating = false; 1415 break; 1416 case GPS_STATUS_ENGINE_ON: 1417 break; 1418 case GPS_STATUS_ENGINE_OFF: 1419 mNavigating = false; 1420 break; 1421 } 1422 1423 if (wasNavigating != mNavigating) { 1424 mGnssStatusListenerHelper.onStatusChanged(mNavigating); 1425 } 1426 } 1427 1428 // Helper class to carry data to handler for reportSvStatus 1429 private static class SvStatusInfo { 1430 private int mSvCount; 1431 private int[] mSvidWithFlags; 1432 private float[] mCn0s; 1433 private float[] mSvElevations; 1434 private float[] mSvAzimuths; 1435 private float[] mSvCarrierFreqs; 1436 } 1437 1438 @NativeEntryPoint reportSvStatus(int svCount, int[] svidWithFlags, float[] cn0s, float[] svElevations, float[] svAzimuths, float[] svCarrierFreqs)1439 private void reportSvStatus(int svCount, int[] svidWithFlags, float[] cn0s, 1440 float[] svElevations, float[] svAzimuths, float[] svCarrierFreqs) { 1441 SvStatusInfo svStatusInfo = new SvStatusInfo(); 1442 svStatusInfo.mSvCount = svCount; 1443 svStatusInfo.mSvidWithFlags = svidWithFlags; 1444 svStatusInfo.mCn0s = cn0s; 1445 svStatusInfo.mSvElevations = svElevations; 1446 svStatusInfo.mSvAzimuths = svAzimuths; 1447 svStatusInfo.mSvCarrierFreqs = svCarrierFreqs; 1448 1449 sendMessage(REPORT_SV_STATUS, 0, svStatusInfo); 1450 } 1451 handleReportSvStatus(SvStatusInfo info)1452 private void handleReportSvStatus(SvStatusInfo info) { 1453 mGnssStatusListenerHelper.onSvStatusChanged( 1454 info.mSvCount, 1455 info.mSvidWithFlags, 1456 info.mCn0s, 1457 info.mSvElevations, 1458 info.mSvAzimuths, 1459 info.mSvCarrierFreqs); 1460 1461 // Log CN0 as part of GNSS metrics 1462 mGnssMetrics.logCn0(info.mCn0s, info.mSvCount); 1463 1464 if (VERBOSE) { 1465 Log.v(TAG, "SV count: " + info.mSvCount); 1466 } 1467 // Calculate number of satellites used in fix. 1468 int usedInFixCount = 0; 1469 int maxCn0 = 0; 1470 int meanCn0 = 0; 1471 for (int i = 0; i < info.mSvCount; i++) { 1472 if ((info.mSvidWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_USED_IN_FIX) != 0) { 1473 ++usedInFixCount; 1474 if (info.mCn0s[i] > maxCn0) { 1475 maxCn0 = (int) info.mCn0s[i]; 1476 } 1477 meanCn0 += info.mCn0s[i]; 1478 } 1479 if (VERBOSE) { 1480 Log.v(TAG, "svid: " + (info.mSvidWithFlags[i] >> GnssStatus.SVID_SHIFT_WIDTH) + 1481 " cn0: " + info.mCn0s[i] + 1482 " elev: " + info.mSvElevations[i] + 1483 " azimuth: " + info.mSvAzimuths[i] + 1484 " carrier frequency: " + info.mSvCarrierFreqs[i] + 1485 ((info.mSvidWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_HAS_EPHEMERIS_DATA) == 0 1486 ? " " : " E") + 1487 ((info.mSvidWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_HAS_ALMANAC_DATA) == 0 1488 ? " " : " A") + 1489 ((info.mSvidWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_USED_IN_FIX) == 0 1490 ? "" : "U") + 1491 ((info.mSvidWithFlags[i] & 1492 GnssStatus.GNSS_SV_FLAGS_HAS_CARRIER_FREQUENCY) == 0 1493 ? "" : "F")); 1494 } 1495 1496 if ((info.mSvidWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_USED_IN_FIX) != 0) { 1497 int constellationType = 1498 (info.mSvidWithFlags[i] >> GnssStatus.CONSTELLATION_TYPE_SHIFT_WIDTH) 1499 & GnssStatus.CONSTELLATION_TYPE_MASK; 1500 mGnssMetrics.logConstellationType(constellationType); 1501 } 1502 } 1503 if (usedInFixCount > 0) { 1504 meanCn0 /= usedInFixCount; 1505 } 1506 // return number of sats used in fix instead of total reported 1507 mLocationExtras.set(usedInFixCount, meanCn0, maxCn0); 1508 1509 if (mNavigating && mStatus == LocationProvider.AVAILABLE && mLastFixTime > 0 && 1510 SystemClock.elapsedRealtime() - mLastFixTime > RECENT_FIX_TIMEOUT) { 1511 updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE); 1512 } 1513 } 1514 1515 @NativeEntryPoint reportAGpsStatus(int agpsType, int agpsStatus, byte[] suplIpAddr)1516 private void reportAGpsStatus(int agpsType, int agpsStatus, byte[] suplIpAddr) { 1517 mNetworkConnectivityHandler.onReportAGpsStatus(agpsType, agpsStatus, suplIpAddr); 1518 } 1519 1520 @NativeEntryPoint reportNmea(long timestamp)1521 private void reportNmea(long timestamp) { 1522 if (!mItarSpeedLimitExceeded) { 1523 int length = native_read_nmea(mNmeaBuffer, mNmeaBuffer.length); 1524 String nmea = new String(mNmeaBuffer, 0 /* offset */, length); 1525 mGnssStatusListenerHelper.onNmeaReceived(timestamp, nmea); 1526 } 1527 } 1528 1529 @NativeEntryPoint reportMeasurementData(GnssMeasurementsEvent event)1530 private void reportMeasurementData(GnssMeasurementsEvent event) { 1531 if (!mItarSpeedLimitExceeded) { 1532 // send to handler to allow native to return quickly 1533 mHandler.post(() -> mGnssMeasurementsProvider.onMeasurementsAvailable(event)); 1534 } 1535 } 1536 1537 @NativeEntryPoint reportNavigationMessage(GnssNavigationMessage event)1538 private void reportNavigationMessage(GnssNavigationMessage event) { 1539 if (!mItarSpeedLimitExceeded) { 1540 // send to handler to allow native to return quickly 1541 mHandler.post(() -> mGnssNavigationMessageProvider.onNavigationMessageAvailable(event)); 1542 } 1543 } 1544 1545 @NativeEntryPoint setTopHalCapabilities(int topHalCapabilities)1546 private void setTopHalCapabilities(int topHalCapabilities) { 1547 mHandler.post(() -> { 1548 mTopHalCapabilities = topHalCapabilities; 1549 1550 if (hasCapability(GPS_CAPABILITY_ON_DEMAND_TIME)) { 1551 mNtpTimeHelper.enablePeriodicTimeInjection(); 1552 requestUtcTime(); 1553 } 1554 1555 mGnssMeasurementsProvider.onCapabilitiesUpdated( 1556 hasCapability(GPS_CAPABILITY_MEASUREMENTS)); 1557 mGnssNavigationMessageProvider.onCapabilitiesUpdated( 1558 hasCapability(GPS_CAPABILITY_NAV_MESSAGES)); 1559 restartRequests(); 1560 1561 mGnssCapabilitiesProvider.setTopHalCapabilities(mTopHalCapabilities); 1562 }); 1563 } 1564 1565 @NativeEntryPoint setSubHalMeasurementCorrectionsCapabilities(int subHalCapabilities)1566 private void setSubHalMeasurementCorrectionsCapabilities(int subHalCapabilities) { 1567 mHandler.post(() -> { 1568 if (!mGnssMeasurementCorrectionsProvider.onCapabilitiesUpdated(subHalCapabilities)) { 1569 return; 1570 } 1571 1572 mGnssCapabilitiesProvider.setSubHalMeasurementCorrectionsCapabilities( 1573 subHalCapabilities); 1574 }); 1575 } 1576 restartRequests()1577 private void restartRequests() { 1578 Log.i(TAG, "restartRequests"); 1579 1580 restartLocationRequest(); 1581 mGnssMeasurementsProvider.resumeIfStarted(); 1582 mGnssNavigationMessageProvider.resumeIfStarted(); 1583 mGnssBatchingProvider.resumeIfStarted(); 1584 mGnssGeofenceProvider.resumeIfStarted(); 1585 } 1586 restartLocationRequest()1587 private void restartLocationRequest() { 1588 if (DEBUG) Log.d(TAG, "restartLocationRequest"); 1589 setStarted(false); 1590 updateRequirements(); 1591 } 1592 1593 @NativeEntryPoint setGnssYearOfHardware(final int yearOfHardware)1594 private void setGnssYearOfHardware(final int yearOfHardware) { 1595 // mHardwareYear is simply set here, to be read elsewhere, and is volatile for safe sync 1596 if (DEBUG) Log.d(TAG, "setGnssYearOfHardware called with " + yearOfHardware); 1597 mHardwareYear = yearOfHardware; 1598 } 1599 1600 @NativeEntryPoint setGnssHardwareModelName(final String modelName)1601 private void setGnssHardwareModelName(final String modelName) { 1602 // mHardwareModelName is simply set here, to be read elsewhere, and volatile for safe sync 1603 if (DEBUG) Log.d(TAG, "setGnssModelName called with " + modelName); 1604 mHardwareModelName = modelName; 1605 } 1606 1607 @NativeEntryPoint reportGnssServiceDied()1608 private void reportGnssServiceDied() { 1609 if (DEBUG) Log.d(TAG, "reportGnssServiceDied"); 1610 mHandler.post(() -> { 1611 setupNativeGnssService(/* reinitializeGnssServiceHandle = */ true); 1612 if (isGpsEnabled()) { 1613 setGpsEnabled(false); 1614 1615 updateEnabled(); 1616 1617 // resend configuration into the restarted HAL service. 1618 reloadGpsProperties(); 1619 } 1620 }); 1621 } 1622 1623 public interface GnssSystemInfoProvider { 1624 /** 1625 * Returns the year of underlying GPS hardware. 1626 */ getGnssYearOfHardware()1627 int getGnssYearOfHardware(); 1628 1629 /** 1630 * Returns the model name of underlying GPS hardware. 1631 */ getGnssHardwareModelName()1632 String getGnssHardwareModelName(); 1633 } 1634 1635 /** 1636 * @hide 1637 */ getGnssSystemInfoProvider()1638 public GnssSystemInfoProvider getGnssSystemInfoProvider() { 1639 return new GnssSystemInfoProvider() { 1640 @Override 1641 public int getGnssYearOfHardware() { 1642 return mHardwareYear; 1643 } 1644 1645 @Override 1646 public String getGnssHardwareModelName() { 1647 return mHardwareModelName; 1648 } 1649 }; 1650 } 1651 1652 /** 1653 * @hide 1654 */ 1655 public GnssBatchingProvider getGnssBatchingProvider() { 1656 return mGnssBatchingProvider; 1657 } 1658 1659 public interface GnssMetricsProvider { 1660 /** 1661 * Returns GNSS metrics as proto string 1662 */ 1663 String getGnssMetricsAsProtoString(); 1664 } 1665 1666 /** 1667 * @hide 1668 */ 1669 public GnssMetricsProvider getGnssMetricsProvider() { 1670 return () -> mGnssMetrics.dumpGnssMetricsAsProtoString(); 1671 } 1672 1673 /** 1674 * @hide 1675 */ 1676 public GnssCapabilitiesProvider getGnssCapabilitiesProvider() { 1677 return mGnssCapabilitiesProvider; 1678 } 1679 1680 @NativeEntryPoint 1681 private void reportLocationBatch(Location[] locationArray) { 1682 List<Location> locations = new ArrayList<>(Arrays.asList(locationArray)); 1683 if (DEBUG) { 1684 Log.d(TAG, "Location batch of size " + locationArray.length + " reported"); 1685 } 1686 reportLocation(locations); 1687 } 1688 1689 @NativeEntryPoint 1690 private void psdsDownloadRequest() { 1691 if (DEBUG) Log.d(TAG, "psdsDownloadRequest"); 1692 sendMessage(DOWNLOAD_PSDS_DATA, 0, null); 1693 } 1694 1695 /** 1696 * Converts the GPS HAL status to the internal Geofence Hardware status. 1697 */ 1698 private static int getGeofenceStatus(int status) { 1699 switch (status) { 1700 case GPS_GEOFENCE_OPERATION_SUCCESS: 1701 return GeofenceHardware.GEOFENCE_SUCCESS; 1702 case GPS_GEOFENCE_ERROR_GENERIC: 1703 return GeofenceHardware.GEOFENCE_FAILURE; 1704 case GPS_GEOFENCE_ERROR_ID_EXISTS: 1705 return GeofenceHardware.GEOFENCE_ERROR_ID_EXISTS; 1706 case GPS_GEOFENCE_ERROR_INVALID_TRANSITION: 1707 return GeofenceHardware.GEOFENCE_ERROR_INVALID_TRANSITION; 1708 case GPS_GEOFENCE_ERROR_TOO_MANY_GEOFENCES: 1709 return GeofenceHardware.GEOFENCE_ERROR_TOO_MANY_GEOFENCES; 1710 case GPS_GEOFENCE_ERROR_ID_UNKNOWN: 1711 return GeofenceHardware.GEOFENCE_ERROR_ID_UNKNOWN; 1712 default: 1713 return -1; 1714 } 1715 } 1716 1717 @NativeEntryPoint 1718 private void reportGeofenceTransition(int geofenceId, Location location, int transition, 1719 long transitionTimestamp) { 1720 mHandler.post(() -> { 1721 if (mGeofenceHardwareImpl == null) { 1722 mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext); 1723 } 1724 1725 mGeofenceHardwareImpl.reportGeofenceTransition( 1726 geofenceId, 1727 location, 1728 transition, 1729 transitionTimestamp, 1730 GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE, 1731 FusedBatchOptions.SourceTechnologies.GNSS); 1732 }); 1733 } 1734 1735 @NativeEntryPoint 1736 private void reportGeofenceStatus(int status, Location location) { 1737 mHandler.post(() -> { 1738 if (mGeofenceHardwareImpl == null) { 1739 mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext); 1740 } 1741 int monitorStatus = GeofenceHardware.MONITOR_CURRENTLY_UNAVAILABLE; 1742 if (status == GPS_GEOFENCE_AVAILABLE) { 1743 monitorStatus = GeofenceHardware.MONITOR_CURRENTLY_AVAILABLE; 1744 } 1745 mGeofenceHardwareImpl.reportGeofenceMonitorStatus( 1746 GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE, 1747 monitorStatus, 1748 location, 1749 FusedBatchOptions.SourceTechnologies.GNSS); 1750 }); 1751 } 1752 1753 @NativeEntryPoint 1754 private void reportGeofenceAddStatus(int geofenceId, int status) { 1755 mHandler.post(() -> { 1756 if (mGeofenceHardwareImpl == null) { 1757 mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext); 1758 } 1759 mGeofenceHardwareImpl.reportGeofenceAddStatus(geofenceId, getGeofenceStatus(status)); 1760 }); 1761 } 1762 1763 @NativeEntryPoint 1764 private void reportGeofenceRemoveStatus(int geofenceId, int status) { 1765 mHandler.post(() -> { 1766 if (mGeofenceHardwareImpl == null) { 1767 mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext); 1768 } 1769 mGeofenceHardwareImpl.reportGeofenceRemoveStatus(geofenceId, getGeofenceStatus(status)); 1770 }); 1771 } 1772 1773 @NativeEntryPoint 1774 private void reportGeofencePauseStatus(int geofenceId, int status) { 1775 mHandler.post(() -> { 1776 if (mGeofenceHardwareImpl == null) { 1777 mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext); 1778 } 1779 mGeofenceHardwareImpl.reportGeofencePauseStatus(geofenceId, getGeofenceStatus(status)); 1780 }); 1781 } 1782 1783 @NativeEntryPoint 1784 private void reportGeofenceResumeStatus(int geofenceId, int status) { 1785 mHandler.post(() -> { 1786 if (mGeofenceHardwareImpl == null) { 1787 mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext); 1788 } 1789 mGeofenceHardwareImpl.reportGeofenceResumeStatus(geofenceId, getGeofenceStatus(status)); 1790 }); 1791 } 1792 1793 //============================================================= 1794 // NI Client support 1795 //============================================================= 1796 private final INetInitiatedListener mNetInitiatedListener = new INetInitiatedListener.Stub() { 1797 // Sends a response for an NI request to HAL. 1798 @Override 1799 public boolean sendNiResponse(int notificationId, int userResponse) { 1800 // TODO Add Permission check 1801 1802 if (DEBUG) { 1803 Log.d(TAG, "sendNiResponse, notifId: " + notificationId + 1804 ", response: " + userResponse); 1805 } 1806 native_send_ni_response(notificationId, userResponse); 1807 1808 StatsLog.write(StatsLog.GNSS_NI_EVENT_REPORTED, 1809 StatsLog.GNSS_NI_EVENT_REPORTED__EVENT_TYPE__NI_RESPONSE, 1810 notificationId, 1811 /* niType= */ 0, 1812 /* needNotify= */ false, 1813 /* needVerify= */ false, 1814 /* privacyOverride= */ false, 1815 /* timeout= */ 0, 1816 /* defaultResponse= */ 0, 1817 /* requestorId= */ null, 1818 /* text= */ null, 1819 /* requestorIdEncoding= */ 0, 1820 /* textEncoding= */ 0, 1821 mSuplEsEnabled, 1822 isGpsEnabled(), 1823 userResponse); 1824 1825 return true; 1826 } 1827 }; 1828 1829 public INetInitiatedListener getNetInitiatedListener() { 1830 return mNetInitiatedListener; 1831 } 1832 1833 /** Reports a NI notification. */ 1834 @NativeEntryPoint 1835 public void reportNiNotification( 1836 int notificationId, 1837 int niType, 1838 int notifyFlags, 1839 int timeout, 1840 int defaultResponse, 1841 String requestorId, 1842 String text, 1843 int requestorIdEncoding, 1844 int textEncoding 1845 ) { 1846 Log.i(TAG, "reportNiNotification: entered"); 1847 Log.i(TAG, "notificationId: " + notificationId + 1848 ", niType: " + niType + 1849 ", notifyFlags: " + notifyFlags + 1850 ", timeout: " + timeout + 1851 ", defaultResponse: " + defaultResponse); 1852 1853 Log.i(TAG, "requestorId: " + requestorId + 1854 ", text: " + text + 1855 ", requestorIdEncoding: " + requestorIdEncoding + 1856 ", textEncoding: " + textEncoding); 1857 1858 GpsNiNotification notification = new GpsNiNotification(); 1859 1860 notification.notificationId = notificationId; 1861 notification.niType = niType; 1862 notification.needNotify = (notifyFlags & GpsNetInitiatedHandler.GPS_NI_NEED_NOTIFY) != 0; 1863 notification.needVerify = (notifyFlags & GpsNetInitiatedHandler.GPS_NI_NEED_VERIFY) != 0; 1864 notification.privacyOverride = 1865 (notifyFlags & GpsNetInitiatedHandler.GPS_NI_PRIVACY_OVERRIDE) != 0; 1866 notification.timeout = timeout; 1867 notification.defaultResponse = defaultResponse; 1868 notification.requestorId = requestorId; 1869 notification.text = text; 1870 notification.requestorIdEncoding = requestorIdEncoding; 1871 notification.textEncoding = textEncoding; 1872 1873 mNIHandler.handleNiNotification(notification); 1874 StatsLog.write(StatsLog.GNSS_NI_EVENT_REPORTED, 1875 StatsLog.GNSS_NI_EVENT_REPORTED__EVENT_TYPE__NI_REQUEST, 1876 notification.notificationId, 1877 notification.niType, 1878 notification.needNotify, 1879 notification.needVerify, 1880 notification.privacyOverride, 1881 notification.timeout, 1882 notification.defaultResponse, 1883 notification.requestorId, 1884 notification.text, 1885 notification.requestorIdEncoding, 1886 notification.textEncoding, 1887 mSuplEsEnabled, 1888 isGpsEnabled(), 1889 /* userResponse= */ 0); 1890 } 1891 1892 /** 1893 * We should be careful about receiving null string from the TelephonyManager, 1894 * because sending null String to JNI function would cause a crash. 1895 */ 1896 @NativeEntryPoint 1897 private void requestSetID(int flags) { 1898 TelephonyManager phone = (TelephonyManager) 1899 mContext.getSystemService(Context.TELEPHONY_SERVICE); 1900 int type = AGPS_SETID_TYPE_NONE; 1901 String setId = null; 1902 1903 int ddSubId = SubscriptionManager.getDefaultDataSubscriptionId(); 1904 if ((flags & AGPS_RIL_REQUEST_SETID_IMSI) == AGPS_RIL_REQUEST_SETID_IMSI) { 1905 if (SubscriptionManager.isValidSubscriptionId(ddSubId)) { 1906 setId = phone.getSubscriberId(ddSubId); 1907 } 1908 if (setId == null) { 1909 setId = phone.getSubscriberId(); 1910 } 1911 if (setId != null) { 1912 // This means the framework has the SIM card. 1913 type = AGPS_SETID_TYPE_IMSI; 1914 } 1915 } else if ((flags & AGPS_RIL_REQUEST_SETID_MSISDN) == AGPS_RIL_REQUEST_SETID_MSISDN) { 1916 if (SubscriptionManager.isValidSubscriptionId(ddSubId)) { 1917 setId = phone.getLine1Number(ddSubId); 1918 } 1919 if (setId == null) { 1920 setId = phone.getLine1Number(); 1921 } 1922 if (setId != null) { 1923 // This means the framework has the SIM card. 1924 type = AGPS_SETID_TYPE_MSISDN; 1925 } 1926 } 1927 1928 native_agps_set_id(type, (setId == null) ? "" : setId); 1929 } 1930 1931 @NativeEntryPoint 1932 private void requestLocation(boolean independentFromGnss, boolean isUserEmergency) { 1933 if (DEBUG) { 1934 Log.d(TAG, "requestLocation. independentFromGnss: " + independentFromGnss 1935 + ", isUserEmergency: " 1936 + isUserEmergency); 1937 } 1938 sendMessage(REQUEST_LOCATION, independentFromGnss ? 1 : 0, isUserEmergency); 1939 } 1940 1941 @NativeEntryPoint 1942 private void requestUtcTime() { 1943 if (DEBUG) Log.d(TAG, "utcTimeRequest"); 1944 sendMessage(INJECT_NTP_TIME, 0, null); 1945 } 1946 1947 @NativeEntryPoint 1948 private void requestRefLocation() { 1949 TelephonyManager phone = (TelephonyManager) 1950 mContext.getSystemService(Context.TELEPHONY_SERVICE); 1951 final int phoneType = phone.getPhoneType(); 1952 if (phoneType == TelephonyManager.PHONE_TYPE_GSM) { 1953 GsmCellLocation gsm_cell = (GsmCellLocation) phone.getCellLocation(); 1954 if ((gsm_cell != null) && (phone.getNetworkOperator() != null) 1955 && (phone.getNetworkOperator().length() > 3)) { 1956 int type; 1957 int mcc = Integer.parseInt(phone.getNetworkOperator().substring(0, 3)); 1958 int mnc = Integer.parseInt(phone.getNetworkOperator().substring(3)); 1959 int networkType = phone.getNetworkType(); 1960 if (networkType == TelephonyManager.NETWORK_TYPE_UMTS 1961 || networkType == TelephonyManager.NETWORK_TYPE_HSDPA 1962 || networkType == TelephonyManager.NETWORK_TYPE_HSUPA 1963 || networkType == TelephonyManager.NETWORK_TYPE_HSPA 1964 || networkType == TelephonyManager.NETWORK_TYPE_HSPAP) { 1965 type = AGPS_REF_LOCATION_TYPE_UMTS_CELLID; 1966 } else { 1967 type = AGPS_REF_LOCATION_TYPE_GSM_CELLID; 1968 } 1969 native_agps_set_ref_location_cellid(type, mcc, mnc, 1970 gsm_cell.getLac(), gsm_cell.getCid()); 1971 } else { 1972 Log.e(TAG, "Error getting cell location info."); 1973 } 1974 } else if (phoneType == TelephonyManager.PHONE_TYPE_CDMA) { 1975 Log.e(TAG, "CDMA not supported."); 1976 } 1977 } 1978 1979 // Implements method nfwNotifyCb() in IGnssVisibilityControlCallback.hal. 1980 @NativeEntryPoint 1981 private void reportNfwNotification(String proxyAppPackageName, byte protocolStack, 1982 String otherProtocolStackName, byte requestor, String requestorId, byte responseType, 1983 boolean inEmergencyMode, boolean isCachedLocation) { 1984 if (mGnssVisibilityControl == null) { 1985 Log.e(TAG, "reportNfwNotification: mGnssVisibilityControl is not initialized."); 1986 return; 1987 } 1988 1989 mGnssVisibilityControl.reportNfwNotification(proxyAppPackageName, protocolStack, 1990 otherProtocolStackName, requestor, requestorId, responseType, inEmergencyMode, 1991 isCachedLocation); 1992 } 1993 1994 // Implements method isInEmergencySession() in IGnssVisibilityControlCallback.hal. 1995 @NativeEntryPoint 1996 boolean isInEmergencySession() { 1997 return mNIHandler.getInEmergency(); 1998 } 1999 2000 private void sendMessage(int message, int arg, Object obj) { 2001 // hold a wake lock until this message is delivered 2002 // note that this assumes the message will not be removed from the queue before 2003 // it is handled (otherwise the wake lock would be leaked). 2004 mWakeLock.acquire(); 2005 if (DEBUG) { 2006 Log.d(TAG, "WakeLock acquired by sendMessage(" + messageIdAsString(message) + ", " + arg 2007 + ", " + obj + ")"); 2008 } 2009 mHandler.obtainMessage(message, arg, 1, obj).sendToTarget(); 2010 } 2011 2012 private final class ProviderHandler extends Handler { 2013 public ProviderHandler(Looper looper) { 2014 super(looper, null, true /*async*/); 2015 } 2016 2017 @Override 2018 public void handleMessage(Message msg) { 2019 int message = msg.what; 2020 switch (message) { 2021 case SET_REQUEST: 2022 GpsRequest gpsRequest = (GpsRequest) msg.obj; 2023 handleSetRequest(gpsRequest.request, gpsRequest.source); 2024 break; 2025 case INJECT_NTP_TIME: 2026 mNtpTimeHelper.retrieveAndInjectNtpTime(); 2027 break; 2028 case REQUEST_LOCATION: 2029 handleRequestLocation(msg.arg1 == 1, (boolean) msg.obj); 2030 break; 2031 case DOWNLOAD_PSDS_DATA: 2032 handleDownloadPsdsData(); 2033 break; 2034 case DOWNLOAD_PSDS_DATA_FINISHED: 2035 mDownloadPsdsDataPending = STATE_IDLE; 2036 break; 2037 case UPDATE_LOCATION: 2038 handleUpdateLocation((Location) msg.obj); 2039 break; 2040 case INITIALIZE_HANDLER: 2041 handleInitialize(); 2042 break; 2043 case REPORT_LOCATION: 2044 handleReportLocation(msg.arg1 == 1, (Location) msg.obj); 2045 break; 2046 case REPORT_SV_STATUS: 2047 handleReportSvStatus((SvStatusInfo) msg.obj); 2048 break; 2049 } 2050 if (msg.arg2 == 1) { 2051 // wakelock was taken for this message, release it 2052 mWakeLock.release(); 2053 if (DEBUG) { 2054 Log.d(TAG, "WakeLock released by handleMessage(" + messageIdAsString(message) 2055 + ", " + msg.arg1 + ", " + msg.obj + ")"); 2056 } 2057 } 2058 } 2059 2060 /** 2061 * This method is bound to {@link #GnssLocationProvider(Context, LocationProviderManager, 2062 * Looper)}. 2063 * It is in charge of loading properties and registering for events that will be posted to 2064 * this handler. 2065 */ 2066 private void handleInitialize() { 2067 // class_init_native() already initializes the GNSS service handle during class loading. 2068 setupNativeGnssService(/* reinitializeGnssServiceHandle = */ false); 2069 2070 if (native_is_gnss_visibility_control_supported()) { 2071 mGnssVisibilityControl = new GnssVisibilityControl(mContext, mLooper, mNIHandler); 2072 } 2073 2074 // load default GPS configuration 2075 // (this configuration might change in the future based on SIM changes) 2076 reloadGpsProperties(); 2077 2078 // listen for events 2079 IntentFilter intentFilter = new IntentFilter(); 2080 intentFilter.addAction(ALARM_WAKEUP); 2081 intentFilter.addAction(ALARM_TIMEOUT); 2082 intentFilter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED); 2083 intentFilter.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED); 2084 intentFilter.addAction(Intent.ACTION_SCREEN_OFF); 2085 intentFilter.addAction(Intent.ACTION_SCREEN_ON); 2086 intentFilter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED); 2087 intentFilter.addAction(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED); 2088 mContext.registerReceiver(mBroadcastReceiver, intentFilter, null, this); 2089 2090 mNetworkConnectivityHandler.registerNetworkCallbacks(); 2091 2092 // listen for PASSIVE_PROVIDER updates 2093 LocationManager locManager = 2094 (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE); 2095 long minTime = 0; 2096 float minDistance = 0; 2097 LocationRequest request = LocationRequest.createFromDeprecatedProvider( 2098 LocationManager.PASSIVE_PROVIDER, 2099 minTime, 2100 minDistance, 2101 false); 2102 // Don't keep track of this request since it's done on behalf of other clients 2103 // (which are kept track of separately). 2104 request.setHideFromAppOps(true); 2105 locManager.requestLocationUpdates( 2106 request, 2107 new NetworkLocationListener(), 2108 getLooper()); 2109 2110 updateEnabled(); 2111 } 2112 } 2113 2114 private abstract class LocationChangeListener implements LocationListener { 2115 private int mNumLocationUpdateRequest; 2116 2117 @Override 2118 public void onStatusChanged(String provider, int status, Bundle extras) { 2119 } 2120 2121 @Override 2122 public void onProviderEnabled(String provider) { 2123 } 2124 2125 @Override 2126 public void onProviderDisabled(String provider) { 2127 } 2128 } 2129 2130 private final class NetworkLocationListener extends LocationChangeListener { 2131 @Override 2132 public void onLocationChanged(Location location) { 2133 // this callback happens on mHandler looper 2134 if (LocationManager.NETWORK_PROVIDER.equals(location.getProvider())) { 2135 handleUpdateLocation(location); 2136 } 2137 } 2138 } 2139 2140 private final class FusedLocationListener extends LocationChangeListener { 2141 @Override 2142 public void onLocationChanged(Location location) { 2143 if (LocationManager.FUSED_PROVIDER.equals(location.getProvider())) { 2144 injectBestLocation(location); 2145 } 2146 } 2147 } 2148 2149 /** 2150 * @return A string representing the given message ID. 2151 */ 2152 private String messageIdAsString(int message) { 2153 switch (message) { 2154 case SET_REQUEST: 2155 return "SET_REQUEST"; 2156 case INJECT_NTP_TIME: 2157 return "INJECT_NTP_TIME"; 2158 case REQUEST_LOCATION: 2159 return "REQUEST_LOCATION"; 2160 case DOWNLOAD_PSDS_DATA: 2161 return "DOWNLOAD_PSDS_DATA"; 2162 case DOWNLOAD_PSDS_DATA_FINISHED: 2163 return "DOWNLOAD_PSDS_DATA_FINISHED"; 2164 case UPDATE_LOCATION: 2165 return "UPDATE_LOCATION"; 2166 case INITIALIZE_HANDLER: 2167 return "INITIALIZE_HANDLER"; 2168 case REPORT_LOCATION: 2169 return "REPORT_LOCATION"; 2170 case REPORT_SV_STATUS: 2171 return "REPORT_SV_STATUS"; 2172 default: 2173 return "<Unknown>"; 2174 } 2175 } 2176 2177 @Override 2178 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 2179 StringBuilder s = new StringBuilder(); 2180 s.append(" mStarted=").append(mStarted).append(" (changed "); 2181 TimeUtils.formatDuration(SystemClock.elapsedRealtime() 2182 - mStartedChangedElapsedRealtime, s); 2183 s.append(" ago)").append('\n'); 2184 s.append(" mFixInterval=").append(mFixInterval).append('\n'); 2185 s.append(" mLowPowerMode=").append(mLowPowerMode).append('\n'); 2186 s.append(" mGnssMeasurementsProvider.isRegistered()=") 2187 .append(mGnssMeasurementsProvider.isRegistered()).append('\n'); 2188 s.append(" mGnssNavigationMessageProvider.isRegistered()=") 2189 .append(mGnssNavigationMessageProvider.isRegistered()).append('\n'); 2190 s.append(" mDisableGpsForPowerManager=").append(mDisableGpsForPowerManager).append('\n'); 2191 s.append(" mTopHalCapabilities=0x").append(Integer.toHexString(mTopHalCapabilities)); 2192 s.append(" ( "); 2193 if (hasCapability(GPS_CAPABILITY_SCHEDULING)) s.append("SCHEDULING "); 2194 if (hasCapability(GPS_CAPABILITY_MSB)) s.append("MSB "); 2195 if (hasCapability(GPS_CAPABILITY_MSA)) s.append("MSA "); 2196 if (hasCapability(GPS_CAPABILITY_SINGLE_SHOT)) s.append("SINGLE_SHOT "); 2197 if (hasCapability(GPS_CAPABILITY_ON_DEMAND_TIME)) s.append("ON_DEMAND_TIME "); 2198 if (hasCapability(GPS_CAPABILITY_GEOFENCING)) s.append("GEOFENCING "); 2199 if (hasCapability(GPS_CAPABILITY_MEASUREMENTS)) s.append("MEASUREMENTS "); 2200 if (hasCapability(GPS_CAPABILITY_NAV_MESSAGES)) s.append("NAV_MESSAGES "); 2201 if (hasCapability(GPS_CAPABILITY_LOW_POWER_MODE)) s.append("LOW_POWER_MODE "); 2202 if (hasCapability(GPS_CAPABILITY_SATELLITE_BLACKLIST)) s.append("SATELLITE_BLACKLIST "); 2203 if (hasCapability(GPS_CAPABILITY_MEASUREMENT_CORRECTIONS)) { 2204 s.append("MEASUREMENT_CORRECTIONS "); 2205 } 2206 s.append(")\n"); 2207 if (hasCapability(GPS_CAPABILITY_MEASUREMENT_CORRECTIONS)) { 2208 s.append(" SubHal=MEASUREMENT_CORRECTIONS["); 2209 s.append(mGnssMeasurementCorrectionsProvider.toStringCapabilities()); 2210 s.append("]\n"); 2211 } 2212 s.append(mGnssMetrics.dumpGnssMetricsAsText()); 2213 s.append(" native internal state: ").append(native_get_internal_state()); 2214 s.append("\n"); 2215 pw.append(s); 2216 } 2217 2218 private void setupNativeGnssService(boolean reinitializeGnssServiceHandle) { 2219 native_init_once(reinitializeGnssServiceHandle); 2220 2221 /* 2222 * A cycle of native_init() and native_cleanup() is needed so that callbacks are 2223 * registered after bootup even when location is disabled. 2224 * This will allow Emergency SUPL to work even when location is disabled before device 2225 * restart. 2226 */ 2227 boolean isInitialized = native_init(); 2228 if (!isInitialized) { 2229 Log.w(TAG, "Native initialization failed."); 2230 } else { 2231 native_cleanup(); 2232 } 2233 } 2234 2235 // preallocated to avoid memory allocation in reportNmea() 2236 private byte[] mNmeaBuffer = new byte[120]; 2237 2238 static { 2239 class_init_native(); 2240 } 2241 2242 private static native void class_init_native(); 2243 2244 private static native boolean native_is_supported(); 2245 2246 private static native boolean native_is_gnss_visibility_control_supported(); 2247 2248 private static native void native_init_once(boolean reinitializeGnssServiceHandle); 2249 2250 private native boolean native_init(); 2251 2252 private native void native_cleanup(); 2253 2254 private native boolean native_set_position_mode(int mode, int recurrence, int min_interval, 2255 int preferred_accuracy, int preferred_time, boolean lowPowerMode); 2256 2257 private native boolean native_start(); 2258 2259 private native boolean native_stop(); 2260 2261 private native void native_delete_aiding_data(int flags); 2262 2263 private native int native_read_nmea(byte[] buffer, int bufferSize); 2264 2265 private native void native_inject_best_location( 2266 int gnssLocationFlags, double latitudeDegrees, double longitudeDegrees, 2267 double altitudeMeters, float speedMetersPerSec, float bearingDegrees, 2268 float horizontalAccuracyMeters, float verticalAccuracyMeters, 2269 float speedAccuracyMetersPerSecond, float bearingAccuracyDegrees, 2270 long timestamp, int elapsedRealtimeFlags, long elapsedRealtimeNanos, 2271 double elapsedRealtimeUncertaintyNanos); 2272 2273 private native void native_inject_location(double latitude, double longitude, float accuracy); 2274 2275 // PSDS Support 2276 private native void native_inject_time(long time, long timeReference, int uncertainty); 2277 2278 private native boolean native_supports_psds(); 2279 2280 private native void native_inject_psds_data(byte[] data, int length); 2281 2282 // DEBUG Support 2283 private native String native_get_internal_state(); 2284 2285 // AGPS Support 2286 private native void native_agps_ni_message(byte[] msg, int length); 2287 2288 private native void native_set_agps_server(int type, String hostname, int port); 2289 2290 // Network-initiated (NI) Support 2291 private native void native_send_ni_response(int notificationId, int userResponse); 2292 2293 // AGPS ril support 2294 private native void native_agps_set_ref_location_cellid(int type, int mcc, int mnc, 2295 int lac, int cid); 2296 2297 private native void native_agps_set_id(int type, String setid); 2298 } 2299