• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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