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