blob: ae98077c7c2c244d7beae8f5c1ecd99cf7e1e494 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Mike Lockwood00b74272010-03-26 10:41:48 -040017package com.android.server.location;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080018
destradaaea8a8a62014-06-23 18:19:03 -070019import com.android.internal.app.IAppOpsService;
20import com.android.internal.app.IBatteryStats;
21import com.android.internal.location.GpsNetInitiatedHandler;
22import com.android.internal.location.GpsNetInitiatedHandler.GpsNiNotification;
23import com.android.internal.location.ProviderProperties;
24import com.android.internal.location.ProviderRequest;
destradaaea8a8a62014-06-23 18:19:03 -070025
Mike Lockwood29c84342009-05-06 14:01:15 -040026import android.app.AlarmManager;
Dianne Hackborna06de0f2012-12-11 16:34:47 -080027import android.app.AppOpsManager;
Mike Lockwood29c84342009-05-06 14:01:15 -040028import android.app.PendingIntent;
The Android Open Source Project10592532009-03-18 17:39:46 -070029import android.content.BroadcastReceiver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080030import android.content.Context;
31import android.content.Intent;
The Android Open Source Project10592532009-03-18 17:39:46 -070032import android.content.IntentFilter;
Kevin Tanga5fe6b22011-06-05 14:25:16 -070033import android.database.Cursor;
destradaa0682809a2013-08-12 18:50:30 -070034import android.hardware.location.GeofenceHardware;
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -070035import android.hardware.location.GeofenceHardwareImpl;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080036import android.location.Criteria;
destradaa0682809a2013-08-12 18:50:30 -070037import android.location.FusedBatchOptions;
Lifu Tang30f95a72016-01-07 23:20:38 -080038import android.location.GnssStatus;
39import android.location.IGnssStatusListener;
40import android.location.IGnssStatusProvider;
Lifu Tang818aa2c2016-02-01 01:52:00 -080041import android.location.GnssMeasurementsEvent;
Lifu Tange8abe8e2016-04-01 10:32:05 -070042import android.location.GnssNavigationMessage;
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -070043import android.location.IGpsGeofenceHardware;
Mike Lockwood4e50b782009-04-03 08:24:43 -070044import android.location.ILocationManager;
Danke Xie22d1f9f2009-08-18 18:28:45 -040045import android.location.INetInitiatedListener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080046import android.location.Location;
Nick Pelly6fa9ad42012-07-16 12:18:23 -070047import android.location.LocationListener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080048import android.location.LocationManager;
49import android.location.LocationProvider;
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -070050import android.location.LocationRequest;
Mike Lockwood58bda982009-04-14 16:25:07 -040051import android.net.ConnectivityManager;
destradaae21252a2015-09-08 12:32:59 -070052import android.net.Network;
53import android.net.NetworkCapabilities;
Mike Lockwood03d24672009-10-08 15:45:03 -040054import android.net.NetworkInfo;
destradaae21252a2015-09-08 12:32:59 -070055import android.net.NetworkRequest;
Kevin Tanga5fe6b22011-06-05 14:25:16 -070056import android.net.Uri;
Kevin Tang40e1baf2012-01-10 14:32:44 -080057import android.os.AsyncTask;
Dianne Hackborn91268cf2013-06-13 19:06:50 -070058import android.os.BatteryStats;
Mike Lockwood63aa5a62010-04-14 19:21:31 -040059import android.os.Binder;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080060import android.os.Bundle;
Mike Lockwood62a8fc12010-03-22 14:23:26 -040061import android.os.Handler;
Victoria Lease5cd731a2012-12-19 15:04:21 -080062import android.os.Looper;
Mike Lockwood62a8fc12010-03-22 14:23:26 -040063import android.os.Message;
Mike Lockwood0528b9b2009-05-07 10:12:54 -040064import android.os.PowerManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080065import android.os.RemoteException;
Mike Lockwood2f82c4e2009-04-17 08:24:10 -040066import android.os.ServiceManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080067import android.os.SystemClock;
Colin Cross7c030ed2014-01-28 09:33:53 -080068import android.os.SystemProperties;
Dianne Hackborn5ac72a22012-08-29 18:32:08 -070069import android.os.UserHandle;
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -070070import android.os.WorkSource;
Mike Lockwoodbcab8df2009-06-25 16:39:09 -040071import android.provider.Settings;
Kevin Tanga5fe6b22011-06-05 14:25:16 -070072import android.provider.Telephony.Carriers;
Miguel Torroja1e84da82010-07-27 07:02:24 +020073import android.provider.Telephony.Sms.Intents;
Jake Hambyb49a73d2011-03-15 20:09:46 -070074import android.telephony.SmsMessage;
Wink Savillea374c3d2014-11-11 11:48:04 -080075import android.telephony.SubscriptionManager;
Wink Savilled09c4ca2014-11-22 10:08:16 -080076import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
Miguel Torroja1e84da82010-07-27 07:02:24 +020077import android.telephony.TelephonyManager;
78import android.telephony.gsm.GsmCellLocation;
Colin Cross7c030ed2014-01-28 09:33:53 -080079import android.text.TextUtils;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080080import android.util.Log;
Jeff Sharkey104344e2011-07-10 14:20:41 -070081import android.util.NtpTrustedTime;
Dianne Hackborna06de0f2012-12-11 16:34:47 -080082
Tsuwei Chen52617bb2014-08-25 11:49:11 -070083import java.io.ByteArrayOutputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080084import java.io.File;
Nick Pelly6fa9ad42012-07-16 12:18:23 -070085import java.io.FileDescriptor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080086import java.io.FileInputStream;
87import java.io.IOException;
Nick Pelly6fa9ad42012-07-16 12:18:23 -070088import java.io.PrintWriter;
Jeff Sharkey104344e2011-07-10 14:20:41 -070089import java.io.StringReader;
destradaaea8a8a62014-06-23 18:19:03 -070090import java.net.InetAddress;
91import java.net.UnknownHostException;
Andreas Gampee6748ce2015-12-11 18:00:38 -080092import java.util.Arrays;
Mike Lockwoodf1218be2010-01-29 09:20:06 -050093import java.util.Date;
Danke Xie22d1f9f2009-08-18 18:28:45 -040094import java.util.Map.Entry;
Jake Hambyb49a73d2011-03-15 20:09:46 -070095import java.util.Properties;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080096
Colin Cross7c030ed2014-01-28 09:33:53 -080097import libcore.io.IoUtils;
98
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080099/**
100 * A GPS implementation of LocationProvider used by LocationManager.
101 *
102 * {@hide}
103 */
Lifu Tang30f95a72016-01-07 23:20:38 -0800104public class GnssLocationProvider implements LocationProviderInterface {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800105
Lifu Tang30f95a72016-01-07 23:20:38 -0800106 private static final String TAG = "GnssLocationProvider";
Mike Lockwood29c84342009-05-06 14:01:15 -0400107
Brian Muramatsu1715cb32012-08-08 17:32:21 -0700108 private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
109 private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400110
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700111 private static final ProviderProperties PROPERTIES = new ProviderProperties(
112 true, true, false, false, true, true, true,
113 Criteria.POWER_HIGH, Criteria.ACCURACY_FINE);
114
The Android Open Source Project10592532009-03-18 17:39:46 -0700115 // these need to match GpsPositionMode enum in gps.h
116 private static final int GPS_POSITION_MODE_STANDALONE = 0;
117 private static final int GPS_POSITION_MODE_MS_BASED = 1;
118 private static final int GPS_POSITION_MODE_MS_ASSISTED = 2;
119
Mike Lockwood04598b62010-04-14 17:17:24 -0400120 // these need to match GpsPositionRecurrence enum in gps.h
121 private static final int GPS_POSITION_RECURRENCE_PERIODIC = 0;
122 private static final int GPS_POSITION_RECURRENCE_SINGLE = 1;
123
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800124 // these need to match GpsStatusValue defines in gps.h
125 private static final int GPS_STATUS_NONE = 0;
126 private static final int GPS_STATUS_SESSION_BEGIN = 1;
127 private static final int GPS_STATUS_SESSION_END = 2;
128 private static final int GPS_STATUS_ENGINE_ON = 3;
129 private static final int GPS_STATUS_ENGINE_OFF = 4;
130
Mike Lockwoode3635c92009-05-11 08:38:02 -0400131 // these need to match GpsApgsStatusValue defines in gps.h
132 /** AGPS status event values. */
133 private static final int GPS_REQUEST_AGPS_DATA_CONN = 1;
134 private static final int GPS_RELEASE_AGPS_DATA_CONN = 2;
135 private static final int GPS_AGPS_DATA_CONNECTED = 3;
136 private static final int GPS_AGPS_DATA_CONN_DONE = 4;
137 private static final int GPS_AGPS_DATA_CONN_FAILED = 5;
Mike Lockwood58bda982009-04-14 16:25:07 -0400138
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800139 // these need to match GpsLocationFlags enum in gps.h
140 private static final int LOCATION_INVALID = 0;
141 private static final int LOCATION_HAS_LAT_LONG = 1;
142 private static final int LOCATION_HAS_ALTITUDE = 2;
143 private static final int LOCATION_HAS_SPEED = 4;
144 private static final int LOCATION_HAS_BEARING = 8;
145 private static final int LOCATION_HAS_ACCURACY = 16;
Mike Lockwoode3635c92009-05-11 08:38:02 -0400146
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700147 // IMPORTANT - the GPS_DELETE_* symbols here must match constants in gps.h
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800148 private static final int GPS_DELETE_EPHEMERIS = 0x0001;
149 private static final int GPS_DELETE_ALMANAC = 0x0002;
150 private static final int GPS_DELETE_POSITION = 0x0004;
151 private static final int GPS_DELETE_TIME = 0x0008;
152 private static final int GPS_DELETE_IONO = 0x0010;
153 private static final int GPS_DELETE_UTC = 0x0020;
154 private static final int GPS_DELETE_HEALTH = 0x0040;
155 private static final int GPS_DELETE_SVDIR = 0x0080;
156 private static final int GPS_DELETE_SVSTEER = 0x0100;
157 private static final int GPS_DELETE_SADATA = 0x0200;
158 private static final int GPS_DELETE_RTI = 0x0400;
159 private static final int GPS_DELETE_CELLDB_INFO = 0x8000;
160 private static final int GPS_DELETE_ALL = 0xFFFF;
161
Mike Lockwood04598b62010-04-14 17:17:24 -0400162 // The GPS_CAPABILITY_* flags must match the values in gps.h
163 private static final int GPS_CAPABILITY_SCHEDULING = 0x0000001;
164 private static final int GPS_CAPABILITY_MSB = 0x0000002;
165 private static final int GPS_CAPABILITY_MSA = 0x0000004;
166 private static final int GPS_CAPABILITY_SINGLE_SHOT = 0x0000008;
Mike Lockwood9b9fb5c2011-06-29 15:09:40 -0400167 private static final int GPS_CAPABILITY_ON_DEMAND_TIME = 0x0000010;
destradaa6568d702014-10-27 12:47:41 -0700168 private static final int GPS_CAPABILITY_GEOFENCING = 0x0000020;
169 private static final int GPS_CAPABILITY_MEASUREMENTS = 0x0000040;
170 private static final int GPS_CAPABILITY_NAV_MESSAGES = 0x0000080;
Mike Lockwood04598b62010-04-14 17:17:24 -0400171
Tsuwei Chen462bcd82014-09-17 12:28:49 -0700172 // The AGPS SUPL mode
173 private static final int AGPS_SUPL_MODE_MSA = 0x02;
174 private static final int AGPS_SUPL_MODE_MSB = 0x01;
175
Mike Lockwoode3635c92009-05-11 08:38:02 -0400176 // these need to match AGpsType enum in gps.h
177 private static final int AGPS_TYPE_SUPL = 1;
178 private static final int AGPS_TYPE_C2K = 2;
179
destradaa96a14702014-06-05 11:36:30 -0700180 // these must match the definitions in gps.h
181 private static final int APN_INVALID = 0;
182 private static final int APN_IPV4 = 1;
183 private static final int APN_IPV6 = 2;
184 private static final int APN_IPV4V6 = 3;
185
Mike Lockwoode3635c92009-05-11 08:38:02 -0400186 // for mAGpsDataConnectionState
187 private static final int AGPS_DATA_CONNECTION_CLOSED = 0;
188 private static final int AGPS_DATA_CONNECTION_OPENING = 1;
189 private static final int AGPS_DATA_CONNECTION_OPEN = 2;
Mike Lockwood58bda982009-04-14 16:25:07 -0400190
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400191 // Handler messages
192 private static final int CHECK_LOCATION = 1;
193 private static final int ENABLE = 2;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700194 private static final int SET_REQUEST = 3;
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400195 private static final int UPDATE_NETWORK_STATE = 4;
196 private static final int INJECT_NTP_TIME = 5;
197 private static final int DOWNLOAD_XTRA_DATA = 6;
198 private static final int UPDATE_LOCATION = 7;
199 private static final int ADD_LISTENER = 8;
200 private static final int REMOVE_LISTENER = 9;
Kevin Tang40e1baf2012-01-10 14:32:44 -0800201 private static final int INJECT_NTP_TIME_FINISHED = 10;
202 private static final int DOWNLOAD_XTRA_DATA_FINISHED = 11;
destradaafb23c672015-04-16 14:01:27 -0700203 private static final int SUBSCRIPTION_OR_SIM_CHANGED = 12;
204 private static final int INITIALIZE_HANDLER = 13;
destradaae21252a2015-09-08 12:32:59 -0700205 private static final int REQUEST_SUPL_CONNECTION = 14;
206 private static final int RELEASE_SUPL_CONNECTION = 15;
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400207
Miguel Torroja1e84da82010-07-27 07:02:24 +0200208 // Request setid
209 private static final int AGPS_RIL_REQUEST_SETID_IMSI = 1;
210 private static final int AGPS_RIL_REQUEST_SETID_MSISDN = 2;
211
212 // Request ref location
213 private static final int AGPS_RIL_REQUEST_REFLOC_CELLID = 1;
214 private static final int AGPS_RIL_REQUEST_REFLOC_MAC = 2;
215
216 // ref. location info
217 private static final int AGPS_REF_LOCATION_TYPE_GSM_CELLID = 1;
218 private static final int AGPS_REF_LOCATION_TYPE_UMTS_CELLID = 2;
219 private static final int AGPS_REG_LOCATION_TYPE_MAC = 3;
220
221 // set id info
222 private static final int AGPS_SETID_TYPE_NONE = 0;
223 private static final int AGPS_SETID_TYPE_IMSI = 1;
224 private static final int AGPS_SETID_TYPE_MSISDN = 2;
225
Colin Cross7c030ed2014-01-28 09:33:53 -0800226 private static final String PROPERTIES_FILE_PREFIX = "/etc/gps";
227 private static final String PROPERTIES_FILE_SUFFIX = ".conf";
228 private static final String DEFAULT_PROPERTIES_FILE = PROPERTIES_FILE_PREFIX + PROPERTIES_FILE_SUFFIX;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800229
destradaa0682809a2013-08-12 18:50:30 -0700230 private static final int GPS_GEOFENCE_UNAVAILABLE = 1<<0L;
231 private static final int GPS_GEOFENCE_AVAILABLE = 1<<1L;
232
233 // GPS Geofence errors. Should match gps.h constants.
234 private static final int GPS_GEOFENCE_OPERATION_SUCCESS = 0;
235 private static final int GPS_GEOFENCE_ERROR_TOO_MANY_GEOFENCES = 100;
236 private static final int GPS_GEOFENCE_ERROR_ID_EXISTS = -101;
237 private static final int GPS_GEOFENCE_ERROR_ID_UNKNOWN = -102;
238 private static final int GPS_GEOFENCE_ERROR_INVALID_TRANSITION = -103;
239 private static final int GPS_GEOFENCE_ERROR_GENERIC = -149;
240
Tsuwei Chen678c13c2014-09-22 17:48:41 -0700241 // TCP/IP constants.
242 // Valid TCP/UDP port range is (0, 65535].
243 private static final int TCP_MIN_PORT = 0;
244 private static final int TCP_MAX_PORT = 0xffff;
245
David Christied4edf4c2014-08-12 15:22:27 -0700246 // Value of batterySaverGpsMode such that GPS isn't affected by battery saver mode.
247 private static final int BATTERY_SAVER_MODE_NO_CHANGE = 0;
248 // Value of batterySaverGpsMode such that GPS is disabled when battery saver mode
249 // is enabled and the screen is off.
250 private static final int BATTERY_SAVER_MODE_DISABLED_WHEN_SCREEN_OFF = 1;
251 // Secure setting for GPS behavior when battery saver mode is on.
252 private static final String BATTERY_SAVER_GPS_MODE = "batterySaverGpsMode";
253
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700254 /** simpler wrapper for ProviderRequest + Worksource */
255 private static class GpsRequest {
256 public ProviderRequest request;
257 public WorkSource source;
258 public GpsRequest(ProviderRequest request, WorkSource source) {
259 this.request = request;
260 this.source = source;
261 }
262 }
263
264 private Object mLock = new Object();
265
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800266 private int mLocationFlags = LOCATION_INVALID;
267
268 // current status
Mike Lockwood15e3d0f2009-05-01 07:53:28 -0400269 private int mStatus = LocationProvider.TEMPORARILY_UNAVAILABLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800270
271 // time for last status update
272 private long mStatusUpdateTime = SystemClock.elapsedRealtime();
Mike Lockwoodd53ba012010-04-15 20:41:26 -0400273
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800274 // turn off GPS fix icon if we haven't received a fix in 10 seconds
Mike Lockwood04598b62010-04-14 17:17:24 -0400275 private static final long RECENT_FIX_TIMEOUT = 10 * 1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800276
Mike Lockwood0632ca72009-05-14 15:51:03 -0400277 // stop trying if we do not receive a fix within 60 seconds
Mike Lockwood04598b62010-04-14 17:17:24 -0400278 private static final int NO_FIX_TIMEOUT = 60 * 1000;
Mike Lockwood0632ca72009-05-14 15:51:03 -0400279
Nick Pellyb041f232012-05-07 17:12:25 -0700280 // if the fix interval is below this we leave GPS on,
281 // if above then we cycle the GPS driver.
282 // Typical hot TTTF is ~5 seconds, so 10 seconds seems sane.
283 private static final int GPS_POLLING_THRESHOLD_INTERVAL = 10 * 1000;
284
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700285 // how often to request NTP time, in milliseconds
286 // current setting 24 hours
287 private static final long NTP_INTERVAL = 24*60*60*1000;
288 // how long to wait if we have a network error in NTP or XTRA downloading
Wei Liu6f6326b2015-06-24 23:47:50 -0700289 // the initial value of the exponential backoff
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700290 // current setting - 5 minutes
291 private static final long RETRY_INTERVAL = 5*60*1000;
Wei Liu6f6326b2015-06-24 23:47:50 -0700292 // how long to wait if we have a network error in NTP or XTRA downloading
293 // the max value of the exponential backoff
294 // current setting - 4 hours
295 private static final long MAX_RETRY_INTERVAL = 4*60*60*1000;
296
297 private BackOff mNtpBackOff = new BackOff(RETRY_INTERVAL, MAX_RETRY_INTERVAL);
298 private BackOff mXtraBackOff = new BackOff(RETRY_INTERVAL, MAX_RETRY_INTERVAL);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700299
300 // true if we are enabled, protected by this
301 private boolean mEnabled;
302
Kevin Tang40e1baf2012-01-10 14:32:44 -0800303 // states for injecting ntp and downloading xtra data
304 private static final int STATE_PENDING_NETWORK = 0;
305 private static final int STATE_DOWNLOADING = 1;
306 private static final int STATE_IDLE = 2;
307
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400308 // flags to trigger NTP or XTRA data download when network becomes available
309 // initialized to true so we do NTP and XTRA when the network comes up after booting
Kevin Tang40e1baf2012-01-10 14:32:44 -0800310 private int mInjectNtpTimePending = STATE_PENDING_NETWORK;
311 private int mDownloadXtraDataPending = STATE_PENDING_NETWORK;
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400312
destradaa56b47f82015-07-24 10:56:18 -0700313 // set to true if the GPS engine requested on-demand NTP time requests
314 private boolean mOnDemandTimeInjection;
Mike Lockwood9b9fb5c2011-06-29 15:09:40 -0400315
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800316 // true if GPS is navigating
317 private boolean mNavigating;
Mike Lockwoodcf1d8cb2010-01-20 10:14:54 -0500318
319 // true if GPS engine is on
320 private boolean mEngineOn;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700321
Mike Lockwood04598b62010-04-14 17:17:24 -0400322 // requested frequency of fixes, in milliseconds
323 private int mFixInterval = 1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800324
325 // true if we started navigation
326 private boolean mStarted;
327
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -0700328 // true if single shot request is in progress
329 private boolean mSingleShot;
330
Mike Lockwood04598b62010-04-14 17:17:24 -0400331 // capabilities of the GPS engine
332 private int mEngineCapabilities;
333
Mike Lockwood1a1cd3a2010-08-17 07:42:54 -0400334 // true if XTRA is supported
335 private boolean mSupportsXtra;
336
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800337 // for calculating time to first fix
338 private long mFixRequestTime = 0;
339 // time to first fix for most recent session
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700340 private int mTimeToFirstFix = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800341 // time we received our last fix
342 private long mLastFixTime;
343
Mike Lockwood04598b62010-04-14 17:17:24 -0400344 private int mPositionMode;
345
David Christied4edf4c2014-08-12 15:22:27 -0700346 // Current request from underlying location clients.
347 private ProviderRequest mProviderRequest = null;
348 // Current list of underlying location clients.
349 private WorkSource mWorkSource = null;
350 // True if gps should be disabled (used to support battery saver mode in settings).
351 private boolean mDisableGps = false;
352
destradaafb23c672015-04-16 14:01:27 -0700353 /**
354 * Properties loaded from PROPERTIES_FILE.
355 * It must be accessed only inside {@link #mHandler}.
356 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800357 private Properties mProperties;
destradaafb23c672015-04-16 14:01:27 -0700358
Mike Lockwood734d6032009-07-28 18:30:25 -0700359 private String mSuplServerHost;
Tsuwei Chen678c13c2014-09-22 17:48:41 -0700360 private int mSuplServerPort = TCP_MIN_PORT;
Mike Lockwood734d6032009-07-28 18:30:25 -0700361 private String mC2KServerHost;
362 private int mC2KServerPort;
Tsuwei Chen3324e952014-09-07 01:30:42 -0700363 private boolean mSuplEsEnabled = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800364
Mike Lockwood15e3d0f2009-05-01 07:53:28 -0400365 private final Context mContext;
Jeff Sharkey104344e2011-07-10 14:20:41 -0700366 private final NtpTrustedTime mNtpTime;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700367 private final ILocationManager mILocationManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800368 private Location mLocation = new Location(LocationManager.GPS_PROVIDER);
369 private Bundle mLocationExtras = new Bundle();
Lifu Tang30f95a72016-01-07 23:20:38 -0800370 private final GnssStatusListenerHelper mListenerHelper;
Lifu Tang818aa2c2016-02-01 01:52:00 -0800371 private final GnssMeasurementsProvider mGnssMeasurementsProvider;
372 private final GnssNavigationMessageProvider mGnssNavigationMessageProvider;
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400373
Victoria Lease5c24fd02012-10-01 11:00:50 -0700374 // Handler for processing events
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400375 private Handler mHandler;
The Android Open Source Project10592532009-03-18 17:39:46 -0700376
destradaae21252a2015-09-08 12:32:59 -0700377 /** It must be accessed only inside {@link #mHandler}. */
Mike Lockwoode3635c92009-05-11 08:38:02 -0400378 private int mAGpsDataConnectionState;
destradaae21252a2015-09-08 12:32:59 -0700379 /** It must be accessed only inside {@link #mHandler}. */
destradaa96a14702014-06-05 11:36:30 -0700380 private InetAddress mAGpsDataConnectionIpAddr;
destradaae21252a2015-09-08 12:32:59 -0700381
Mike Lockwood2f82c4e2009-04-17 08:24:10 -0400382 private final ConnectivityManager mConnMgr;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700383 private final GpsNetInitiatedHandler mNIHandler;
Mike Lockwood2f82c4e2009-04-17 08:24:10 -0400384
Mike Lockwood0528b9b2009-05-07 10:12:54 -0400385 // Wakelocks
Lifu Tang30f95a72016-01-07 23:20:38 -0800386 private final static String WAKELOCK_KEY = "GnssLocationProvider";
Mike Lockwood0528b9b2009-05-07 10:12:54 -0400387 private final PowerManager.WakeLock mWakeLock;
388
Mike Lockwood29c84342009-05-06 14:01:15 -0400389 // Alarms
390 private final static String ALARM_WAKEUP = "com.android.internal.location.ALARM_WAKEUP";
Mike Lockwood0632ca72009-05-14 15:51:03 -0400391 private final static String ALARM_TIMEOUT = "com.android.internal.location.ALARM_TIMEOUT";
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700392
393 // SIM/Carrier info.
394 private final static String SIM_STATE_CHANGED = "android.intent.action.SIM_STATE_CHANGED";
395
Ecco Park624ac3c2016-07-18 14:08:05 -0700396 // Persist property for LPP_PROFILE
397 private final static String LPP_PROFILE = "persist.sys.gps.lpp";
398
399 // VZW PLMN info
400 private static final String[] VzwMccMncList = {"311480", "310004", "20404"};
401 // corresponding GID1 value, empty string means ignore gid1 match.
402 private static final String[] VzwGid1List = {"", "", "BAE0000000000000"};
403
404
David Christied4edf4c2014-08-12 15:22:27 -0700405 private final PowerManager mPowerManager;
Mike Lockwood29c84342009-05-06 14:01:15 -0400406 private final AlarmManager mAlarmManager;
407 private final PendingIntent mWakeupIntent;
Mike Lockwood0632ca72009-05-14 15:51:03 -0400408 private final PendingIntent mTimeoutIntent;
Mike Lockwood29c84342009-05-06 14:01:15 -0400409
Dianne Hackborna06de0f2012-12-11 16:34:47 -0800410 private final IAppOpsService mAppOpsService;
Mike Lockwood2f82c4e2009-04-17 08:24:10 -0400411 private final IBatteryStats mBatteryStats;
The Android Open Source Project10592532009-03-18 17:39:46 -0700412
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700413 // only modified on handler thread
Dianne Hackborn002a54e2013-01-10 17:34:55 -0800414 private WorkSource mClientSource = new WorkSource();
Mike Lockwoodf1218be2010-01-29 09:20:06 -0500415
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -0700416 private GeofenceHardwareImpl mGeofenceHardwareImpl;
417
Lifu Tang82f893d2016-01-21 18:15:33 -0800418 private int mYearOfHardware = 0;
419
Lifu Tang30f95a72016-01-07 23:20:38 -0800420 private final IGnssStatusProvider mGnssStatusProvider = new IGnssStatusProvider.Stub() {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700421 @Override
Lifu Tang30f95a72016-01-07 23:20:38 -0800422 public void registerGnssStatusCallback(IGnssStatusListener callback) {
423 mListenerHelper.addListener(callback);
Mike Lockwood15e3d0f2009-05-01 07:53:28 -0400424 }
425
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700426 @Override
Lifu Tang30f95a72016-01-07 23:20:38 -0800427 public void unregisterGnssStatusCallback(IGnssStatusListener callback) {
428 mListenerHelper.removeListener(callback);
destradaaea8a8a62014-06-23 18:19:03 -0700429 }
430 };
Mike Lockwood15e3d0f2009-05-01 07:53:28 -0400431
Lifu Tang30f95a72016-01-07 23:20:38 -0800432 public IGnssStatusProvider getGnssStatusProvider() {
433 return mGnssStatusProvider;
Mike Lockwood15e3d0f2009-05-01 07:53:28 -0400434 }
435
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -0700436 public IGpsGeofenceHardware getGpsGeofenceProxy() {
437 return mGpsGeofenceBinder;
438 }
439
Lifu Tang818aa2c2016-02-01 01:52:00 -0800440 public GnssMeasurementsProvider getGnssMeasurementsProvider() {
441 return mGnssMeasurementsProvider;
destradaaea8a8a62014-06-23 18:19:03 -0700442 }
443
Lifu Tang818aa2c2016-02-01 01:52:00 -0800444 public GnssNavigationMessageProvider getGnssNavigationMessageProvider() {
445 return mGnssNavigationMessageProvider;
destradaa4b3e3932014-07-21 18:01:47 -0700446 }
447
destradaae21252a2015-09-08 12:32:59 -0700448 /**
449 * Callback used to listen for data connectivity changes.
450 */
451 private final ConnectivityManager.NetworkCallback mNetworkConnectivityCallback =
452 new ConnectivityManager.NetworkCallback() {
453 @Override
454 public void onAvailable(Network network) {
Wyatt Riley0d6e54e22016-10-05 12:03:03 -0700455 if (mInjectNtpTimePending == STATE_PENDING_NETWORK) {
456 requestUtcTime();
457 }
458 if (mDownloadXtraDataPending == STATE_PENDING_NETWORK) {
459 xtraDownloadRequest();
460 }
destradaae21252a2015-09-08 12:32:59 -0700461 }
462 };
463
464 /**
465 * Callback used to listen for availability of a requested SUPL connection.
466 * It is kept as a separate instance from {@link #mNetworkConnectivityCallback} to be able to
467 * manage the registration/un-registration lifetimes separate.
468 */
469 private final ConnectivityManager.NetworkCallback mSuplConnectivityCallback =
470 new ConnectivityManager.NetworkCallback() {
471 @Override
472 public void onAvailable(Network network) {
473 sendMessage(UPDATE_NETWORK_STATE, 0 /*arg*/, network);
474 }
475
476 @Override
477 public void onLost(Network network) {
478 releaseSuplConnection(GPS_RELEASE_AGPS_DATA_CONN);
479 }
480
481 @Override
482 public void onUnavailable() {
483 // timeout, it was not possible to establish the required connection
484 releaseSuplConnection(GPS_AGPS_DATA_CONN_FAILED);
485 }
486 };
487
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700488 private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
The Android Open Source Project10592532009-03-18 17:39:46 -0700489 @Override public void onReceive(Context context, Intent intent) {
490 String action = intent.getAction();
Tsuwei Chen48d37f92014-09-05 15:15:34 -0700491 if (DEBUG) Log.d(TAG, "receive broadcast intent, action: " + action);
destradaaee9fd342015-08-31 13:31:17 -0700492 if (action == null) {
493 return;
494 }
495
Mike Lockwood29c84342009-05-06 14:01:15 -0400496 if (action.equals(ALARM_WAKEUP)) {
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -0700497 startNavigating(false);
Mike Lockwood0632ca72009-05-14 15:51:03 -0400498 } else if (action.equals(ALARM_TIMEOUT)) {
Mike Lockwood0632ca72009-05-14 15:51:03 -0400499 hibernate();
Miguel Torroja1e84da82010-07-27 07:02:24 +0200500 } else if (action.equals(Intents.DATA_SMS_RECEIVED_ACTION)) {
501 checkSmsSuplInit(intent);
502 } else if (action.equals(Intents.WAP_PUSH_RECEIVED_ACTION)) {
503 checkWapSuplInit(intent);
David Christied4edf4c2014-08-12 15:22:27 -0700504 } else if (PowerManager.ACTION_POWER_SAVE_MODE_CHANGED.equals(action)
Adam Lesinski87c17df2015-05-27 13:24:13 -0700505 || PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED.equals(action)
David Christied4edf4c2014-08-12 15:22:27 -0700506 || Intent.ACTION_SCREEN_OFF.equals(action)
507 || Intent.ACTION_SCREEN_ON.equals(action)) {
508 updateLowPowerMode();
Wink Savillea374c3d2014-11-11 11:48:04 -0800509 } else if (action.equals(SIM_STATE_CHANGED)) {
510 subscriptionOrSimChanged(context);
David Christied4edf4c2014-08-12 15:22:27 -0700511 }
The Android Open Source Project10592532009-03-18 17:39:46 -0700512 }
Mike Lockwood29c84342009-05-06 14:01:15 -0400513 };
The Android Open Source Project10592532009-03-18 17:39:46 -0700514
Wink Savilled09c4ca2014-11-22 10:08:16 -0800515 private final OnSubscriptionsChangedListener mOnSubscriptionsChangedListener =
516 new OnSubscriptionsChangedListener() {
Wink Savillea374c3d2014-11-11 11:48:04 -0800517 @Override
Wink Savilled09c4ca2014-11-22 10:08:16 -0800518 public void onSubscriptionsChanged() {
destradaafb23c672015-04-16 14:01:27 -0700519 sendMessage(SUBSCRIPTION_OR_SIM_CHANGED, 0, null);
Wink Savillea374c3d2014-11-11 11:48:04 -0800520 }
521 };
522
Ecco Park624ac3c2016-07-18 14:08:05 -0700523 private final boolean isVerizon(String mccMnc, String imsi, String groupId) {
524 if (DEBUG) Log.d(TAG, "simOperator: " + mccMnc);
525 if (!TextUtils.isEmpty(mccMnc) || !TextUtils.isEmpty(imsi)) {
526 for (int i = 0; i < VzwMccMncList.length; i++) {
527 if ((!TextUtils.isEmpty(mccMnc) && mccMnc.equals(VzwMccMncList[i])) ||
528 (!TextUtils.isEmpty(imsi) && imsi.startsWith(VzwMccMncList[i]))) {
529 // check gid too if needed
530 if (TextUtils.isEmpty(VzwGid1List[i]) || VzwGid1List[i].equals(groupId)) {
531 if (DEBUG) Log.d(TAG, "Verizon UICC");
532 return true;
533 }
534 }
535 }
536 }
537 return false;
538 }
539
Wink Savillea374c3d2014-11-11 11:48:04 -0800540 private void subscriptionOrSimChanged(Context context) {
Joe Onorato0c484102016-02-01 18:04:24 -0800541 if (DEBUG) Log.d(TAG, "received SIM related action: ");
Wink Savillea374c3d2014-11-11 11:48:04 -0800542 TelephonyManager phone = (TelephonyManager)
543 mContext.getSystemService(Context.TELEPHONY_SERVICE);
544 String mccMnc = phone.getSimOperator();
Ecco Park624ac3c2016-07-18 14:08:05 -0700545 String imsi = phone.getSubscriberId();
546 String groupId = phone.getGroupIdLevel1();
Wink Savillea374c3d2014-11-11 11:48:04 -0800547 if (!TextUtils.isEmpty(mccMnc)) {
Joe Onorato0c484102016-02-01 18:04:24 -0800548 if (DEBUG) Log.d(TAG, "SIM MCC/MNC is available: " + mccMnc);
Wink Savillea374c3d2014-11-11 11:48:04 -0800549 synchronized (mLock) {
Ecco Park624ac3c2016-07-18 14:08:05 -0700550 if (isVerizon(mccMnc, imsi, groupId)) {
551 // load current properties for carrier VZW
552 loadPropertiesFromResource(context, mProperties);
553 String lpp_profile = mProperties.getProperty("LPP_PROFILE");
554 // set the persist property LPP_PROFILE for VZW
555 SystemProperties.set(LPP_PROFILE, lpp_profile);
556 } else {
557 // reset the persist property for Non VZW
558 SystemProperties.set(LPP_PROFILE, "");
559 }
Wink Savillea374c3d2014-11-11 11:48:04 -0800560 reloadGpsProperties(context, mProperties);
561 mNIHandler.setSuplEsEnabled(mSuplEsEnabled);
562 }
563 } else {
Joe Onorato0c484102016-02-01 18:04:24 -0800564 if (DEBUG) Log.d(TAG, "SIM MCC/MNC is still not available");
Wink Savillea374c3d2014-11-11 11:48:04 -0800565 }
566 }
567
Miguel Torroja1e84da82010-07-27 07:02:24 +0200568 private void checkSmsSuplInit(Intent intent) {
569 SmsMessage[] messages = Intents.getMessagesFromIntent(intent);
Jack Yuefea9672015-07-31 15:13:39 -0700570 if (messages == null) {
571 Log.e(TAG, "Message does not exist in the intent.");
572 return;
573 }
574
destradaaee9fd342015-08-31 13:31:17 -0700575 for (SmsMessage message : messages) {
576 if (message != null && message.mWrappedSmsMessage != null) {
577 byte[] suplInit = message.getUserData();
578 if (suplInit != null) {
579 native_agps_ni_message(suplInit, suplInit.length);
580 }
581 }
Miguel Torroja1e84da82010-07-27 07:02:24 +0200582 }
583 }
584
585 private void checkWapSuplInit(Intent intent) {
destradaaee9fd342015-08-31 13:31:17 -0700586 byte[] suplInit = intent.getByteArrayExtra("data");
587 if (suplInit == null) {
588 return;
589 }
590 native_agps_ni_message(suplInit,suplInit.length);
Miguel Torroja1e84da82010-07-27 07:02:24 +0200591 }
592
David Christied4edf4c2014-08-12 15:22:27 -0700593 private void updateLowPowerMode() {
Adam Lesinski87c17df2015-05-27 13:24:13 -0700594 // Disable GPS if we are in device idle mode.
595 boolean disableGps = mPowerManager.isDeviceIdleMode();
David Christied4edf4c2014-08-12 15:22:27 -0700596 switch (Settings.Secure.getInt(mContext.getContentResolver(), BATTERY_SAVER_GPS_MODE,
597 BATTERY_SAVER_MODE_DISABLED_WHEN_SCREEN_OFF)) {
598 case BATTERY_SAVER_MODE_DISABLED_WHEN_SCREEN_OFF:
Adam Lesinski87c17df2015-05-27 13:24:13 -0700599 // If we are in battery saver mode and the screen is off, disable GPS.
600 disableGps |= mPowerManager.isPowerSaveMode() && !mPowerManager.isInteractive();
David Christied4edf4c2014-08-12 15:22:27 -0700601 break;
David Christied4edf4c2014-08-12 15:22:27 -0700602 }
603 if (disableGps != mDisableGps) {
604 mDisableGps = disableGps;
605 updateRequirements();
606 }
607 }
608
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800609 public static boolean isSupported() {
610 return native_is_supported();
611 }
612
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700613 private void reloadGpsProperties(Context context, Properties properties) {
Joe Onorato0c484102016-02-01 18:04:24 -0800614 if (DEBUG) Log.d(TAG, "Reset GPS properties, previous size = " + properties.size());
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700615 loadPropertiesFromResource(context, properties);
Ecco Park624ac3c2016-07-18 14:08:05 -0700616
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700617 boolean isPropertiesLoadedFromFile = false;
618 final String gpsHardware = SystemProperties.get("ro.hardware.gps");
Ecco Park624ac3c2016-07-18 14:08:05 -0700619
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700620 if (!TextUtils.isEmpty(gpsHardware)) {
621 final String propFilename =
622 PROPERTIES_FILE_PREFIX + "." + gpsHardware + PROPERTIES_FILE_SUFFIX;
623 isPropertiesLoadedFromFile =
624 loadPropertiesFromFile(propFilename, properties);
625 }
626 if (!isPropertiesLoadedFromFile) {
627 loadPropertiesFromFile(DEFAULT_PROPERTIES_FILE, properties);
628 }
Joe Onorato0c484102016-02-01 18:04:24 -0800629 if (DEBUG) Log.d(TAG, "GPS properties reloaded, size = " + properties.size());
Ecco Park624ac3c2016-07-18 14:08:05 -0700630 String lpp_prof = SystemProperties.get(LPP_PROFILE);
631 if (!TextUtils.isEmpty(lpp_prof)) {
632 // override default value of this if lpp_prof is not empty
633 properties.setProperty("LPP_PROFILE", lpp_prof);
634 }
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700635 // TODO: we should get rid of C2K specific setting.
636 setSuplHostPort(properties.getProperty("SUPL_HOST"),
637 properties.getProperty("SUPL_PORT"));
638 mC2KServerHost = properties.getProperty("C2K_HOST");
639 String portString = properties.getProperty("C2K_PORT");
640 if (mC2KServerHost != null && portString != null) {
641 try {
642 mC2KServerPort = Integer.parseInt(portString);
643 } catch (NumberFormatException e) {
644 Log.e(TAG, "unable to parse C2K_PORT: " + portString);
645 }
646 }
647
destradaaef752b62015-04-17 13:10:47 -0700648 if (native_is_gnss_configuration_supported()) {
649 try {
650 // Convert properties to string contents and send it to HAL.
651 ByteArrayOutputStream baos = new ByteArrayOutputStream(4096);
652 properties.store(baos, null);
653 native_configuration_update(baos.toString());
Joe Onorato0c484102016-02-01 18:04:24 -0800654 if (DEBUG) Log.d(TAG, "final config = " + baos.toString());
destradaaef752b62015-04-17 13:10:47 -0700655 } catch (IOException ex) {
destradaae21252a2015-09-08 12:32:59 -0700656 Log.e(TAG, "failed to dump properties contents");
destradaaef752b62015-04-17 13:10:47 -0700657 }
658 } else if (DEBUG) {
659 Log.d(TAG, "Skipped configuration update because GNSS configuration in GPS HAL is not"
660 + " supported");
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700661 }
Tsuwei Chen3324e952014-09-07 01:30:42 -0700662
663 // SUPL_ES configuration.
664 String suplESProperty = mProperties.getProperty("SUPL_ES");
665 if (suplESProperty != null) {
666 try {
667 mSuplEsEnabled = (Integer.parseInt(suplESProperty) == 1);
668 } catch (NumberFormatException e) {
669 Log.e(TAG, "unable to parse SUPL_ES: " + suplESProperty);
670 }
671 }
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700672 }
673
674 private void loadPropertiesFromResource(Context context,
675 Properties properties) {
676 String[] configValues = context.getResources().getStringArray(
677 com.android.internal.R.array.config_gpsParameters);
678 for (String item : configValues) {
Joe Onorato0c484102016-02-01 18:04:24 -0800679 if (DEBUG) Log.d(TAG, "GpsParamsResource: " + item);
Tsuwei Chen7c485bf2014-09-10 15:33:34 -0700680 // We need to support "KEY =", but not "=VALUE".
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700681 String[] split = item.split("=");
682 if (split.length == 2) {
683 properties.setProperty(split[0].trim().toUpperCase(), split[1]);
684 } else {
685 Log.w(TAG, "malformed contents: " + item);
686 }
687 }
688 }
689
690 private boolean loadPropertiesFromFile(String filename,
691 Properties properties) {
Colin Cross7c030ed2014-01-28 09:33:53 -0800692 try {
693 File file = new File(filename);
694 FileInputStream stream = null;
695 try {
696 stream = new FileInputStream(file);
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700697 properties.load(stream);
Colin Cross7c030ed2014-01-28 09:33:53 -0800698 } finally {
699 IoUtils.closeQuietly(stream);
700 }
701
Colin Cross7c030ed2014-01-28 09:33:53 -0800702 } catch (IOException e) {
703 Log.w(TAG, "Could not open GPS configuration file " + filename);
704 return false;
705 }
706 return true;
707 }
708
Lifu Tang30f95a72016-01-07 23:20:38 -0800709 public GnssLocationProvider(Context context, ILocationManager ilocationManager,
Victoria Lease5cd731a2012-12-19 15:04:21 -0800710 Looper looper) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800711 mContext = context;
Jeff Sharkey104344e2011-07-10 14:20:41 -0700712 mNtpTime = NtpTrustedTime.getInstance(context);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700713 mILocationManager = ilocationManager;
Mike Lockwood63598a02010-02-24 11:52:59 -0500714
715 mLocation.setExtras(mLocationExtras);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800716
Mike Lockwood0528b9b2009-05-07 10:12:54 -0400717 // Create a wake lock
David Christied4edf4c2014-08-12 15:22:27 -0700718 mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
719 mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700720 mWakeLock.setReferenceCounted(true);
Mike Lockwood0528b9b2009-05-07 10:12:54 -0400721
Mike Lockwood29c84342009-05-06 14:01:15 -0400722 mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
723 mWakeupIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_WAKEUP), 0);
Mike Lockwood0632ca72009-05-14 15:51:03 -0400724 mTimeoutIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_TIMEOUT), 0);
Mike Lockwood29c84342009-05-06 14:01:15 -0400725
Mike Lockwood58bda982009-04-14 16:25:07 -0400726 mConnMgr = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
727
Dianne Hackborna06de0f2012-12-11 16:34:47 -0800728 // App ops service to keep track of who is accessing the GPS
729 mAppOpsService = IAppOpsService.Stub.asInterface(ServiceManager.getService(
730 Context.APP_OPS_SERVICE));
731
Mike Lockwood2f82c4e2009-04-17 08:24:10 -0400732 // Battery statistics service to be notified when GPS turns on or off
Dianne Hackborn91268cf2013-06-13 19:06:50 -0700733 mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService(
734 BatteryStats.SERVICE_NAME));
Mike Lockwood2f82c4e2009-04-17 08:24:10 -0400735
destradaafb23c672015-04-16 14:01:27 -0700736 // Construct internal handler
737 mHandler = new ProviderHandler(looper);
738
739 // Load GPS configuration and register listeners in the background:
740 // some operations, such as opening files and registering broadcast receivers, can take a
741 // relative long time, so the ctor() is kept to create objects needed by this instance,
742 // while IO initialization and registration is delegated to our internal handler
743 // this approach is just fine because events are posted to our handler anyway
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700744 mProperties = new Properties();
destradaafb23c672015-04-16 14:01:27 -0700745 sendMessage(INITIALIZE_HANDLER, 0, null);
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400746
Tsuwei Chen3324e952014-09-07 01:30:42 -0700747 // Create a GPS net-initiated handler.
748 mNIHandler = new GpsNetInitiatedHandler(context,
749 mNetInitiatedListener,
750 mSuplEsEnabled);
751
Lifu Tang30f95a72016-01-07 23:20:38 -0800752 mListenerHelper = new GnssStatusListenerHelper(mHandler) {
destradaa6568d702014-10-27 12:47:41 -0700753 @Override
754 protected boolean isAvailableInPlatform() {
destradaa13a60b02015-01-15 18:36:01 -0800755 return isSupported();
destradaa6568d702014-10-27 12:47:41 -0700756 }
757
758 @Override
759 protected boolean isGpsEnabled() {
760 return isEnabled();
761 }
762 };
763
Lifu Tang818aa2c2016-02-01 01:52:00 -0800764 mGnssMeasurementsProvider = new GnssMeasurementsProvider(mHandler) {
destradaa6568d702014-10-27 12:47:41 -0700765 @Override
766 public boolean isAvailableInPlatform() {
767 return native_is_measurement_supported();
768 }
769
770 @Override
771 protected boolean registerWithService() {
772 return native_start_measurement_collection();
773 }
774
775 @Override
776 protected void unregisterFromService() {
777 native_stop_measurement_collection();
778 }
779
780 @Override
781 protected boolean isGpsEnabled() {
782 return isEnabled();
783 }
784 };
785
Lifu Tang818aa2c2016-02-01 01:52:00 -0800786 mGnssNavigationMessageProvider = new GnssNavigationMessageProvider(mHandler) {
destradaa6568d702014-10-27 12:47:41 -0700787 @Override
788 protected boolean isAvailableInPlatform() {
789 return native_is_navigation_message_supported();
790 }
791
792 @Override
793 protected boolean registerWithService() {
794 return native_start_navigation_message_collection();
795 }
796
797 @Override
798 protected void unregisterFromService() {
799 native_stop_navigation_message_collection();
800 }
801
802 @Override
803 protected boolean isGpsEnabled() {
804 return isEnabled();
805 }
806 };
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400807 }
808
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800809 /**
Mike Lockwoodd03ff942010-02-09 08:46:14 -0500810 * Returns the name of this provider.
811 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700812 @Override
Mike Lockwoodd03ff942010-02-09 08:46:14 -0500813 public String getName() {
814 return LocationManager.GPS_PROVIDER;
815 }
816
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700817 @Override
818 public ProviderProperties getProperties() {
819 return PROPERTIES;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800820 }
821
destradaae21252a2015-09-08 12:32:59 -0700822 private void handleUpdateNetworkState(Network network) {
823 // retrieve NetworkInfo for this UID
824 NetworkInfo info = mConnMgr.getNetworkInfo(network);
825 if (info == null) {
826 return;
827 }
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400828
destradaae21252a2015-09-08 12:32:59 -0700829 boolean isConnected = info.isConnected();
Joe Onoratof5d95cb2010-01-07 21:48:32 -0500830 if (DEBUG) {
destradaae21252a2015-09-08 12:32:59 -0700831 String message = String.format(
832 "UpdateNetworkState, state=%s, connected=%s, info=%s, capabilities=%S",
833 agpsDataConnStateAsString(),
834 isConnected,
835 info,
836 mConnMgr.getNetworkCapabilities(network));
837 Log.d(TAG, message);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800838 }
Mike Lockwood03d24672009-10-08 15:45:03 -0400839
destradaae21252a2015-09-08 12:32:59 -0700840 if (native_is_agps_ril_supported()) {
841 boolean dataEnabled = TelephonyManager.getDefault().getDataEnabled();
842 boolean networkAvailable = info.isAvailable() && dataEnabled;
843 String defaultApn = getSelectedApn();
844 if (defaultApn == null) {
845 defaultApn = "dummy-apn";
destradaaef752b62015-04-17 13:10:47 -0700846 }
destradaae21252a2015-09-08 12:32:59 -0700847
848 native_update_network_state(
849 isConnected,
850 info.getType(),
851 info.isRoaming(),
852 networkAvailable,
853 info.getExtraInfo(),
854 defaultApn);
855 } else if (DEBUG) {
856 Log.d(TAG, "Skipped network state update because GPS HAL AGPS-RIL is not supported");
Mike Lockwood50130bb2010-10-11 06:22:50 -0400857 }
858
destradaae21252a2015-09-08 12:32:59 -0700859 if (mAGpsDataConnectionState == AGPS_DATA_CONNECTION_OPENING) {
860 if (isConnected) {
destradaa96a14702014-06-05 11:36:30 -0700861 String apnName = info.getExtraInfo();
Stephen Li83b69712011-01-25 18:47:28 -0800862 if (apnName == null) {
destradaae21252a2015-09-08 12:32:59 -0700863 // assign a dummy value in the case of C2K as otherwise we will have a runtime
864 // exception in the following call to native_agps_data_conn_open
Stephen Li83b69712011-01-25 18:47:28 -0800865 apnName = "dummy-apn";
866 }
destradaae21252a2015-09-08 12:32:59 -0700867 int apnIpType = getApnIpType(apnName);
destradaa96a14702014-06-05 11:36:30 -0700868 setRouting();
869 if (DEBUG) {
870 String message = String.format(
871 "native_agps_data_conn_open: mAgpsApn=%s, mApnIpType=%s",
destradaae21252a2015-09-08 12:32:59 -0700872 apnName,
873 apnIpType);
destradaa96a14702014-06-05 11:36:30 -0700874 Log.d(TAG, message);
Stephen Li8efd74d2011-03-01 20:56:00 -0800875 }
destradaae21252a2015-09-08 12:32:59 -0700876 native_agps_data_conn_open(apnName, apnIpType);
Mike Lockwood03d24672009-10-08 15:45:03 -0400877 mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPEN;
878 } else {
destradaae21252a2015-09-08 12:32:59 -0700879 handleReleaseSuplConnection(GPS_AGPS_DATA_CONN_FAILED);
Mike Lockwood03d24672009-10-08 15:45:03 -0400880 }
881 }
destradaae21252a2015-09-08 12:32:59 -0700882 }
Mike Lockwood03d24672009-10-08 15:45:03 -0400883
destradaae21252a2015-09-08 12:32:59 -0700884 private void handleRequestSuplConnection(InetAddress address) {
885 if (DEBUG) {
886 String message = String.format(
887 "requestSuplConnection, state=%s, address=%s",
888 agpsDataConnStateAsString(),
889 address);
890 Log.d(TAG, message);
891 }
892
893 if (mAGpsDataConnectionState != AGPS_DATA_CONNECTION_CLOSED) {
894 return;
895 }
896 mAGpsDataConnectionIpAddr = address;
897 mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPENING;
898
899 NetworkRequest.Builder requestBuilder = new NetworkRequest.Builder();
900 requestBuilder.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
901 requestBuilder.addCapability(NetworkCapabilities.NET_CAPABILITY_SUPL);
902 NetworkRequest request = requestBuilder.build();
903 mConnMgr.requestNetwork(
904 request,
905 mSuplConnectivityCallback,
906 ConnectivityManager.MAX_NETWORK_REQUEST_TIMEOUT_MS);
907 }
908
909 private void handleReleaseSuplConnection(int agpsDataConnStatus) {
910 if (DEBUG) {
911 String message = String.format(
912 "releaseSuplConnection, state=%s, status=%s",
913 agpsDataConnStateAsString(),
914 agpsDataConnStatusAsString(agpsDataConnStatus));
915 Log.d(TAG, message);
916 }
917
918 if (mAGpsDataConnectionState == AGPS_DATA_CONNECTION_CLOSED) {
919 return;
920 }
921 mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED;
922
923 mConnMgr.unregisterNetworkCallback(mSuplConnectivityCallback);
924 switch (agpsDataConnStatus) {
925 case GPS_AGPS_DATA_CONN_FAILED:
926 native_agps_data_conn_failed();
927 break;
928 case GPS_RELEASE_AGPS_DATA_CONN:
929 native_agps_data_conn_closed();
930 break;
931 default:
932 Log.e(TAG, "Invalid status to release SUPL connection: " + agpsDataConnStatus);
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400933 }
934 }
935
936 private void handleInjectNtpTime() {
Kevin Tang40e1baf2012-01-10 14:32:44 -0800937 if (mInjectNtpTimePending == STATE_DOWNLOADING) {
938 // already downloading data
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400939 return;
940 }
destradaae21252a2015-09-08 12:32:59 -0700941 if (!isDataNetworkConnected()) {
Kevin Tang40e1baf2012-01-10 14:32:44 -0800942 // try again when network is up
943 mInjectNtpTimePending = STATE_PENDING_NETWORK;
944 return;
Jeff Sharkey104344e2011-07-10 14:20:41 -0700945 }
Kevin Tang40e1baf2012-01-10 14:32:44 -0800946 mInjectNtpTimePending = STATE_DOWNLOADING;
Jeff Sharkey104344e2011-07-10 14:20:41 -0700947
Jeff Brown028872f2012-08-25 13:07:01 -0700948 // hold wake lock while task runs
949 mWakeLock.acquire();
Lifu Tangcbd2a142016-06-22 10:57:55 -0700950 Log.i(TAG, "WakeLock acquired by handleInjectNtpTime()");
Kevin Tang40e1baf2012-01-10 14:32:44 -0800951 AsyncTask.THREAD_POOL_EXECUTOR.execute(new Runnable() {
952 @Override
953 public void run() {
954 long delay;
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400955
Kevin Tang40e1baf2012-01-10 14:32:44 -0800956 // force refresh NTP cache when outdated
destradaa56b47f82015-07-24 10:56:18 -0700957 boolean refreshSuccess = true;
Kevin Tang40e1baf2012-01-10 14:32:44 -0800958 if (mNtpTime.getCacheAge() >= NTP_INTERVAL) {
destradaa56b47f82015-07-24 10:56:18 -0700959 refreshSuccess = mNtpTime.forceRefresh();
Kevin Tang40e1baf2012-01-10 14:32:44 -0800960 }
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400961
Kevin Tang40e1baf2012-01-10 14:32:44 -0800962 // only update when NTP time is fresh
963 if (mNtpTime.getCacheAge() < NTP_INTERVAL) {
964 long time = mNtpTime.getCachedNtpTime();
965 long timeReference = mNtpTime.getCachedNtpTimeReference();
966 long certainty = mNtpTime.getCacheCertainty();
967 long now = System.currentTimeMillis();
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400968
Joe Onorato0c484102016-02-01 18:04:24 -0800969 if (DEBUG) {
970 Log.d(TAG, "NTP server returned: "
971 + time + " (" + new Date(time)
972 + ") reference: " + timeReference
973 + " certainty: " + certainty
974 + " system time offset: " + (time - now));
975 }
Kevin Tang40e1baf2012-01-10 14:32:44 -0800976
977 native_inject_time(time, timeReference, (int) certainty);
978 delay = NTP_INTERVAL;
Wei Liu6f6326b2015-06-24 23:47:50 -0700979 mNtpBackOff.reset();
Kevin Tang40e1baf2012-01-10 14:32:44 -0800980 } else {
destradaa56b47f82015-07-24 10:56:18 -0700981 Log.e(TAG, "requestTime failed");
Wei Liu6f6326b2015-06-24 23:47:50 -0700982 delay = mNtpBackOff.nextBackoffMillis();
Kevin Tang40e1baf2012-01-10 14:32:44 -0800983 }
984
Jeff Brown028872f2012-08-25 13:07:01 -0700985 sendMessage(INJECT_NTP_TIME_FINISHED, 0, null);
Kevin Tang40e1baf2012-01-10 14:32:44 -0800986
destradaa56b47f82015-07-24 10:56:18 -0700987 if (DEBUG) {
988 String message = String.format(
989 "onDemandTimeInjection=%s, refreshSuccess=%s, delay=%s",
990 mOnDemandTimeInjection,
991 refreshSuccess,
992 delay);
993 Log.d(TAG, message);
994 }
995 if (mOnDemandTimeInjection || !refreshSuccess) {
Kevin Tang40e1baf2012-01-10 14:32:44 -0800996 // send delayed message for next NTP injection
997 // since this is delayed and not urgent we do not hold a wake lock here
Jeff Brown028872f2012-08-25 13:07:01 -0700998 mHandler.sendEmptyMessageDelayed(INJECT_NTP_TIME, delay);
Kevin Tang40e1baf2012-01-10 14:32:44 -0800999 }
Jeff Brown028872f2012-08-25 13:07:01 -07001000
1001 // release wake lock held by task
1002 mWakeLock.release();
Lifu Tangcbd2a142016-06-22 10:57:55 -07001003 Log.i(TAG, "WakeLock released by handleInjectNtpTime()");
Kevin Tang40e1baf2012-01-10 14:32:44 -08001004 }
1005 });
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001006 }
1007
1008 private void handleDownloadXtraData() {
Wyatt Riley0d6e54e22016-10-05 12:03:03 -07001009 if (!mSupportsXtra) {
1010 // native code reports xtra not supported, don't try
1011 Log.d(TAG, "handleDownloadXtraData() called when Xtra not supported");
1012 return;
1013 }
Kevin Tang40e1baf2012-01-10 14:32:44 -08001014 if (mDownloadXtraDataPending == STATE_DOWNLOADING) {
1015 // already downloading data
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001016 return;
1017 }
destradaae21252a2015-09-08 12:32:59 -07001018 if (!isDataNetworkConnected()) {
Kevin Tang40e1baf2012-01-10 14:32:44 -08001019 // try again when network is up
1020 mDownloadXtraDataPending = STATE_PENDING_NETWORK;
1021 return;
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001022 }
Kevin Tang40e1baf2012-01-10 14:32:44 -08001023 mDownloadXtraDataPending = STATE_DOWNLOADING;
1024
Jeff Brown028872f2012-08-25 13:07:01 -07001025 // hold wake lock while task runs
1026 mWakeLock.acquire();
Lifu Tangcbd2a142016-06-22 10:57:55 -07001027 Log.i(TAG, "WakeLock acquired by handleDownloadXtraData()");
Kevin Tang40e1baf2012-01-10 14:32:44 -08001028 AsyncTask.THREAD_POOL_EXECUTOR.execute(new Runnable() {
1029 @Override
1030 public void run() {
Andreas Gampedfdc6ac2014-10-28 20:42:53 -07001031 GpsXtraDownloader xtraDownloader = new GpsXtraDownloader(mProperties);
Kevin Tang40e1baf2012-01-10 14:32:44 -08001032 byte[] data = xtraDownloader.downloadXtraData();
1033 if (data != null) {
destradaae21252a2015-09-08 12:32:59 -07001034 if (DEBUG) Log.d(TAG, "calling native_inject_xtra_data");
Kevin Tang40e1baf2012-01-10 14:32:44 -08001035 native_inject_xtra_data(data, data.length);
Wei Liu6f6326b2015-06-24 23:47:50 -07001036 mXtraBackOff.reset();
Kevin Tang40e1baf2012-01-10 14:32:44 -08001037 }
1038
Jeff Brown028872f2012-08-25 13:07:01 -07001039 sendMessage(DOWNLOAD_XTRA_DATA_FINISHED, 0, null);
Kevin Tang40e1baf2012-01-10 14:32:44 -08001040
1041 if (data == null) {
1042 // try again later
1043 // since this is delayed and not urgent we do not hold a wake lock here
Wei Liu6f6326b2015-06-24 23:47:50 -07001044 mHandler.sendEmptyMessageDelayed(DOWNLOAD_XTRA_DATA,
1045 mXtraBackOff.nextBackoffMillis());
Kevin Tang40e1baf2012-01-10 14:32:44 -08001046 }
Kevin Tang40e1baf2012-01-10 14:32:44 -08001047
Jeff Brown028872f2012-08-25 13:07:01 -07001048 // release wake lock held by task
1049 mWakeLock.release();
Lifu Tangcbd2a142016-06-22 10:57:55 -07001050 Log.i(TAG, "WakeLock released by handleDownloadXtraData()");
Jeff Brown028872f2012-08-25 13:07:01 -07001051 }
Kevin Tang40e1baf2012-01-10 14:32:44 -08001052 });
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001053 }
1054
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001055 private void handleUpdateLocation(Location location) {
Mike Lockwoodd26ce0d2009-06-11 12:25:46 -04001056 if (location.hasAccuracy()) {
1057 native_inject_location(location.getLatitude(), location.getLongitude(),
1058 location.getAccuracy());
1059 }
Mike Lockwoodfd6e5f02009-05-21 11:28:20 -04001060 }
1061
1062 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001063 * Enables this provider. When enabled, calls to getStatus()
Mike Lockwood4e50b782009-04-03 08:24:43 -07001064 * must be handled. Hardware may be started up
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001065 * when the provider is enabled.
1066 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001067 @Override
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001068 public void enable() {
Laurent Tu7b5aeca2013-01-24 15:10:24 -08001069 synchronized (mLock) {
1070 if (mEnabled) return;
1071 mEnabled = true;
1072 }
1073
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001074 sendMessage(ENABLE, 1, null);
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001075 }
1076
Tsuwei Chen52617bb2014-08-25 11:49:11 -07001077 private void setSuplHostPort(String hostString, String portString) {
1078 if (hostString != null) {
1079 mSuplServerHost = hostString;
1080 }
1081 if (portString != null) {
1082 try {
1083 mSuplServerPort = Integer.parseInt(portString);
1084 } catch (NumberFormatException e) {
1085 Log.e(TAG, "unable to parse SUPL_PORT: " + portString);
1086 }
1087 }
Tsuwei Chen678c13c2014-09-22 17:48:41 -07001088 if (mSuplServerHost != null
1089 && mSuplServerPort > TCP_MIN_PORT
1090 && mSuplServerPort <= TCP_MAX_PORT) {
1091 native_set_agps_server(AGPS_TYPE_SUPL, mSuplServerHost, mSuplServerPort);
1092 }
Tsuwei Chen52617bb2014-08-25 11:49:11 -07001093 }
1094
Tsuwei Chen462bcd82014-09-17 12:28:49 -07001095 /**
1096 * Checks what SUPL mode to use, according to the AGPS mode as well as the
1097 * allowed mode from properties.
1098 *
1099 * @param properties GPS properties
1100 * @param agpsEnabled whether AGPS is enabled by settings value
1101 * @param singleShot whether "singleshot" is needed
1102 * @return SUPL mode (MSA vs MSB vs STANDALONE)
1103 */
1104 private int getSuplMode(Properties properties, boolean agpsEnabled, boolean singleShot) {
1105 if (agpsEnabled) {
1106 String modeString = properties.getProperty("SUPL_MODE");
1107 int suplMode = 0;
1108 if (!TextUtils.isEmpty(modeString)) {
1109 try {
1110 suplMode = Integer.parseInt(modeString);
1111 } catch (NumberFormatException e) {
1112 Log.e(TAG, "unable to parse SUPL_MODE: " + modeString);
1113 return GPS_POSITION_MODE_STANDALONE;
1114 }
1115 }
destradaabfb3bdb2015-04-29 14:42:35 -07001116 // MS-Based is the preferred mode for Assisted-GPS position computation, so we favor
1117 // such mode when it is available
1118 if (hasCapability(GPS_CAPABILITY_MSB) && (suplMode & AGPS_SUPL_MODE_MSB) != 0) {
1119 return GPS_POSITION_MODE_MS_BASED;
1120 }
1121 // for now, just as the legacy code did, we fallback to MS-Assisted if it is available,
1122 // do fallback only for single-shot requests, because it is too expensive to do for
1123 // periodic requests as well
Tsuwei Chen462bcd82014-09-17 12:28:49 -07001124 if (singleShot
1125 && hasCapability(GPS_CAPABILITY_MSA)
1126 && (suplMode & AGPS_SUPL_MODE_MSA) != 0) {
1127 return GPS_POSITION_MODE_MS_ASSISTED;
Tsuwei Chen462bcd82014-09-17 12:28:49 -07001128 }
1129 }
1130 return GPS_POSITION_MODE_STANDALONE;
1131 }
1132
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001133 private void handleEnable() {
1134 if (DEBUG) Log.d(TAG, "handleEnable");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001135
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001136 boolean enabled = native_init();
1137
1138 if (enabled) {
Mike Lockwood1a1cd3a2010-08-17 07:42:54 -04001139 mSupportsXtra = native_supports_xtra();
Tsuwei Chen678c13c2014-09-22 17:48:41 -07001140
1141 // TODO: remove the following native calls if we can make sure they are redundant.
Mike Lockwood734d6032009-07-28 18:30:25 -07001142 if (mSuplServerHost != null) {
1143 native_set_agps_server(AGPS_TYPE_SUPL, mSuplServerHost, mSuplServerPort);
1144 }
1145 if (mC2KServerHost != null) {
1146 native_set_agps_server(AGPS_TYPE_C2K, mC2KServerHost, mC2KServerPort);
1147 }
destradaa13a60b02015-01-15 18:36:01 -08001148
Lifu Tang818aa2c2016-02-01 01:52:00 -08001149 mGnssMeasurementsProvider.onGpsEnabledChanged();
1150 mGnssNavigationMessageProvider.onGpsEnabledChanged();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001151 } else {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001152 synchronized (mLock) {
1153 mEnabled = false;
1154 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001155 Log.w(TAG, "Failed to enable location provider");
1156 }
1157 }
1158
1159 /**
1160 * Disables this provider. When disabled, calls to getStatus()
Mike Lockwood4e50b782009-04-03 08:24:43 -07001161 * need not be handled. Hardware may be shut
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001162 * down while the provider is disabled.
1163 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001164 @Override
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001165 public void disable() {
Laurent Tu7b5aeca2013-01-24 15:10:24 -08001166 synchronized (mLock) {
1167 if (!mEnabled) return;
1168 mEnabled = false;
1169 }
1170
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001171 sendMessage(ENABLE, 0, null);
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001172 }
1173
1174 private void handleDisable() {
Mike Lockwood89096312010-03-24 10:14:55 -04001175 if (DEBUG) Log.d(TAG, "handleDisable");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001176
David Christie3bc26142013-12-19 14:53:44 -08001177 updateClientUids(new WorkSource());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001178 stopNavigating();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001179 mAlarmManager.cancel(mWakeupIntent);
1180 mAlarmManager.cancel(mTimeoutIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001181
Mike Lockwoodcf1d8cb2010-01-20 10:14:54 -05001182 // do this before releasing wakelock
1183 native_cleanup();
destradaa13a60b02015-01-15 18:36:01 -08001184
Lifu Tang818aa2c2016-02-01 01:52:00 -08001185 mGnssMeasurementsProvider.onGpsEnabledChanged();
1186 mGnssNavigationMessageProvider.onGpsEnabledChanged();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001187 }
1188
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001189 @Override
Mike Lockwoodd03ff942010-02-09 08:46:14 -05001190 public boolean isEnabled() {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001191 synchronized (mLock) {
1192 return mEnabled;
1193 }
Mike Lockwoodd03ff942010-02-09 08:46:14 -05001194 }
1195
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001196 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001197 public int getStatus(Bundle extras) {
1198 if (extras != null) {
1199 extras.putInt("satellites", mSvCount);
1200 }
1201 return mStatus;
1202 }
1203
1204 private void updateStatus(int status, int svCount) {
1205 if (status != mStatus || svCount != mSvCount) {
1206 mStatus = status;
1207 mSvCount = svCount;
1208 mLocationExtras.putInt("satellites", svCount);
1209 mStatusUpdateTime = SystemClock.elapsedRealtime();
1210 }
1211 }
1212
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001213 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001214 public long getStatusUpdateTime() {
1215 return mStatusUpdateTime;
1216 }
1217
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001218 @Override
1219 public void setRequest(ProviderRequest request, WorkSource source) {
1220 sendMessage(SET_REQUEST, 0, new GpsRequest(request, source));
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001221 }
1222
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001223 private void handleSetRequest(ProviderRequest request, WorkSource source) {
David Christied4edf4c2014-08-12 15:22:27 -07001224 mProviderRequest = request;
1225 mWorkSource = source;
1226 updateRequirements();
1227 }
1228
1229 // Called when the requirements for GPS may have changed
1230 private void updateRequirements() {
1231 if (mProviderRequest == null || mWorkSource == null) {
1232 return;
1233 }
1234
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001235 boolean singleShot = false;
1236
1237 // see if the request is for a single update
David Christied4edf4c2014-08-12 15:22:27 -07001238 if (mProviderRequest.locationRequests != null
1239 && mProviderRequest.locationRequests.size() > 0) {
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001240 // if any request has zero or more than one updates
1241 // requested, then this is not single-shot mode
1242 singleShot = true;
1243
David Christied4edf4c2014-08-12 15:22:27 -07001244 for (LocationRequest lr : mProviderRequest.locationRequests) {
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001245 if (lr.getNumUpdates() != 1) {
1246 singleShot = false;
1247 }
1248 }
1249 }
1250
David Christied4edf4c2014-08-12 15:22:27 -07001251 if (DEBUG) Log.d(TAG, "setRequest " + mProviderRequest);
Dante Russo260d6672016-06-20 11:11:59 -07001252 if (mProviderRequest.reportLocation && !mDisableGps && isEnabled()) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001253 // update client uids
David Christied4edf4c2014-08-12 15:22:27 -07001254 updateClientUids(mWorkSource);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001255
David Christied4edf4c2014-08-12 15:22:27 -07001256 mFixInterval = (int) mProviderRequest.interval;
Mike Lockwood03ca2162010-04-01 08:10:09 -07001257
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001258 // check for overflow
David Christied4edf4c2014-08-12 15:22:27 -07001259 if (mFixInterval != mProviderRequest.interval) {
1260 Log.w(TAG, "interval overflow: " + mProviderRequest.interval);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001261 mFixInterval = Integer.MAX_VALUE;
1262 }
Mike Lockwood03ca2162010-04-01 08:10:09 -07001263
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001264 // apply request to GPS engine
Mike Lockwood04598b62010-04-14 17:17:24 -04001265 if (mStarted && hasCapability(GPS_CAPABILITY_SCHEDULING)) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001266 // change period
Mike Lockwood04598b62010-04-14 17:17:24 -04001267 if (!native_set_position_mode(mPositionMode, GPS_POSITION_RECURRENCE_PERIODIC,
1268 mFixInterval, 0, 0)) {
1269 Log.e(TAG, "set_position_mode failed in setMinTime()");
1270 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001271 } else if (!mStarted) {
1272 // start GPS
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001273 startNavigating(singleShot);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001274 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001275 } else {
Dianne Hackborn002a54e2013-01-10 17:34:55 -08001276 updateClientUids(new WorkSource());
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001277
1278 stopNavigating();
1279 mAlarmManager.cancel(mWakeupIntent);
1280 mAlarmManager.cancel(mTimeoutIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001281 }
1282 }
1283
Dianne Hackborn002a54e2013-01-10 17:34:55 -08001284 private void updateClientUids(WorkSource source) {
1285 // Update work source.
1286 WorkSource[] changes = mClientSource.setReturningDiffs(source);
Victoria Leaseea78b852013-01-15 10:39:28 -08001287 if (changes == null) {
1288 return;
1289 }
Dianne Hackborn002a54e2013-01-10 17:34:55 -08001290 WorkSource newWork = changes[0];
1291 WorkSource goneWork = changes[1];
1292
1293 // Update sources that were not previously tracked.
1294 if (newWork != null) {
1295 int lastuid = -1;
1296 for (int i=0; i<newWork.size(); i++) {
Dianne Hackborn2e418422009-06-22 20:00:17 -07001297 try {
Dianne Hackborn002a54e2013-01-10 17:34:55 -08001298 int uid = newWork.get(i);
Dianne Hackborne98f5db2013-07-17 17:23:25 -07001299 mAppOpsService.startOperation(AppOpsManager.getToken(mAppOpsService),
1300 AppOpsManager.OP_GPS, uid, newWork.getName(i));
Dianne Hackborn002a54e2013-01-10 17:34:55 -08001301 if (uid != lastuid) {
1302 lastuid = uid;
1303 mBatteryStats.noteStartGps(uid);
1304 }
Dianne Hackborn2e418422009-06-22 20:00:17 -07001305 } catch (RemoteException e) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001306 Log.w(TAG, "RemoteException", e);
1307 }
1308 }
1309 }
1310
Dianne Hackborn002a54e2013-01-10 17:34:55 -08001311 // Update sources that are no longer tracked.
1312 if (goneWork != null) {
1313 int lastuid = -1;
1314 for (int i=0; i<goneWork.size(); i++) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001315 try {
Dianne Hackborn002a54e2013-01-10 17:34:55 -08001316 int uid = goneWork.get(i);
Dianne Hackborne98f5db2013-07-17 17:23:25 -07001317 mAppOpsService.finishOperation(AppOpsManager.getToken(mAppOpsService),
1318 AppOpsManager.OP_GPS, uid, goneWork.getName(i));
Dianne Hackborn002a54e2013-01-10 17:34:55 -08001319 if (uid != lastuid) {
1320 lastuid = uid;
1321 mBatteryStats.noteStopGps(uid);
1322 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001323 } catch (RemoteException e) {
1324 Log.w(TAG, "RemoteException", e);
Dianne Hackborn2e418422009-06-22 20:00:17 -07001325 }
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001326 }
1327 }
1328 }
1329
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001330 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001331 public boolean sendExtraCommand(String command, Bundle extras) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001332
Mike Lockwood63aa5a62010-04-14 19:21:31 -04001333 long identity = Binder.clearCallingIdentity();
1334 boolean result = false;
1335
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001336 if ("delete_aiding_data".equals(command)) {
Mike Lockwood63aa5a62010-04-14 19:21:31 -04001337 result = deleteAidingData(extras);
1338 } else if ("force_time_injection".equals(command)) {
destradaae21252a2015-09-08 12:32:59 -07001339 requestUtcTime();
Mike Lockwood63aa5a62010-04-14 19:21:31 -04001340 result = true;
1341 } else if ("force_xtra_injection".equals(command)) {
Mike Lockwood1a1cd3a2010-08-17 07:42:54 -04001342 if (mSupportsXtra) {
Mike Lockwood93bc44d2009-05-20 16:58:22 -04001343 xtraDownloadRequest();
Mike Lockwood63aa5a62010-04-14 19:21:31 -04001344 result = true;
Mike Lockwood93bc44d2009-05-20 16:58:22 -04001345 }
Mike Lockwood63aa5a62010-04-14 19:21:31 -04001346 } else {
1347 Log.w(TAG, "sendExtraCommand: unknown command " + command);
Mike Lockwood93bc44d2009-05-20 16:58:22 -04001348 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001349
Mike Lockwood63aa5a62010-04-14 19:21:31 -04001350 Binder.restoreCallingIdentity(identity);
1351 return result;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001352 }
1353
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001354 private IGpsGeofenceHardware mGpsGeofenceBinder = new IGpsGeofenceHardware.Stub() {
1355 public boolean isHardwareGeofenceSupported() {
1356 return native_is_geofence_supported();
1357 }
1358
1359 public boolean addCircularHardwareGeofence(int geofenceId, double latitude,
1360 double longitude, double radius, int lastTransition, int monitorTransitions,
1361 int notificationResponsiveness, int unknownTimer) {
1362 return native_add_geofence(geofenceId, latitude, longitude, radius,
1363 lastTransition, monitorTransitions, notificationResponsiveness, unknownTimer);
1364 }
1365
1366 public boolean removeHardwareGeofence(int geofenceId) {
1367 return native_remove_geofence(geofenceId);
1368 }
1369
1370 public boolean pauseHardwareGeofence(int geofenceId) {
1371 return native_pause_geofence(geofenceId);
1372 }
1373
1374 public boolean resumeHardwareGeofence(int geofenceId, int monitorTransition) {
1375 return native_resume_geofence(geofenceId, monitorTransition);
1376 }
1377 };
1378
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001379 private boolean deleteAidingData(Bundle extras) {
1380 int flags;
1381
1382 if (extras == null) {
1383 flags = GPS_DELETE_ALL;
1384 } else {
1385 flags = 0;
1386 if (extras.getBoolean("ephemeris")) flags |= GPS_DELETE_EPHEMERIS;
1387 if (extras.getBoolean("almanac")) flags |= GPS_DELETE_ALMANAC;
1388 if (extras.getBoolean("position")) flags |= GPS_DELETE_POSITION;
1389 if (extras.getBoolean("time")) flags |= GPS_DELETE_TIME;
1390 if (extras.getBoolean("iono")) flags |= GPS_DELETE_IONO;
1391 if (extras.getBoolean("utc")) flags |= GPS_DELETE_UTC;
1392 if (extras.getBoolean("health")) flags |= GPS_DELETE_HEALTH;
1393 if (extras.getBoolean("svdir")) flags |= GPS_DELETE_SVDIR;
1394 if (extras.getBoolean("svsteer")) flags |= GPS_DELETE_SVSTEER;
1395 if (extras.getBoolean("sadata")) flags |= GPS_DELETE_SADATA;
1396 if (extras.getBoolean("rti")) flags |= GPS_DELETE_RTI;
1397 if (extras.getBoolean("celldb-info")) flags |= GPS_DELETE_CELLDB_INFO;
1398 if (extras.getBoolean("all")) flags |= GPS_DELETE_ALL;
1399 }
1400
1401 if (flags != 0) {
1402 native_delete_aiding_data(flags);
1403 return true;
1404 }
1405
1406 return false;
1407 }
1408
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001409 private void startNavigating(boolean singleShot) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001410 if (!mStarted) {
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001411 if (DEBUG) Log.d(TAG, "startNavigating, singleShot is " + singleShot);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001412 mTimeToFirstFix = 0;
1413 mLastFixTime = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001414 mStarted = true;
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001415 mSingleShot = singleShot;
Mike Lockwood03ca2162010-04-01 08:10:09 -07001416 mPositionMode = GPS_POSITION_MODE_STANDALONE;
1417
Tsuwei Chen462bcd82014-09-17 12:28:49 -07001418 boolean agpsEnabled =
1419 (Settings.Global.getInt(mContext.getContentResolver(),
1420 Settings.Global.ASSISTED_GPS_ENABLED, 1) != 0);
1421 mPositionMode = getSuplMode(mProperties, agpsEnabled, singleShot);
Mike Lockwoodbcab8df2009-06-25 16:39:09 -04001422
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001423 if (DEBUG) {
1424 String mode;
1425
1426 switch(mPositionMode) {
1427 case GPS_POSITION_MODE_STANDALONE:
1428 mode = "standalone";
1429 break;
1430 case GPS_POSITION_MODE_MS_ASSISTED:
1431 mode = "MS_ASSISTED";
1432 break;
1433 case GPS_POSITION_MODE_MS_BASED:
1434 mode = "MS_BASED";
1435 break;
1436 default:
1437 mode = "unknown";
1438 break;
1439 }
1440 Log.d(TAG, "setting position_mode to " + mode);
1441 }
1442
Mike Lockwood04598b62010-04-14 17:17:24 -04001443 int interval = (hasCapability(GPS_CAPABILITY_SCHEDULING) ? mFixInterval : 1000);
1444 if (!native_set_position_mode(mPositionMode, GPS_POSITION_RECURRENCE_PERIODIC,
1445 interval, 0, 0)) {
1446 mStarted = false;
1447 Log.e(TAG, "set_position_mode failed in startNavigating()");
1448 return;
1449 }
1450 if (!native_start()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001451 mStarted = false;
1452 Log.e(TAG, "native_start failed in startNavigating()");
Mike Lockwood0632ca72009-05-14 15:51:03 -04001453 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001454 }
1455
1456 // reset SV count to zero
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001457 updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, 0);
Mike Lockwood29c84342009-05-06 14:01:15 -04001458 mFixRequestTime = System.currentTimeMillis();
Mike Lockwood04598b62010-04-14 17:17:24 -04001459 if (!hasCapability(GPS_CAPABILITY_SCHEDULING)) {
1460 // set timer to give up if we do not receive a fix within NO_FIX_TIMEOUT
1461 // and our fix interval is not short
1462 if (mFixInterval >= NO_FIX_TIMEOUT) {
1463 mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
1464 SystemClock.elapsedRealtime() + NO_FIX_TIMEOUT, mTimeoutIntent);
1465 }
Mike Lockwood0632ca72009-05-14 15:51:03 -04001466 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001467 }
1468 }
1469
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001470 private void stopNavigating() {
Mike Lockwood29c84342009-05-06 14:01:15 -04001471 if (DEBUG) Log.d(TAG, "stopNavigating");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001472 if (mStarted) {
1473 mStarted = false;
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001474 mSingleShot = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001475 native_stop();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001476 mTimeToFirstFix = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001477 mLastFixTime = 0;
1478 mLocationFlags = LOCATION_INVALID;
1479
1480 // reset SV count to zero
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001481 updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001482 }
1483 }
1484
Mike Lockwood0632ca72009-05-14 15:51:03 -04001485 private void hibernate() {
1486 // stop GPS until our next fix interval arrives
1487 stopNavigating();
Mike Lockwood0632ca72009-05-14 15:51:03 -04001488 mAlarmManager.cancel(mTimeoutIntent);
1489 mAlarmManager.cancel(mWakeupIntent);
1490 long now = SystemClock.elapsedRealtime();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001491 mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, now + mFixInterval, mWakeupIntent);
Mike Lockwood04598b62010-04-14 17:17:24 -04001492 }
1493
1494 private boolean hasCapability(int capability) {
1495 return ((mEngineCapabilities & capability) != 0);
Mike Lockwood0632ca72009-05-14 15:51:03 -04001496 }
1497
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001498
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001499 /**
1500 * called from native code to update our position.
1501 */
1502 private void reportLocation(int flags, double latitude, double longitude, double altitude,
1503 float speed, float bearing, float accuracy, long timestamp) {
Mike Lockwood29c84342009-05-06 14:01:15 -04001504 if (VERBOSE) Log.v(TAG, "reportLocation lat: " + latitude + " long: " + longitude +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001505 " timestamp: " + timestamp);
1506
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001507 synchronized (mLocation) {
1508 mLocationFlags = flags;
1509 if ((flags & LOCATION_HAS_LAT_LONG) == LOCATION_HAS_LAT_LONG) {
1510 mLocation.setLatitude(latitude);
1511 mLocation.setLongitude(longitude);
1512 mLocation.setTime(timestamp);
Nick Pelly2eeeec22012-07-18 13:13:37 -07001513 // It would be nice to push the elapsed real-time timestamp
1514 // further down the stack, but this is still useful
Philip Milne41180122012-09-26 11:29:25 -07001515 mLocation.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001516 }
1517 if ((flags & LOCATION_HAS_ALTITUDE) == LOCATION_HAS_ALTITUDE) {
1518 mLocation.setAltitude(altitude);
1519 } else {
1520 mLocation.removeAltitude();
1521 }
1522 if ((flags & LOCATION_HAS_SPEED) == LOCATION_HAS_SPEED) {
1523 mLocation.setSpeed(speed);
1524 } else {
1525 mLocation.removeSpeed();
1526 }
1527 if ((flags & LOCATION_HAS_BEARING) == LOCATION_HAS_BEARING) {
1528 mLocation.setBearing(bearing);
1529 } else {
1530 mLocation.removeBearing();
1531 }
1532 if ((flags & LOCATION_HAS_ACCURACY) == LOCATION_HAS_ACCURACY) {
1533 mLocation.setAccuracy(accuracy);
1534 } else {
1535 mLocation.removeAccuracy();
1536 }
Sean Barbeauced2b2c2011-12-19 04:43:07 -05001537 mLocation.setExtras(mLocationExtras);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001538
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001539 try {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001540 mILocationManager.reportLocation(mLocation, false);
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001541 } catch (RemoteException e) {
1542 Log.e(TAG, "RemoteException calling reportLocation");
1543 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001544 }
1545
Hakan Gustavssonfa94ff02010-02-23 09:12:38 +01001546 mLastFixTime = System.currentTimeMillis();
1547 // report time to first fix
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001548 if (mTimeToFirstFix == 0 && (flags & LOCATION_HAS_LAT_LONG) == LOCATION_HAS_LAT_LONG) {
1549 mTimeToFirstFix = (int)(mLastFixTime - mFixRequestTime);
1550 if (DEBUG) Log.d(TAG, "TTFF: " + mTimeToFirstFix);
Hakan Gustavssonfa94ff02010-02-23 09:12:38 +01001551
1552 // notify status listeners
destradaaea8a8a62014-06-23 18:19:03 -07001553 mListenerHelper.onFirstFix(mTimeToFirstFix);
Hakan Gustavssonfa94ff02010-02-23 09:12:38 +01001554 }
1555
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001556 if (mSingleShot) {
1557 stopNavigating();
1558 }
1559
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001560 if (mStarted && mStatus != LocationProvider.AVAILABLE) {
Mike Lockwoodd53ba012010-04-15 20:41:26 -04001561 // we want to time out if we do not receive a fix
Mike Lockwoodb7be5442010-02-24 14:34:50 -05001562 // within the time out and we are requesting infrequent fixes
Mike Lockwood04598b62010-04-14 17:17:24 -04001563 if (!hasCapability(GPS_CAPABILITY_SCHEDULING) && mFixInterval < NO_FIX_TIMEOUT) {
Mike Lockwoodb7be5442010-02-24 14:34:50 -05001564 mAlarmManager.cancel(mTimeoutIntent);
1565 }
1566
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001567 // send an intent to notify that the GPS is receiving fixes.
Mike Lockwood00b74272010-03-26 10:41:48 -04001568 Intent intent = new Intent(LocationManager.GPS_FIX_CHANGE_ACTION);
1569 intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, true);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07001570 mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001571 updateStatus(LocationProvider.AVAILABLE, mSvCount);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001572 }
Mike Lockwood29c84342009-05-06 14:01:15 -04001573
Nick Pellyb041f232012-05-07 17:12:25 -07001574 if (!hasCapability(GPS_CAPABILITY_SCHEDULING) && mStarted &&
1575 mFixInterval > GPS_POLLING_THRESHOLD_INTERVAL) {
Mike Lockwoodd53ba012010-04-15 20:41:26 -04001576 if (DEBUG) Log.d(TAG, "got fix, hibernating");
Mike Lockwood0632ca72009-05-14 15:51:03 -04001577 hibernate();
Mike Lockwood29c84342009-05-06 14:01:15 -04001578 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001579 }
1580
1581 /**
1582 * called from native code to update our status
1583 */
1584 private void reportStatus(int status) {
Mike Lockwoodb8d90332010-10-18 17:59:48 -04001585 if (DEBUG) Log.v(TAG, "reportStatus status: " + status);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001586
destradaaea8a8a62014-06-23 18:19:03 -07001587 boolean wasNavigating = mNavigating;
1588 switch (status) {
1589 case GPS_STATUS_SESSION_BEGIN:
1590 mNavigating = true;
1591 mEngineOn = true;
1592 break;
1593 case GPS_STATUS_SESSION_END:
1594 mNavigating = false;
1595 break;
1596 case GPS_STATUS_ENGINE_ON:
1597 mEngineOn = true;
1598 break;
1599 case GPS_STATUS_ENGINE_OFF:
1600 mEngineOn = false;
1601 mNavigating = false;
1602 break;
1603 }
Mike Lockwooddbd6fd82009-12-07 18:43:36 -05001604
destradaaea8a8a62014-06-23 18:19:03 -07001605 if (wasNavigating != mNavigating) {
destradaa13a60b02015-01-15 18:36:01 -08001606 mListenerHelper.onStatusChanged(mNavigating);
Mike Lockwoodcf1d8cb2010-01-20 10:14:54 -05001607
destradaaea8a8a62014-06-23 18:19:03 -07001608 // send an intent to notify that the GPS has been enabled or disabled
1609 Intent intent = new Intent(LocationManager.GPS_ENABLED_CHANGE_ACTION);
1610 intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, mNavigating);
1611 mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001612 }
1613 }
1614
1615 /**
1616 * called from native code to update SV info
1617 */
1618 private void reportSvStatus() {
Lifu Tang76a620f2016-02-26 19:53:01 -08001619 int svCount = native_read_sv_status(mSvidWithFlags, mCn0s, mSvElevations, mSvAzimuths);
destradaaea8a8a62014-06-23 18:19:03 -07001620 mListenerHelper.onSvStatusChanged(
1621 svCount,
Lifu Tang120480f2016-02-07 18:08:19 -08001622 mSvidWithFlags,
Lifu Tang76a620f2016-02-26 19:53:01 -08001623 mCn0s,
destradaaea8a8a62014-06-23 18:19:03 -07001624 mSvElevations,
Lifu Tang120480f2016-02-07 18:08:19 -08001625 mSvAzimuths);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001626
Mike Lockwood29c84342009-05-06 14:01:15 -04001627 if (VERBOSE) {
Lifu Tang30f95a72016-01-07 23:20:38 -08001628 Log.v(TAG, "SV count: " + svCount);
1629 }
1630 // Calculate number of sets used in fix.
1631 int usedInFixCount = 0;
1632 for (int i = 0; i < svCount; i++) {
Lifu Tang120480f2016-02-07 18:08:19 -08001633 if ((mSvidWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_USED_IN_FIX) != 0) {
Lifu Tang30f95a72016-01-07 23:20:38 -08001634 ++usedInFixCount;
1635 }
1636 if (VERBOSE) {
Lifu Tang120480f2016-02-07 18:08:19 -08001637 Log.v(TAG, "svid: " + (mSvidWithFlags[i] >> GnssStatus.SVID_SHIFT_WIDTH) +
Lifu Tang76a620f2016-02-26 19:53:01 -08001638 " cn0: " + mCn0s[i]/10 +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001639 " elev: " + mSvElevations[i] +
1640 " azimuth: " + mSvAzimuths[i] +
Lifu Tang120480f2016-02-07 18:08:19 -08001641 ((mSvidWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_HAS_EPHEMERIS_DATA) == 0
Lifu Tang30f95a72016-01-07 23:20:38 -08001642 ? " " : " E") +
Lifu Tang120480f2016-02-07 18:08:19 -08001643 ((mSvidWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_HAS_ALMANAC_DATA) == 0
Lifu Tang30f95a72016-01-07 23:20:38 -08001644 ? " " : " A") +
Lifu Tang120480f2016-02-07 18:08:19 -08001645 ((mSvidWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_USED_IN_FIX) == 0
Lifu Tang30f95a72016-01-07 23:20:38 -08001646 ? "" : "U"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001647 }
1648 }
Kevin.KY Tsai0881f4f2010-05-21 15:10:39 -04001649 // return number of sets used in fix instead of total
Lifu Tang30f95a72016-01-07 23:20:38 -08001650 updateStatus(mStatus, usedInFixCount);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001651
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001652 if (mNavigating && mStatus == LocationProvider.AVAILABLE && mLastFixTime > 0 &&
Mike Lockwood04598b62010-04-14 17:17:24 -04001653 System.currentTimeMillis() - mLastFixTime > RECENT_FIX_TIMEOUT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001654 // send an intent to notify that the GPS is no longer receiving fixes.
Mike Lockwood00b74272010-03-26 10:41:48 -04001655 Intent intent = new Intent(LocationManager.GPS_FIX_CHANGE_ACTION);
1656 intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, false);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07001657 mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001658 updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, mSvCount);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001659 }
1660 }
Mike Lockwood58bda982009-04-14 16:25:07 -04001661
1662 /**
Mike Lockwoode3635c92009-05-11 08:38:02 -04001663 * called from native code to update AGPS status
Mike Lockwood58bda982009-04-14 16:25:07 -04001664 */
destradaa96a14702014-06-05 11:36:30 -07001665 private void reportAGpsStatus(int type, int status, byte[] ipaddr) {
Mike Lockwood58bda982009-04-14 16:25:07 -04001666 switch (status) {
Mike Lockwoode3635c92009-05-11 08:38:02 -04001667 case GPS_REQUEST_AGPS_DATA_CONN:
Mike Lockwoodb6e5fa82010-10-09 20:10:46 -04001668 if (DEBUG) Log.d(TAG, "GPS_REQUEST_AGPS_DATA_CONN");
Andreas Gampee6748ce2015-12-11 18:00:38 -08001669 Log.v(TAG, "Received SUPL IP addr[]: " + Arrays.toString(ipaddr));
destradaae21252a2015-09-08 12:32:59 -07001670 InetAddress connectionIpAddress = null;
destradaa96a14702014-06-05 11:36:30 -07001671 if (ipaddr != null) {
1672 try {
destradaae21252a2015-09-08 12:32:59 -07001673 connectionIpAddress = InetAddress.getByAddress(ipaddr);
1674 if (DEBUG) Log.d(TAG, "IP address converted to: " + connectionIpAddress);
destradaa96a14702014-06-05 11:36:30 -07001675 } catch (UnknownHostException e) {
1676 Log.e(TAG, "Bad IP Address: " + ipaddr, e);
destradaa96a14702014-06-05 11:36:30 -07001677 }
1678 }
destradaae21252a2015-09-08 12:32:59 -07001679 sendMessage(REQUEST_SUPL_CONNECTION, 0 /*arg*/, connectionIpAddress);
Mike Lockwood58bda982009-04-14 16:25:07 -04001680 break;
Mike Lockwoode3635c92009-05-11 08:38:02 -04001681 case GPS_RELEASE_AGPS_DATA_CONN:
Mike Lockwoodb6e5fa82010-10-09 20:10:46 -04001682 if (DEBUG) Log.d(TAG, "GPS_RELEASE_AGPS_DATA_CONN");
destradaae21252a2015-09-08 12:32:59 -07001683 releaseSuplConnection(GPS_RELEASE_AGPS_DATA_CONN);
Mike Lockwood58bda982009-04-14 16:25:07 -04001684 break;
Mike Lockwoode3635c92009-05-11 08:38:02 -04001685 case GPS_AGPS_DATA_CONNECTED:
Mike Lockwoodb6e5fa82010-10-09 20:10:46 -04001686 if (DEBUG) Log.d(TAG, "GPS_AGPS_DATA_CONNECTED");
Mike Lockwood58bda982009-04-14 16:25:07 -04001687 break;
Mike Lockwoode3635c92009-05-11 08:38:02 -04001688 case GPS_AGPS_DATA_CONN_DONE:
Mike Lockwoodb6e5fa82010-10-09 20:10:46 -04001689 if (DEBUG) Log.d(TAG, "GPS_AGPS_DATA_CONN_DONE");
Mike Lockwood58bda982009-04-14 16:25:07 -04001690 break;
Mike Lockwoode3635c92009-05-11 08:38:02 -04001691 case GPS_AGPS_DATA_CONN_FAILED:
Mike Lockwoodb6e5fa82010-10-09 20:10:46 -04001692 if (DEBUG) Log.d(TAG, "GPS_AGPS_DATA_CONN_FAILED");
Mike Lockwood58bda982009-04-14 16:25:07 -04001693 break;
destradaa931a37f2014-08-12 16:36:59 -07001694 default:
Joe Onorato0c484102016-02-01 18:04:24 -08001695 if (DEBUG) Log.d(TAG, "Received Unknown AGPS status: " + status);
Mike Lockwood58bda982009-04-14 16:25:07 -04001696 }
1697 }
1698
destradaae21252a2015-09-08 12:32:59 -07001699 private void releaseSuplConnection(int connStatus) {
1700 sendMessage(RELEASE_SUPL_CONNECTION, connStatus, null /*obj*/);
1701 }
1702
Mike Lockwoodb16e7802009-08-06 09:26:02 -04001703 /**
1704 * called from native code to report NMEA data received
1705 */
Mike Lockwoodf602d362010-06-20 14:28:16 -07001706 private void reportNmea(long timestamp) {
destradaaea8a8a62014-06-23 18:19:03 -07001707 int length = native_read_nmea(mNmeaBuffer, mNmeaBuffer.length);
1708 String nmea = new String(mNmeaBuffer, 0 /* offset */, length);
1709 mListenerHelper.onNmeaReceived(timestamp, nmea);
1710 }
Mike Lockwoodb16e7802009-08-06 09:26:02 -04001711
destradaaea8a8a62014-06-23 18:19:03 -07001712 /**
destradaa4b3e3932014-07-21 18:01:47 -07001713 * called from native code - Gps measurements callback
destradaaea8a8a62014-06-23 18:19:03 -07001714 */
Lifu Tang818aa2c2016-02-01 01:52:00 -08001715 private void reportMeasurementData(GnssMeasurementsEvent event) {
1716 mGnssMeasurementsProvider.onMeasurementsAvailable(event);
Mike Lockwoodb16e7802009-08-06 09:26:02 -04001717 }
1718
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001719 /**
destradaa4b3e3932014-07-21 18:01:47 -07001720 * called from native code - GPS navigation message callback
1721 */
Lifu Tange8abe8e2016-04-01 10:32:05 -07001722 private void reportNavigationMessage(GnssNavigationMessage event) {
Lifu Tang818aa2c2016-02-01 01:52:00 -08001723 mGnssNavigationMessageProvider.onNavigationMessageAvailable(event);
destradaa4b3e3932014-07-21 18:01:47 -07001724 }
1725
1726 /**
Mike Lockwood04598b62010-04-14 17:17:24 -04001727 * called from native code to inform us what the GPS engine capabilities are
1728 */
1729 private void setEngineCapabilities(int capabilities) {
1730 mEngineCapabilities = capabilities;
Mike Lockwood9b9fb5c2011-06-29 15:09:40 -04001731
destradaa56b47f82015-07-24 10:56:18 -07001732 if (hasCapability(GPS_CAPABILITY_ON_DEMAND_TIME)) {
1733 mOnDemandTimeInjection = true;
Mike Lockwood9b9fb5c2011-06-29 15:09:40 -04001734 requestUtcTime();
1735 }
destradaa6568d702014-10-27 12:47:41 -07001736
Lifu Tang818aa2c2016-02-01 01:52:00 -08001737 mGnssMeasurementsProvider.onCapabilitiesUpdated(
destradaa6568d702014-10-27 12:47:41 -07001738 (capabilities & GPS_CAPABILITY_MEASUREMENTS) == GPS_CAPABILITY_MEASUREMENTS);
Lifu Tang818aa2c2016-02-01 01:52:00 -08001739 mGnssNavigationMessageProvider.onCapabilitiesUpdated(
destradaa6568d702014-10-27 12:47:41 -07001740 (capabilities & GPS_CAPABILITY_NAV_MESSAGES) == GPS_CAPABILITY_NAV_MESSAGES);
Mike Lockwood04598b62010-04-14 17:17:24 -04001741 }
1742
1743 /**
Lifu Tang82f893d2016-01-21 18:15:33 -08001744 * Called from native code to inform us the hardware information.
1745 */
Lifu Tang9363b942016-02-16 18:07:00 -08001746 private void setGnssYearOfHardware(int yearOfHardware) {
1747 if (DEBUG) Log.d(TAG, "setGnssYearOfHardware called with " + yearOfHardware);
Lifu Tang82f893d2016-01-21 18:15:33 -08001748 mYearOfHardware = yearOfHardware;
1749 }
1750
Lifu Tang9363b942016-02-16 18:07:00 -08001751 public interface GnssSystemInfoProvider {
Lifu Tang82f893d2016-01-21 18:15:33 -08001752 /**
1753 * Returns the year of GPS hardware.
1754 */
Lifu Tang9363b942016-02-16 18:07:00 -08001755 int getGnssYearOfHardware();
Lifu Tang82f893d2016-01-21 18:15:33 -08001756 }
1757
1758 /**
1759 * @hide
1760 */
Lifu Tang9363b942016-02-16 18:07:00 -08001761 public GnssSystemInfoProvider getGnssSystemInfoProvider() {
1762 return new GnssSystemInfoProvider() {
Lifu Tang82f893d2016-01-21 18:15:33 -08001763 @Override
Lifu Tang9363b942016-02-16 18:07:00 -08001764 public int getGnssYearOfHardware() {
Lifu Tang82f893d2016-01-21 18:15:33 -08001765 return mYearOfHardware;
1766 }
1767 };
1768 }
1769
1770 /**
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001771 * called from native code to request XTRA data
1772 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001773 private void xtraDownloadRequest() {
Joe Onoratof5d95cb2010-01-07 21:48:32 -05001774 if (DEBUG) Log.d(TAG, "xtraDownloadRequest");
Mike Lockwood98e48692010-04-07 16:32:51 -04001775 sendMessage(DOWNLOAD_XTRA_DATA, 0, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001776 }
1777
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001778 /**
destradaa0682809a2013-08-12 18:50:30 -07001779 * Helper method to construct a location object.
1780 */
1781 private Location buildLocation(
1782 int flags,
1783 double latitude,
1784 double longitude,
1785 double altitude,
1786 float speed,
1787 float bearing,
1788 float accuracy,
1789 long timestamp) {
1790 Location location = new Location(LocationManager.GPS_PROVIDER);
1791 if((flags & LOCATION_HAS_LAT_LONG) == LOCATION_HAS_LAT_LONG) {
1792 location.setLatitude(latitude);
1793 location.setLongitude(longitude);
1794 location.setTime(timestamp);
1795 location.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());
1796 }
1797 if((flags & LOCATION_HAS_ALTITUDE) == LOCATION_HAS_ALTITUDE) {
1798 location.setAltitude(altitude);
1799 }
1800 if((flags & LOCATION_HAS_SPEED) == LOCATION_HAS_SPEED) {
1801 location.setSpeed(speed);
1802 }
1803 if((flags & LOCATION_HAS_BEARING) == LOCATION_HAS_BEARING) {
1804 location.setBearing(bearing);
1805 }
1806 if((flags & LOCATION_HAS_ACCURACY) == LOCATION_HAS_ACCURACY) {
1807 location.setAccuracy(accuracy);
1808 }
1809 return location;
1810 }
1811
1812 /**
1813 * Converts the GPS HAL status to the internal Geofence Hardware status.
1814 */
1815 private int getGeofenceStatus(int status) {
1816 switch(status) {
1817 case GPS_GEOFENCE_OPERATION_SUCCESS:
1818 return GeofenceHardware.GEOFENCE_SUCCESS;
1819 case GPS_GEOFENCE_ERROR_GENERIC:
1820 return GeofenceHardware.GEOFENCE_FAILURE;
1821 case GPS_GEOFENCE_ERROR_ID_EXISTS:
1822 return GeofenceHardware.GEOFENCE_ERROR_ID_EXISTS;
1823 case GPS_GEOFENCE_ERROR_INVALID_TRANSITION:
1824 return GeofenceHardware.GEOFENCE_ERROR_INVALID_TRANSITION;
1825 case GPS_GEOFENCE_ERROR_TOO_MANY_GEOFENCES:
1826 return GeofenceHardware.GEOFENCE_ERROR_TOO_MANY_GEOFENCES;
1827 case GPS_GEOFENCE_ERROR_ID_UNKNOWN:
1828 return GeofenceHardware.GEOFENCE_ERROR_ID_UNKNOWN;
1829 default:
1830 return -1;
1831 }
1832 }
1833
1834 /**
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001835 * Called from native to report GPS Geofence transition
1836 * All geofence callbacks are called on the same thread
1837 */
1838 private void reportGeofenceTransition(int geofenceId, int flags, double latitude,
1839 double longitude, double altitude, float speed, float bearing, float accuracy,
1840 long timestamp, int transition, long transitionTimestamp) {
1841 if (mGeofenceHardwareImpl == null) {
1842 mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
1843 }
destradaa0682809a2013-08-12 18:50:30 -07001844 Location location = buildLocation(
1845 flags,
1846 latitude,
1847 longitude,
1848 altitude,
1849 speed,
1850 bearing,
1851 accuracy,
1852 timestamp);
1853 mGeofenceHardwareImpl.reportGeofenceTransition(
1854 geofenceId,
1855 location,
1856 transition,
1857 transitionTimestamp,
1858 GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE,
1859 FusedBatchOptions.SourceTechnologies.GNSS);
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001860 }
1861
1862 /**
1863 * called from native code to report GPS status change.
1864 */
1865 private void reportGeofenceStatus(int status, int flags, double latitude,
1866 double longitude, double altitude, float speed, float bearing, float accuracy,
1867 long timestamp) {
1868 if (mGeofenceHardwareImpl == null) {
1869 mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
1870 }
destradaa0682809a2013-08-12 18:50:30 -07001871 Location location = buildLocation(
1872 flags,
1873 latitude,
1874 longitude,
1875 altitude,
1876 speed,
1877 bearing,
1878 accuracy,
1879 timestamp);
1880 int monitorStatus = GeofenceHardware.MONITOR_CURRENTLY_UNAVAILABLE;
1881 if(status == GPS_GEOFENCE_AVAILABLE) {
1882 monitorStatus = GeofenceHardware.MONITOR_CURRENTLY_AVAILABLE;
1883 }
1884 mGeofenceHardwareImpl.reportGeofenceMonitorStatus(
1885 GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE,
1886 monitorStatus,
1887 location,
1888 FusedBatchOptions.SourceTechnologies.GNSS);
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001889 }
1890
1891 /**
1892 * called from native code - Geofence Add callback
1893 */
1894 private void reportGeofenceAddStatus(int geofenceId, int status) {
1895 if (mGeofenceHardwareImpl == null) {
1896 mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
1897 }
destradaa0682809a2013-08-12 18:50:30 -07001898 mGeofenceHardwareImpl.reportGeofenceAddStatus(geofenceId, getGeofenceStatus(status));
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001899 }
1900
1901 /**
1902 * called from native code - Geofence Remove callback
1903 */
1904 private void reportGeofenceRemoveStatus(int geofenceId, int status) {
1905 if (mGeofenceHardwareImpl == null) {
1906 mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
1907 }
destradaa0682809a2013-08-12 18:50:30 -07001908 mGeofenceHardwareImpl.reportGeofenceRemoveStatus(geofenceId, getGeofenceStatus(status));
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001909 }
1910
1911 /**
1912 * called from native code - Geofence Pause callback
1913 */
1914 private void reportGeofencePauseStatus(int geofenceId, int status) {
1915 if (mGeofenceHardwareImpl == null) {
1916 mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
1917 }
destradaa0682809a2013-08-12 18:50:30 -07001918 mGeofenceHardwareImpl.reportGeofencePauseStatus(geofenceId, getGeofenceStatus(status));
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001919 }
1920
1921 /**
1922 * called from native code - Geofence Resume callback
1923 */
1924 private void reportGeofenceResumeStatus(int geofenceId, int status) {
1925 if (mGeofenceHardwareImpl == null) {
1926 mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
1927 }
destradaa0682809a2013-08-12 18:50:30 -07001928 mGeofenceHardwareImpl.reportGeofenceResumeStatus(geofenceId, getGeofenceStatus(status));
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001929 }
1930
Danke Xie22d1f9f2009-08-18 18:28:45 -04001931 //=============================================================
1932 // NI Client support
Miguel Torroja1e84da82010-07-27 07:02:24 +02001933 //=============================================================
Danke Xie22d1f9f2009-08-18 18:28:45 -04001934 private final INetInitiatedListener mNetInitiatedListener = new INetInitiatedListener.Stub() {
destradaaef752b62015-04-17 13:10:47 -07001935 // Sends a response for an NI request to HAL.
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001936 @Override
Miguel Torroja1e84da82010-07-27 07:02:24 +02001937 public boolean sendNiResponse(int notificationId, int userResponse)
1938 {
1939 // TODO Add Permission check
Danke Xie22d1f9f2009-08-18 18:28:45 -04001940
Miguel Torroja1e84da82010-07-27 07:02:24 +02001941 if (DEBUG) Log.d(TAG, "sendNiResponse, notifId: " + notificationId +
1942 ", response: " + userResponse);
1943 native_send_ni_response(notificationId, userResponse);
1944 return true;
1945 }
Danke Xie22d1f9f2009-08-18 18:28:45 -04001946 };
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001947
Danke Xie22d1f9f2009-08-18 18:28:45 -04001948 public INetInitiatedListener getNetInitiatedListener() {
1949 return mNetInitiatedListener;
1950 }
1951
1952 // Called by JNI function to report an NI request.
Miguel Torroja1e84da82010-07-27 07:02:24 +02001953 public void reportNiNotification(
1954 int notificationId,
1955 int niType,
1956 int notifyFlags,
1957 int timeout,
1958 int defaultResponse,
1959 String requestorId,
1960 String text,
1961 int requestorIdEncoding,
1962 int textEncoding,
1963 String extras // Encoded extra data
Danke Xie22d1f9f2009-08-18 18:28:45 -04001964 )
Miguel Torroja1e84da82010-07-27 07:02:24 +02001965 {
1966 Log.i(TAG, "reportNiNotification: entered");
1967 Log.i(TAG, "notificationId: " + notificationId +
1968 ", niType: " + niType +
1969 ", notifyFlags: " + notifyFlags +
1970 ", timeout: " + timeout +
1971 ", defaultResponse: " + defaultResponse);
1972
1973 Log.i(TAG, "requestorId: " + requestorId +
1974 ", text: " + text +
1975 ", requestorIdEncoding: " + requestorIdEncoding +
1976 ", textEncoding: " + textEncoding);
1977
1978 GpsNiNotification notification = new GpsNiNotification();
1979
1980 notification.notificationId = notificationId;
1981 notification.niType = niType;
1982 notification.needNotify = (notifyFlags & GpsNetInitiatedHandler.GPS_NI_NEED_NOTIFY) != 0;
1983 notification.needVerify = (notifyFlags & GpsNetInitiatedHandler.GPS_NI_NEED_VERIFY) != 0;
1984 notification.privacyOverride = (notifyFlags & GpsNetInitiatedHandler.GPS_NI_PRIVACY_OVERRIDE) != 0;
1985 notification.timeout = timeout;
1986 notification.defaultResponse = defaultResponse;
1987 notification.requestorId = requestorId;
1988 notification.text = text;
1989 notification.requestorIdEncoding = requestorIdEncoding;
1990 notification.textEncoding = textEncoding;
1991
1992 // Process extras, assuming the format is
1993 // one of more lines of "key = value"
1994 Bundle bundle = new Bundle();
1995
1996 if (extras == null) extras = "";
1997 Properties extraProp = new Properties();
1998
1999 try {
Jeff Sharkey104344e2011-07-10 14:20:41 -07002000 extraProp.load(new StringReader(extras));
Miguel Torroja1e84da82010-07-27 07:02:24 +02002001 }
2002 catch (IOException e)
2003 {
2004 Log.e(TAG, "reportNiNotification cannot parse extras data: " + extras);
2005 }
2006
2007 for (Entry<Object, Object> ent : extraProp.entrySet())
2008 {
2009 bundle.putString((String) ent.getKey(), (String) ent.getValue());
2010 }
2011
2012 notification.extras = bundle;
2013
2014 mNIHandler.handleNiNotification(notification);
2015 }
2016
2017 /**
2018 * Called from native code to request set id info.
2019 * We should be careful about receiving null string from the TelephonyManager,
2020 * because sending null String to JNI function would cause a crash.
2021 */
2022
2023 private void requestSetID(int flags) {
2024 TelephonyManager phone = (TelephonyManager)
2025 mContext.getSystemService(Context.TELEPHONY_SERVICE);
destradaaef752b62015-04-17 13:10:47 -07002026 int type = AGPS_SETID_TYPE_NONE;
Miguel Torroja1e84da82010-07-27 07:02:24 +02002027 String data = "";
2028
2029 if ((flags & AGPS_RIL_REQUEST_SETID_IMSI) == AGPS_RIL_REQUEST_SETID_IMSI) {
2030 String data_temp = phone.getSubscriberId();
2031 if (data_temp == null) {
2032 // This means the framework does not have the SIM card ready.
2033 } else {
2034 // This means the framework has the SIM card.
2035 data = data_temp;
2036 type = AGPS_SETID_TYPE_IMSI;
2037 }
2038 }
2039 else if ((flags & AGPS_RIL_REQUEST_SETID_MSISDN) == AGPS_RIL_REQUEST_SETID_MSISDN) {
2040 String data_temp = phone.getLine1Number();
2041 if (data_temp == null) {
2042 // This means the framework does not have the SIM card ready.
2043 } else {
2044 // This means the framework has the SIM card.
2045 data = data_temp;
2046 type = AGPS_SETID_TYPE_MSISDN;
2047 }
2048 }
2049 native_agps_set_id(type, data);
2050 }
2051
2052 /**
Mike Lockwood9b9fb5c2011-06-29 15:09:40 -04002053 * Called from native code to request utc time info
2054 */
Mike Lockwood9b9fb5c2011-06-29 15:09:40 -04002055 private void requestUtcTime() {
destradaae21252a2015-09-08 12:32:59 -07002056 if (DEBUG) Log.d(TAG, "utcTimeRequest");
Mike Lockwood9b9fb5c2011-06-29 15:09:40 -04002057 sendMessage(INJECT_NTP_TIME, 0, null);
2058 }
2059
2060 /**
Miguel Torroja1e84da82010-07-27 07:02:24 +02002061 * Called from native code to request reference location info
2062 */
2063
2064 private void requestRefLocation(int flags) {
2065 TelephonyManager phone = (TelephonyManager)
2066 mContext.getSystemService(Context.TELEPHONY_SERVICE);
Victoria Leased50d0c32012-10-29 13:16:17 -07002067 final int phoneType = phone.getPhoneType();
2068 if (phoneType == TelephonyManager.PHONE_TYPE_GSM) {
Miguel Torroja1e84da82010-07-27 07:02:24 +02002069 GsmCellLocation gsm_cell = (GsmCellLocation) phone.getCellLocation();
Victoria Leased50d0c32012-10-29 13:16:17 -07002070 if ((gsm_cell != null) && (phone.getNetworkOperator() != null)
2071 && (phone.getNetworkOperator().length() > 3)) {
Miguel Torroja1e84da82010-07-27 07:02:24 +02002072 int type;
2073 int mcc = Integer.parseInt(phone.getNetworkOperator().substring(0,3));
2074 int mnc = Integer.parseInt(phone.getNetworkOperator().substring(3));
Mike Lockwoodedc0f3872010-10-22 09:16:17 -04002075 int networkType = phone.getNetworkType();
2076 if (networkType == TelephonyManager.NETWORK_TYPE_UMTS
2077 || networkType == TelephonyManager.NETWORK_TYPE_HSDPA
2078 || networkType == TelephonyManager.NETWORK_TYPE_HSUPA
Arun Ravindran58d46122012-07-30 17:50:21 +03002079 || networkType == TelephonyManager.NETWORK_TYPE_HSPA
2080 || networkType == TelephonyManager.NETWORK_TYPE_HSPAP) {
Miguel Torroja1e84da82010-07-27 07:02:24 +02002081 type = AGPS_REF_LOCATION_TYPE_UMTS_CELLID;
Mike Lockwoodedc0f3872010-10-22 09:16:17 -04002082 } else {
Miguel Torroja1e84da82010-07-27 07:02:24 +02002083 type = AGPS_REF_LOCATION_TYPE_GSM_CELLID;
Mike Lockwoodedc0f3872010-10-22 09:16:17 -04002084 }
Miguel Torroja1e84da82010-07-27 07:02:24 +02002085 native_agps_set_ref_location_cellid(type, mcc, mnc,
2086 gsm_cell.getLac(), gsm_cell.getCid());
Mike Lockwoodedc0f3872010-10-22 09:16:17 -04002087 } else {
Miguel Torroja1e84da82010-07-27 07:02:24 +02002088 Log.e(TAG,"Error getting cell location info.");
Mike Lockwoodedc0f3872010-10-22 09:16:17 -04002089 }
Victoria Leased50d0c32012-10-29 13:16:17 -07002090 } else if (phoneType == TelephonyManager.PHONE_TYPE_CDMA) {
2091 Log.e(TAG, "CDMA not supported.");
Mike Lockwoodedc0f3872010-10-22 09:16:17 -04002092 }
Miguel Torroja1e84da82010-07-27 07:02:24 +02002093 }
Danke Xie22d1f9f2009-08-18 18:28:45 -04002094
Mike Lockwood98e48692010-04-07 16:32:51 -04002095 private void sendMessage(int message, int arg, Object obj) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002096 // hold a wake lock until this message is delivered
Jeff Brown028872f2012-08-25 13:07:01 -07002097 // note that this assumes the message will not be removed from the queue before
2098 // it is handled (otherwise the wake lock would be leaked).
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002099 mWakeLock.acquire();
Lifu Tangcbd2a142016-06-22 10:57:55 -07002100 Log.i(TAG, "WakeLock acquired by sendMessage(" + message + ", " + arg + ", " + obj + ")");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002101 mHandler.obtainMessage(message, arg, 1, obj).sendToTarget();
Mike Lockwood98e48692010-04-07 16:32:51 -04002102 }
2103
Mike Lockwood62a8fc12010-03-22 14:23:26 -04002104 private final class ProviderHandler extends Handler {
Victoria Lease5cd731a2012-12-19 15:04:21 -08002105 public ProviderHandler(Looper looper) {
2106 super(looper, null, true /*async*/);
Jeff Brown028872f2012-08-25 13:07:01 -07002107 }
2108
Mike Lockwood62a8fc12010-03-22 14:23:26 -04002109 @Override
Mike Lockwood4a7b65e2010-10-25 16:35:55 -04002110 public void handleMessage(Message msg) {
Mike Lockwood98e48692010-04-07 16:32:51 -04002111 int message = msg.what;
2112 switch (message) {
Mike Lockwood62a8fc12010-03-22 14:23:26 -04002113 case ENABLE:
2114 if (msg.arg1 == 1) {
2115 handleEnable();
2116 } else {
2117 handleDisable();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002118 }
Mike Lockwood62a8fc12010-03-22 14:23:26 -04002119 break;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002120 case SET_REQUEST:
2121 GpsRequest gpsRequest = (GpsRequest) msg.obj;
2122 handleSetRequest(gpsRequest.request, gpsRequest.source);
Mike Lockwood03ca2162010-04-01 08:10:09 -07002123 break;
Mike Lockwood62a8fc12010-03-22 14:23:26 -04002124 case UPDATE_NETWORK_STATE:
destradaae21252a2015-09-08 12:32:59 -07002125 handleUpdateNetworkState((Network) msg.obj);
2126 break;
2127 case REQUEST_SUPL_CONNECTION:
2128 handleRequestSuplConnection((InetAddress) msg.obj);
2129 break;
2130 case RELEASE_SUPL_CONNECTION:
2131 handleReleaseSuplConnection(msg.arg1);
Mike Lockwood62a8fc12010-03-22 14:23:26 -04002132 break;
2133 case INJECT_NTP_TIME:
2134 handleInjectNtpTime();
2135 break;
2136 case DOWNLOAD_XTRA_DATA:
Wyatt Riley0d6e54e22016-10-05 12:03:03 -07002137 handleDownloadXtraData();
Mike Lockwood62a8fc12010-03-22 14:23:26 -04002138 break;
Kevin Tang40e1baf2012-01-10 14:32:44 -08002139 case INJECT_NTP_TIME_FINISHED:
2140 mInjectNtpTimePending = STATE_IDLE;
2141 break;
2142 case DOWNLOAD_XTRA_DATA_FINISHED:
2143 mDownloadXtraDataPending = STATE_IDLE;
2144 break;
Mike Lockwood62a8fc12010-03-22 14:23:26 -04002145 case UPDATE_LOCATION:
destradaae21252a2015-09-08 12:32:59 -07002146 handleUpdateLocation((Location) msg.obj);
Mike Lockwood62a8fc12010-03-22 14:23:26 -04002147 break;
destradaafb23c672015-04-16 14:01:27 -07002148 case SUBSCRIPTION_OR_SIM_CHANGED:
2149 subscriptionOrSimChanged(mContext);
2150 break;
2151 case INITIALIZE_HANDLER:
destradaae21252a2015-09-08 12:32:59 -07002152 handleInitialize();
destradaafb23c672015-04-16 14:01:27 -07002153 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002154 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002155 if (msg.arg2 == 1) {
2156 // wakelock was taken for this message, release it
2157 mWakeLock.release();
Lifu Tangcbd2a142016-06-22 10:57:55 -07002158 Log.i(TAG, "WakeLock released by handleMessage(" + message + ", " + msg.arg1 + ", "
2159 + msg.obj + ")");
Mike Lockwood98e48692010-04-07 16:32:51 -04002160 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002161 }
destradaafb23c672015-04-16 14:01:27 -07002162
2163 /**
Lifu Tang30f95a72016-01-07 23:20:38 -08002164 * This method is bound to {@link #GnssLocationProvider(Context, ILocationManager, Looper)}.
destradaafb23c672015-04-16 14:01:27 -07002165 * It is in charge of loading properties and registering for events that will be posted to
2166 * this handler.
2167 */
destradaae21252a2015-09-08 12:32:59 -07002168 private void handleInitialize() {
destradaafb23c672015-04-16 14:01:27 -07002169 // load default GPS configuration
2170 // (this configuration might change in the future based on SIM changes)
2171 reloadGpsProperties(mContext, mProperties);
2172
2173 // TODO: When this object "finishes" we should unregister by invoking
2174 // SubscriptionManager.getInstance(mContext).unregister(mOnSubscriptionsChangedListener);
2175 // This is not strictly necessary because it will be unregistered if the
2176 // notification fails but it is good form.
2177
2178 // Register for SubscriptionInfo list changes which is guaranteed
2179 // to invoke onSubscriptionsChanged the first time.
2180 SubscriptionManager.from(mContext)
2181 .addOnSubscriptionsChangedListener(mOnSubscriptionsChangedListener);
2182
2183 // listen for events
destradaaef752b62015-04-17 13:10:47 -07002184 IntentFilter intentFilter;
2185 if (native_is_agps_ril_supported()) {
2186 intentFilter = new IntentFilter();
2187 intentFilter.addAction(Intents.DATA_SMS_RECEIVED_ACTION);
2188 intentFilter.addDataScheme("sms");
2189 intentFilter.addDataAuthority("localhost", "7275");
2190 mContext.registerReceiver(mBroadcastReceiver, intentFilter, null, this);
destradaafb23c672015-04-16 14:01:27 -07002191
destradaaef752b62015-04-17 13:10:47 -07002192 intentFilter = new IntentFilter();
2193 intentFilter.addAction(Intents.WAP_PUSH_RECEIVED_ACTION);
2194 try {
2195 intentFilter.addDataType("application/vnd.omaloc-supl-init");
2196 } catch (IntentFilter.MalformedMimeTypeException e) {
2197 Log.w(TAG, "Malformed SUPL init mime type");
2198 }
2199 mContext.registerReceiver(mBroadcastReceiver, intentFilter, null, this);
2200 } else if (DEBUG) {
2201 Log.d(TAG, "Skipped registration for SMS/WAP-PUSH messages because AGPS Ril in GPS"
2202 + " HAL is not supported");
destradaafb23c672015-04-16 14:01:27 -07002203 }
destradaafb23c672015-04-16 14:01:27 -07002204
2205 intentFilter = new IntentFilter();
2206 intentFilter.addAction(ALARM_WAKEUP);
2207 intentFilter.addAction(ALARM_TIMEOUT);
destradaafb23c672015-04-16 14:01:27 -07002208 intentFilter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED);
Adam Lesinski87c17df2015-05-27 13:24:13 -07002209 intentFilter.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
destradaafb23c672015-04-16 14:01:27 -07002210 intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
2211 intentFilter.addAction(Intent.ACTION_SCREEN_ON);
2212 intentFilter.addAction(SIM_STATE_CHANGED);
2213 mContext.registerReceiver(mBroadcastReceiver, intentFilter, null, this);
2214
destradaae21252a2015-09-08 12:32:59 -07002215 // register for connectivity change events, this is equivalent to the deprecated way of
2216 // registering for CONNECTIVITY_ACTION broadcasts
2217 NetworkRequest.Builder networkRequestBuilder = new NetworkRequest.Builder();
2218 networkRequestBuilder.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
2219 networkRequestBuilder.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
2220 NetworkRequest networkRequest = networkRequestBuilder.build();
2221 mConnMgr.registerNetworkCallback(networkRequest, mNetworkConnectivityCallback);
2222
destradaafb23c672015-04-16 14:01:27 -07002223 // listen for PASSIVE_PROVIDER updates
2224 LocationManager locManager =
2225 (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
2226 long minTime = 0;
2227 float minDistance = 0;
2228 boolean oneShot = false;
2229 LocationRequest request = LocationRequest.createFromDeprecatedProvider(
2230 LocationManager.PASSIVE_PROVIDER,
2231 minTime,
2232 minDistance,
2233 oneShot);
2234 // Don't keep track of this request since it's done on behalf of other clients
2235 // (which are kept track of separately).
2236 request.setHideFromAppOps(true);
2237 locManager.requestLocationUpdates(
2238 request,
2239 new NetworkLocationListener(),
2240 getLooper());
2241 }
2242 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002243
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002244 private final class NetworkLocationListener implements LocationListener {
2245 @Override
2246 public void onLocationChanged(Location location) {
2247 // this callback happens on mHandler looper
2248 if (LocationManager.NETWORK_PROVIDER.equals(location.getProvider())) {
2249 handleUpdateLocation(location);
2250 }
2251 }
2252 @Override
2253 public void onStatusChanged(String provider, int status, Bundle extras) { }
2254 @Override
2255 public void onProviderEnabled(String provider) { }
2256 @Override
2257 public void onProviderDisabled(String provider) { }
2258 }
2259
Kevin Tanga5fe6b22011-06-05 14:25:16 -07002260 private String getSelectedApn() {
2261 Uri uri = Uri.parse("content://telephony/carriers/preferapn");
destradaa96a14702014-06-05 11:36:30 -07002262 Cursor cursor = null;
2263 try {
2264 cursor = mContext.getContentResolver().query(
2265 uri,
2266 new String[] { "apn" },
2267 null /* selection */,
2268 null /* selectionArgs */,
2269 Carriers.DEFAULT_SORT_ORDER);
2270 if (cursor != null && cursor.moveToFirst()) {
2271 return cursor.getString(0);
2272 } else {
2273 Log.e(TAG, "No APN found to select.");
2274 }
2275 } catch (Exception e) {
destradaaea8a8a62014-06-23 18:19:03 -07002276 Log.e(TAG, "Error encountered on selecting the APN.", e);
destradaa96a14702014-06-05 11:36:30 -07002277 } finally {
2278 if (cursor != null) {
Kevin Tanga5fe6b22011-06-05 14:25:16 -07002279 cursor.close();
2280 }
2281 }
destradaa96a14702014-06-05 11:36:30 -07002282
2283 return null;
2284 }
2285
2286 private int getApnIpType(String apn) {
destradaae21252a2015-09-08 12:32:59 -07002287 ensureInHandlerThread();
destradaa96a14702014-06-05 11:36:30 -07002288 if (apn == null) {
2289 return APN_INVALID;
2290 }
2291
destradaa96a14702014-06-05 11:36:30 -07002292 String selection = String.format("current = 1 and apn = '%s' and carrier_enabled = 1", apn);
2293 Cursor cursor = null;
2294 try {
2295 cursor = mContext.getContentResolver().query(
2296 Carriers.CONTENT_URI,
2297 new String[] { Carriers.PROTOCOL },
2298 selection,
2299 null,
2300 Carriers.DEFAULT_SORT_ORDER);
2301
2302 if (null != cursor && cursor.moveToFirst()) {
2303 return translateToApnIpType(cursor.getString(0), apn);
2304 } else {
2305 Log.e(TAG, "No entry found in query for APN: " + apn);
2306 }
2307 } catch (Exception e) {
2308 Log.e(TAG, "Error encountered on APN query for: " + apn, e);
2309 } finally {
2310 if (cursor != null) {
2311 cursor.close();
2312 }
2313 }
2314
2315 return APN_INVALID;
2316 }
2317
2318 private int translateToApnIpType(String ipProtocol, String apn) {
2319 if ("IP".equals(ipProtocol)) {
2320 return APN_IPV4;
2321 }
2322 if ("IPV6".equals(ipProtocol)) {
2323 return APN_IPV6;
2324 }
2325 if ("IPV4V6".equals(ipProtocol)) {
2326 return APN_IPV4V6;
2327 }
2328
2329 // we hit the default case so the ipProtocol is not recognized
2330 String message = String.format("Unknown IP Protocol: %s, for APN: %s", ipProtocol, apn);
2331 Log.e(TAG, message);
2332 return APN_INVALID;
2333 }
2334
2335 private void setRouting() {
2336 if (mAGpsDataConnectionIpAddr == null) {
2337 return;
2338 }
2339
destradaae21252a2015-09-08 12:32:59 -07002340 // TODO: replace the use of this deprecated API
destradaa96a14702014-06-05 11:36:30 -07002341 boolean result = mConnMgr.requestRouteToHostAddress(
2342 ConnectivityManager.TYPE_MOBILE_SUPL,
2343 mAGpsDataConnectionIpAddr);
2344
2345 if (!result) {
2346 Log.e(TAG, "Error requesting route to host: " + mAGpsDataConnectionIpAddr);
2347 } else if (DEBUG) {
2348 Log.d(TAG, "Successfully requested route to host: " + mAGpsDataConnectionIpAddr);
2349 }
Kevin Tanga5fe6b22011-06-05 14:25:16 -07002350 }
2351
destradaae21252a2015-09-08 12:32:59 -07002352 /**
2353 * @return {@code true} if there is a data network available for outgoing connections,
2354 * {@code false} otherwise.
2355 */
2356 private boolean isDataNetworkConnected() {
2357 NetworkInfo activeNetworkInfo = mConnMgr.getActiveNetworkInfo();
2358 return activeNetworkInfo != null && activeNetworkInfo.isConnected();
2359 }
2360
2361 /**
2362 * Ensures the calling function is running in the thread associated with {@link #mHandler}.
2363 */
2364 private void ensureInHandlerThread() {
2365 if (mHandler != null && Looper.myLooper() == mHandler.getLooper()) {
2366 return;
2367 }
2368 throw new RuntimeException("This method must run on the Handler thread.");
2369 }
2370
2371 /**
2372 * @return A string representing the current state stored in {@link #mAGpsDataConnectionState}.
2373 */
2374 private String agpsDataConnStateAsString() {
2375 switch(mAGpsDataConnectionState) {
2376 case AGPS_DATA_CONNECTION_CLOSED:
2377 return "CLOSED";
2378 case AGPS_DATA_CONNECTION_OPEN:
2379 return "OPEN";
2380 case AGPS_DATA_CONNECTION_OPENING:
2381 return "OPENING";
2382 default:
2383 return "<Unknown>";
2384 }
2385 }
2386
2387 /**
2388 * @return A string representing the given GPS_AGPS_DATA status.
2389 */
2390 private String agpsDataConnStatusAsString(int agpsDataConnStatus) {
2391 switch (agpsDataConnStatus) {
2392 case GPS_AGPS_DATA_CONNECTED:
2393 return "CONNECTED";
2394 case GPS_AGPS_DATA_CONN_DONE:
2395 return "DONE";
2396 case GPS_AGPS_DATA_CONN_FAILED:
2397 return "FAILED";
2398 case GPS_RELEASE_AGPS_DATA_CONN:
2399 return "RELEASE";
2400 case GPS_REQUEST_AGPS_DATA_CONN:
2401 return "REQUEST";
2402 default:
2403 return "<Unknown>";
2404 }
2405 }
2406
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002407 @Override
2408 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
2409 StringBuilder s = new StringBuilder();
destradaa25e8caf2015-08-24 14:14:44 -07002410 s.append(" mFixInterval=").append(mFixInterval).append('\n');
2411 s.append(" mDisableGps (battery saver mode)=").append(mDisableGps).append('\n');
2412 s.append(" mEngineCapabilities=0x").append(Integer.toHexString(mEngineCapabilities));
2413 s.append(" ( ");
2414 if (hasCapability(GPS_CAPABILITY_SCHEDULING)) s.append("SCHEDULING ");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002415 if (hasCapability(GPS_CAPABILITY_MSB)) s.append("MSB ");
2416 if (hasCapability(GPS_CAPABILITY_MSA)) s.append("MSA ");
2417 if (hasCapability(GPS_CAPABILITY_SINGLE_SHOT)) s.append("SINGLE_SHOT ");
2418 if (hasCapability(GPS_CAPABILITY_ON_DEMAND_TIME)) s.append("ON_DEMAND_TIME ");
destradaa25e8caf2015-08-24 14:14:44 -07002419 if (hasCapability(GPS_CAPABILITY_GEOFENCING)) s.append("GEOFENCING ");
2420 if (hasCapability(GPS_CAPABILITY_MEASUREMENTS)) s.append("MEASUREMENTS ");
2421 if (hasCapability(GPS_CAPABILITY_NAV_MESSAGES)) s.append("NAV_MESSAGES ");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002422 s.append(")\n");
2423
2424 s.append(native_get_internal_state());
2425 pw.append(s);
2426 }
2427
Wei Liu6f6326b2015-06-24 23:47:50 -07002428 /**
2429 * A simple implementation of exponential backoff.
2430 */
2431 private static final class BackOff {
2432 private static final int MULTIPLIER = 2;
2433 private final long mInitIntervalMillis;
2434 private final long mMaxIntervalMillis;
2435 private long mCurrentIntervalMillis;
2436
2437 public BackOff(long initIntervalMillis, long maxIntervalMillis) {
2438 mInitIntervalMillis = initIntervalMillis;
2439 mMaxIntervalMillis = maxIntervalMillis;
2440
2441 mCurrentIntervalMillis = mInitIntervalMillis / MULTIPLIER;
2442 }
2443
2444 public long nextBackoffMillis() {
2445 if (mCurrentIntervalMillis > mMaxIntervalMillis) {
2446 return mMaxIntervalMillis;
2447 }
2448
2449 mCurrentIntervalMillis *= MULTIPLIER;
2450 return mCurrentIntervalMillis;
2451 }
2452
2453 public void reset() {
2454 mCurrentIntervalMillis = mInitIntervalMillis / MULTIPLIER;
2455 }
2456 }
2457
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002458 // for GPS SV statistics
Lifu Tang120480f2016-02-07 18:08:19 -08002459 private static final int MAX_SVS = 64;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002460
2461 // preallocated arrays, to avoid memory allocation in reportStatus()
Lifu Tang120480f2016-02-07 18:08:19 -08002462 private int mSvidWithFlags[] = new int[MAX_SVS];
Lifu Tang76a620f2016-02-26 19:53:01 -08002463 private float mCn0s[] = new float[MAX_SVS];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002464 private float mSvElevations[] = new float[MAX_SVS];
2465 private float mSvAzimuths[] = new float[MAX_SVS];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002466 private int mSvCount;
Mike Lockwoodb16e7802009-08-06 09:26:02 -04002467 // preallocated to avoid memory allocation in reportNmea()
2468 private byte[] mNmeaBuffer = new byte[120];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002469
2470 static { class_init_native(); }
2471 private static native void class_init_native();
2472 private static native boolean native_is_supported();
destradaaef752b62015-04-17 13:10:47 -07002473 private static native boolean native_is_agps_ril_supported();
2474 private static native boolean native_is_gnss_configuration_supported();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002475
2476 private native boolean native_init();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002477 private native void native_cleanup();
Mike Lockwood04598b62010-04-14 17:17:24 -04002478 private native boolean native_set_position_mode(int mode, int recurrence, int min_interval,
2479 int preferred_accuracy, int preferred_time);
2480 private native boolean native_start();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002481 private native boolean native_stop();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002482 private native void native_delete_aiding_data(int flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002483 // returns number of SVs
2484 // mask[0] is ephemeris mask and mask[1] is almanac mask
Lifu Tang76a620f2016-02-26 19:53:01 -08002485 private native int native_read_sv_status(int[] prnWithFlags, float[] cn0s, float[] elevations,
Lifu Tang120480f2016-02-07 18:08:19 -08002486 float[] azimuths);
Mike Lockwoodf602d362010-06-20 14:28:16 -07002487 private native int native_read_nmea(byte[] buffer, int bufferSize);
Mike Lockwoodd26ce0d2009-06-11 12:25:46 -04002488 private native void native_inject_location(double latitude, double longitude, float accuracy);
2489
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -06002490 // XTRA Support
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002491 private native void native_inject_time(long time, long timeReference, int uncertainty);
2492 private native boolean native_supports_xtra();
2493 private native void native_inject_xtra_data(byte[] data, int length);
The Android Open Source Project10592532009-03-18 17:39:46 -07002494
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -06002495 // DEBUG Support
2496 private native String native_get_internal_state();
2497
2498 // AGPS Support
destradaa96a14702014-06-05 11:36:30 -07002499 private native void native_agps_data_conn_open(String apn, int apnIpType);
Mike Lockwoode3635c92009-05-11 08:38:02 -04002500 private native void native_agps_data_conn_closed();
2501 private native void native_agps_data_conn_failed();
Miguel Torroja1e84da82010-07-27 07:02:24 +02002502 private native void native_agps_ni_message(byte [] msg, int length);
Mike Lockwooda9e54612009-06-19 14:54:42 -04002503 private native void native_set_agps_server(int type, String hostname, int port);
Danke Xie22d1f9f2009-08-18 18:28:45 -04002504
2505 // Network-initiated (NI) Support
2506 private native void native_send_ni_response(int notificationId, int userResponse);
Miguel Torroja1e84da82010-07-27 07:02:24 +02002507
2508 // AGPS ril suport
2509 private native void native_agps_set_ref_location_cellid(int type, int mcc, int mnc,
2510 int lac, int cid);
2511 private native void native_agps_set_id(int type, String setid);
Mike Lockwood50130bb2010-10-11 06:22:50 -04002512
2513 private native void native_update_network_state(boolean connected, int type,
Kevin Tanga5fe6b22011-06-05 14:25:16 -07002514 boolean roaming, boolean available, String extraInfo, String defaultAPN);
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07002515
2516 // Hardware Geofence support.
2517 private static native boolean native_is_geofence_supported();
2518 private static native boolean native_add_geofence(int geofenceId, double latitude,
2519 double longitude, double radius, int lastTransition,int monitorTransitions,
2520 int notificationResponsivenes, int unknownTimer);
2521 private static native boolean native_remove_geofence(int geofenceId);
2522 private static native boolean native_resume_geofence(int geofenceId, int transitions);
2523 private static native boolean native_pause_geofence(int geofenceId);
destradaaea8a8a62014-06-23 18:19:03 -07002524
2525 // Gps Hal measurements support.
2526 private static native boolean native_is_measurement_supported();
destradaa4b3e3932014-07-21 18:01:47 -07002527 private native boolean native_start_measurement_collection();
2528 private native boolean native_stop_measurement_collection();
2529
2530 // Gps Navigation message support.
2531 private static native boolean native_is_navigation_message_supported();
2532 private native boolean native_start_navigation_message_collection();
2533 private native boolean native_stop_navigation_message_collection();
Tsuwei Chen52617bb2014-08-25 11:49:11 -07002534
2535 // GNSS Configuration
2536 private static native void native_configuration_update(String configData);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002537}