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