blob: 9798e56237e541cd532a5788bd38fd6b4c7426b0 [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;
destradaaea8a8a62014-06-23 18:19:03 -070041import android.location.GpsMeasurementsEvent;
destradaa4b3e3932014-07-21 18:01:47 -070042import android.location.GpsNavigationMessageEvent;
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;
destradaa6568d702014-10-27 12:47:41 -0700371 private final GpsMeasurementsProvider mGpsMeasurementsProvider;
372 private final GpsNavigationMessageProvider mGpsNavigationMessageProvider;
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
David Christied4edf4c2014-08-12 15:22:27 -0700396 private final PowerManager mPowerManager;
Mike Lockwood29c84342009-05-06 14:01:15 -0400397 private final AlarmManager mAlarmManager;
398 private final PendingIntent mWakeupIntent;
Mike Lockwood0632ca72009-05-14 15:51:03 -0400399 private final PendingIntent mTimeoutIntent;
Mike Lockwood29c84342009-05-06 14:01:15 -0400400
Dianne Hackborna06de0f2012-12-11 16:34:47 -0800401 private final IAppOpsService mAppOpsService;
Mike Lockwood2f82c4e2009-04-17 08:24:10 -0400402 private final IBatteryStats mBatteryStats;
The Android Open Source Project10592532009-03-18 17:39:46 -0700403
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700404 // only modified on handler thread
Dianne Hackborn002a54e2013-01-10 17:34:55 -0800405 private WorkSource mClientSource = new WorkSource();
Mike Lockwoodf1218be2010-01-29 09:20:06 -0500406
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -0700407 private GeofenceHardwareImpl mGeofenceHardwareImpl;
408
Lifu Tang82f893d2016-01-21 18:15:33 -0800409 private int mYearOfHardware = 0;
410
Lifu Tang30f95a72016-01-07 23:20:38 -0800411 private final IGnssStatusProvider mGnssStatusProvider = new IGnssStatusProvider.Stub() {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700412 @Override
Lifu Tang30f95a72016-01-07 23:20:38 -0800413 public void registerGnssStatusCallback(IGnssStatusListener callback) {
414 mListenerHelper.addListener(callback);
Mike Lockwood15e3d0f2009-05-01 07:53:28 -0400415 }
416
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700417 @Override
Lifu Tang30f95a72016-01-07 23:20:38 -0800418 public void unregisterGnssStatusCallback(IGnssStatusListener callback) {
419 mListenerHelper.removeListener(callback);
destradaaea8a8a62014-06-23 18:19:03 -0700420 }
421 };
Mike Lockwood15e3d0f2009-05-01 07:53:28 -0400422
Lifu Tang30f95a72016-01-07 23:20:38 -0800423 public IGnssStatusProvider getGnssStatusProvider() {
424 return mGnssStatusProvider;
Mike Lockwood15e3d0f2009-05-01 07:53:28 -0400425 }
426
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -0700427 public IGpsGeofenceHardware getGpsGeofenceProxy() {
428 return mGpsGeofenceBinder;
429 }
430
destradaaea8a8a62014-06-23 18:19:03 -0700431 public GpsMeasurementsProvider getGpsMeasurementsProvider() {
432 return mGpsMeasurementsProvider;
433 }
434
destradaa4b3e3932014-07-21 18:01:47 -0700435 public GpsNavigationMessageProvider getGpsNavigationMessageProvider() {
436 return mGpsNavigationMessageProvider;
437 }
438
destradaae21252a2015-09-08 12:32:59 -0700439 /**
440 * Callback used to listen for data connectivity changes.
441 */
442 private final ConnectivityManager.NetworkCallback mNetworkConnectivityCallback =
443 new ConnectivityManager.NetworkCallback() {
444 @Override
445 public void onAvailable(Network network) {
446 requestUtcTime();
447 xtraDownloadRequest();
448 }
449 };
450
451 /**
452 * Callback used to listen for availability of a requested SUPL connection.
453 * It is kept as a separate instance from {@link #mNetworkConnectivityCallback} to be able to
454 * manage the registration/un-registration lifetimes separate.
455 */
456 private final ConnectivityManager.NetworkCallback mSuplConnectivityCallback =
457 new ConnectivityManager.NetworkCallback() {
458 @Override
459 public void onAvailable(Network network) {
460 sendMessage(UPDATE_NETWORK_STATE, 0 /*arg*/, network);
461 }
462
463 @Override
464 public void onLost(Network network) {
465 releaseSuplConnection(GPS_RELEASE_AGPS_DATA_CONN);
466 }
467
468 @Override
469 public void onUnavailable() {
470 // timeout, it was not possible to establish the required connection
471 releaseSuplConnection(GPS_AGPS_DATA_CONN_FAILED);
472 }
473 };
474
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700475 private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
The Android Open Source Project10592532009-03-18 17:39:46 -0700476 @Override public void onReceive(Context context, Intent intent) {
477 String action = intent.getAction();
Tsuwei Chen48d37f92014-09-05 15:15:34 -0700478 if (DEBUG) Log.d(TAG, "receive broadcast intent, action: " + action);
destradaaee9fd342015-08-31 13:31:17 -0700479 if (action == null) {
480 return;
481 }
482
Mike Lockwood29c84342009-05-06 14:01:15 -0400483 if (action.equals(ALARM_WAKEUP)) {
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -0700484 startNavigating(false);
Mike Lockwood0632ca72009-05-14 15:51:03 -0400485 } else if (action.equals(ALARM_TIMEOUT)) {
Mike Lockwood0632ca72009-05-14 15:51:03 -0400486 hibernate();
Miguel Torroja1e84da82010-07-27 07:02:24 +0200487 } else if (action.equals(Intents.DATA_SMS_RECEIVED_ACTION)) {
488 checkSmsSuplInit(intent);
489 } else if (action.equals(Intents.WAP_PUSH_RECEIVED_ACTION)) {
490 checkWapSuplInit(intent);
David Christied4edf4c2014-08-12 15:22:27 -0700491 } else if (PowerManager.ACTION_POWER_SAVE_MODE_CHANGED.equals(action)
Adam Lesinski87c17df2015-05-27 13:24:13 -0700492 || PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED.equals(action)
David Christied4edf4c2014-08-12 15:22:27 -0700493 || Intent.ACTION_SCREEN_OFF.equals(action)
494 || Intent.ACTION_SCREEN_ON.equals(action)) {
495 updateLowPowerMode();
Wink Savillea374c3d2014-11-11 11:48:04 -0800496 } else if (action.equals(SIM_STATE_CHANGED)) {
497 subscriptionOrSimChanged(context);
David Christied4edf4c2014-08-12 15:22:27 -0700498 }
The Android Open Source Project10592532009-03-18 17:39:46 -0700499 }
Mike Lockwood29c84342009-05-06 14:01:15 -0400500 };
The Android Open Source Project10592532009-03-18 17:39:46 -0700501
Wink Savilled09c4ca2014-11-22 10:08:16 -0800502 private final OnSubscriptionsChangedListener mOnSubscriptionsChangedListener =
503 new OnSubscriptionsChangedListener() {
Wink Savillea374c3d2014-11-11 11:48:04 -0800504 @Override
Wink Savilled09c4ca2014-11-22 10:08:16 -0800505 public void onSubscriptionsChanged() {
destradaafb23c672015-04-16 14:01:27 -0700506 sendMessage(SUBSCRIPTION_OR_SIM_CHANGED, 0, null);
Wink Savillea374c3d2014-11-11 11:48:04 -0800507 }
508 };
509
510 private void subscriptionOrSimChanged(Context context) {
Ian Pedowitz9139b292015-07-04 18:07:33 -0700511 Log.d(TAG, "received SIM related action: ");
Wink Savillea374c3d2014-11-11 11:48:04 -0800512 TelephonyManager phone = (TelephonyManager)
513 mContext.getSystemService(Context.TELEPHONY_SERVICE);
514 String mccMnc = phone.getSimOperator();
515 if (!TextUtils.isEmpty(mccMnc)) {
516 Log.d(TAG, "SIM MCC/MNC is available: " + mccMnc);
517 synchronized (mLock) {
518 reloadGpsProperties(context, mProperties);
519 mNIHandler.setSuplEsEnabled(mSuplEsEnabled);
520 }
521 } else {
522 Log.d(TAG, "SIM MCC/MNC is still not available");
523 }
524 }
525
Miguel Torroja1e84da82010-07-27 07:02:24 +0200526 private void checkSmsSuplInit(Intent intent) {
527 SmsMessage[] messages = Intents.getMessagesFromIntent(intent);
Jack Yuefea9672015-07-31 15:13:39 -0700528 if (messages == null) {
529 Log.e(TAG, "Message does not exist in the intent.");
530 return;
531 }
532
destradaaee9fd342015-08-31 13:31:17 -0700533 for (SmsMessage message : messages) {
534 if (message != null && message.mWrappedSmsMessage != null) {
535 byte[] suplInit = message.getUserData();
536 if (suplInit != null) {
537 native_agps_ni_message(suplInit, suplInit.length);
538 }
539 }
Miguel Torroja1e84da82010-07-27 07:02:24 +0200540 }
541 }
542
543 private void checkWapSuplInit(Intent intent) {
destradaaee9fd342015-08-31 13:31:17 -0700544 byte[] suplInit = intent.getByteArrayExtra("data");
545 if (suplInit == null) {
546 return;
547 }
548 native_agps_ni_message(suplInit,suplInit.length);
Miguel Torroja1e84da82010-07-27 07:02:24 +0200549 }
550
David Christied4edf4c2014-08-12 15:22:27 -0700551 private void updateLowPowerMode() {
Adam Lesinski87c17df2015-05-27 13:24:13 -0700552 // Disable GPS if we are in device idle mode.
553 boolean disableGps = mPowerManager.isDeviceIdleMode();
David Christied4edf4c2014-08-12 15:22:27 -0700554 switch (Settings.Secure.getInt(mContext.getContentResolver(), BATTERY_SAVER_GPS_MODE,
555 BATTERY_SAVER_MODE_DISABLED_WHEN_SCREEN_OFF)) {
556 case BATTERY_SAVER_MODE_DISABLED_WHEN_SCREEN_OFF:
Adam Lesinski87c17df2015-05-27 13:24:13 -0700557 // If we are in battery saver mode and the screen is off, disable GPS.
558 disableGps |= mPowerManager.isPowerSaveMode() && !mPowerManager.isInteractive();
David Christied4edf4c2014-08-12 15:22:27 -0700559 break;
David Christied4edf4c2014-08-12 15:22:27 -0700560 }
561 if (disableGps != mDisableGps) {
562 mDisableGps = disableGps;
563 updateRequirements();
564 }
565 }
566
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800567 public static boolean isSupported() {
568 return native_is_supported();
569 }
570
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700571 private void reloadGpsProperties(Context context, Properties properties) {
572 Log.d(TAG, "Reset GPS properties, previous size = " + properties.size());
573 loadPropertiesFromResource(context, properties);
574 boolean isPropertiesLoadedFromFile = false;
575 final String gpsHardware = SystemProperties.get("ro.hardware.gps");
576 if (!TextUtils.isEmpty(gpsHardware)) {
577 final String propFilename =
578 PROPERTIES_FILE_PREFIX + "." + gpsHardware + PROPERTIES_FILE_SUFFIX;
579 isPropertiesLoadedFromFile =
580 loadPropertiesFromFile(propFilename, properties);
581 }
582 if (!isPropertiesLoadedFromFile) {
583 loadPropertiesFromFile(DEFAULT_PROPERTIES_FILE, properties);
584 }
585 Log.d(TAG, "GPS properties reloaded, size = " + properties.size());
586
587 // TODO: we should get rid of C2K specific setting.
588 setSuplHostPort(properties.getProperty("SUPL_HOST"),
589 properties.getProperty("SUPL_PORT"));
590 mC2KServerHost = properties.getProperty("C2K_HOST");
591 String portString = properties.getProperty("C2K_PORT");
592 if (mC2KServerHost != null && portString != null) {
593 try {
594 mC2KServerPort = Integer.parseInt(portString);
595 } catch (NumberFormatException e) {
596 Log.e(TAG, "unable to parse C2K_PORT: " + portString);
597 }
598 }
599
destradaaef752b62015-04-17 13:10:47 -0700600 if (native_is_gnss_configuration_supported()) {
601 try {
602 // Convert properties to string contents and send it to HAL.
603 ByteArrayOutputStream baos = new ByteArrayOutputStream(4096);
604 properties.store(baos, null);
605 native_configuration_update(baos.toString());
606 Log.d(TAG, "final config = " + baos.toString());
607 } catch (IOException ex) {
destradaae21252a2015-09-08 12:32:59 -0700608 Log.e(TAG, "failed to dump properties contents");
destradaaef752b62015-04-17 13:10:47 -0700609 }
610 } else if (DEBUG) {
611 Log.d(TAG, "Skipped configuration update because GNSS configuration in GPS HAL is not"
612 + " supported");
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700613 }
Tsuwei Chen3324e952014-09-07 01:30:42 -0700614
615 // SUPL_ES configuration.
616 String suplESProperty = mProperties.getProperty("SUPL_ES");
617 if (suplESProperty != null) {
618 try {
619 mSuplEsEnabled = (Integer.parseInt(suplESProperty) == 1);
620 } catch (NumberFormatException e) {
621 Log.e(TAG, "unable to parse SUPL_ES: " + suplESProperty);
622 }
623 }
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700624 }
625
626 private void loadPropertiesFromResource(Context context,
627 Properties properties) {
628 String[] configValues = context.getResources().getStringArray(
629 com.android.internal.R.array.config_gpsParameters);
630 for (String item : configValues) {
631 Log.d(TAG, "GpsParamsResource: " + item);
Tsuwei Chen7c485bf2014-09-10 15:33:34 -0700632 // We need to support "KEY =", but not "=VALUE".
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700633 String[] split = item.split("=");
634 if (split.length == 2) {
635 properties.setProperty(split[0].trim().toUpperCase(), split[1]);
636 } else {
637 Log.w(TAG, "malformed contents: " + item);
638 }
639 }
640 }
641
642 private boolean loadPropertiesFromFile(String filename,
643 Properties properties) {
Colin Cross7c030ed2014-01-28 09:33:53 -0800644 try {
645 File file = new File(filename);
646 FileInputStream stream = null;
647 try {
648 stream = new FileInputStream(file);
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700649 properties.load(stream);
Colin Cross7c030ed2014-01-28 09:33:53 -0800650 } finally {
651 IoUtils.closeQuietly(stream);
652 }
653
Colin Cross7c030ed2014-01-28 09:33:53 -0800654 } catch (IOException e) {
655 Log.w(TAG, "Could not open GPS configuration file " + filename);
656 return false;
657 }
658 return true;
659 }
660
Lifu Tang30f95a72016-01-07 23:20:38 -0800661 public GnssLocationProvider(Context context, ILocationManager ilocationManager,
Victoria Lease5cd731a2012-12-19 15:04:21 -0800662 Looper looper) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800663 mContext = context;
Jeff Sharkey104344e2011-07-10 14:20:41 -0700664 mNtpTime = NtpTrustedTime.getInstance(context);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700665 mILocationManager = ilocationManager;
Mike Lockwood63598a02010-02-24 11:52:59 -0500666
667 mLocation.setExtras(mLocationExtras);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800668
Mike Lockwood0528b9b2009-05-07 10:12:54 -0400669 // Create a wake lock
David Christied4edf4c2014-08-12 15:22:27 -0700670 mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
671 mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700672 mWakeLock.setReferenceCounted(true);
Mike Lockwood0528b9b2009-05-07 10:12:54 -0400673
Mike Lockwood29c84342009-05-06 14:01:15 -0400674 mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
675 mWakeupIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_WAKEUP), 0);
Mike Lockwood0632ca72009-05-14 15:51:03 -0400676 mTimeoutIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_TIMEOUT), 0);
Mike Lockwood29c84342009-05-06 14:01:15 -0400677
Mike Lockwood58bda982009-04-14 16:25:07 -0400678 mConnMgr = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
679
Dianne Hackborna06de0f2012-12-11 16:34:47 -0800680 // App ops service to keep track of who is accessing the GPS
681 mAppOpsService = IAppOpsService.Stub.asInterface(ServiceManager.getService(
682 Context.APP_OPS_SERVICE));
683
Mike Lockwood2f82c4e2009-04-17 08:24:10 -0400684 // Battery statistics service to be notified when GPS turns on or off
Dianne Hackborn91268cf2013-06-13 19:06:50 -0700685 mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService(
686 BatteryStats.SERVICE_NAME));
Mike Lockwood2f82c4e2009-04-17 08:24:10 -0400687
destradaafb23c672015-04-16 14:01:27 -0700688 // Construct internal handler
689 mHandler = new ProviderHandler(looper);
690
691 // Load GPS configuration and register listeners in the background:
692 // some operations, such as opening files and registering broadcast receivers, can take a
693 // relative long time, so the ctor() is kept to create objects needed by this instance,
694 // while IO initialization and registration is delegated to our internal handler
695 // this approach is just fine because events are posted to our handler anyway
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700696 mProperties = new Properties();
destradaafb23c672015-04-16 14:01:27 -0700697 sendMessage(INITIALIZE_HANDLER, 0, null);
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400698
Tsuwei Chen3324e952014-09-07 01:30:42 -0700699 // Create a GPS net-initiated handler.
700 mNIHandler = new GpsNetInitiatedHandler(context,
701 mNetInitiatedListener,
702 mSuplEsEnabled);
703
Lifu Tang30f95a72016-01-07 23:20:38 -0800704 mListenerHelper = new GnssStatusListenerHelper(mHandler) {
destradaa6568d702014-10-27 12:47:41 -0700705 @Override
706 protected boolean isAvailableInPlatform() {
destradaa13a60b02015-01-15 18:36:01 -0800707 return isSupported();
destradaa6568d702014-10-27 12:47:41 -0700708 }
709
710 @Override
711 protected boolean isGpsEnabled() {
712 return isEnabled();
713 }
714 };
715
716 mGpsMeasurementsProvider = new GpsMeasurementsProvider(mHandler) {
717 @Override
718 public boolean isAvailableInPlatform() {
719 return native_is_measurement_supported();
720 }
721
722 @Override
723 protected boolean registerWithService() {
724 return native_start_measurement_collection();
725 }
726
727 @Override
728 protected void unregisterFromService() {
729 native_stop_measurement_collection();
730 }
731
732 @Override
733 protected boolean isGpsEnabled() {
734 return isEnabled();
735 }
736 };
737
738 mGpsNavigationMessageProvider = new GpsNavigationMessageProvider(mHandler) {
739 @Override
740 protected boolean isAvailableInPlatform() {
741 return native_is_navigation_message_supported();
742 }
743
744 @Override
745 protected boolean registerWithService() {
746 return native_start_navigation_message_collection();
747 }
748
749 @Override
750 protected void unregisterFromService() {
751 native_stop_navigation_message_collection();
752 }
753
754 @Override
755 protected boolean isGpsEnabled() {
756 return isEnabled();
757 }
758 };
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400759 }
760
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800761 /**
Mike Lockwoodd03ff942010-02-09 08:46:14 -0500762 * Returns the name of this provider.
763 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700764 @Override
Mike Lockwoodd03ff942010-02-09 08:46:14 -0500765 public String getName() {
766 return LocationManager.GPS_PROVIDER;
767 }
768
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700769 @Override
770 public ProviderProperties getProperties() {
771 return PROPERTIES;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800772 }
773
destradaae21252a2015-09-08 12:32:59 -0700774 private void handleUpdateNetworkState(Network network) {
775 // retrieve NetworkInfo for this UID
776 NetworkInfo info = mConnMgr.getNetworkInfo(network);
777 if (info == null) {
778 return;
779 }
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400780
destradaae21252a2015-09-08 12:32:59 -0700781 boolean isConnected = info.isConnected();
Joe Onoratof5d95cb2010-01-07 21:48:32 -0500782 if (DEBUG) {
destradaae21252a2015-09-08 12:32:59 -0700783 String message = String.format(
784 "UpdateNetworkState, state=%s, connected=%s, info=%s, capabilities=%S",
785 agpsDataConnStateAsString(),
786 isConnected,
787 info,
788 mConnMgr.getNetworkCapabilities(network));
789 Log.d(TAG, message);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800790 }
Mike Lockwood03d24672009-10-08 15:45:03 -0400791
destradaae21252a2015-09-08 12:32:59 -0700792 if (native_is_agps_ril_supported()) {
793 boolean dataEnabled = TelephonyManager.getDefault().getDataEnabled();
794 boolean networkAvailable = info.isAvailable() && dataEnabled;
795 String defaultApn = getSelectedApn();
796 if (defaultApn == null) {
797 defaultApn = "dummy-apn";
destradaaef752b62015-04-17 13:10:47 -0700798 }
destradaae21252a2015-09-08 12:32:59 -0700799
800 native_update_network_state(
801 isConnected,
802 info.getType(),
803 info.isRoaming(),
804 networkAvailable,
805 info.getExtraInfo(),
806 defaultApn);
807 } else if (DEBUG) {
808 Log.d(TAG, "Skipped network state update because GPS HAL AGPS-RIL is not supported");
Mike Lockwood50130bb2010-10-11 06:22:50 -0400809 }
810
destradaae21252a2015-09-08 12:32:59 -0700811 if (mAGpsDataConnectionState == AGPS_DATA_CONNECTION_OPENING) {
812 if (isConnected) {
destradaa96a14702014-06-05 11:36:30 -0700813 String apnName = info.getExtraInfo();
Stephen Li83b69712011-01-25 18:47:28 -0800814 if (apnName == null) {
destradaae21252a2015-09-08 12:32:59 -0700815 // assign a dummy value in the case of C2K as otherwise we will have a runtime
816 // exception in the following call to native_agps_data_conn_open
Stephen Li83b69712011-01-25 18:47:28 -0800817 apnName = "dummy-apn";
818 }
destradaae21252a2015-09-08 12:32:59 -0700819 int apnIpType = getApnIpType(apnName);
destradaa96a14702014-06-05 11:36:30 -0700820 setRouting();
821 if (DEBUG) {
822 String message = String.format(
823 "native_agps_data_conn_open: mAgpsApn=%s, mApnIpType=%s",
destradaae21252a2015-09-08 12:32:59 -0700824 apnName,
825 apnIpType);
destradaa96a14702014-06-05 11:36:30 -0700826 Log.d(TAG, message);
Stephen Li8efd74d2011-03-01 20:56:00 -0800827 }
destradaae21252a2015-09-08 12:32:59 -0700828 native_agps_data_conn_open(apnName, apnIpType);
Mike Lockwood03d24672009-10-08 15:45:03 -0400829 mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPEN;
830 } else {
destradaae21252a2015-09-08 12:32:59 -0700831 handleReleaseSuplConnection(GPS_AGPS_DATA_CONN_FAILED);
Mike Lockwood03d24672009-10-08 15:45:03 -0400832 }
833 }
destradaae21252a2015-09-08 12:32:59 -0700834 }
Mike Lockwood03d24672009-10-08 15:45:03 -0400835
destradaae21252a2015-09-08 12:32:59 -0700836 private void handleRequestSuplConnection(InetAddress address) {
837 if (DEBUG) {
838 String message = String.format(
839 "requestSuplConnection, state=%s, address=%s",
840 agpsDataConnStateAsString(),
841 address);
842 Log.d(TAG, message);
843 }
844
845 if (mAGpsDataConnectionState != AGPS_DATA_CONNECTION_CLOSED) {
846 return;
847 }
848 mAGpsDataConnectionIpAddr = address;
849 mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPENING;
850
851 NetworkRequest.Builder requestBuilder = new NetworkRequest.Builder();
852 requestBuilder.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
853 requestBuilder.addCapability(NetworkCapabilities.NET_CAPABILITY_SUPL);
854 NetworkRequest request = requestBuilder.build();
855 mConnMgr.requestNetwork(
856 request,
857 mSuplConnectivityCallback,
858 ConnectivityManager.MAX_NETWORK_REQUEST_TIMEOUT_MS);
859 }
860
861 private void handleReleaseSuplConnection(int agpsDataConnStatus) {
862 if (DEBUG) {
863 String message = String.format(
864 "releaseSuplConnection, state=%s, status=%s",
865 agpsDataConnStateAsString(),
866 agpsDataConnStatusAsString(agpsDataConnStatus));
867 Log.d(TAG, message);
868 }
869
870 if (mAGpsDataConnectionState == AGPS_DATA_CONNECTION_CLOSED) {
871 return;
872 }
873 mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED;
874
875 mConnMgr.unregisterNetworkCallback(mSuplConnectivityCallback);
876 switch (agpsDataConnStatus) {
877 case GPS_AGPS_DATA_CONN_FAILED:
878 native_agps_data_conn_failed();
879 break;
880 case GPS_RELEASE_AGPS_DATA_CONN:
881 native_agps_data_conn_closed();
882 break;
883 default:
884 Log.e(TAG, "Invalid status to release SUPL connection: " + agpsDataConnStatus);
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400885 }
886 }
887
888 private void handleInjectNtpTime() {
Kevin Tang40e1baf2012-01-10 14:32:44 -0800889 if (mInjectNtpTimePending == STATE_DOWNLOADING) {
890 // already downloading data
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400891 return;
892 }
destradaae21252a2015-09-08 12:32:59 -0700893 if (!isDataNetworkConnected()) {
Kevin Tang40e1baf2012-01-10 14:32:44 -0800894 // try again when network is up
895 mInjectNtpTimePending = STATE_PENDING_NETWORK;
896 return;
Jeff Sharkey104344e2011-07-10 14:20:41 -0700897 }
Kevin Tang40e1baf2012-01-10 14:32:44 -0800898 mInjectNtpTimePending = STATE_DOWNLOADING;
Jeff Sharkey104344e2011-07-10 14:20:41 -0700899
Jeff Brown028872f2012-08-25 13:07:01 -0700900 // hold wake lock while task runs
901 mWakeLock.acquire();
Kevin Tang40e1baf2012-01-10 14:32:44 -0800902 AsyncTask.THREAD_POOL_EXECUTOR.execute(new Runnable() {
903 @Override
904 public void run() {
905 long delay;
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400906
Kevin Tang40e1baf2012-01-10 14:32:44 -0800907 // force refresh NTP cache when outdated
destradaa56b47f82015-07-24 10:56:18 -0700908 boolean refreshSuccess = true;
Kevin Tang40e1baf2012-01-10 14:32:44 -0800909 if (mNtpTime.getCacheAge() >= NTP_INTERVAL) {
destradaa56b47f82015-07-24 10:56:18 -0700910 refreshSuccess = mNtpTime.forceRefresh();
Kevin Tang40e1baf2012-01-10 14:32:44 -0800911 }
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400912
Kevin Tang40e1baf2012-01-10 14:32:44 -0800913 // only update when NTP time is fresh
914 if (mNtpTime.getCacheAge() < NTP_INTERVAL) {
915 long time = mNtpTime.getCachedNtpTime();
916 long timeReference = mNtpTime.getCachedNtpTimeReference();
917 long certainty = mNtpTime.getCacheCertainty();
918 long now = System.currentTimeMillis();
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400919
Kevin Tang40e1baf2012-01-10 14:32:44 -0800920 Log.d(TAG, "NTP server returned: "
921 + time + " (" + new Date(time)
922 + ") reference: " + timeReference
923 + " certainty: " + certainty
924 + " system time offset: " + (time - now));
925
926 native_inject_time(time, timeReference, (int) certainty);
927 delay = NTP_INTERVAL;
Wei Liu6f6326b2015-06-24 23:47:50 -0700928 mNtpBackOff.reset();
Kevin Tang40e1baf2012-01-10 14:32:44 -0800929 } else {
destradaa56b47f82015-07-24 10:56:18 -0700930 Log.e(TAG, "requestTime failed");
Wei Liu6f6326b2015-06-24 23:47:50 -0700931 delay = mNtpBackOff.nextBackoffMillis();
Kevin Tang40e1baf2012-01-10 14:32:44 -0800932 }
933
Jeff Brown028872f2012-08-25 13:07:01 -0700934 sendMessage(INJECT_NTP_TIME_FINISHED, 0, null);
Kevin Tang40e1baf2012-01-10 14:32:44 -0800935
destradaa56b47f82015-07-24 10:56:18 -0700936 if (DEBUG) {
937 String message = String.format(
938 "onDemandTimeInjection=%s, refreshSuccess=%s, delay=%s",
939 mOnDemandTimeInjection,
940 refreshSuccess,
941 delay);
942 Log.d(TAG, message);
943 }
944 if (mOnDemandTimeInjection || !refreshSuccess) {
Kevin Tang40e1baf2012-01-10 14:32:44 -0800945 // send delayed message for next NTP injection
946 // since this is delayed and not urgent we do not hold a wake lock here
Jeff Brown028872f2012-08-25 13:07:01 -0700947 mHandler.sendEmptyMessageDelayed(INJECT_NTP_TIME, delay);
Kevin Tang40e1baf2012-01-10 14:32:44 -0800948 }
Jeff Brown028872f2012-08-25 13:07:01 -0700949
950 // release wake lock held by task
951 mWakeLock.release();
Kevin Tang40e1baf2012-01-10 14:32:44 -0800952 }
953 });
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400954 }
955
956 private void handleDownloadXtraData() {
Kevin Tang40e1baf2012-01-10 14:32:44 -0800957 if (mDownloadXtraDataPending == STATE_DOWNLOADING) {
958 // already downloading data
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400959 return;
960 }
destradaae21252a2015-09-08 12:32:59 -0700961 if (!isDataNetworkConnected()) {
Kevin Tang40e1baf2012-01-10 14:32:44 -0800962 // try again when network is up
963 mDownloadXtraDataPending = STATE_PENDING_NETWORK;
964 return;
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400965 }
Kevin Tang40e1baf2012-01-10 14:32:44 -0800966 mDownloadXtraDataPending = STATE_DOWNLOADING;
967
Jeff Brown028872f2012-08-25 13:07:01 -0700968 // hold wake lock while task runs
969 mWakeLock.acquire();
Kevin Tang40e1baf2012-01-10 14:32:44 -0800970 AsyncTask.THREAD_POOL_EXECUTOR.execute(new Runnable() {
971 @Override
972 public void run() {
Andreas Gampedfdc6ac2014-10-28 20:42:53 -0700973 GpsXtraDownloader xtraDownloader = new GpsXtraDownloader(mProperties);
Kevin Tang40e1baf2012-01-10 14:32:44 -0800974 byte[] data = xtraDownloader.downloadXtraData();
975 if (data != null) {
destradaae21252a2015-09-08 12:32:59 -0700976 if (DEBUG) Log.d(TAG, "calling native_inject_xtra_data");
Kevin Tang40e1baf2012-01-10 14:32:44 -0800977 native_inject_xtra_data(data, data.length);
Wei Liu6f6326b2015-06-24 23:47:50 -0700978 mXtraBackOff.reset();
Kevin Tang40e1baf2012-01-10 14:32:44 -0800979 }
980
Jeff Brown028872f2012-08-25 13:07:01 -0700981 sendMessage(DOWNLOAD_XTRA_DATA_FINISHED, 0, null);
Kevin Tang40e1baf2012-01-10 14:32:44 -0800982
983 if (data == null) {
984 // try again later
985 // since this is delayed and not urgent we do not hold a wake lock here
Wei Liu6f6326b2015-06-24 23:47:50 -0700986 mHandler.sendEmptyMessageDelayed(DOWNLOAD_XTRA_DATA,
987 mXtraBackOff.nextBackoffMillis());
Kevin Tang40e1baf2012-01-10 14:32:44 -0800988 }
Kevin Tang40e1baf2012-01-10 14:32:44 -0800989
Jeff Brown028872f2012-08-25 13:07:01 -0700990 // release wake lock held by task
991 mWakeLock.release();
992 }
Kevin Tang40e1baf2012-01-10 14:32:44 -0800993 });
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800994 }
995
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400996 private void handleUpdateLocation(Location location) {
Mike Lockwoodd26ce0d2009-06-11 12:25:46 -0400997 if (location.hasAccuracy()) {
998 native_inject_location(location.getLatitude(), location.getLongitude(),
999 location.getAccuracy());
1000 }
Mike Lockwoodfd6e5f02009-05-21 11:28:20 -04001001 }
1002
1003 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001004 * Enables this provider. When enabled, calls to getStatus()
Mike Lockwood4e50b782009-04-03 08:24:43 -07001005 * must be handled. Hardware may be started up
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001006 * when the provider is enabled.
1007 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001008 @Override
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001009 public void enable() {
Laurent Tu7b5aeca2013-01-24 15:10:24 -08001010 synchronized (mLock) {
1011 if (mEnabled) return;
1012 mEnabled = true;
1013 }
1014
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001015 sendMessage(ENABLE, 1, null);
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001016 }
1017
Tsuwei Chen52617bb2014-08-25 11:49:11 -07001018 private void setSuplHostPort(String hostString, String portString) {
1019 if (hostString != null) {
1020 mSuplServerHost = hostString;
1021 }
1022 if (portString != null) {
1023 try {
1024 mSuplServerPort = Integer.parseInt(portString);
1025 } catch (NumberFormatException e) {
1026 Log.e(TAG, "unable to parse SUPL_PORT: " + portString);
1027 }
1028 }
Tsuwei Chen678c13c2014-09-22 17:48:41 -07001029 if (mSuplServerHost != null
1030 && mSuplServerPort > TCP_MIN_PORT
1031 && mSuplServerPort <= TCP_MAX_PORT) {
1032 native_set_agps_server(AGPS_TYPE_SUPL, mSuplServerHost, mSuplServerPort);
1033 }
Tsuwei Chen52617bb2014-08-25 11:49:11 -07001034 }
1035
Tsuwei Chen462bcd82014-09-17 12:28:49 -07001036 /**
1037 * Checks what SUPL mode to use, according to the AGPS mode as well as the
1038 * allowed mode from properties.
1039 *
1040 * @param properties GPS properties
1041 * @param agpsEnabled whether AGPS is enabled by settings value
1042 * @param singleShot whether "singleshot" is needed
1043 * @return SUPL mode (MSA vs MSB vs STANDALONE)
1044 */
1045 private int getSuplMode(Properties properties, boolean agpsEnabled, boolean singleShot) {
1046 if (agpsEnabled) {
1047 String modeString = properties.getProperty("SUPL_MODE");
1048 int suplMode = 0;
1049 if (!TextUtils.isEmpty(modeString)) {
1050 try {
1051 suplMode = Integer.parseInt(modeString);
1052 } catch (NumberFormatException e) {
1053 Log.e(TAG, "unable to parse SUPL_MODE: " + modeString);
1054 return GPS_POSITION_MODE_STANDALONE;
1055 }
1056 }
destradaabfb3bdb2015-04-29 14:42:35 -07001057 // MS-Based is the preferred mode for Assisted-GPS position computation, so we favor
1058 // such mode when it is available
1059 if (hasCapability(GPS_CAPABILITY_MSB) && (suplMode & AGPS_SUPL_MODE_MSB) != 0) {
1060 return GPS_POSITION_MODE_MS_BASED;
1061 }
1062 // for now, just as the legacy code did, we fallback to MS-Assisted if it is available,
1063 // do fallback only for single-shot requests, because it is too expensive to do for
1064 // periodic requests as well
Tsuwei Chen462bcd82014-09-17 12:28:49 -07001065 if (singleShot
1066 && hasCapability(GPS_CAPABILITY_MSA)
1067 && (suplMode & AGPS_SUPL_MODE_MSA) != 0) {
1068 return GPS_POSITION_MODE_MS_ASSISTED;
Tsuwei Chen462bcd82014-09-17 12:28:49 -07001069 }
1070 }
1071 return GPS_POSITION_MODE_STANDALONE;
1072 }
1073
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001074 private void handleEnable() {
1075 if (DEBUG) Log.d(TAG, "handleEnable");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001076
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001077 boolean enabled = native_init();
1078
1079 if (enabled) {
Mike Lockwood1a1cd3a2010-08-17 07:42:54 -04001080 mSupportsXtra = native_supports_xtra();
Tsuwei Chen678c13c2014-09-22 17:48:41 -07001081
1082 // TODO: remove the following native calls if we can make sure they are redundant.
Mike Lockwood734d6032009-07-28 18:30:25 -07001083 if (mSuplServerHost != null) {
1084 native_set_agps_server(AGPS_TYPE_SUPL, mSuplServerHost, mSuplServerPort);
1085 }
1086 if (mC2KServerHost != null) {
1087 native_set_agps_server(AGPS_TYPE_C2K, mC2KServerHost, mC2KServerPort);
1088 }
destradaa13a60b02015-01-15 18:36:01 -08001089
1090 mGpsMeasurementsProvider.onGpsEnabledChanged();
1091 mGpsNavigationMessageProvider.onGpsEnabledChanged();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001092 } else {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001093 synchronized (mLock) {
1094 mEnabled = false;
1095 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001096 Log.w(TAG, "Failed to enable location provider");
1097 }
1098 }
1099
1100 /**
1101 * Disables this provider. When disabled, calls to getStatus()
Mike Lockwood4e50b782009-04-03 08:24:43 -07001102 * need not be handled. Hardware may be shut
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001103 * down while the provider is disabled.
1104 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001105 @Override
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001106 public void disable() {
Laurent Tu7b5aeca2013-01-24 15:10:24 -08001107 synchronized (mLock) {
1108 if (!mEnabled) return;
1109 mEnabled = false;
1110 }
1111
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001112 sendMessage(ENABLE, 0, null);
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001113 }
1114
1115 private void handleDisable() {
Mike Lockwood89096312010-03-24 10:14:55 -04001116 if (DEBUG) Log.d(TAG, "handleDisable");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001117
David Christie3bc26142013-12-19 14:53:44 -08001118 updateClientUids(new WorkSource());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001119 stopNavigating();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001120 mAlarmManager.cancel(mWakeupIntent);
1121 mAlarmManager.cancel(mTimeoutIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001122
Mike Lockwoodcf1d8cb2010-01-20 10:14:54 -05001123 // do this before releasing wakelock
1124 native_cleanup();
destradaa13a60b02015-01-15 18:36:01 -08001125
1126 mGpsMeasurementsProvider.onGpsEnabledChanged();
1127 mGpsNavigationMessageProvider.onGpsEnabledChanged();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001128 }
1129
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001130 @Override
Mike Lockwoodd03ff942010-02-09 08:46:14 -05001131 public boolean isEnabled() {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001132 synchronized (mLock) {
1133 return mEnabled;
1134 }
Mike Lockwoodd03ff942010-02-09 08:46:14 -05001135 }
1136
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001137 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001138 public int getStatus(Bundle extras) {
1139 if (extras != null) {
1140 extras.putInt("satellites", mSvCount);
1141 }
1142 return mStatus;
1143 }
1144
1145 private void updateStatus(int status, int svCount) {
1146 if (status != mStatus || svCount != mSvCount) {
1147 mStatus = status;
1148 mSvCount = svCount;
1149 mLocationExtras.putInt("satellites", svCount);
1150 mStatusUpdateTime = SystemClock.elapsedRealtime();
1151 }
1152 }
1153
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001154 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001155 public long getStatusUpdateTime() {
1156 return mStatusUpdateTime;
1157 }
1158
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001159 @Override
1160 public void setRequest(ProviderRequest request, WorkSource source) {
1161 sendMessage(SET_REQUEST, 0, new GpsRequest(request, source));
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001162 }
1163
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001164 private void handleSetRequest(ProviderRequest request, WorkSource source) {
David Christied4edf4c2014-08-12 15:22:27 -07001165 mProviderRequest = request;
1166 mWorkSource = source;
1167 updateRequirements();
1168 }
1169
1170 // Called when the requirements for GPS may have changed
1171 private void updateRequirements() {
1172 if (mProviderRequest == null || mWorkSource == null) {
1173 return;
1174 }
1175
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001176 boolean singleShot = false;
1177
1178 // see if the request is for a single update
David Christied4edf4c2014-08-12 15:22:27 -07001179 if (mProviderRequest.locationRequests != null
1180 && mProviderRequest.locationRequests.size() > 0) {
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001181 // if any request has zero or more than one updates
1182 // requested, then this is not single-shot mode
1183 singleShot = true;
1184
David Christied4edf4c2014-08-12 15:22:27 -07001185 for (LocationRequest lr : mProviderRequest.locationRequests) {
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001186 if (lr.getNumUpdates() != 1) {
1187 singleShot = false;
1188 }
1189 }
1190 }
1191
David Christied4edf4c2014-08-12 15:22:27 -07001192 if (DEBUG) Log.d(TAG, "setRequest " + mProviderRequest);
1193 if (mProviderRequest.reportLocation && !mDisableGps) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001194 // update client uids
David Christied4edf4c2014-08-12 15:22:27 -07001195 updateClientUids(mWorkSource);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001196
David Christied4edf4c2014-08-12 15:22:27 -07001197 mFixInterval = (int) mProviderRequest.interval;
Mike Lockwood03ca2162010-04-01 08:10:09 -07001198
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001199 // check for overflow
David Christied4edf4c2014-08-12 15:22:27 -07001200 if (mFixInterval != mProviderRequest.interval) {
1201 Log.w(TAG, "interval overflow: " + mProviderRequest.interval);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001202 mFixInterval = Integer.MAX_VALUE;
1203 }
Mike Lockwood03ca2162010-04-01 08:10:09 -07001204
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001205 // apply request to GPS engine
Mike Lockwood04598b62010-04-14 17:17:24 -04001206 if (mStarted && hasCapability(GPS_CAPABILITY_SCHEDULING)) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001207 // change period
Mike Lockwood04598b62010-04-14 17:17:24 -04001208 if (!native_set_position_mode(mPositionMode, GPS_POSITION_RECURRENCE_PERIODIC,
1209 mFixInterval, 0, 0)) {
1210 Log.e(TAG, "set_position_mode failed in setMinTime()");
1211 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001212 } else if (!mStarted) {
1213 // start GPS
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001214 startNavigating(singleShot);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001215 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001216 } else {
Dianne Hackborn002a54e2013-01-10 17:34:55 -08001217 updateClientUids(new WorkSource());
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001218
1219 stopNavigating();
1220 mAlarmManager.cancel(mWakeupIntent);
1221 mAlarmManager.cancel(mTimeoutIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001222 }
1223 }
1224
Dianne Hackborn002a54e2013-01-10 17:34:55 -08001225 private void updateClientUids(WorkSource source) {
1226 // Update work source.
1227 WorkSource[] changes = mClientSource.setReturningDiffs(source);
Victoria Leaseea78b852013-01-15 10:39:28 -08001228 if (changes == null) {
1229 return;
1230 }
Dianne Hackborn002a54e2013-01-10 17:34:55 -08001231 WorkSource newWork = changes[0];
1232 WorkSource goneWork = changes[1];
1233
1234 // Update sources that were not previously tracked.
1235 if (newWork != null) {
1236 int lastuid = -1;
1237 for (int i=0; i<newWork.size(); i++) {
Dianne Hackborn2e418422009-06-22 20:00:17 -07001238 try {
Dianne Hackborn002a54e2013-01-10 17:34:55 -08001239 int uid = newWork.get(i);
Dianne Hackborne98f5db2013-07-17 17:23:25 -07001240 mAppOpsService.startOperation(AppOpsManager.getToken(mAppOpsService),
1241 AppOpsManager.OP_GPS, uid, newWork.getName(i));
Dianne Hackborn002a54e2013-01-10 17:34:55 -08001242 if (uid != lastuid) {
1243 lastuid = uid;
1244 mBatteryStats.noteStartGps(uid);
1245 }
Dianne Hackborn2e418422009-06-22 20:00:17 -07001246 } catch (RemoteException e) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001247 Log.w(TAG, "RemoteException", e);
1248 }
1249 }
1250 }
1251
Dianne Hackborn002a54e2013-01-10 17:34:55 -08001252 // Update sources that are no longer tracked.
1253 if (goneWork != null) {
1254 int lastuid = -1;
1255 for (int i=0; i<goneWork.size(); i++) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001256 try {
Dianne Hackborn002a54e2013-01-10 17:34:55 -08001257 int uid = goneWork.get(i);
Dianne Hackborne98f5db2013-07-17 17:23:25 -07001258 mAppOpsService.finishOperation(AppOpsManager.getToken(mAppOpsService),
1259 AppOpsManager.OP_GPS, uid, goneWork.getName(i));
Dianne Hackborn002a54e2013-01-10 17:34:55 -08001260 if (uid != lastuid) {
1261 lastuid = uid;
1262 mBatteryStats.noteStopGps(uid);
1263 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001264 } catch (RemoteException e) {
1265 Log.w(TAG, "RemoteException", e);
Dianne Hackborn2e418422009-06-22 20:00:17 -07001266 }
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001267 }
1268 }
1269 }
1270
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001271 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001272 public boolean sendExtraCommand(String command, Bundle extras) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001273
Mike Lockwood63aa5a62010-04-14 19:21:31 -04001274 long identity = Binder.clearCallingIdentity();
1275 boolean result = false;
1276
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001277 if ("delete_aiding_data".equals(command)) {
Mike Lockwood63aa5a62010-04-14 19:21:31 -04001278 result = deleteAidingData(extras);
1279 } else if ("force_time_injection".equals(command)) {
destradaae21252a2015-09-08 12:32:59 -07001280 requestUtcTime();
Mike Lockwood63aa5a62010-04-14 19:21:31 -04001281 result = true;
1282 } else if ("force_xtra_injection".equals(command)) {
Mike Lockwood1a1cd3a2010-08-17 07:42:54 -04001283 if (mSupportsXtra) {
Mike Lockwood93bc44d2009-05-20 16:58:22 -04001284 xtraDownloadRequest();
Mike Lockwood63aa5a62010-04-14 19:21:31 -04001285 result = true;
Mike Lockwood93bc44d2009-05-20 16:58:22 -04001286 }
Mike Lockwood63aa5a62010-04-14 19:21:31 -04001287 } else {
1288 Log.w(TAG, "sendExtraCommand: unknown command " + command);
Mike Lockwood93bc44d2009-05-20 16:58:22 -04001289 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001290
Mike Lockwood63aa5a62010-04-14 19:21:31 -04001291 Binder.restoreCallingIdentity(identity);
1292 return result;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001293 }
1294
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001295 private IGpsGeofenceHardware mGpsGeofenceBinder = new IGpsGeofenceHardware.Stub() {
1296 public boolean isHardwareGeofenceSupported() {
1297 return native_is_geofence_supported();
1298 }
1299
1300 public boolean addCircularHardwareGeofence(int geofenceId, double latitude,
1301 double longitude, double radius, int lastTransition, int monitorTransitions,
1302 int notificationResponsiveness, int unknownTimer) {
1303 return native_add_geofence(geofenceId, latitude, longitude, radius,
1304 lastTransition, monitorTransitions, notificationResponsiveness, unknownTimer);
1305 }
1306
1307 public boolean removeHardwareGeofence(int geofenceId) {
1308 return native_remove_geofence(geofenceId);
1309 }
1310
1311 public boolean pauseHardwareGeofence(int geofenceId) {
1312 return native_pause_geofence(geofenceId);
1313 }
1314
1315 public boolean resumeHardwareGeofence(int geofenceId, int monitorTransition) {
1316 return native_resume_geofence(geofenceId, monitorTransition);
1317 }
1318 };
1319
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001320 private boolean deleteAidingData(Bundle extras) {
1321 int flags;
1322
1323 if (extras == null) {
1324 flags = GPS_DELETE_ALL;
1325 } else {
1326 flags = 0;
1327 if (extras.getBoolean("ephemeris")) flags |= GPS_DELETE_EPHEMERIS;
1328 if (extras.getBoolean("almanac")) flags |= GPS_DELETE_ALMANAC;
1329 if (extras.getBoolean("position")) flags |= GPS_DELETE_POSITION;
1330 if (extras.getBoolean("time")) flags |= GPS_DELETE_TIME;
1331 if (extras.getBoolean("iono")) flags |= GPS_DELETE_IONO;
1332 if (extras.getBoolean("utc")) flags |= GPS_DELETE_UTC;
1333 if (extras.getBoolean("health")) flags |= GPS_DELETE_HEALTH;
1334 if (extras.getBoolean("svdir")) flags |= GPS_DELETE_SVDIR;
1335 if (extras.getBoolean("svsteer")) flags |= GPS_DELETE_SVSTEER;
1336 if (extras.getBoolean("sadata")) flags |= GPS_DELETE_SADATA;
1337 if (extras.getBoolean("rti")) flags |= GPS_DELETE_RTI;
1338 if (extras.getBoolean("celldb-info")) flags |= GPS_DELETE_CELLDB_INFO;
1339 if (extras.getBoolean("all")) flags |= GPS_DELETE_ALL;
1340 }
1341
1342 if (flags != 0) {
1343 native_delete_aiding_data(flags);
1344 return true;
1345 }
1346
1347 return false;
1348 }
1349
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001350 private void startNavigating(boolean singleShot) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001351 if (!mStarted) {
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001352 if (DEBUG) Log.d(TAG, "startNavigating, singleShot is " + singleShot);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001353 mTimeToFirstFix = 0;
1354 mLastFixTime = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001355 mStarted = true;
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001356 mSingleShot = singleShot;
Mike Lockwood03ca2162010-04-01 08:10:09 -07001357 mPositionMode = GPS_POSITION_MODE_STANDALONE;
1358
Tsuwei Chen462bcd82014-09-17 12:28:49 -07001359 boolean agpsEnabled =
1360 (Settings.Global.getInt(mContext.getContentResolver(),
1361 Settings.Global.ASSISTED_GPS_ENABLED, 1) != 0);
1362 mPositionMode = getSuplMode(mProperties, agpsEnabled, singleShot);
Mike Lockwoodbcab8df2009-06-25 16:39:09 -04001363
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001364 if (DEBUG) {
1365 String mode;
1366
1367 switch(mPositionMode) {
1368 case GPS_POSITION_MODE_STANDALONE:
1369 mode = "standalone";
1370 break;
1371 case GPS_POSITION_MODE_MS_ASSISTED:
1372 mode = "MS_ASSISTED";
1373 break;
1374 case GPS_POSITION_MODE_MS_BASED:
1375 mode = "MS_BASED";
1376 break;
1377 default:
1378 mode = "unknown";
1379 break;
1380 }
1381 Log.d(TAG, "setting position_mode to " + mode);
1382 }
1383
Mike Lockwood04598b62010-04-14 17:17:24 -04001384 int interval = (hasCapability(GPS_CAPABILITY_SCHEDULING) ? mFixInterval : 1000);
1385 if (!native_set_position_mode(mPositionMode, GPS_POSITION_RECURRENCE_PERIODIC,
1386 interval, 0, 0)) {
1387 mStarted = false;
1388 Log.e(TAG, "set_position_mode failed in startNavigating()");
1389 return;
1390 }
1391 if (!native_start()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001392 mStarted = false;
1393 Log.e(TAG, "native_start failed in startNavigating()");
Mike Lockwood0632ca72009-05-14 15:51:03 -04001394 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001395 }
1396
1397 // reset SV count to zero
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001398 updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, 0);
Mike Lockwood29c84342009-05-06 14:01:15 -04001399 mFixRequestTime = System.currentTimeMillis();
Mike Lockwood04598b62010-04-14 17:17:24 -04001400 if (!hasCapability(GPS_CAPABILITY_SCHEDULING)) {
1401 // set timer to give up if we do not receive a fix within NO_FIX_TIMEOUT
1402 // and our fix interval is not short
1403 if (mFixInterval >= NO_FIX_TIMEOUT) {
1404 mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
1405 SystemClock.elapsedRealtime() + NO_FIX_TIMEOUT, mTimeoutIntent);
1406 }
Mike Lockwood0632ca72009-05-14 15:51:03 -04001407 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001408 }
1409 }
1410
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001411 private void stopNavigating() {
Mike Lockwood29c84342009-05-06 14:01:15 -04001412 if (DEBUG) Log.d(TAG, "stopNavigating");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001413 if (mStarted) {
1414 mStarted = false;
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001415 mSingleShot = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001416 native_stop();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001417 mTimeToFirstFix = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001418 mLastFixTime = 0;
1419 mLocationFlags = LOCATION_INVALID;
1420
1421 // reset SV count to zero
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001422 updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001423 }
1424 }
1425
Mike Lockwood0632ca72009-05-14 15:51:03 -04001426 private void hibernate() {
1427 // stop GPS until our next fix interval arrives
1428 stopNavigating();
Mike Lockwood0632ca72009-05-14 15:51:03 -04001429 mAlarmManager.cancel(mTimeoutIntent);
1430 mAlarmManager.cancel(mWakeupIntent);
1431 long now = SystemClock.elapsedRealtime();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001432 mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, now + mFixInterval, mWakeupIntent);
Mike Lockwood04598b62010-04-14 17:17:24 -04001433 }
1434
1435 private boolean hasCapability(int capability) {
1436 return ((mEngineCapabilities & capability) != 0);
Mike Lockwood0632ca72009-05-14 15:51:03 -04001437 }
1438
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001439
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001440 /**
1441 * called from native code to update our position.
1442 */
1443 private void reportLocation(int flags, double latitude, double longitude, double altitude,
1444 float speed, float bearing, float accuracy, long timestamp) {
Mike Lockwood29c84342009-05-06 14:01:15 -04001445 if (VERBOSE) Log.v(TAG, "reportLocation lat: " + latitude + " long: " + longitude +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001446 " timestamp: " + timestamp);
1447
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001448 synchronized (mLocation) {
1449 mLocationFlags = flags;
1450 if ((flags & LOCATION_HAS_LAT_LONG) == LOCATION_HAS_LAT_LONG) {
1451 mLocation.setLatitude(latitude);
1452 mLocation.setLongitude(longitude);
1453 mLocation.setTime(timestamp);
Nick Pelly2eeeec22012-07-18 13:13:37 -07001454 // It would be nice to push the elapsed real-time timestamp
1455 // further down the stack, but this is still useful
Philip Milne41180122012-09-26 11:29:25 -07001456 mLocation.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001457 }
1458 if ((flags & LOCATION_HAS_ALTITUDE) == LOCATION_HAS_ALTITUDE) {
1459 mLocation.setAltitude(altitude);
1460 } else {
1461 mLocation.removeAltitude();
1462 }
1463 if ((flags & LOCATION_HAS_SPEED) == LOCATION_HAS_SPEED) {
1464 mLocation.setSpeed(speed);
1465 } else {
1466 mLocation.removeSpeed();
1467 }
1468 if ((flags & LOCATION_HAS_BEARING) == LOCATION_HAS_BEARING) {
1469 mLocation.setBearing(bearing);
1470 } else {
1471 mLocation.removeBearing();
1472 }
1473 if ((flags & LOCATION_HAS_ACCURACY) == LOCATION_HAS_ACCURACY) {
1474 mLocation.setAccuracy(accuracy);
1475 } else {
1476 mLocation.removeAccuracy();
1477 }
Sean Barbeauced2b2c2011-12-19 04:43:07 -05001478 mLocation.setExtras(mLocationExtras);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001479
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001480 try {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001481 mILocationManager.reportLocation(mLocation, false);
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001482 } catch (RemoteException e) {
1483 Log.e(TAG, "RemoteException calling reportLocation");
1484 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001485 }
1486
Hakan Gustavssonfa94ff02010-02-23 09:12:38 +01001487 mLastFixTime = System.currentTimeMillis();
1488 // report time to first fix
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001489 if (mTimeToFirstFix == 0 && (flags & LOCATION_HAS_LAT_LONG) == LOCATION_HAS_LAT_LONG) {
1490 mTimeToFirstFix = (int)(mLastFixTime - mFixRequestTime);
1491 if (DEBUG) Log.d(TAG, "TTFF: " + mTimeToFirstFix);
Hakan Gustavssonfa94ff02010-02-23 09:12:38 +01001492
1493 // notify status listeners
destradaaea8a8a62014-06-23 18:19:03 -07001494 mListenerHelper.onFirstFix(mTimeToFirstFix);
Hakan Gustavssonfa94ff02010-02-23 09:12:38 +01001495 }
1496
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001497 if (mSingleShot) {
1498 stopNavigating();
1499 }
1500
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001501 if (mStarted && mStatus != LocationProvider.AVAILABLE) {
Mike Lockwoodd53ba012010-04-15 20:41:26 -04001502 // we want to time out if we do not receive a fix
Mike Lockwoodb7be5442010-02-24 14:34:50 -05001503 // within the time out and we are requesting infrequent fixes
Mike Lockwood04598b62010-04-14 17:17:24 -04001504 if (!hasCapability(GPS_CAPABILITY_SCHEDULING) && mFixInterval < NO_FIX_TIMEOUT) {
Mike Lockwoodb7be5442010-02-24 14:34:50 -05001505 mAlarmManager.cancel(mTimeoutIntent);
1506 }
1507
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001508 // send an intent to notify that the GPS is receiving fixes.
Mike Lockwood00b74272010-03-26 10:41:48 -04001509 Intent intent = new Intent(LocationManager.GPS_FIX_CHANGE_ACTION);
1510 intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, true);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07001511 mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001512 updateStatus(LocationProvider.AVAILABLE, mSvCount);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001513 }
Mike Lockwood29c84342009-05-06 14:01:15 -04001514
Nick Pellyb041f232012-05-07 17:12:25 -07001515 if (!hasCapability(GPS_CAPABILITY_SCHEDULING) && mStarted &&
1516 mFixInterval > GPS_POLLING_THRESHOLD_INTERVAL) {
Mike Lockwoodd53ba012010-04-15 20:41:26 -04001517 if (DEBUG) Log.d(TAG, "got fix, hibernating");
Mike Lockwood0632ca72009-05-14 15:51:03 -04001518 hibernate();
Mike Lockwood29c84342009-05-06 14:01:15 -04001519 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001520 }
1521
1522 /**
1523 * called from native code to update our status
1524 */
1525 private void reportStatus(int status) {
Mike Lockwoodb8d90332010-10-18 17:59:48 -04001526 if (DEBUG) Log.v(TAG, "reportStatus status: " + status);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001527
destradaaea8a8a62014-06-23 18:19:03 -07001528 boolean wasNavigating = mNavigating;
1529 switch (status) {
1530 case GPS_STATUS_SESSION_BEGIN:
1531 mNavigating = true;
1532 mEngineOn = true;
1533 break;
1534 case GPS_STATUS_SESSION_END:
1535 mNavigating = false;
1536 break;
1537 case GPS_STATUS_ENGINE_ON:
1538 mEngineOn = true;
1539 break;
1540 case GPS_STATUS_ENGINE_OFF:
1541 mEngineOn = false;
1542 mNavigating = false;
1543 break;
1544 }
Mike Lockwooddbd6fd82009-12-07 18:43:36 -05001545
destradaaea8a8a62014-06-23 18:19:03 -07001546 if (wasNavigating != mNavigating) {
destradaa13a60b02015-01-15 18:36:01 -08001547 mListenerHelper.onStatusChanged(mNavigating);
Mike Lockwoodcf1d8cb2010-01-20 10:14:54 -05001548
destradaaea8a8a62014-06-23 18:19:03 -07001549 // send an intent to notify that the GPS has been enabled or disabled
1550 Intent intent = new Intent(LocationManager.GPS_ENABLED_CHANGE_ACTION);
1551 intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, mNavigating);
1552 mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001553 }
1554 }
1555
1556 /**
1557 * called from native code to update SV info
1558 */
1559 private void reportSvStatus() {
Lifu Tang30f95a72016-01-07 23:20:38 -08001560 int svCount = native_read_sv_status(mPrnWithFlags, mSnrs, mSvElevations, mSvAzimuths,
1561 mConstellationTypes);
destradaaea8a8a62014-06-23 18:19:03 -07001562 mListenerHelper.onSvStatusChanged(
1563 svCount,
Lifu Tang30f95a72016-01-07 23:20:38 -08001564 mPrnWithFlags,
destradaaea8a8a62014-06-23 18:19:03 -07001565 mSnrs,
1566 mSvElevations,
1567 mSvAzimuths,
Lifu Tang30f95a72016-01-07 23:20:38 -08001568 mConstellationTypes);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001569
Mike Lockwood29c84342009-05-06 14:01:15 -04001570 if (VERBOSE) {
Lifu Tang30f95a72016-01-07 23:20:38 -08001571 Log.v(TAG, "SV count: " + svCount);
1572 }
1573 // Calculate number of sets used in fix.
1574 int usedInFixCount = 0;
1575 for (int i = 0; i < svCount; i++) {
1576 if ((mPrnWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_USED_IN_FIX) != 0) {
1577 ++usedInFixCount;
1578 }
1579 if (VERBOSE) {
1580 Log.v(TAG, "prn: " + (mPrnWithFlags[i] >> GnssStatus.PRN_SHIFT_WIDTH) +
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001581 " snr: " + mSnrs[i]/10 +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001582 " elev: " + mSvElevations[i] +
1583 " azimuth: " + mSvAzimuths[i] +
Lifu Tang30f95a72016-01-07 23:20:38 -08001584 ((mPrnWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_HAS_EPHEMERIS_DATA) == 0
1585 ? " " : " E") +
1586 ((mPrnWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_HAS_ALMANAC_DATA) == 0
1587 ? " " : " A") +
1588 ((mPrnWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_USED_IN_FIX) == 0
1589 ? "" : "U"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001590 }
1591 }
Kevin.KY Tsai0881f4f2010-05-21 15:10:39 -04001592 // return number of sets used in fix instead of total
Lifu Tang30f95a72016-01-07 23:20:38 -08001593 updateStatus(mStatus, usedInFixCount);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001594
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001595 if (mNavigating && mStatus == LocationProvider.AVAILABLE && mLastFixTime > 0 &&
Mike Lockwood04598b62010-04-14 17:17:24 -04001596 System.currentTimeMillis() - mLastFixTime > RECENT_FIX_TIMEOUT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001597 // send an intent to notify that the GPS is no longer receiving fixes.
Mike Lockwood00b74272010-03-26 10:41:48 -04001598 Intent intent = new Intent(LocationManager.GPS_FIX_CHANGE_ACTION);
1599 intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, false);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07001600 mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001601 updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, mSvCount);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001602 }
1603 }
Mike Lockwood58bda982009-04-14 16:25:07 -04001604
1605 /**
Mike Lockwoode3635c92009-05-11 08:38:02 -04001606 * called from native code to update AGPS status
Mike Lockwood58bda982009-04-14 16:25:07 -04001607 */
destradaa96a14702014-06-05 11:36:30 -07001608 private void reportAGpsStatus(int type, int status, byte[] ipaddr) {
Mike Lockwood58bda982009-04-14 16:25:07 -04001609 switch (status) {
Mike Lockwoode3635c92009-05-11 08:38:02 -04001610 case GPS_REQUEST_AGPS_DATA_CONN:
Mike Lockwoodb6e5fa82010-10-09 20:10:46 -04001611 if (DEBUG) Log.d(TAG, "GPS_REQUEST_AGPS_DATA_CONN");
Andreas Gampee6748ce2015-12-11 18:00:38 -08001612 Log.v(TAG, "Received SUPL IP addr[]: " + Arrays.toString(ipaddr));
destradaae21252a2015-09-08 12:32:59 -07001613 InetAddress connectionIpAddress = null;
destradaa96a14702014-06-05 11:36:30 -07001614 if (ipaddr != null) {
1615 try {
destradaae21252a2015-09-08 12:32:59 -07001616 connectionIpAddress = InetAddress.getByAddress(ipaddr);
1617 if (DEBUG) Log.d(TAG, "IP address converted to: " + connectionIpAddress);
destradaa96a14702014-06-05 11:36:30 -07001618 } catch (UnknownHostException e) {
1619 Log.e(TAG, "Bad IP Address: " + ipaddr, e);
destradaa96a14702014-06-05 11:36:30 -07001620 }
1621 }
destradaae21252a2015-09-08 12:32:59 -07001622 sendMessage(REQUEST_SUPL_CONNECTION, 0 /*arg*/, connectionIpAddress);
Mike Lockwood58bda982009-04-14 16:25:07 -04001623 break;
Mike Lockwoode3635c92009-05-11 08:38:02 -04001624 case GPS_RELEASE_AGPS_DATA_CONN:
Mike Lockwoodb6e5fa82010-10-09 20:10:46 -04001625 if (DEBUG) Log.d(TAG, "GPS_RELEASE_AGPS_DATA_CONN");
destradaae21252a2015-09-08 12:32:59 -07001626 releaseSuplConnection(GPS_RELEASE_AGPS_DATA_CONN);
Mike Lockwood58bda982009-04-14 16:25:07 -04001627 break;
Mike Lockwoode3635c92009-05-11 08:38:02 -04001628 case GPS_AGPS_DATA_CONNECTED:
Mike Lockwoodb6e5fa82010-10-09 20:10:46 -04001629 if (DEBUG) Log.d(TAG, "GPS_AGPS_DATA_CONNECTED");
Mike Lockwood58bda982009-04-14 16:25:07 -04001630 break;
Mike Lockwoode3635c92009-05-11 08:38:02 -04001631 case GPS_AGPS_DATA_CONN_DONE:
Mike Lockwoodb6e5fa82010-10-09 20:10:46 -04001632 if (DEBUG) Log.d(TAG, "GPS_AGPS_DATA_CONN_DONE");
Mike Lockwood58bda982009-04-14 16:25:07 -04001633 break;
Mike Lockwoode3635c92009-05-11 08:38:02 -04001634 case GPS_AGPS_DATA_CONN_FAILED:
Mike Lockwoodb6e5fa82010-10-09 20:10:46 -04001635 if (DEBUG) Log.d(TAG, "GPS_AGPS_DATA_CONN_FAILED");
Mike Lockwood58bda982009-04-14 16:25:07 -04001636 break;
destradaa931a37f2014-08-12 16:36:59 -07001637 default:
1638 Log.d(TAG, "Received Unknown AGPS status: " + status);
Mike Lockwood58bda982009-04-14 16:25:07 -04001639 }
1640 }
1641
destradaae21252a2015-09-08 12:32:59 -07001642 private void releaseSuplConnection(int connStatus) {
1643 sendMessage(RELEASE_SUPL_CONNECTION, connStatus, null /*obj*/);
1644 }
1645
Mike Lockwoodb16e7802009-08-06 09:26:02 -04001646 /**
1647 * called from native code to report NMEA data received
1648 */
Mike Lockwoodf602d362010-06-20 14:28:16 -07001649 private void reportNmea(long timestamp) {
destradaaea8a8a62014-06-23 18:19:03 -07001650 int length = native_read_nmea(mNmeaBuffer, mNmeaBuffer.length);
1651 String nmea = new String(mNmeaBuffer, 0 /* offset */, length);
1652 mListenerHelper.onNmeaReceived(timestamp, nmea);
1653 }
Mike Lockwoodb16e7802009-08-06 09:26:02 -04001654
destradaaea8a8a62014-06-23 18:19:03 -07001655 /**
destradaa4b3e3932014-07-21 18:01:47 -07001656 * called from native code - Gps measurements callback
destradaaea8a8a62014-06-23 18:19:03 -07001657 */
1658 private void reportMeasurementData(GpsMeasurementsEvent event) {
1659 mGpsMeasurementsProvider.onMeasurementsAvailable(event);
Mike Lockwoodb16e7802009-08-06 09:26:02 -04001660 }
1661
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001662 /**
destradaa4b3e3932014-07-21 18:01:47 -07001663 * called from native code - GPS navigation message callback
1664 */
1665 private void reportNavigationMessage(GpsNavigationMessageEvent event) {
1666 mGpsNavigationMessageProvider.onNavigationMessageAvailable(event);
1667 }
1668
1669 /**
Mike Lockwood04598b62010-04-14 17:17:24 -04001670 * called from native code to inform us what the GPS engine capabilities are
1671 */
1672 private void setEngineCapabilities(int capabilities) {
1673 mEngineCapabilities = capabilities;
Mike Lockwood9b9fb5c2011-06-29 15:09:40 -04001674
destradaa56b47f82015-07-24 10:56:18 -07001675 if (hasCapability(GPS_CAPABILITY_ON_DEMAND_TIME)) {
1676 mOnDemandTimeInjection = true;
Mike Lockwood9b9fb5c2011-06-29 15:09:40 -04001677 requestUtcTime();
1678 }
destradaa6568d702014-10-27 12:47:41 -07001679
1680 mGpsMeasurementsProvider.onCapabilitiesUpdated(
1681 (capabilities & GPS_CAPABILITY_MEASUREMENTS) == GPS_CAPABILITY_MEASUREMENTS);
1682 mGpsNavigationMessageProvider.onCapabilitiesUpdated(
1683 (capabilities & GPS_CAPABILITY_NAV_MESSAGES) == GPS_CAPABILITY_NAV_MESSAGES);
Mike Lockwood04598b62010-04-14 17:17:24 -04001684 }
1685
1686 /**
Lifu Tang82f893d2016-01-21 18:15:33 -08001687 * Called from native code to inform us the hardware information.
1688 */
1689 private void setGpsYearOfHardware(int yearOfHardware) {
1690 if (DEBUG) Log.d(TAG, "setGpsYearOfHardware called with " + yearOfHardware);
1691 mYearOfHardware = yearOfHardware;
1692 }
1693
1694 public interface GpsSystemInfoProvider {
1695 /**
1696 * Returns the year of GPS hardware.
1697 */
1698 int getGpsYearOfHardware();
1699 }
1700
1701 /**
1702 * @hide
1703 */
1704 public GpsSystemInfoProvider getGpsSystemInfoProvider() {
1705 return new GpsSystemInfoProvider() {
1706 @Override
1707 public int getGpsYearOfHardware() {
1708 return mYearOfHardware;
1709 }
1710 };
1711 }
1712
1713 /**
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001714 * called from native code to request XTRA data
1715 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001716 private void xtraDownloadRequest() {
Joe Onoratof5d95cb2010-01-07 21:48:32 -05001717 if (DEBUG) Log.d(TAG, "xtraDownloadRequest");
Mike Lockwood98e48692010-04-07 16:32:51 -04001718 sendMessage(DOWNLOAD_XTRA_DATA, 0, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001719 }
1720
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001721 /**
destradaa0682809a2013-08-12 18:50:30 -07001722 * Helper method to construct a location object.
1723 */
1724 private Location buildLocation(
1725 int flags,
1726 double latitude,
1727 double longitude,
1728 double altitude,
1729 float speed,
1730 float bearing,
1731 float accuracy,
1732 long timestamp) {
1733 Location location = new Location(LocationManager.GPS_PROVIDER);
1734 if((flags & LOCATION_HAS_LAT_LONG) == LOCATION_HAS_LAT_LONG) {
1735 location.setLatitude(latitude);
1736 location.setLongitude(longitude);
1737 location.setTime(timestamp);
1738 location.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());
1739 }
1740 if((flags & LOCATION_HAS_ALTITUDE) == LOCATION_HAS_ALTITUDE) {
1741 location.setAltitude(altitude);
1742 }
1743 if((flags & LOCATION_HAS_SPEED) == LOCATION_HAS_SPEED) {
1744 location.setSpeed(speed);
1745 }
1746 if((flags & LOCATION_HAS_BEARING) == LOCATION_HAS_BEARING) {
1747 location.setBearing(bearing);
1748 }
1749 if((flags & LOCATION_HAS_ACCURACY) == LOCATION_HAS_ACCURACY) {
1750 location.setAccuracy(accuracy);
1751 }
1752 return location;
1753 }
1754
1755 /**
1756 * Converts the GPS HAL status to the internal Geofence Hardware status.
1757 */
1758 private int getGeofenceStatus(int status) {
1759 switch(status) {
1760 case GPS_GEOFENCE_OPERATION_SUCCESS:
1761 return GeofenceHardware.GEOFENCE_SUCCESS;
1762 case GPS_GEOFENCE_ERROR_GENERIC:
1763 return GeofenceHardware.GEOFENCE_FAILURE;
1764 case GPS_GEOFENCE_ERROR_ID_EXISTS:
1765 return GeofenceHardware.GEOFENCE_ERROR_ID_EXISTS;
1766 case GPS_GEOFENCE_ERROR_INVALID_TRANSITION:
1767 return GeofenceHardware.GEOFENCE_ERROR_INVALID_TRANSITION;
1768 case GPS_GEOFENCE_ERROR_TOO_MANY_GEOFENCES:
1769 return GeofenceHardware.GEOFENCE_ERROR_TOO_MANY_GEOFENCES;
1770 case GPS_GEOFENCE_ERROR_ID_UNKNOWN:
1771 return GeofenceHardware.GEOFENCE_ERROR_ID_UNKNOWN;
1772 default:
1773 return -1;
1774 }
1775 }
1776
1777 /**
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001778 * Called from native to report GPS Geofence transition
1779 * All geofence callbacks are called on the same thread
1780 */
1781 private void reportGeofenceTransition(int geofenceId, int flags, double latitude,
1782 double longitude, double altitude, float speed, float bearing, float accuracy,
1783 long timestamp, int transition, long transitionTimestamp) {
1784 if (mGeofenceHardwareImpl == null) {
1785 mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
1786 }
destradaa0682809a2013-08-12 18:50:30 -07001787 Location location = buildLocation(
1788 flags,
1789 latitude,
1790 longitude,
1791 altitude,
1792 speed,
1793 bearing,
1794 accuracy,
1795 timestamp);
1796 mGeofenceHardwareImpl.reportGeofenceTransition(
1797 geofenceId,
1798 location,
1799 transition,
1800 transitionTimestamp,
1801 GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE,
1802 FusedBatchOptions.SourceTechnologies.GNSS);
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001803 }
1804
1805 /**
1806 * called from native code to report GPS status change.
1807 */
1808 private void reportGeofenceStatus(int status, int flags, double latitude,
1809 double longitude, double altitude, float speed, float bearing, float accuracy,
1810 long timestamp) {
1811 if (mGeofenceHardwareImpl == null) {
1812 mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
1813 }
destradaa0682809a2013-08-12 18:50:30 -07001814 Location location = buildLocation(
1815 flags,
1816 latitude,
1817 longitude,
1818 altitude,
1819 speed,
1820 bearing,
1821 accuracy,
1822 timestamp);
1823 int monitorStatus = GeofenceHardware.MONITOR_CURRENTLY_UNAVAILABLE;
1824 if(status == GPS_GEOFENCE_AVAILABLE) {
1825 monitorStatus = GeofenceHardware.MONITOR_CURRENTLY_AVAILABLE;
1826 }
1827 mGeofenceHardwareImpl.reportGeofenceMonitorStatus(
1828 GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE,
1829 monitorStatus,
1830 location,
1831 FusedBatchOptions.SourceTechnologies.GNSS);
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001832 }
1833
1834 /**
1835 * called from native code - Geofence Add callback
1836 */
1837 private void reportGeofenceAddStatus(int geofenceId, int status) {
1838 if (mGeofenceHardwareImpl == null) {
1839 mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
1840 }
destradaa0682809a2013-08-12 18:50:30 -07001841 mGeofenceHardwareImpl.reportGeofenceAddStatus(geofenceId, getGeofenceStatus(status));
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001842 }
1843
1844 /**
1845 * called from native code - Geofence Remove callback
1846 */
1847 private void reportGeofenceRemoveStatus(int geofenceId, int status) {
1848 if (mGeofenceHardwareImpl == null) {
1849 mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
1850 }
destradaa0682809a2013-08-12 18:50:30 -07001851 mGeofenceHardwareImpl.reportGeofenceRemoveStatus(geofenceId, getGeofenceStatus(status));
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001852 }
1853
1854 /**
1855 * called from native code - Geofence Pause callback
1856 */
1857 private void reportGeofencePauseStatus(int geofenceId, int status) {
1858 if (mGeofenceHardwareImpl == null) {
1859 mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
1860 }
destradaa0682809a2013-08-12 18:50:30 -07001861 mGeofenceHardwareImpl.reportGeofencePauseStatus(geofenceId, getGeofenceStatus(status));
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001862 }
1863
1864 /**
1865 * called from native code - Geofence Resume callback
1866 */
1867 private void reportGeofenceResumeStatus(int geofenceId, int status) {
1868 if (mGeofenceHardwareImpl == null) {
1869 mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
1870 }
destradaa0682809a2013-08-12 18:50:30 -07001871 mGeofenceHardwareImpl.reportGeofenceResumeStatus(geofenceId, getGeofenceStatus(status));
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001872 }
1873
Danke Xie22d1f9f2009-08-18 18:28:45 -04001874 //=============================================================
1875 // NI Client support
Miguel Torroja1e84da82010-07-27 07:02:24 +02001876 //=============================================================
Danke Xie22d1f9f2009-08-18 18:28:45 -04001877 private final INetInitiatedListener mNetInitiatedListener = new INetInitiatedListener.Stub() {
destradaaef752b62015-04-17 13:10:47 -07001878 // Sends a response for an NI request to HAL.
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001879 @Override
Miguel Torroja1e84da82010-07-27 07:02:24 +02001880 public boolean sendNiResponse(int notificationId, int userResponse)
1881 {
1882 // TODO Add Permission check
Danke Xie22d1f9f2009-08-18 18:28:45 -04001883
Miguel Torroja1e84da82010-07-27 07:02:24 +02001884 if (DEBUG) Log.d(TAG, "sendNiResponse, notifId: " + notificationId +
1885 ", response: " + userResponse);
1886 native_send_ni_response(notificationId, userResponse);
1887 return true;
1888 }
Danke Xie22d1f9f2009-08-18 18:28:45 -04001889 };
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001890
Danke Xie22d1f9f2009-08-18 18:28:45 -04001891 public INetInitiatedListener getNetInitiatedListener() {
1892 return mNetInitiatedListener;
1893 }
1894
1895 // Called by JNI function to report an NI request.
Miguel Torroja1e84da82010-07-27 07:02:24 +02001896 public void reportNiNotification(
1897 int notificationId,
1898 int niType,
1899 int notifyFlags,
1900 int timeout,
1901 int defaultResponse,
1902 String requestorId,
1903 String text,
1904 int requestorIdEncoding,
1905 int textEncoding,
1906 String extras // Encoded extra data
Danke Xie22d1f9f2009-08-18 18:28:45 -04001907 )
Miguel Torroja1e84da82010-07-27 07:02:24 +02001908 {
1909 Log.i(TAG, "reportNiNotification: entered");
1910 Log.i(TAG, "notificationId: " + notificationId +
1911 ", niType: " + niType +
1912 ", notifyFlags: " + notifyFlags +
1913 ", timeout: " + timeout +
1914 ", defaultResponse: " + defaultResponse);
1915
1916 Log.i(TAG, "requestorId: " + requestorId +
1917 ", text: " + text +
1918 ", requestorIdEncoding: " + requestorIdEncoding +
1919 ", textEncoding: " + textEncoding);
1920
1921 GpsNiNotification notification = new GpsNiNotification();
1922
1923 notification.notificationId = notificationId;
1924 notification.niType = niType;
1925 notification.needNotify = (notifyFlags & GpsNetInitiatedHandler.GPS_NI_NEED_NOTIFY) != 0;
1926 notification.needVerify = (notifyFlags & GpsNetInitiatedHandler.GPS_NI_NEED_VERIFY) != 0;
1927 notification.privacyOverride = (notifyFlags & GpsNetInitiatedHandler.GPS_NI_PRIVACY_OVERRIDE) != 0;
1928 notification.timeout = timeout;
1929 notification.defaultResponse = defaultResponse;
1930 notification.requestorId = requestorId;
1931 notification.text = text;
1932 notification.requestorIdEncoding = requestorIdEncoding;
1933 notification.textEncoding = textEncoding;
1934
1935 // Process extras, assuming the format is
1936 // one of more lines of "key = value"
1937 Bundle bundle = new Bundle();
1938
1939 if (extras == null) extras = "";
1940 Properties extraProp = new Properties();
1941
1942 try {
Jeff Sharkey104344e2011-07-10 14:20:41 -07001943 extraProp.load(new StringReader(extras));
Miguel Torroja1e84da82010-07-27 07:02:24 +02001944 }
1945 catch (IOException e)
1946 {
1947 Log.e(TAG, "reportNiNotification cannot parse extras data: " + extras);
1948 }
1949
1950 for (Entry<Object, Object> ent : extraProp.entrySet())
1951 {
1952 bundle.putString((String) ent.getKey(), (String) ent.getValue());
1953 }
1954
1955 notification.extras = bundle;
1956
1957 mNIHandler.handleNiNotification(notification);
1958 }
1959
1960 /**
1961 * Called from native code to request set id info.
1962 * We should be careful about receiving null string from the TelephonyManager,
1963 * because sending null String to JNI function would cause a crash.
1964 */
1965
1966 private void requestSetID(int flags) {
1967 TelephonyManager phone = (TelephonyManager)
1968 mContext.getSystemService(Context.TELEPHONY_SERVICE);
destradaaef752b62015-04-17 13:10:47 -07001969 int type = AGPS_SETID_TYPE_NONE;
Miguel Torroja1e84da82010-07-27 07:02:24 +02001970 String data = "";
1971
1972 if ((flags & AGPS_RIL_REQUEST_SETID_IMSI) == AGPS_RIL_REQUEST_SETID_IMSI) {
1973 String data_temp = phone.getSubscriberId();
1974 if (data_temp == null) {
1975 // This means the framework does not have the SIM card ready.
1976 } else {
1977 // This means the framework has the SIM card.
1978 data = data_temp;
1979 type = AGPS_SETID_TYPE_IMSI;
1980 }
1981 }
1982 else if ((flags & AGPS_RIL_REQUEST_SETID_MSISDN) == AGPS_RIL_REQUEST_SETID_MSISDN) {
1983 String data_temp = phone.getLine1Number();
1984 if (data_temp == null) {
1985 // This means the framework does not have the SIM card ready.
1986 } else {
1987 // This means the framework has the SIM card.
1988 data = data_temp;
1989 type = AGPS_SETID_TYPE_MSISDN;
1990 }
1991 }
1992 native_agps_set_id(type, data);
1993 }
1994
1995 /**
Mike Lockwood9b9fb5c2011-06-29 15:09:40 -04001996 * Called from native code to request utc time info
1997 */
Mike Lockwood9b9fb5c2011-06-29 15:09:40 -04001998 private void requestUtcTime() {
destradaae21252a2015-09-08 12:32:59 -07001999 if (DEBUG) Log.d(TAG, "utcTimeRequest");
Mike Lockwood9b9fb5c2011-06-29 15:09:40 -04002000 sendMessage(INJECT_NTP_TIME, 0, null);
2001 }
2002
2003 /**
Miguel Torroja1e84da82010-07-27 07:02:24 +02002004 * Called from native code to request reference location info
2005 */
2006
2007 private void requestRefLocation(int flags) {
2008 TelephonyManager phone = (TelephonyManager)
2009 mContext.getSystemService(Context.TELEPHONY_SERVICE);
Victoria Leased50d0c32012-10-29 13:16:17 -07002010 final int phoneType = phone.getPhoneType();
2011 if (phoneType == TelephonyManager.PHONE_TYPE_GSM) {
Miguel Torroja1e84da82010-07-27 07:02:24 +02002012 GsmCellLocation gsm_cell = (GsmCellLocation) phone.getCellLocation();
Victoria Leased50d0c32012-10-29 13:16:17 -07002013 if ((gsm_cell != null) && (phone.getNetworkOperator() != null)
2014 && (phone.getNetworkOperator().length() > 3)) {
Miguel Torroja1e84da82010-07-27 07:02:24 +02002015 int type;
2016 int mcc = Integer.parseInt(phone.getNetworkOperator().substring(0,3));
2017 int mnc = Integer.parseInt(phone.getNetworkOperator().substring(3));
Mike Lockwoodedc0f3872010-10-22 09:16:17 -04002018 int networkType = phone.getNetworkType();
2019 if (networkType == TelephonyManager.NETWORK_TYPE_UMTS
2020 || networkType == TelephonyManager.NETWORK_TYPE_HSDPA
2021 || networkType == TelephonyManager.NETWORK_TYPE_HSUPA
Arun Ravindran58d46122012-07-30 17:50:21 +03002022 || networkType == TelephonyManager.NETWORK_TYPE_HSPA
2023 || networkType == TelephonyManager.NETWORK_TYPE_HSPAP) {
Miguel Torroja1e84da82010-07-27 07:02:24 +02002024 type = AGPS_REF_LOCATION_TYPE_UMTS_CELLID;
Mike Lockwoodedc0f3872010-10-22 09:16:17 -04002025 } else {
Miguel Torroja1e84da82010-07-27 07:02:24 +02002026 type = AGPS_REF_LOCATION_TYPE_GSM_CELLID;
Mike Lockwoodedc0f3872010-10-22 09:16:17 -04002027 }
Miguel Torroja1e84da82010-07-27 07:02:24 +02002028 native_agps_set_ref_location_cellid(type, mcc, mnc,
2029 gsm_cell.getLac(), gsm_cell.getCid());
Mike Lockwoodedc0f3872010-10-22 09:16:17 -04002030 } else {
Miguel Torroja1e84da82010-07-27 07:02:24 +02002031 Log.e(TAG,"Error getting cell location info.");
Mike Lockwoodedc0f3872010-10-22 09:16:17 -04002032 }
Victoria Leased50d0c32012-10-29 13:16:17 -07002033 } else if (phoneType == TelephonyManager.PHONE_TYPE_CDMA) {
2034 Log.e(TAG, "CDMA not supported.");
Mike Lockwoodedc0f3872010-10-22 09:16:17 -04002035 }
Miguel Torroja1e84da82010-07-27 07:02:24 +02002036 }
Danke Xie22d1f9f2009-08-18 18:28:45 -04002037
Mike Lockwood98e48692010-04-07 16:32:51 -04002038 private void sendMessage(int message, int arg, Object obj) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002039 // hold a wake lock until this message is delivered
Jeff Brown028872f2012-08-25 13:07:01 -07002040 // note that this assumes the message will not be removed from the queue before
2041 // it is handled (otherwise the wake lock would be leaked).
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002042 mWakeLock.acquire();
2043 mHandler.obtainMessage(message, arg, 1, obj).sendToTarget();
Mike Lockwood98e48692010-04-07 16:32:51 -04002044 }
2045
Mike Lockwood62a8fc12010-03-22 14:23:26 -04002046 private final class ProviderHandler extends Handler {
Victoria Lease5cd731a2012-12-19 15:04:21 -08002047 public ProviderHandler(Looper looper) {
2048 super(looper, null, true /*async*/);
Jeff Brown028872f2012-08-25 13:07:01 -07002049 }
2050
Mike Lockwood62a8fc12010-03-22 14:23:26 -04002051 @Override
Mike Lockwood4a7b65e2010-10-25 16:35:55 -04002052 public void handleMessage(Message msg) {
Mike Lockwood98e48692010-04-07 16:32:51 -04002053 int message = msg.what;
2054 switch (message) {
Mike Lockwood62a8fc12010-03-22 14:23:26 -04002055 case ENABLE:
2056 if (msg.arg1 == 1) {
2057 handleEnable();
2058 } else {
2059 handleDisable();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002060 }
Mike Lockwood62a8fc12010-03-22 14:23:26 -04002061 break;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002062 case SET_REQUEST:
2063 GpsRequest gpsRequest = (GpsRequest) msg.obj;
2064 handleSetRequest(gpsRequest.request, gpsRequest.source);
Mike Lockwood03ca2162010-04-01 08:10:09 -07002065 break;
Mike Lockwood62a8fc12010-03-22 14:23:26 -04002066 case UPDATE_NETWORK_STATE:
destradaae21252a2015-09-08 12:32:59 -07002067 handleUpdateNetworkState((Network) msg.obj);
2068 break;
2069 case REQUEST_SUPL_CONNECTION:
2070 handleRequestSuplConnection((InetAddress) msg.obj);
2071 break;
2072 case RELEASE_SUPL_CONNECTION:
2073 handleReleaseSuplConnection(msg.arg1);
Mike Lockwood62a8fc12010-03-22 14:23:26 -04002074 break;
2075 case INJECT_NTP_TIME:
2076 handleInjectNtpTime();
2077 break;
2078 case DOWNLOAD_XTRA_DATA:
Mike Lockwood1a1cd3a2010-08-17 07:42:54 -04002079 if (mSupportsXtra) {
Mike Lockwood62a8fc12010-03-22 14:23:26 -04002080 handleDownloadXtraData();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002081 }
Mike Lockwood62a8fc12010-03-22 14:23:26 -04002082 break;
Kevin Tang40e1baf2012-01-10 14:32:44 -08002083 case INJECT_NTP_TIME_FINISHED:
2084 mInjectNtpTimePending = STATE_IDLE;
2085 break;
2086 case DOWNLOAD_XTRA_DATA_FINISHED:
2087 mDownloadXtraDataPending = STATE_IDLE;
2088 break;
Mike Lockwood62a8fc12010-03-22 14:23:26 -04002089 case UPDATE_LOCATION:
destradaae21252a2015-09-08 12:32:59 -07002090 handleUpdateLocation((Location) msg.obj);
Mike Lockwood62a8fc12010-03-22 14:23:26 -04002091 break;
destradaafb23c672015-04-16 14:01:27 -07002092 case SUBSCRIPTION_OR_SIM_CHANGED:
2093 subscriptionOrSimChanged(mContext);
2094 break;
2095 case INITIALIZE_HANDLER:
destradaae21252a2015-09-08 12:32:59 -07002096 handleInitialize();
destradaafb23c672015-04-16 14:01:27 -07002097 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002098 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002099 if (msg.arg2 == 1) {
2100 // wakelock was taken for this message, release it
2101 mWakeLock.release();
Mike Lockwood98e48692010-04-07 16:32:51 -04002102 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002103 }
destradaafb23c672015-04-16 14:01:27 -07002104
2105 /**
Lifu Tang30f95a72016-01-07 23:20:38 -08002106 * This method is bound to {@link #GnssLocationProvider(Context, ILocationManager, Looper)}.
destradaafb23c672015-04-16 14:01:27 -07002107 * It is in charge of loading properties and registering for events that will be posted to
2108 * this handler.
2109 */
destradaae21252a2015-09-08 12:32:59 -07002110 private void handleInitialize() {
destradaafb23c672015-04-16 14:01:27 -07002111 // load default GPS configuration
2112 // (this configuration might change in the future based on SIM changes)
2113 reloadGpsProperties(mContext, mProperties);
2114
2115 // TODO: When this object "finishes" we should unregister by invoking
2116 // SubscriptionManager.getInstance(mContext).unregister(mOnSubscriptionsChangedListener);
2117 // This is not strictly necessary because it will be unregistered if the
2118 // notification fails but it is good form.
2119
2120 // Register for SubscriptionInfo list changes which is guaranteed
2121 // to invoke onSubscriptionsChanged the first time.
2122 SubscriptionManager.from(mContext)
2123 .addOnSubscriptionsChangedListener(mOnSubscriptionsChangedListener);
2124
2125 // listen for events
destradaaef752b62015-04-17 13:10:47 -07002126 IntentFilter intentFilter;
2127 if (native_is_agps_ril_supported()) {
2128 intentFilter = new IntentFilter();
2129 intentFilter.addAction(Intents.DATA_SMS_RECEIVED_ACTION);
2130 intentFilter.addDataScheme("sms");
2131 intentFilter.addDataAuthority("localhost", "7275");
2132 mContext.registerReceiver(mBroadcastReceiver, intentFilter, null, this);
destradaafb23c672015-04-16 14:01:27 -07002133
destradaaef752b62015-04-17 13:10:47 -07002134 intentFilter = new IntentFilter();
2135 intentFilter.addAction(Intents.WAP_PUSH_RECEIVED_ACTION);
2136 try {
2137 intentFilter.addDataType("application/vnd.omaloc-supl-init");
2138 } catch (IntentFilter.MalformedMimeTypeException e) {
2139 Log.w(TAG, "Malformed SUPL init mime type");
2140 }
2141 mContext.registerReceiver(mBroadcastReceiver, intentFilter, null, this);
2142 } else if (DEBUG) {
2143 Log.d(TAG, "Skipped registration for SMS/WAP-PUSH messages because AGPS Ril in GPS"
2144 + " HAL is not supported");
destradaafb23c672015-04-16 14:01:27 -07002145 }
destradaafb23c672015-04-16 14:01:27 -07002146
2147 intentFilter = new IntentFilter();
2148 intentFilter.addAction(ALARM_WAKEUP);
2149 intentFilter.addAction(ALARM_TIMEOUT);
destradaafb23c672015-04-16 14:01:27 -07002150 intentFilter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED);
Adam Lesinski87c17df2015-05-27 13:24:13 -07002151 intentFilter.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
destradaafb23c672015-04-16 14:01:27 -07002152 intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
2153 intentFilter.addAction(Intent.ACTION_SCREEN_ON);
2154 intentFilter.addAction(SIM_STATE_CHANGED);
2155 mContext.registerReceiver(mBroadcastReceiver, intentFilter, null, this);
2156
destradaae21252a2015-09-08 12:32:59 -07002157 // register for connectivity change events, this is equivalent to the deprecated way of
2158 // registering for CONNECTIVITY_ACTION broadcasts
2159 NetworkRequest.Builder networkRequestBuilder = new NetworkRequest.Builder();
2160 networkRequestBuilder.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
2161 networkRequestBuilder.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
2162 NetworkRequest networkRequest = networkRequestBuilder.build();
2163 mConnMgr.registerNetworkCallback(networkRequest, mNetworkConnectivityCallback);
2164
destradaafb23c672015-04-16 14:01:27 -07002165 // listen for PASSIVE_PROVIDER updates
2166 LocationManager locManager =
2167 (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
2168 long minTime = 0;
2169 float minDistance = 0;
2170 boolean oneShot = false;
2171 LocationRequest request = LocationRequest.createFromDeprecatedProvider(
2172 LocationManager.PASSIVE_PROVIDER,
2173 minTime,
2174 minDistance,
2175 oneShot);
2176 // Don't keep track of this request since it's done on behalf of other clients
2177 // (which are kept track of separately).
2178 request.setHideFromAppOps(true);
2179 locManager.requestLocationUpdates(
2180 request,
2181 new NetworkLocationListener(),
2182 getLooper());
2183 }
2184 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002185
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002186 private final class NetworkLocationListener implements LocationListener {
2187 @Override
2188 public void onLocationChanged(Location location) {
2189 // this callback happens on mHandler looper
2190 if (LocationManager.NETWORK_PROVIDER.equals(location.getProvider())) {
2191 handleUpdateLocation(location);
2192 }
2193 }
2194 @Override
2195 public void onStatusChanged(String provider, int status, Bundle extras) { }
2196 @Override
2197 public void onProviderEnabled(String provider) { }
2198 @Override
2199 public void onProviderDisabled(String provider) { }
2200 }
2201
Kevin Tanga5fe6b22011-06-05 14:25:16 -07002202 private String getSelectedApn() {
2203 Uri uri = Uri.parse("content://telephony/carriers/preferapn");
destradaa96a14702014-06-05 11:36:30 -07002204 Cursor cursor = null;
2205 try {
2206 cursor = mContext.getContentResolver().query(
2207 uri,
2208 new String[] { "apn" },
2209 null /* selection */,
2210 null /* selectionArgs */,
2211 Carriers.DEFAULT_SORT_ORDER);
2212 if (cursor != null && cursor.moveToFirst()) {
2213 return cursor.getString(0);
2214 } else {
2215 Log.e(TAG, "No APN found to select.");
2216 }
2217 } catch (Exception e) {
destradaaea8a8a62014-06-23 18:19:03 -07002218 Log.e(TAG, "Error encountered on selecting the APN.", e);
destradaa96a14702014-06-05 11:36:30 -07002219 } finally {
2220 if (cursor != null) {
Kevin Tanga5fe6b22011-06-05 14:25:16 -07002221 cursor.close();
2222 }
2223 }
destradaa96a14702014-06-05 11:36:30 -07002224
2225 return null;
2226 }
2227
2228 private int getApnIpType(String apn) {
destradaae21252a2015-09-08 12:32:59 -07002229 ensureInHandlerThread();
destradaa96a14702014-06-05 11:36:30 -07002230 if (apn == null) {
2231 return APN_INVALID;
2232 }
2233
destradaa96a14702014-06-05 11:36:30 -07002234 String selection = String.format("current = 1 and apn = '%s' and carrier_enabled = 1", apn);
2235 Cursor cursor = null;
2236 try {
2237 cursor = mContext.getContentResolver().query(
2238 Carriers.CONTENT_URI,
2239 new String[] { Carriers.PROTOCOL },
2240 selection,
2241 null,
2242 Carriers.DEFAULT_SORT_ORDER);
2243
2244 if (null != cursor && cursor.moveToFirst()) {
2245 return translateToApnIpType(cursor.getString(0), apn);
2246 } else {
2247 Log.e(TAG, "No entry found in query for APN: " + apn);
2248 }
2249 } catch (Exception e) {
2250 Log.e(TAG, "Error encountered on APN query for: " + apn, e);
2251 } finally {
2252 if (cursor != null) {
2253 cursor.close();
2254 }
2255 }
2256
2257 return APN_INVALID;
2258 }
2259
2260 private int translateToApnIpType(String ipProtocol, String apn) {
2261 if ("IP".equals(ipProtocol)) {
2262 return APN_IPV4;
2263 }
2264 if ("IPV6".equals(ipProtocol)) {
2265 return APN_IPV6;
2266 }
2267 if ("IPV4V6".equals(ipProtocol)) {
2268 return APN_IPV4V6;
2269 }
2270
2271 // we hit the default case so the ipProtocol is not recognized
2272 String message = String.format("Unknown IP Protocol: %s, for APN: %s", ipProtocol, apn);
2273 Log.e(TAG, message);
2274 return APN_INVALID;
2275 }
2276
2277 private void setRouting() {
2278 if (mAGpsDataConnectionIpAddr == null) {
2279 return;
2280 }
2281
destradaae21252a2015-09-08 12:32:59 -07002282 // TODO: replace the use of this deprecated API
destradaa96a14702014-06-05 11:36:30 -07002283 boolean result = mConnMgr.requestRouteToHostAddress(
2284 ConnectivityManager.TYPE_MOBILE_SUPL,
2285 mAGpsDataConnectionIpAddr);
2286
2287 if (!result) {
2288 Log.e(TAG, "Error requesting route to host: " + mAGpsDataConnectionIpAddr);
2289 } else if (DEBUG) {
2290 Log.d(TAG, "Successfully requested route to host: " + mAGpsDataConnectionIpAddr);
2291 }
Kevin Tanga5fe6b22011-06-05 14:25:16 -07002292 }
2293
destradaae21252a2015-09-08 12:32:59 -07002294 /**
2295 * @return {@code true} if there is a data network available for outgoing connections,
2296 * {@code false} otherwise.
2297 */
2298 private boolean isDataNetworkConnected() {
2299 NetworkInfo activeNetworkInfo = mConnMgr.getActiveNetworkInfo();
2300 return activeNetworkInfo != null && activeNetworkInfo.isConnected();
2301 }
2302
2303 /**
2304 * Ensures the calling function is running in the thread associated with {@link #mHandler}.
2305 */
2306 private void ensureInHandlerThread() {
2307 if (mHandler != null && Looper.myLooper() == mHandler.getLooper()) {
2308 return;
2309 }
2310 throw new RuntimeException("This method must run on the Handler thread.");
2311 }
2312
2313 /**
2314 * @return A string representing the current state stored in {@link #mAGpsDataConnectionState}.
2315 */
2316 private String agpsDataConnStateAsString() {
2317 switch(mAGpsDataConnectionState) {
2318 case AGPS_DATA_CONNECTION_CLOSED:
2319 return "CLOSED";
2320 case AGPS_DATA_CONNECTION_OPEN:
2321 return "OPEN";
2322 case AGPS_DATA_CONNECTION_OPENING:
2323 return "OPENING";
2324 default:
2325 return "<Unknown>";
2326 }
2327 }
2328
2329 /**
2330 * @return A string representing the given GPS_AGPS_DATA status.
2331 */
2332 private String agpsDataConnStatusAsString(int agpsDataConnStatus) {
2333 switch (agpsDataConnStatus) {
2334 case GPS_AGPS_DATA_CONNECTED:
2335 return "CONNECTED";
2336 case GPS_AGPS_DATA_CONN_DONE:
2337 return "DONE";
2338 case GPS_AGPS_DATA_CONN_FAILED:
2339 return "FAILED";
2340 case GPS_RELEASE_AGPS_DATA_CONN:
2341 return "RELEASE";
2342 case GPS_REQUEST_AGPS_DATA_CONN:
2343 return "REQUEST";
2344 default:
2345 return "<Unknown>";
2346 }
2347 }
2348
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002349 @Override
2350 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
2351 StringBuilder s = new StringBuilder();
destradaa25e8caf2015-08-24 14:14:44 -07002352 s.append(" mFixInterval=").append(mFixInterval).append('\n');
2353 s.append(" mDisableGps (battery saver mode)=").append(mDisableGps).append('\n');
2354 s.append(" mEngineCapabilities=0x").append(Integer.toHexString(mEngineCapabilities));
2355 s.append(" ( ");
2356 if (hasCapability(GPS_CAPABILITY_SCHEDULING)) s.append("SCHEDULING ");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002357 if (hasCapability(GPS_CAPABILITY_MSB)) s.append("MSB ");
2358 if (hasCapability(GPS_CAPABILITY_MSA)) s.append("MSA ");
2359 if (hasCapability(GPS_CAPABILITY_SINGLE_SHOT)) s.append("SINGLE_SHOT ");
2360 if (hasCapability(GPS_CAPABILITY_ON_DEMAND_TIME)) s.append("ON_DEMAND_TIME ");
destradaa25e8caf2015-08-24 14:14:44 -07002361 if (hasCapability(GPS_CAPABILITY_GEOFENCING)) s.append("GEOFENCING ");
2362 if (hasCapability(GPS_CAPABILITY_MEASUREMENTS)) s.append("MEASUREMENTS ");
2363 if (hasCapability(GPS_CAPABILITY_NAV_MESSAGES)) s.append("NAV_MESSAGES ");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002364 s.append(")\n");
2365
2366 s.append(native_get_internal_state());
2367 pw.append(s);
2368 }
2369
Wei Liu6f6326b2015-06-24 23:47:50 -07002370 /**
2371 * A simple implementation of exponential backoff.
2372 */
2373 private static final class BackOff {
2374 private static final int MULTIPLIER = 2;
2375 private final long mInitIntervalMillis;
2376 private final long mMaxIntervalMillis;
2377 private long mCurrentIntervalMillis;
2378
2379 public BackOff(long initIntervalMillis, long maxIntervalMillis) {
2380 mInitIntervalMillis = initIntervalMillis;
2381 mMaxIntervalMillis = maxIntervalMillis;
2382
2383 mCurrentIntervalMillis = mInitIntervalMillis / MULTIPLIER;
2384 }
2385
2386 public long nextBackoffMillis() {
2387 if (mCurrentIntervalMillis > mMaxIntervalMillis) {
2388 return mMaxIntervalMillis;
2389 }
2390
2391 mCurrentIntervalMillis *= MULTIPLIER;
2392 return mCurrentIntervalMillis;
2393 }
2394
2395 public void reset() {
2396 mCurrentIntervalMillis = mInitIntervalMillis / MULTIPLIER;
2397 }
2398 }
2399
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002400 // for GPS SV statistics
Lifu Tang30f95a72016-01-07 23:20:38 -08002401 private static final int MAX_SVS = 512;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002402
2403 // preallocated arrays, to avoid memory allocation in reportStatus()
Lifu Tang30f95a72016-01-07 23:20:38 -08002404 private int mPrnWithFlags[] = new int[MAX_SVS];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002405 private float mSnrs[] = new float[MAX_SVS];
2406 private float mSvElevations[] = new float[MAX_SVS];
2407 private float mSvAzimuths[] = new float[MAX_SVS];
Lifu Tang30f95a72016-01-07 23:20:38 -08002408 private int mConstellationTypes[] = new int[MAX_SVS];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002409 private int mSvCount;
Mike Lockwoodb16e7802009-08-06 09:26:02 -04002410 // preallocated to avoid memory allocation in reportNmea()
2411 private byte[] mNmeaBuffer = new byte[120];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002412
2413 static { class_init_native(); }
2414 private static native void class_init_native();
2415 private static native boolean native_is_supported();
destradaaef752b62015-04-17 13:10:47 -07002416 private static native boolean native_is_agps_ril_supported();
2417 private static native boolean native_is_gnss_configuration_supported();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002418
2419 private native boolean native_init();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002420 private native void native_cleanup();
Mike Lockwood04598b62010-04-14 17:17:24 -04002421 private native boolean native_set_position_mode(int mode, int recurrence, int min_interval,
2422 int preferred_accuracy, int preferred_time);
2423 private native boolean native_start();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002424 private native boolean native_stop();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002425 private native void native_delete_aiding_data(int flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002426 // returns number of SVs
2427 // mask[0] is ephemeris mask and mask[1] is almanac mask
Lifu Tang30f95a72016-01-07 23:20:38 -08002428 private native int native_read_sv_status(int[] prnWithFlags, float[] snrs, float[] elevations,
2429 float[] azimuths, int[] constellationTypes);
Mike Lockwoodf602d362010-06-20 14:28:16 -07002430 private native int native_read_nmea(byte[] buffer, int bufferSize);
Mike Lockwoodd26ce0d2009-06-11 12:25:46 -04002431 private native void native_inject_location(double latitude, double longitude, float accuracy);
2432
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -06002433 // XTRA Support
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002434 private native void native_inject_time(long time, long timeReference, int uncertainty);
2435 private native boolean native_supports_xtra();
2436 private native void native_inject_xtra_data(byte[] data, int length);
The Android Open Source Project10592532009-03-18 17:39:46 -07002437
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -06002438 // DEBUG Support
2439 private native String native_get_internal_state();
2440
2441 // AGPS Support
destradaa96a14702014-06-05 11:36:30 -07002442 private native void native_agps_data_conn_open(String apn, int apnIpType);
Mike Lockwoode3635c92009-05-11 08:38:02 -04002443 private native void native_agps_data_conn_closed();
2444 private native void native_agps_data_conn_failed();
Miguel Torroja1e84da82010-07-27 07:02:24 +02002445 private native void native_agps_ni_message(byte [] msg, int length);
Mike Lockwooda9e54612009-06-19 14:54:42 -04002446 private native void native_set_agps_server(int type, String hostname, int port);
Danke Xie22d1f9f2009-08-18 18:28:45 -04002447
2448 // Network-initiated (NI) Support
2449 private native void native_send_ni_response(int notificationId, int userResponse);
Miguel Torroja1e84da82010-07-27 07:02:24 +02002450
2451 // AGPS ril suport
2452 private native void native_agps_set_ref_location_cellid(int type, int mcc, int mnc,
2453 int lac, int cid);
2454 private native void native_agps_set_id(int type, String setid);
Mike Lockwood50130bb2010-10-11 06:22:50 -04002455
2456 private native void native_update_network_state(boolean connected, int type,
Kevin Tanga5fe6b22011-06-05 14:25:16 -07002457 boolean roaming, boolean available, String extraInfo, String defaultAPN);
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07002458
2459 // Hardware Geofence support.
2460 private static native boolean native_is_geofence_supported();
2461 private static native boolean native_add_geofence(int geofenceId, double latitude,
2462 double longitude, double radius, int lastTransition,int monitorTransitions,
2463 int notificationResponsivenes, int unknownTimer);
2464 private static native boolean native_remove_geofence(int geofenceId);
2465 private static native boolean native_resume_geofence(int geofenceId, int transitions);
2466 private static native boolean native_pause_geofence(int geofenceId);
destradaaea8a8a62014-06-23 18:19:03 -07002467
2468 // Gps Hal measurements support.
2469 private static native boolean native_is_measurement_supported();
destradaa4b3e3932014-07-21 18:01:47 -07002470 private native boolean native_start_measurement_collection();
2471 private native boolean native_stop_measurement_collection();
2472
2473 // Gps Navigation message support.
2474 private static native boolean native_is_navigation_message_supported();
2475 private native boolean native_start_navigation_message_collection();
2476 private native boolean native_stop_navigation_message_collection();
Tsuwei Chen52617bb2014-08-25 11:49:11 -07002477
2478 // GNSS Configuration
2479 private static native void native_configuration_update(String configData);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002480}