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 (location.isFromMockProvider()) { 845 return; 846 } 847 if (DEBUG) { 848 Log.d(TAG, "injectBestLocation: " + location); 849 } 850 int gnssLocationFlags = LOCATION_HAS_LAT_LONG | 851 (location.hasAltitude() ? LOCATION_HAS_ALTITUDE : 0) | 852 (location.hasSpeed() ? LOCATION_HAS_SPEED : 0) | 853 (location.hasBearing() ? LOCATION_HAS_BEARING : 0) | 854 (location.hasAccuracy() ? LOCATION_HAS_HORIZONTAL_ACCURACY : 0) | 855 (location.hasVerticalAccuracy() ? LOCATION_HAS_VERTICAL_ACCURACY : 0) | 856 (location.hasSpeedAccuracy() ? LOCATION_HAS_SPEED_ACCURACY : 0) | 857 (location.hasBearingAccuracy() ? LOCATION_HAS_BEARING_ACCURACY : 0); 858 859 double latitudeDegrees = location.getLatitude(); 860 double longitudeDegrees = location.getLongitude(); 861 double altitudeMeters = location.getAltitude(); 862 float speedMetersPerSec = location.getSpeed(); 863 float bearingDegrees = location.getBearing(); 864 float horizontalAccuracyMeters = location.getAccuracy(); 865 float verticalAccuracyMeters = location.getVerticalAccuracyMeters(); 866 float speedAccuracyMetersPerSecond = location.getSpeedAccuracyMetersPerSecond(); 867 float bearingAccuracyDegrees = location.getBearingAccuracyDegrees(); 868 long timestamp = location.getTime(); 869 870 int elapsedRealtimeFlags = ELAPSED_REALTIME_HAS_TIMESTAMP_NS 871 | (location.hasElapsedRealtimeUncertaintyNanos() 872 ? ELAPSED_REALTIME_HAS_TIME_UNCERTAINTY_NS : 0); 873 long elapsedRealtimeNanos = location.getElapsedRealtimeNanos(); 874 double elapsedRealtimeUncertaintyNanos = location.getElapsedRealtimeUncertaintyNanos(); 875 876 native_inject_best_location( 877 gnssLocationFlags, latitudeDegrees, longitudeDegrees, 878 altitudeMeters, speedMetersPerSec, bearingDegrees, 879 horizontalAccuracyMeters, verticalAccuracyMeters, 880 speedAccuracyMetersPerSecond, bearingAccuracyDegrees, timestamp, 881 elapsedRealtimeFlags, elapsedRealtimeNanos, elapsedRealtimeUncertaintyNanos); 882 } 883 884 /** Returns true if the location request is too frequent. */ isRequestLocationRateLimited()885 private boolean isRequestLocationRateLimited() { 886 // TODO: implement exponential backoff. 887 return false; 888 } 889 handleDownloadPsdsData()890 private void handleDownloadPsdsData() { 891 if (!mSupportsPsds) { 892 // native code reports psds not supported, don't try 893 Log.d(TAG, "handleDownloadPsdsData() called when PSDS not supported"); 894 return; 895 } 896 if (mDownloadPsdsDataPending == STATE_DOWNLOADING) { 897 // already downloading data 898 return; 899 } 900 if (!mNetworkConnectivityHandler.isDataNetworkConnected()) { 901 // try again when network is up 902 mDownloadPsdsDataPending = STATE_PENDING_NETWORK; 903 return; 904 } 905 mDownloadPsdsDataPending = STATE_DOWNLOADING; 906 907 synchronized (mLock) { 908 // hold wake lock while task runs 909 mDownloadPsdsWakeLock.acquire(DOWNLOAD_PSDS_DATA_TIMEOUT_MS); 910 } 911 Log.i(TAG, "WakeLock acquired by handleDownloadPsdsData()"); 912 AsyncTask.THREAD_POOL_EXECUTOR.execute(() -> { 913 GpsPsdsDownloader psdsDownloader = new GpsPsdsDownloader( 914 mGnssConfiguration.getProperties()); 915 byte[] data = psdsDownloader.downloadPsdsData(); 916 if (data != null) { 917 if (DEBUG) Log.d(TAG, "calling native_inject_psds_data"); 918 native_inject_psds_data(data, data.length); 919 mPsdsBackOff.reset(); 920 } 921 922 sendMessage(DOWNLOAD_PSDS_DATA_FINISHED, 0, null); 923 924 if (data == null) { 925 // try again later 926 // since this is delayed and not urgent we do not hold a wake lock here 927 mHandler.sendEmptyMessageDelayed(DOWNLOAD_PSDS_DATA, 928 mPsdsBackOff.nextBackoffMillis()); 929 } 930 931 // Release wake lock held by task, synchronize on mLock in case multiple 932 // download tasks overrun. 933 synchronized (mLock) { 934 if (mDownloadPsdsWakeLock.isHeld()) { 935 // This wakelock may have time-out, if a timeout was specified. 936 // Catch (and ignore) any timeout exceptions. 937 mDownloadPsdsWakeLock.release(); 938 if (DEBUG) Log.d(TAG, "WakeLock released by handleDownloadPsdsData()"); 939 } else { 940 Log.e(TAG, "WakeLock expired before release in " 941 + "handleDownloadPsdsData()"); 942 } 943 } 944 }); 945 } 946 injectLocation(Location location)947 private void injectLocation(Location location) { 948 if (location.isFromMockProvider()) { 949 return; 950 } 951 if (location.hasAccuracy()) { 952 if (DEBUG) { 953 Log.d(TAG, "injectLocation: " + location); 954 } 955 native_inject_location(location.getLatitude(), location.getLongitude(), 956 location.getAccuracy()); 957 } 958 } 959 setSuplHostPort()960 private void setSuplHostPort() { 961 mSuplServerHost = mGnssConfiguration.getSuplHost(); 962 mSuplServerPort = mGnssConfiguration.getSuplPort(TCP_MIN_PORT); 963 if (mSuplServerHost != null 964 && mSuplServerPort > TCP_MIN_PORT 965 && mSuplServerPort <= TCP_MAX_PORT) { 966 native_set_agps_server(GnssNetworkConnectivityHandler.AGPS_TYPE_SUPL, 967 mSuplServerHost, mSuplServerPort); 968 } 969 } 970 971 /** 972 * Checks what SUPL mode to use, according to the AGPS mode as well as the 973 * allowed mode from properties. 974 * 975 * @param agpsEnabled whether AGPS is enabled by settings value 976 * @return SUPL mode (MSA vs MSB vs STANDALONE) 977 */ getSuplMode(boolean agpsEnabled)978 private int getSuplMode(boolean agpsEnabled) { 979 if (agpsEnabled) { 980 int suplMode = mGnssConfiguration.getSuplMode(0); 981 if (suplMode == 0) { 982 return GPS_POSITION_MODE_STANDALONE; 983 } 984 985 // MS-Based is the preferred mode for Assisted-GPS position computation, so we favor 986 // such mode when it is available 987 if (hasCapability(GPS_CAPABILITY_MSB) && (suplMode & AGPS_SUPL_MODE_MSB) != 0) { 988 return GPS_POSITION_MODE_MS_BASED; 989 } 990 } 991 return GPS_POSITION_MODE_STANDALONE; 992 } 993 setGpsEnabled(boolean enabled)994 private void setGpsEnabled(boolean enabled) { 995 synchronized (mLock) { 996 mGpsEnabled = enabled; 997 } 998 } 999 handleEnable()1000 private void handleEnable() { 1001 if (DEBUG) Log.d(TAG, "handleEnable"); 1002 1003 boolean inited = native_init(); 1004 1005 if (inited) { 1006 setGpsEnabled(true); 1007 mSupportsPsds = native_supports_psds(); 1008 1009 // TODO: remove the following native calls if we can make sure they are redundant. 1010 if (mSuplServerHost != null) { 1011 native_set_agps_server(GnssNetworkConnectivityHandler.AGPS_TYPE_SUPL, 1012 mSuplServerHost, mSuplServerPort); 1013 } 1014 if (mC2KServerHost != null) { 1015 native_set_agps_server(GnssNetworkConnectivityHandler.AGPS_TYPE_C2K, 1016 mC2KServerHost, mC2KServerPort); 1017 } 1018 1019 mGnssMeasurementsProvider.onGpsEnabledChanged(); 1020 mGnssNavigationMessageProvider.onGpsEnabledChanged(); 1021 mGnssAntennaInfoProvider.onGpsEnabledChanged(); 1022 mGnssBatchingProvider.enable(); 1023 if (mGnssVisibilityControl != null) { 1024 mGnssVisibilityControl.onGpsEnabledChanged(/* isEnabled= */ true); 1025 } 1026 } else { 1027 setGpsEnabled(false); 1028 Log.w(TAG, "Failed to enable location provider"); 1029 } 1030 } 1031 handleDisable()1032 private void handleDisable() { 1033 if (DEBUG) Log.d(TAG, "handleDisable"); 1034 1035 setGpsEnabled(false); 1036 updateClientUids(new WorkSource()); 1037 stopNavigating(); 1038 mAlarmManager.cancel(mWakeupIntent); 1039 mAlarmManager.cancel(mTimeoutIntent); 1040 1041 if (mGnssVisibilityControl != null) { 1042 mGnssVisibilityControl.onGpsEnabledChanged(/* isEnabled= */ false); 1043 } 1044 mGnssBatchingProvider.disable(); 1045 // do this before releasing wakelock 1046 native_cleanup(); 1047 1048 mGnssAntennaInfoProvider.onGpsEnabledChanged(); 1049 mGnssMeasurementsProvider.onGpsEnabledChanged(); 1050 mGnssNavigationMessageProvider.onGpsEnabledChanged(); 1051 } 1052 updateEnabled()1053 private void updateEnabled() { 1054 // Generally follow location setting for current user 1055 boolean enabled = mContext.getSystemService(LocationManager.class) 1056 .isLocationEnabledForUser(UserHandle.CURRENT); 1057 1058 // ... but disable if PowerManager overrides 1059 enabled &= !mDisableGpsForPowerManager; 1060 1061 // .. but enable anyway, if there's an active settings-ignored request (e.g. ELS) 1062 enabled |= (mProviderRequest != null && mProviderRequest.reportLocation 1063 && mProviderRequest.locationSettingsIgnored); 1064 1065 // ... and, finally, disable anyway, if device is being shut down 1066 enabled &= !mShutdown; 1067 1068 if (enabled == isGpsEnabled()) { 1069 return; 1070 } 1071 1072 if (enabled) { 1073 handleEnable(); 1074 } else { 1075 handleDisable(); 1076 } 1077 } 1078 isGpsEnabled()1079 private boolean isGpsEnabled() { 1080 synchronized (mLock) { 1081 return mGpsEnabled; 1082 } 1083 } 1084 1085 @Override onSetRequest(ProviderRequest request)1086 public void onSetRequest(ProviderRequest request) { 1087 sendMessage(SET_REQUEST, 0, new GpsRequest(request, request.workSource)); 1088 } 1089 handleSetRequest(ProviderRequest request, WorkSource source)1090 private void handleSetRequest(ProviderRequest request, WorkSource source) { 1091 mProviderRequest = request; 1092 mWorkSource = source; 1093 updateEnabled(); 1094 updateRequirements(); 1095 } 1096 1097 // Called when the requirements for GPS may have changed updateRequirements()1098 private void updateRequirements() { 1099 if (mProviderRequest == null || mWorkSource == null) { 1100 return; 1101 } 1102 1103 if (DEBUG) Log.d(TAG, "setRequest " + mProviderRequest); 1104 if (mProviderRequest.reportLocation && isGpsEnabled()) { 1105 // update client uids 1106 updateClientUids(mWorkSource); 1107 1108 mFixInterval = (int) mProviderRequest.interval; 1109 mLowPowerMode = mProviderRequest.lowPowerMode; 1110 // check for overflow 1111 if (mFixInterval != mProviderRequest.interval) { 1112 Log.w(TAG, "interval overflow: " + mProviderRequest.interval); 1113 mFixInterval = Integer.MAX_VALUE; 1114 } 1115 1116 // apply request to GPS engine 1117 if (mStarted && hasCapability(GPS_CAPABILITY_SCHEDULING)) { 1118 // change period and/or lowPowerMode 1119 if (!setPositionMode(mPositionMode, GPS_POSITION_RECURRENCE_PERIODIC, 1120 mFixInterval, 0, 0, mLowPowerMode)) { 1121 Log.e(TAG, "set_position_mode failed in updateRequirements"); 1122 } 1123 } else if (!mStarted) { 1124 // start GPS 1125 startNavigating(); 1126 } else { 1127 // GNSS Engine is already ON, but no GPS_CAPABILITY_SCHEDULING 1128 mAlarmManager.cancel(mTimeoutIntent); 1129 if (mFixInterval >= NO_FIX_TIMEOUT) { 1130 // set timer to give up if we do not receive a fix within NO_FIX_TIMEOUT 1131 // and our fix interval is not short 1132 mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, 1133 SystemClock.elapsedRealtime() + NO_FIX_TIMEOUT, mTimeoutIntent); 1134 } 1135 } 1136 } else { 1137 updateClientUids(new WorkSource()); 1138 1139 stopNavigating(); 1140 mAlarmManager.cancel(mWakeupIntent); 1141 mAlarmManager.cancel(mTimeoutIntent); 1142 } 1143 } 1144 setPositionMode(int mode, int recurrence, int minInterval, int preferredAccuracy, int preferredTime, boolean lowPowerMode)1145 private boolean setPositionMode(int mode, int recurrence, int minInterval, 1146 int preferredAccuracy, int preferredTime, boolean lowPowerMode) { 1147 GnssPositionMode positionMode = new GnssPositionMode(mode, recurrence, minInterval, 1148 preferredAccuracy, preferredTime, lowPowerMode); 1149 if (mLastPositionMode != null && mLastPositionMode.equals(positionMode)) { 1150 return true; 1151 } 1152 1153 boolean result = native_set_position_mode(mode, recurrence, minInterval, 1154 preferredAccuracy, preferredTime, lowPowerMode); 1155 if (result) { 1156 mLastPositionMode = positionMode; 1157 } else { 1158 mLastPositionMode = null; 1159 } 1160 return result; 1161 } 1162 updateClientUids(WorkSource source)1163 private void updateClientUids(WorkSource source) { 1164 if (source.equals(mClientSource)) { 1165 return; 1166 } 1167 1168 // (1) Inform BatteryStats that the list of IDs we're tracking changed. 1169 try { 1170 mBatteryStats.noteGpsChanged(mClientSource, source); 1171 } catch (RemoteException e) { 1172 Log.w(TAG, "RemoteException", e); 1173 } 1174 1175 // (2) Inform AppOps service about the list of changes to UIDs. 1176 1177 List<WorkChain>[] diffs = WorkSource.diffChains(mClientSource, source); 1178 if (diffs != null) { 1179 List<WorkChain> newChains = diffs[0]; 1180 List<WorkChain> goneChains = diffs[1]; 1181 1182 if (newChains != null) { 1183 for (WorkChain newChain : newChains) { 1184 mAppOps.startOpNoThrow(AppOpsManager.OP_GPS, newChain.getAttributionUid(), 1185 newChain.getAttributionTag()); 1186 } 1187 } 1188 1189 if (goneChains != null) { 1190 for (WorkChain goneChain : goneChains) { 1191 mAppOps.finishOp(AppOpsManager.OP_GPS, goneChain.getAttributionUid(), 1192 goneChain.getAttributionTag()); 1193 } 1194 } 1195 1196 mClientSource.transferWorkChains(source); 1197 } 1198 1199 // Update the flat UIDs and names list and inform app-ops of all changes. 1200 WorkSource[] changes = mClientSource.setReturningDiffs(source); 1201 if (changes != null) { 1202 WorkSource newWork = changes[0]; 1203 WorkSource goneWork = changes[1]; 1204 1205 // Update sources that were not previously tracked. 1206 if (newWork != null) { 1207 for (int i = 0; i < newWork.size(); i++) { 1208 mAppOps.startOpNoThrow(AppOpsManager.OP_GPS, 1209 newWork.getUid(i), newWork.getPackageName(i)); 1210 } 1211 } 1212 1213 // Update sources that are no longer tracked. 1214 if (goneWork != null) { 1215 for (int i = 0; i < goneWork.size(); i++) { 1216 mAppOps.finishOp(AppOpsManager.OP_GPS, goneWork.getUid(i), 1217 goneWork.getPackageName(i)); 1218 } 1219 } 1220 } 1221 } 1222 1223 @Override onExtraCommand(int uid, int pid, String command, Bundle extras)1224 public void onExtraCommand(int uid, int pid, String command, Bundle extras) { 1225 1226 long identity = Binder.clearCallingIdentity(); 1227 try { 1228 if ("delete_aiding_data".equals(command)) { 1229 deleteAidingData(extras); 1230 } else if ("force_time_injection".equals(command)) { 1231 requestUtcTime(); 1232 } else if ("force_psds_injection".equals(command)) { 1233 if (mSupportsPsds) { 1234 psdsDownloadRequest(); 1235 } 1236 } else { 1237 Log.w(TAG, "sendExtraCommand: unknown command " + command); 1238 } 1239 } finally { 1240 Binder.restoreCallingIdentity(identity); 1241 } 1242 } 1243 deleteAidingData(Bundle extras)1244 private void deleteAidingData(Bundle extras) { 1245 int flags; 1246 1247 if (extras == null) { 1248 flags = GPS_DELETE_ALL; 1249 } else { 1250 flags = 0; 1251 if (extras.getBoolean("ephemeris")) flags |= GPS_DELETE_EPHEMERIS; 1252 if (extras.getBoolean("almanac")) flags |= GPS_DELETE_ALMANAC; 1253 if (extras.getBoolean("position")) flags |= GPS_DELETE_POSITION; 1254 if (extras.getBoolean("time")) flags |= GPS_DELETE_TIME; 1255 if (extras.getBoolean("iono")) flags |= GPS_DELETE_IONO; 1256 if (extras.getBoolean("utc")) flags |= GPS_DELETE_UTC; 1257 if (extras.getBoolean("health")) flags |= GPS_DELETE_HEALTH; 1258 if (extras.getBoolean("svdir")) flags |= GPS_DELETE_SVDIR; 1259 if (extras.getBoolean("svsteer")) flags |= GPS_DELETE_SVSTEER; 1260 if (extras.getBoolean("sadata")) flags |= GPS_DELETE_SADATA; 1261 if (extras.getBoolean("rti")) flags |= GPS_DELETE_RTI; 1262 if (extras.getBoolean("celldb-info")) flags |= GPS_DELETE_CELLDB_INFO; 1263 if (extras.getBoolean("all")) flags |= GPS_DELETE_ALL; 1264 } 1265 1266 if (flags != 0) { 1267 native_delete_aiding_data(flags); 1268 } 1269 } 1270 startNavigating()1271 private void startNavigating() { 1272 if (!mStarted) { 1273 if (DEBUG) Log.d(TAG, "startNavigating"); 1274 mTimeToFirstFix = 0; 1275 mLastFixTime = 0; 1276 setStarted(true); 1277 mPositionMode = GPS_POSITION_MODE_STANDALONE; 1278 // Notify about suppressed output, if speed limit was previously exceeded. 1279 // Elsewhere, we check again with every speed output reported. 1280 if (mItarSpeedLimitExceeded) { 1281 Log.i(TAG, "startNavigating with ITAR limit in place. Output limited " + 1282 "until slow enough speed reported."); 1283 } 1284 1285 boolean agpsEnabled = 1286 (Settings.Global.getInt(mContext.getContentResolver(), 1287 Settings.Global.ASSISTED_GPS_ENABLED, 1) != 0); 1288 mPositionMode = getSuplMode(agpsEnabled); 1289 1290 if (DEBUG) { 1291 String mode; 1292 1293 switch (mPositionMode) { 1294 case GPS_POSITION_MODE_STANDALONE: 1295 mode = "standalone"; 1296 break; 1297 case GPS_POSITION_MODE_MS_ASSISTED: 1298 mode = "MS_ASSISTED"; 1299 break; 1300 case GPS_POSITION_MODE_MS_BASED: 1301 mode = "MS_BASED"; 1302 break; 1303 default: 1304 mode = "unknown"; 1305 break; 1306 } 1307 Log.d(TAG, "setting position_mode to " + mode); 1308 } 1309 1310 int interval = (hasCapability(GPS_CAPABILITY_SCHEDULING) ? mFixInterval : 1000); 1311 mLowPowerMode = mProviderRequest.lowPowerMode; 1312 if (!setPositionMode(mPositionMode, GPS_POSITION_RECURRENCE_PERIODIC, 1313 interval, 0, 0, mLowPowerMode)) { 1314 setStarted(false); 1315 Log.e(TAG, "set_position_mode failed in startNavigating()"); 1316 return; 1317 } 1318 if (!native_start()) { 1319 setStarted(false); 1320 Log.e(TAG, "native_start failed in startNavigating()"); 1321 return; 1322 } 1323 1324 // reset SV count to zero 1325 mLocationExtras.reset(); 1326 mFixRequestTime = SystemClock.elapsedRealtime(); 1327 if (!hasCapability(GPS_CAPABILITY_SCHEDULING)) { 1328 // set timer to give up if we do not receive a fix within NO_FIX_TIMEOUT 1329 // and our fix interval is not short 1330 if (mFixInterval >= NO_FIX_TIMEOUT) { 1331 mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, 1332 SystemClock.elapsedRealtime() + NO_FIX_TIMEOUT, mTimeoutIntent); 1333 } 1334 } 1335 } 1336 } 1337 stopNavigating()1338 private void stopNavigating() { 1339 if (DEBUG) Log.d(TAG, "stopNavigating"); 1340 if (mStarted) { 1341 setStarted(false); 1342 native_stop(); 1343 mLastFixTime = 0; 1344 // native_stop() may reset the position mode in hardware. 1345 mLastPositionMode = null; 1346 1347 // reset SV count to zero 1348 mLocationExtras.reset(); 1349 } 1350 } 1351 setStarted(boolean started)1352 private void setStarted(boolean started) { 1353 if (mStarted != started) { 1354 mStarted = started; 1355 mStartedChangedElapsedRealtime = SystemClock.elapsedRealtime(); 1356 } 1357 } 1358 hibernate()1359 private void hibernate() { 1360 // stop GPS until our next fix interval arrives 1361 stopNavigating(); 1362 mAlarmManager.cancel(mTimeoutIntent); 1363 mAlarmManager.cancel(mWakeupIntent); 1364 long now = SystemClock.elapsedRealtime(); 1365 mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, now + mFixInterval, mWakeupIntent); 1366 } 1367 hasCapability(int capability)1368 private boolean hasCapability(int capability) { 1369 return (mTopHalCapabilities & capability) != 0; 1370 } 1371 1372 @NativeEntryPoint reportLocation(boolean hasLatLong, Location location)1373 private void reportLocation(boolean hasLatLong, Location location) { 1374 sendMessage(REPORT_LOCATION, hasLatLong ? 1 : 0, location); 1375 } 1376 handleReportLocation(boolean hasLatLong, Location location)1377 private void handleReportLocation(boolean hasLatLong, Location location) { 1378 if (location.hasSpeed()) { 1379 mItarSpeedLimitExceeded = location.getSpeed() > ITAR_SPEED_LIMIT_METERS_PER_SECOND; 1380 } 1381 1382 if (mItarSpeedLimitExceeded) { 1383 Log.i(TAG, "Hal reported a speed in excess of ITAR limit." + 1384 " GPS/GNSS Navigation output blocked."); 1385 if (mStarted) { 1386 mGnssMetrics.logReceivedLocationStatus(false); 1387 } 1388 return; // No output of location allowed 1389 } 1390 1391 if (VERBOSE) Log.v(TAG, "reportLocation " + location.toString()); 1392 1393 location.setExtras(mLocationExtras.getBundle()); 1394 1395 reportLocation(location); 1396 1397 if (mStarted) { 1398 mGnssMetrics.logReceivedLocationStatus(hasLatLong); 1399 if (hasLatLong) { 1400 if (location.hasAccuracy()) { 1401 mGnssMetrics.logPositionAccuracyMeters(location.getAccuracy()); 1402 } 1403 if (mTimeToFirstFix > 0) { 1404 int timeBetweenFixes = (int) (SystemClock.elapsedRealtime() - mLastFixTime); 1405 mGnssMetrics.logMissedReports(mFixInterval, timeBetweenFixes); 1406 } 1407 } 1408 } else { 1409 // Warn or error about long delayed GNSS engine shutdown as this generally wastes 1410 // power and sends location when not expected. 1411 long locationAfterStartedFalseMillis = 1412 SystemClock.elapsedRealtime() - mStartedChangedElapsedRealtime; 1413 if (locationAfterStartedFalseMillis > LOCATION_OFF_DELAY_THRESHOLD_WARN_MILLIS) { 1414 String logMessage = "Unexpected GNSS Location report " 1415 + TimeUtils.formatDuration(locationAfterStartedFalseMillis) 1416 + " after location turned off"; 1417 if (locationAfterStartedFalseMillis > LOCATION_OFF_DELAY_THRESHOLD_ERROR_MILLIS) { 1418 Log.e(TAG, logMessage); 1419 } else { 1420 Log.w(TAG, logMessage); 1421 } 1422 } 1423 } 1424 1425 mLastFixTime = SystemClock.elapsedRealtime(); 1426 // report time to first fix 1427 if (mTimeToFirstFix == 0 && hasLatLong) { 1428 mTimeToFirstFix = (int) (mLastFixTime - mFixRequestTime); 1429 if (DEBUG) Log.d(TAG, "TTFF: " + mTimeToFirstFix); 1430 if (mStarted) { 1431 mGnssMetrics.logTimeToFirstFixMilliSecs(mTimeToFirstFix); 1432 } 1433 1434 // notify status listeners 1435 mGnssStatusListenerHelper.onFirstFix(mTimeToFirstFix); 1436 } 1437 1438 if (mStarted) { 1439 // For devices that use framework scheduling, a timer may be set to ensure we don't 1440 // spend too much power searching for a location, when the requested update rate is 1441 // slow. 1442 // As we just recievied a location, we'll cancel that timer. 1443 if (!hasCapability(GPS_CAPABILITY_SCHEDULING) && mFixInterval < NO_FIX_TIMEOUT) { 1444 mAlarmManager.cancel(mTimeoutIntent); 1445 } 1446 } 1447 1448 if (!hasCapability(GPS_CAPABILITY_SCHEDULING) && mStarted && 1449 mFixInterval > GPS_POLLING_THRESHOLD_INTERVAL) { 1450 if (DEBUG) Log.d(TAG, "got fix, hibernating"); 1451 hibernate(); 1452 } 1453 } 1454 1455 @NativeEntryPoint reportStatus(int status)1456 private void reportStatus(int status) { 1457 if (DEBUG) Log.v(TAG, "reportStatus status: " + status); 1458 1459 boolean wasNavigating = mNavigating; 1460 switch (status) { 1461 case GPS_STATUS_SESSION_BEGIN: 1462 mNavigating = true; 1463 break; 1464 case GPS_STATUS_SESSION_END: 1465 mNavigating = false; 1466 break; 1467 case GPS_STATUS_ENGINE_ON: 1468 break; 1469 case GPS_STATUS_ENGINE_OFF: 1470 mNavigating = false; 1471 break; 1472 } 1473 1474 if (wasNavigating != mNavigating) { 1475 mGnssStatusListenerHelper.onStatusChanged(mNavigating); 1476 } 1477 } 1478 1479 // Helper class to carry data to handler for reportSvStatus 1480 private static class SvStatusInfo { 1481 private int mSvCount; 1482 private int[] mSvidWithFlags; 1483 private float[] mCn0s; 1484 private float[] mSvElevations; 1485 private float[] mSvAzimuths; 1486 private float[] mSvCarrierFreqs; 1487 private float[] mBasebandCn0s; 1488 } 1489 1490 @NativeEntryPoint reportSvStatus(int svCount, int[] svidWithFlags, float[] cn0s, float[] svElevations, float[] svAzimuths, float[] svCarrierFreqs, float[] basebandCn0s)1491 private void reportSvStatus(int svCount, int[] svidWithFlags, float[] cn0s, 1492 float[] svElevations, float[] svAzimuths, float[] svCarrierFreqs, 1493 float[] basebandCn0s) { 1494 SvStatusInfo svStatusInfo = new SvStatusInfo(); 1495 svStatusInfo.mSvCount = svCount; 1496 svStatusInfo.mSvidWithFlags = svidWithFlags; 1497 svStatusInfo.mCn0s = cn0s; 1498 svStatusInfo.mSvElevations = svElevations; 1499 svStatusInfo.mSvAzimuths = svAzimuths; 1500 svStatusInfo.mSvCarrierFreqs = svCarrierFreqs; 1501 svStatusInfo.mBasebandCn0s = basebandCn0s; 1502 1503 sendMessage(REPORT_SV_STATUS, 0, svStatusInfo); 1504 } 1505 handleReportSvStatus(SvStatusInfo info)1506 private void handleReportSvStatus(SvStatusInfo info) { 1507 mGnssStatusListenerHelper.onSvStatusChanged( 1508 info.mSvCount, 1509 info.mSvidWithFlags, 1510 info.mCn0s, 1511 info.mSvElevations, 1512 info.mSvAzimuths, 1513 info.mSvCarrierFreqs, 1514 info.mBasebandCn0s); 1515 1516 // Log CN0 as part of GNSS metrics 1517 mGnssMetrics.logCn0(info.mCn0s, info.mSvCount, info.mSvCarrierFreqs); 1518 1519 if (VERBOSE) { 1520 Log.v(TAG, "SV count: " + info.mSvCount); 1521 } 1522 // Calculate number of satellites used in fix. 1523 GnssStatus gnssStatus = GnssStatus.wrap( 1524 info.mSvCount, 1525 info.mSvidWithFlags, 1526 info.mCn0s, 1527 info.mSvElevations, 1528 info.mSvAzimuths, 1529 info.mSvCarrierFreqs, 1530 info.mBasebandCn0s); 1531 int usedInFixCount = 0; 1532 int maxCn0 = 0; 1533 int meanCn0 = 0; 1534 for (int i = 0; i < gnssStatus.getSatelliteCount(); i++) { 1535 if (gnssStatus.usedInFix(i)) { 1536 ++usedInFixCount; 1537 if (gnssStatus.getCn0DbHz(i) > maxCn0) { 1538 maxCn0 = (int) gnssStatus.getCn0DbHz(i); 1539 } 1540 meanCn0 += gnssStatus.getCn0DbHz(i); 1541 mGnssMetrics.logConstellationType(gnssStatus.getConstellationType(i)); 1542 } 1543 if (VERBOSE) { 1544 Log.v(TAG, "svid: " + gnssStatus.getSvid(i) 1545 + " cn0: " + gnssStatus.getCn0DbHz(i) 1546 + " basebandCn0: " + gnssStatus.getBasebandCn0DbHz(i) 1547 + " elev: " + gnssStatus.getElevationDegrees(i) 1548 + " azimuth: " + gnssStatus.getAzimuthDegrees(i) 1549 + " carrier frequency: " + gnssStatus.getCn0DbHz(i) 1550 + (gnssStatus.hasEphemerisData(i) ? " E" : " ") 1551 + (gnssStatus.hasAlmanacData(i) ? " A" : " ") 1552 + (gnssStatus.usedInFix(i) ? "U" : "") 1553 + (gnssStatus.hasCarrierFrequencyHz(i) ? "F" : "") 1554 + (gnssStatus.hasBasebandCn0DbHz(i) ? "B" : "")); 1555 } 1556 } 1557 if (usedInFixCount > 0) { 1558 meanCn0 /= usedInFixCount; 1559 } 1560 // return number of sats used in fix instead of total reported 1561 mLocationExtras.set(usedInFixCount, meanCn0, maxCn0); 1562 1563 mGnssMetrics.logSvStatus(gnssStatus); 1564 } 1565 1566 @NativeEntryPoint reportAGpsStatus(int agpsType, int agpsStatus, byte[] suplIpAddr)1567 private void reportAGpsStatus(int agpsType, int agpsStatus, byte[] suplIpAddr) { 1568 mNetworkConnectivityHandler.onReportAGpsStatus(agpsType, agpsStatus, suplIpAddr); 1569 } 1570 1571 @NativeEntryPoint reportNmea(long timestamp)1572 private void reportNmea(long timestamp) { 1573 if (!mItarSpeedLimitExceeded) { 1574 int length = native_read_nmea(mNmeaBuffer, mNmeaBuffer.length); 1575 String nmea = new String(mNmeaBuffer, 0 /* offset */, length); 1576 mGnssStatusListenerHelper.onNmeaReceived(timestamp, nmea); 1577 } 1578 } 1579 1580 @NativeEntryPoint reportMeasurementData(GnssMeasurementsEvent event)1581 private void reportMeasurementData(GnssMeasurementsEvent event) { 1582 if (!mItarSpeedLimitExceeded) { 1583 // send to handler to allow native to return quickly 1584 mHandler.post(() -> mGnssMeasurementsProvider.onMeasurementsAvailable(event)); 1585 } 1586 } 1587 1588 @NativeEntryPoint reportAntennaInfo(List<GnssAntennaInfo> antennaInfos)1589 private void reportAntennaInfo(List<GnssAntennaInfo> antennaInfos) { 1590 mHandler.post(() -> mGnssAntennaInfoProvider.onGnssAntennaInfoAvailable(antennaInfos)); 1591 } 1592 1593 @NativeEntryPoint reportNavigationMessage(GnssNavigationMessage event)1594 private void reportNavigationMessage(GnssNavigationMessage event) { 1595 if (!mItarSpeedLimitExceeded) { 1596 // send to handler to allow native to return quickly 1597 mHandler.post(() -> mGnssNavigationMessageProvider.onNavigationMessageAvailable(event)); 1598 } 1599 } 1600 1601 @NativeEntryPoint setTopHalCapabilities(int topHalCapabilities)1602 private void setTopHalCapabilities(int topHalCapabilities) { 1603 mHandler.post(() -> { 1604 mTopHalCapabilities = topHalCapabilities; 1605 1606 if (hasCapability(GPS_CAPABILITY_ON_DEMAND_TIME)) { 1607 mNtpTimeHelper.enablePeriodicTimeInjection(); 1608 requestUtcTime(); 1609 } 1610 1611 mGnssMeasurementsProvider.onCapabilitiesUpdated( 1612 hasCapability(GPS_CAPABILITY_MEASUREMENTS)); 1613 mGnssNavigationMessageProvider.onCapabilitiesUpdated( 1614 hasCapability(GPS_CAPABILITY_NAV_MESSAGES)); 1615 restartRequests(); 1616 mGnssAntennaInfoProvider.onCapabilitiesUpdated( 1617 hasCapability(GPS_CAPABILITY_ANTENNA_INFO)); 1618 1619 mGnssCapabilitiesProvider.setTopHalCapabilities(mTopHalCapabilities); 1620 }); 1621 } 1622 1623 @NativeEntryPoint setSubHalMeasurementCorrectionsCapabilities(int subHalCapabilities)1624 private void setSubHalMeasurementCorrectionsCapabilities(int subHalCapabilities) { 1625 mHandler.post(() -> { 1626 if (!mGnssMeasurementCorrectionsProvider.onCapabilitiesUpdated(subHalCapabilities)) { 1627 return; 1628 } 1629 1630 mGnssCapabilitiesProvider.setSubHalMeasurementCorrectionsCapabilities( 1631 subHalCapabilities); 1632 }); 1633 } 1634 restartRequests()1635 private void restartRequests() { 1636 Log.i(TAG, "restartRequests"); 1637 1638 restartLocationRequest(); 1639 mGnssAntennaInfoProvider.resumeIfStarted(); 1640 mGnssMeasurementsProvider.resumeIfStarted(); 1641 mGnssNavigationMessageProvider.resumeIfStarted(); 1642 mGnssBatchingProvider.resumeIfStarted(); 1643 mGnssGeofenceProvider.resumeIfStarted(); 1644 } 1645 restartLocationRequest()1646 private void restartLocationRequest() { 1647 if (DEBUG) Log.d(TAG, "restartLocationRequest"); 1648 setStarted(false); 1649 updateRequirements(); 1650 } 1651 1652 @NativeEntryPoint setGnssYearOfHardware(final int yearOfHardware)1653 private void setGnssYearOfHardware(final int yearOfHardware) { 1654 // mHardwareYear is simply set here, to be read elsewhere, and is volatile for safe sync 1655 if (DEBUG) Log.d(TAG, "setGnssYearOfHardware called with " + yearOfHardware); 1656 mHardwareYear = yearOfHardware; 1657 } 1658 1659 @NativeEntryPoint setGnssHardwareModelName(final String modelName)1660 private void setGnssHardwareModelName(final String modelName) { 1661 // mHardwareModelName is simply set here, to be read elsewhere, and volatile for safe sync 1662 if (DEBUG) Log.d(TAG, "setGnssModelName called with " + modelName); 1663 mHardwareModelName = modelName; 1664 } 1665 1666 @NativeEntryPoint reportGnssServiceDied()1667 private void reportGnssServiceDied() { 1668 if (DEBUG) Log.d(TAG, "reportGnssServiceDied"); 1669 mHandler.post(() -> { 1670 setupNativeGnssService(/* reinitializeGnssServiceHandle = */ true); 1671 // resend configuration into the restarted HAL service. 1672 reloadGpsProperties(); 1673 if (isGpsEnabled()) { 1674 setGpsEnabled(false); 1675 updateEnabled(); 1676 } 1677 }); 1678 } 1679 1680 public interface GnssSystemInfoProvider { 1681 /** 1682 * Returns the year of underlying GPS hardware. 1683 */ getGnssYearOfHardware()1684 int getGnssYearOfHardware(); 1685 1686 /** 1687 * Returns the model name of underlying GPS hardware. 1688 */ getGnssHardwareModelName()1689 String getGnssHardwareModelName(); 1690 } 1691 1692 /** 1693 * @hide 1694 */ getGnssSystemInfoProvider()1695 public GnssSystemInfoProvider getGnssSystemInfoProvider() { 1696 return new GnssSystemInfoProvider() { 1697 @Override 1698 public int getGnssYearOfHardware() { 1699 return mHardwareYear; 1700 } 1701 1702 @Override 1703 public String getGnssHardwareModelName() { 1704 return mHardwareModelName; 1705 } 1706 }; 1707 } 1708 1709 /** 1710 * @hide 1711 */ 1712 public GnssBatchingProvider getGnssBatchingProvider() { 1713 return mGnssBatchingProvider; 1714 } 1715 1716 public interface GnssMetricsProvider { 1717 /** 1718 * Returns GNSS metrics as proto string 1719 */ 1720 String getGnssMetricsAsProtoString(); 1721 } 1722 1723 /** 1724 * @hide 1725 */ 1726 public GnssMetricsProvider getGnssMetricsProvider() { 1727 return () -> mGnssMetrics.dumpGnssMetricsAsProtoString(); 1728 } 1729 1730 /** 1731 * @hide 1732 */ 1733 public GnssCapabilitiesProvider getGnssCapabilitiesProvider() { 1734 return mGnssCapabilitiesProvider; 1735 } 1736 1737 @NativeEntryPoint 1738 private void reportLocationBatch(Location[] locationArray) { 1739 List<Location> locations = new ArrayList<>(Arrays.asList(locationArray)); 1740 if (DEBUG) { 1741 Log.d(TAG, "Location batch of size " + locationArray.length + " reported"); 1742 } 1743 reportLocation(locations); 1744 } 1745 1746 @NativeEntryPoint 1747 private void psdsDownloadRequest() { 1748 if (DEBUG) Log.d(TAG, "psdsDownloadRequest"); 1749 sendMessage(DOWNLOAD_PSDS_DATA, 0, null); 1750 } 1751 1752 /** 1753 * Converts the GPS HAL status to the internal Geofence Hardware status. 1754 */ 1755 private static int getGeofenceStatus(int status) { 1756 switch (status) { 1757 case GPS_GEOFENCE_OPERATION_SUCCESS: 1758 return GeofenceHardware.GEOFENCE_SUCCESS; 1759 case GPS_GEOFENCE_ERROR_GENERIC: 1760 return GeofenceHardware.GEOFENCE_FAILURE; 1761 case GPS_GEOFENCE_ERROR_ID_EXISTS: 1762 return GeofenceHardware.GEOFENCE_ERROR_ID_EXISTS; 1763 case GPS_GEOFENCE_ERROR_INVALID_TRANSITION: 1764 return GeofenceHardware.GEOFENCE_ERROR_INVALID_TRANSITION; 1765 case GPS_GEOFENCE_ERROR_TOO_MANY_GEOFENCES: 1766 return GeofenceHardware.GEOFENCE_ERROR_TOO_MANY_GEOFENCES; 1767 case GPS_GEOFENCE_ERROR_ID_UNKNOWN: 1768 return GeofenceHardware.GEOFENCE_ERROR_ID_UNKNOWN; 1769 default: 1770 return -1; 1771 } 1772 } 1773 1774 @NativeEntryPoint 1775 private void reportGeofenceTransition(int geofenceId, Location location, int transition, 1776 long transitionTimestamp) { 1777 mHandler.post(() -> { 1778 if (mGeofenceHardwareImpl == null) { 1779 mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext); 1780 } 1781 1782 mGeofenceHardwareImpl.reportGeofenceTransition( 1783 geofenceId, 1784 location, 1785 transition, 1786 transitionTimestamp, 1787 GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE, 1788 FusedBatchOptions.SourceTechnologies.GNSS); 1789 }); 1790 } 1791 1792 @NativeEntryPoint 1793 private void reportGeofenceStatus(int status, Location location) { 1794 mHandler.post(() -> { 1795 if (mGeofenceHardwareImpl == null) { 1796 mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext); 1797 } 1798 int monitorStatus = GeofenceHardware.MONITOR_CURRENTLY_UNAVAILABLE; 1799 if (status == GPS_GEOFENCE_AVAILABLE) { 1800 monitorStatus = GeofenceHardware.MONITOR_CURRENTLY_AVAILABLE; 1801 } 1802 mGeofenceHardwareImpl.reportGeofenceMonitorStatus( 1803 GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE, 1804 monitorStatus, 1805 location, 1806 FusedBatchOptions.SourceTechnologies.GNSS); 1807 }); 1808 } 1809 1810 @NativeEntryPoint 1811 private void reportGeofenceAddStatus(int geofenceId, int status) { 1812 mHandler.post(() -> { 1813 if (mGeofenceHardwareImpl == null) { 1814 mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext); 1815 } 1816 mGeofenceHardwareImpl.reportGeofenceAddStatus(geofenceId, getGeofenceStatus(status)); 1817 }); 1818 } 1819 1820 @NativeEntryPoint 1821 private void reportGeofenceRemoveStatus(int geofenceId, int status) { 1822 mHandler.post(() -> { 1823 if (mGeofenceHardwareImpl == null) { 1824 mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext); 1825 } 1826 mGeofenceHardwareImpl.reportGeofenceRemoveStatus(geofenceId, getGeofenceStatus(status)); 1827 }); 1828 } 1829 1830 @NativeEntryPoint 1831 private void reportGeofencePauseStatus(int geofenceId, int status) { 1832 mHandler.post(() -> { 1833 if (mGeofenceHardwareImpl == null) { 1834 mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext); 1835 } 1836 mGeofenceHardwareImpl.reportGeofencePauseStatus(geofenceId, getGeofenceStatus(status)); 1837 }); 1838 } 1839 1840 @NativeEntryPoint 1841 private void reportGeofenceResumeStatus(int geofenceId, int status) { 1842 mHandler.post(() -> { 1843 if (mGeofenceHardwareImpl == null) { 1844 mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext); 1845 } 1846 mGeofenceHardwareImpl.reportGeofenceResumeStatus(geofenceId, getGeofenceStatus(status)); 1847 }); 1848 } 1849 1850 //============================================================= 1851 // NI Client support 1852 //============================================================= 1853 private final INetInitiatedListener mNetInitiatedListener = new INetInitiatedListener.Stub() { 1854 // Sends a response for an NI request to HAL. 1855 @Override 1856 public boolean sendNiResponse(int notificationId, int userResponse) { 1857 // TODO Add Permission check 1858 1859 if (DEBUG) { 1860 Log.d(TAG, "sendNiResponse, notifId: " + notificationId + 1861 ", response: " + userResponse); 1862 } 1863 native_send_ni_response(notificationId, userResponse); 1864 1865 FrameworkStatsLog.write(FrameworkStatsLog.GNSS_NI_EVENT_REPORTED, 1866 FrameworkStatsLog.GNSS_NI_EVENT_REPORTED__EVENT_TYPE__NI_RESPONSE, 1867 notificationId, 1868 /* niType= */ 0, 1869 /* needNotify= */ false, 1870 /* needVerify= */ false, 1871 /* privacyOverride= */ false, 1872 /* timeout= */ 0, 1873 /* defaultResponse= */ 0, 1874 /* requestorId= */ null, 1875 /* text= */ null, 1876 /* requestorIdEncoding= */ 0, 1877 /* textEncoding= */ 0, 1878 mSuplEsEnabled, 1879 isGpsEnabled(), 1880 userResponse); 1881 1882 return true; 1883 } 1884 }; 1885 1886 public INetInitiatedListener getNetInitiatedListener() { 1887 return mNetInitiatedListener; 1888 } 1889 1890 /** Reports a NI notification. */ 1891 @NativeEntryPoint 1892 public void reportNiNotification( 1893 int notificationId, 1894 int niType, 1895 int notifyFlags, 1896 int timeout, 1897 int defaultResponse, 1898 String requestorId, 1899 String text, 1900 int requestorIdEncoding, 1901 int textEncoding 1902 ) { 1903 Log.i(TAG, "reportNiNotification: entered"); 1904 Log.i(TAG, "notificationId: " + notificationId + 1905 ", niType: " + niType + 1906 ", notifyFlags: " + notifyFlags + 1907 ", timeout: " + timeout + 1908 ", defaultResponse: " + defaultResponse); 1909 1910 Log.i(TAG, "requestorId: " + requestorId + 1911 ", text: " + text + 1912 ", requestorIdEncoding: " + requestorIdEncoding + 1913 ", textEncoding: " + textEncoding); 1914 1915 GpsNiNotification notification = new GpsNiNotification(); 1916 1917 notification.notificationId = notificationId; 1918 notification.niType = niType; 1919 notification.needNotify = (notifyFlags & GpsNetInitiatedHandler.GPS_NI_NEED_NOTIFY) != 0; 1920 notification.needVerify = (notifyFlags & GpsNetInitiatedHandler.GPS_NI_NEED_VERIFY) != 0; 1921 notification.privacyOverride = 1922 (notifyFlags & GpsNetInitiatedHandler.GPS_NI_PRIVACY_OVERRIDE) != 0; 1923 notification.timeout = timeout; 1924 notification.defaultResponse = defaultResponse; 1925 notification.requestorId = requestorId; 1926 notification.text = text; 1927 notification.requestorIdEncoding = requestorIdEncoding; 1928 notification.textEncoding = textEncoding; 1929 1930 mNIHandler.handleNiNotification(notification); 1931 FrameworkStatsLog.write(FrameworkStatsLog.GNSS_NI_EVENT_REPORTED, 1932 FrameworkStatsLog.GNSS_NI_EVENT_REPORTED__EVENT_TYPE__NI_REQUEST, 1933 notification.notificationId, 1934 notification.niType, 1935 notification.needNotify, 1936 notification.needVerify, 1937 notification.privacyOverride, 1938 notification.timeout, 1939 notification.defaultResponse, 1940 notification.requestorId, 1941 notification.text, 1942 notification.requestorIdEncoding, 1943 notification.textEncoding, 1944 mSuplEsEnabled, 1945 isGpsEnabled(), 1946 /* userResponse= */ 0); 1947 } 1948 1949 /** 1950 * We should be careful about receiving null string from the TelephonyManager, 1951 * because sending null String to JNI function would cause a crash. 1952 */ 1953 @NativeEntryPoint 1954 private void requestSetID(int flags) { 1955 TelephonyManager phone = (TelephonyManager) 1956 mContext.getSystemService(Context.TELEPHONY_SERVICE); 1957 int type = AGPS_SETID_TYPE_NONE; 1958 String setId = null; 1959 1960 int ddSubId = SubscriptionManager.getDefaultDataSubscriptionId(); 1961 if (SubscriptionManager.isValidSubscriptionId(ddSubId)) { 1962 phone = phone.createForSubscriptionId(ddSubId); 1963 } 1964 if ((flags & AGPS_RIL_REQUEST_SETID_IMSI) == AGPS_RIL_REQUEST_SETID_IMSI) { 1965 setId = phone.getSubscriberId(); 1966 if (setId != null) { 1967 // This means the framework has the SIM card. 1968 type = AGPS_SETID_TYPE_IMSI; 1969 } 1970 } else if ((flags & AGPS_RIL_REQUEST_SETID_MSISDN) == AGPS_RIL_REQUEST_SETID_MSISDN) { 1971 setId = phone.getLine1Number(); 1972 if (setId != null) { 1973 // This means the framework has the SIM card. 1974 type = AGPS_SETID_TYPE_MSISDN; 1975 } 1976 } 1977 1978 native_agps_set_id(type, (setId == null) ? "" : setId); 1979 } 1980 1981 @NativeEntryPoint 1982 private void requestLocation(boolean independentFromGnss, boolean isUserEmergency) { 1983 if (DEBUG) { 1984 Log.d(TAG, "requestLocation. independentFromGnss: " + independentFromGnss 1985 + ", isUserEmergency: " 1986 + isUserEmergency); 1987 } 1988 sendMessage(REQUEST_LOCATION, independentFromGnss ? 1 : 0, isUserEmergency); 1989 } 1990 1991 @NativeEntryPoint 1992 private void requestUtcTime() { 1993 if (DEBUG) Log.d(TAG, "utcTimeRequest"); 1994 sendMessage(INJECT_NTP_TIME, 0, null); 1995 } 1996 1997 @NativeEntryPoint 1998 private void requestRefLocation() { 1999 TelephonyManager phone = (TelephonyManager) 2000 mContext.getSystemService(Context.TELEPHONY_SERVICE); 2001 final int phoneType = phone.getPhoneType(); 2002 if (phoneType == TelephonyManager.PHONE_TYPE_GSM) { 2003 GsmCellLocation gsm_cell = (GsmCellLocation) phone.getCellLocation(); 2004 if ((gsm_cell != null) && (phone.getNetworkOperator() != null) 2005 && (phone.getNetworkOperator().length() > 3)) { 2006 int type; 2007 int mcc = Integer.parseInt(phone.getNetworkOperator().substring(0, 3)); 2008 int mnc = Integer.parseInt(phone.getNetworkOperator().substring(3)); 2009 int networkType = phone.getNetworkType(); 2010 if (networkType == TelephonyManager.NETWORK_TYPE_UMTS 2011 || networkType == TelephonyManager.NETWORK_TYPE_HSDPA 2012 || networkType == TelephonyManager.NETWORK_TYPE_HSUPA 2013 || networkType == TelephonyManager.NETWORK_TYPE_HSPA 2014 || networkType == TelephonyManager.NETWORK_TYPE_HSPAP) { 2015 type = AGPS_REF_LOCATION_TYPE_UMTS_CELLID; 2016 } else { 2017 type = AGPS_REF_LOCATION_TYPE_GSM_CELLID; 2018 } 2019 native_agps_set_ref_location_cellid(type, mcc, mnc, 2020 gsm_cell.getLac(), gsm_cell.getCid()); 2021 } else { 2022 Log.e(TAG, "Error getting cell location info."); 2023 } 2024 } else if (phoneType == TelephonyManager.PHONE_TYPE_CDMA) { 2025 Log.e(TAG, "CDMA not supported."); 2026 } 2027 } 2028 2029 // Implements method nfwNotifyCb() in IGnssVisibilityControlCallback.hal. 2030 @NativeEntryPoint 2031 private void reportNfwNotification(String proxyAppPackageName, byte protocolStack, 2032 String otherProtocolStackName, byte requestor, String requestorId, byte responseType, 2033 boolean inEmergencyMode, boolean isCachedLocation) { 2034 if (mGnssVisibilityControl == null) { 2035 Log.e(TAG, "reportNfwNotification: mGnssVisibilityControl is not initialized."); 2036 return; 2037 } 2038 2039 mGnssVisibilityControl.reportNfwNotification(proxyAppPackageName, protocolStack, 2040 otherProtocolStackName, requestor, requestorId, responseType, inEmergencyMode, 2041 isCachedLocation); 2042 } 2043 2044 // Implements method isInEmergencySession() in IGnssVisibilityControlCallback.hal. 2045 @NativeEntryPoint 2046 boolean isInEmergencySession() { 2047 return mNIHandler.getInEmergency(); 2048 } 2049 2050 private void sendMessage(int message, int arg, Object obj) { 2051 // hold a wake lock until this message is delivered 2052 // note that this assumes the message will not be removed from the queue before 2053 // it is handled (otherwise the wake lock would be leaked). 2054 mWakeLock.acquire(WAKELOCK_TIMEOUT_MILLIS); 2055 if (DEBUG) { 2056 Log.d(TAG, "WakeLock acquired by sendMessage(" + messageIdAsString(message) + ", " + arg 2057 + ", " + obj + ")"); 2058 } 2059 mHandler.obtainMessage(message, arg, 1, obj).sendToTarget(); 2060 } 2061 2062 private final class ProviderHandler extends Handler { 2063 public ProviderHandler(Looper looper) { 2064 super(looper, null, true /*async*/); 2065 } 2066 2067 @Override 2068 public void handleMessage(Message msg) { 2069 int message = msg.what; 2070 switch (message) { 2071 case SET_REQUEST: 2072 GpsRequest gpsRequest = (GpsRequest) msg.obj; 2073 handleSetRequest(gpsRequest.request, gpsRequest.source); 2074 break; 2075 case INJECT_NTP_TIME: 2076 mNtpTimeHelper.retrieveAndInjectNtpTime(); 2077 break; 2078 case REQUEST_LOCATION: 2079 handleRequestLocation(msg.arg1 == 1, (boolean) msg.obj); 2080 break; 2081 case DOWNLOAD_PSDS_DATA: 2082 handleDownloadPsdsData(); 2083 break; 2084 case DOWNLOAD_PSDS_DATA_FINISHED: 2085 mDownloadPsdsDataPending = STATE_IDLE; 2086 break; 2087 case INITIALIZE_HANDLER: 2088 handleInitialize(); 2089 break; 2090 case REPORT_LOCATION: 2091 handleReportLocation(msg.arg1 == 1, (Location) msg.obj); 2092 break; 2093 case REPORT_SV_STATUS: 2094 handleReportSvStatus((SvStatusInfo) msg.obj); 2095 break; 2096 case UPDATE_LOW_POWER_MODE: 2097 updateLowPowerMode(); 2098 break; 2099 } 2100 if (msg.arg2 == 1) { 2101 // wakelock was taken for this message, release it 2102 mWakeLock.release(); 2103 if (DEBUG) { 2104 Log.d(TAG, "WakeLock released by handleMessage(" + messageIdAsString(message) 2105 + ", " + msg.arg1 + ", " + msg.obj + ")"); 2106 } 2107 } 2108 } 2109 2110 /** 2111 * This method is bound to the constructor. It is in charge of loading properties and 2112 * registering for events that will be posted to this handler. 2113 */ 2114 private void handleInitialize() { 2115 // class_init_native() already initializes the GNSS service handle during class loading. 2116 setupNativeGnssService(/* reinitializeGnssServiceHandle = */ false); 2117 2118 if (native_is_gnss_visibility_control_supported()) { 2119 mGnssVisibilityControl = new GnssVisibilityControl(mContext, mLooper, mNIHandler); 2120 } 2121 2122 // load default GPS configuration 2123 // (this configuration might change in the future based on SIM changes) 2124 reloadGpsProperties(); 2125 2126 // listen for events 2127 IntentFilter intentFilter = new IntentFilter(); 2128 intentFilter.addAction(ALARM_WAKEUP); 2129 intentFilter.addAction(ALARM_TIMEOUT); 2130 intentFilter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED); 2131 intentFilter.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED); 2132 intentFilter.addAction(Intent.ACTION_SCREEN_OFF); 2133 intentFilter.addAction(Intent.ACTION_SCREEN_ON); 2134 intentFilter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED); 2135 intentFilter.addAction(TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED); 2136 mContext.registerReceiver(mBroadcastReceiver, intentFilter, null, this); 2137 2138 mNetworkConnectivityHandler.registerNetworkCallbacks(); 2139 2140 // listen for PASSIVE_PROVIDER updates 2141 LocationManager locManager = 2142 (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE); 2143 long minTime = 0; 2144 float minDistance = 0; 2145 LocationRequest request = LocationRequest.createFromDeprecatedProvider( 2146 LocationManager.PASSIVE_PROVIDER, 2147 minTime, 2148 minDistance, 2149 false); 2150 // Don't keep track of this request since it's done on behalf of other clients 2151 // (which are kept track of separately). 2152 request.setHideFromAppOps(true); 2153 locManager.requestLocationUpdates( 2154 request, 2155 new NetworkLocationListener(), 2156 getLooper()); 2157 2158 updateEnabled(); 2159 } 2160 } 2161 2162 private abstract class LocationChangeListener implements LocationListener { 2163 private int mNumLocationUpdateRequest; 2164 2165 @Override 2166 public void onStatusChanged(String provider, int status, Bundle extras) { 2167 } 2168 2169 @Override 2170 public void onProviderEnabled(String provider) { 2171 } 2172 2173 @Override 2174 public void onProviderDisabled(String provider) { 2175 } 2176 } 2177 2178 private final class NetworkLocationListener extends LocationChangeListener { 2179 @Override 2180 public void onLocationChanged(Location location) { 2181 // this callback happens on mHandler looper 2182 if (LocationManager.NETWORK_PROVIDER.equals(location.getProvider())) { 2183 injectLocation(location); 2184 } 2185 } 2186 } 2187 2188 private final class FusedLocationListener extends LocationChangeListener { 2189 @Override 2190 public void onLocationChanged(Location location) { 2191 if (LocationManager.FUSED_PROVIDER.equals(location.getProvider())) { 2192 injectBestLocation(location); 2193 } 2194 } 2195 } 2196 2197 /** 2198 * @return A string representing the given message ID. 2199 */ 2200 private String messageIdAsString(int message) { 2201 switch (message) { 2202 case SET_REQUEST: 2203 return "SET_REQUEST"; 2204 case INJECT_NTP_TIME: 2205 return "INJECT_NTP_TIME"; 2206 case REQUEST_LOCATION: 2207 return "REQUEST_LOCATION"; 2208 case DOWNLOAD_PSDS_DATA: 2209 return "DOWNLOAD_PSDS_DATA"; 2210 case DOWNLOAD_PSDS_DATA_FINISHED: 2211 return "DOWNLOAD_PSDS_DATA_FINISHED"; 2212 case INITIALIZE_HANDLER: 2213 return "INITIALIZE_HANDLER"; 2214 case REPORT_LOCATION: 2215 return "REPORT_LOCATION"; 2216 case REPORT_SV_STATUS: 2217 return "REPORT_SV_STATUS"; 2218 default: 2219 return "<Unknown>"; 2220 } 2221 } 2222 2223 @Override 2224 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 2225 StringBuilder s = new StringBuilder(); 2226 s.append("mStarted=").append(mStarted).append(" (changed "); 2227 TimeUtils.formatDuration(SystemClock.elapsedRealtime() 2228 - mStartedChangedElapsedRealtime, s); 2229 s.append(" ago)").append('\n'); 2230 s.append("mFixInterval=").append(mFixInterval).append('\n'); 2231 s.append("mLowPowerMode=").append(mLowPowerMode).append('\n'); 2232 s.append("mGnssAntennaInfoProvider.isRegistered()=") 2233 .append(mGnssAntennaInfoProvider.isRegistered()).append('\n'); 2234 s.append("mGnssMeasurementsProvider.isRegistered()=") 2235 .append(mGnssMeasurementsProvider.isRegistered()).append('\n'); 2236 s.append("mGnssNavigationMessageProvider.isRegistered()=") 2237 .append(mGnssNavigationMessageProvider.isRegistered()).append('\n'); 2238 s.append("mDisableGpsForPowerManager=").append(mDisableGpsForPowerManager).append('\n'); 2239 s.append("mTopHalCapabilities=0x").append(Integer.toHexString(mTopHalCapabilities)); 2240 s.append(" ( "); 2241 if (hasCapability(GPS_CAPABILITY_SCHEDULING)) s.append("SCHEDULING "); 2242 if (hasCapability(GPS_CAPABILITY_MSB)) s.append("MSB "); 2243 if (hasCapability(GPS_CAPABILITY_MSA)) s.append("MSA "); 2244 if (hasCapability(GPS_CAPABILITY_SINGLE_SHOT)) s.append("SINGLE_SHOT "); 2245 if (hasCapability(GPS_CAPABILITY_ON_DEMAND_TIME)) s.append("ON_DEMAND_TIME "); 2246 if (hasCapability(GPS_CAPABILITY_GEOFENCING)) s.append("GEOFENCING "); 2247 if (hasCapability(GPS_CAPABILITY_MEASUREMENTS)) s.append("MEASUREMENTS "); 2248 if (hasCapability(GPS_CAPABILITY_NAV_MESSAGES)) s.append("NAV_MESSAGES "); 2249 if (hasCapability(GPS_CAPABILITY_LOW_POWER_MODE)) s.append("LOW_POWER_MODE "); 2250 if (hasCapability(GPS_CAPABILITY_SATELLITE_BLACKLIST)) s.append("SATELLITE_BLACKLIST "); 2251 if (hasCapability(GPS_CAPABILITY_MEASUREMENT_CORRECTIONS)) { 2252 s.append("MEASUREMENT_CORRECTIONS "); 2253 } 2254 if (hasCapability(GPS_CAPABILITY_ANTENNA_INFO)) s.append("ANTENNA_INFO "); 2255 s.append(")\n"); 2256 if (hasCapability(GPS_CAPABILITY_MEASUREMENT_CORRECTIONS)) { 2257 s.append("SubHal=MEASUREMENT_CORRECTIONS["); 2258 s.append(mGnssMeasurementCorrectionsProvider.toStringCapabilities()); 2259 s.append("]\n"); 2260 } 2261 s.append(mGnssMetrics.dumpGnssMetricsAsText()); 2262 s.append("native internal state: \n"); 2263 s.append(" ").append(native_get_internal_state()); 2264 s.append("\n"); 2265 pw.append(s); 2266 } 2267 2268 private void setupNativeGnssService(boolean reinitializeGnssServiceHandle) { 2269 native_init_once(reinitializeGnssServiceHandle); 2270 2271 /* 2272 * A cycle of native_init() and native_cleanup() is needed so that callbacks are 2273 * registered after bootup even when location is disabled. 2274 * This will allow Emergency SUPL to work even when location is disabled before device 2275 * restart. 2276 */ 2277 boolean isInitialized = native_init(); 2278 if (!isInitialized) { 2279 Log.w(TAG, "Native initialization failed."); 2280 } else { 2281 native_cleanup(); 2282 } 2283 } 2284 2285 // preallocated to avoid memory allocation in reportNmea() 2286 private byte[] mNmeaBuffer = new byte[120]; 2287 2288 private static native void class_init_native(); 2289 2290 private static native boolean native_is_supported(); 2291 2292 private static native boolean native_is_gnss_visibility_control_supported(); 2293 2294 private static native void native_init_once(boolean reinitializeGnssServiceHandle); 2295 2296 private native boolean native_init(); 2297 2298 private native void native_cleanup(); 2299 2300 private native boolean native_set_position_mode(int mode, int recurrence, int min_interval, 2301 int preferred_accuracy, int preferred_time, boolean lowPowerMode); 2302 2303 private native boolean native_start(); 2304 2305 private native boolean native_stop(); 2306 2307 private native void native_delete_aiding_data(int flags); 2308 2309 private native int native_read_nmea(byte[] buffer, int bufferSize); 2310 2311 private native void native_inject_best_location( 2312 int gnssLocationFlags, double latitudeDegrees, double longitudeDegrees, 2313 double altitudeMeters, float speedMetersPerSec, float bearingDegrees, 2314 float horizontalAccuracyMeters, float verticalAccuracyMeters, 2315 float speedAccuracyMetersPerSecond, float bearingAccuracyDegrees, 2316 long timestamp, int elapsedRealtimeFlags, long elapsedRealtimeNanos, 2317 double elapsedRealtimeUncertaintyNanos); 2318 2319 private native void native_inject_location(double latitude, double longitude, float accuracy); 2320 2321 // PSDS Support 2322 private native void native_inject_time(long time, long timeReference, int uncertainty); 2323 2324 private native boolean native_supports_psds(); 2325 2326 private native void native_inject_psds_data(byte[] data, int length); 2327 2328 // DEBUG Support 2329 private native String native_get_internal_state(); 2330 2331 // AGPS Support 2332 private native void native_agps_ni_message(byte[] msg, int length); 2333 2334 private native void native_set_agps_server(int type, String hostname, int port); 2335 2336 // Network-initiated (NI) Support 2337 private native void native_send_ni_response(int notificationId, int userResponse); 2338 2339 // AGPS ril support 2340 private native void native_agps_set_ref_location_cellid(int type, int mcc, int mnc, 2341 int lac, int cid); 2342 2343 private native void native_agps_set_id(int type, String setid); 2344 } 2345