blob: a72c77e97ffe0aa6e614522b46e0c128efc62993 [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;
25import com.android.internal.telephony.Phone;
26import com.android.internal.telephony.PhoneConstants;
27
Mike Lockwood29c84342009-05-06 14:01:15 -040028import android.app.AlarmManager;
Dianne Hackborna06de0f2012-12-11 16:34:47 -080029import android.app.AppOpsManager;
Mike Lockwood29c84342009-05-06 14:01:15 -040030import android.app.PendingIntent;
The Android Open Source Project10592532009-03-18 17:39:46 -070031import android.content.BroadcastReceiver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080032import android.content.Context;
33import android.content.Intent;
The Android Open Source Project10592532009-03-18 17:39:46 -070034import android.content.IntentFilter;
Kevin Tanga5fe6b22011-06-05 14:25:16 -070035import android.database.Cursor;
destradaa0682809a2013-08-12 18:50:30 -070036import android.hardware.location.GeofenceHardware;
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -070037import android.hardware.location.GeofenceHardwareImpl;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080038import android.location.Criteria;
destradaa0682809a2013-08-12 18:50:30 -070039import android.location.FusedBatchOptions;
destradaaea8a8a62014-06-23 18:19:03 -070040import android.location.GpsMeasurementsEvent;
destradaa4b3e3932014-07-21 18:01:47 -070041import android.location.GpsNavigationMessageEvent;
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -070042import android.location.IGpsGeofenceHardware;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080043import android.location.IGpsStatusListener;
Mike Lockwood15e3d0f2009-05-01 07:53:28 -040044import android.location.IGpsStatusProvider;
Mike Lockwood4e50b782009-04-03 08:24:43 -070045import android.location.ILocationManager;
Danke Xie22d1f9f2009-08-18 18:28:45 -040046import android.location.INetInitiatedListener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080047import android.location.Location;
Nick Pelly6fa9ad42012-07-16 12:18:23 -070048import android.location.LocationListener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080049import android.location.LocationManager;
50import android.location.LocationProvider;
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -070051import android.location.LocationRequest;
Mike Lockwood58bda982009-04-14 16:25:07 -040052import android.net.ConnectivityManager;
Mike Lockwood03d24672009-10-08 15:45:03 -040053import android.net.NetworkInfo;
Kevin Tanga5fe6b22011-06-05 14:25:16 -070054import android.net.Uri;
Kevin Tang40e1baf2012-01-10 14:32:44 -080055import android.os.AsyncTask;
Dianne Hackborn91268cf2013-06-13 19:06:50 -070056import android.os.BatteryStats;
Mike Lockwood63aa5a62010-04-14 19:21:31 -040057import android.os.Binder;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080058import android.os.Bundle;
Mike Lockwood62a8fc12010-03-22 14:23:26 -040059import android.os.Handler;
Victoria Lease5cd731a2012-12-19 15:04:21 -080060import android.os.Looper;
Mike Lockwood62a8fc12010-03-22 14:23:26 -040061import android.os.Message;
Mike Lockwood0528b9b2009-05-07 10:12:54 -040062import android.os.PowerManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080063import android.os.RemoteException;
Mike Lockwood2f82c4e2009-04-17 08:24:10 -040064import android.os.ServiceManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080065import android.os.SystemClock;
Colin Cross7c030ed2014-01-28 09:33:53 -080066import android.os.SystemProperties;
Dianne Hackborn5ac72a22012-08-29 18:32:08 -070067import android.os.UserHandle;
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -070068import android.os.WorkSource;
Mike Lockwoodbcab8df2009-06-25 16:39:09 -040069import android.provider.Settings;
Kevin Tanga5fe6b22011-06-05 14:25:16 -070070import android.provider.Telephony.Carriers;
Miguel Torroja1e84da82010-07-27 07:02:24 +020071import android.provider.Telephony.Sms.Intents;
Jake Hambyb49a73d2011-03-15 20:09:46 -070072import android.telephony.SmsMessage;
Wink Savillea374c3d2014-11-11 11:48:04 -080073import android.telephony.SubscriptionManager;
Wink Savilled09c4ca2014-11-22 10:08:16 -080074import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
Miguel Torroja1e84da82010-07-27 07:02:24 +020075import android.telephony.TelephonyManager;
76import android.telephony.gsm.GsmCellLocation;
Colin Cross7c030ed2014-01-28 09:33:53 -080077import android.text.TextUtils;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080078import android.util.Log;
Jeff Sharkey104344e2011-07-10 14:20:41 -070079import android.util.NtpTrustedTime;
Dianne Hackborna06de0f2012-12-11 16:34:47 -080080
Tsuwei Chen52617bb2014-08-25 11:49:11 -070081import java.io.ByteArrayOutputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080082import java.io.File;
Nick Pelly6fa9ad42012-07-16 12:18:23 -070083import java.io.FileDescriptor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080084import java.io.FileInputStream;
85import java.io.IOException;
Nick Pelly6fa9ad42012-07-16 12:18:23 -070086import java.io.PrintWriter;
Jeff Sharkey104344e2011-07-10 14:20:41 -070087import java.io.StringReader;
destradaaea8a8a62014-06-23 18:19:03 -070088import java.net.InetAddress;
89import java.net.UnknownHostException;
Mike Lockwoodf1218be2010-01-29 09:20:06 -050090import java.util.Date;
Danke Xie22d1f9f2009-08-18 18:28:45 -040091import java.util.Map.Entry;
Jake Hambyb49a73d2011-03-15 20:09:46 -070092import java.util.Properties;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080093
Colin Cross7c030ed2014-01-28 09:33:53 -080094import libcore.io.IoUtils;
95
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080096/**
97 * A GPS implementation of LocationProvider used by LocationManager.
98 *
99 * {@hide}
100 */
Mike Lockwood89096312010-03-24 10:14:55 -0400101public class GpsLocationProvider implements LocationProviderInterface {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800102
103 private static final String TAG = "GpsLocationProvider";
Mike Lockwood29c84342009-05-06 14:01:15 -0400104
Brian Muramatsu1715cb32012-08-08 17:32:21 -0700105 private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
106 private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400107
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700108 private static final ProviderProperties PROPERTIES = new ProviderProperties(
109 true, true, false, false, true, true, true,
110 Criteria.POWER_HIGH, Criteria.ACCURACY_FINE);
111
The Android Open Source Project10592532009-03-18 17:39:46 -0700112 // these need to match GpsPositionMode enum in gps.h
113 private static final int GPS_POSITION_MODE_STANDALONE = 0;
114 private static final int GPS_POSITION_MODE_MS_BASED = 1;
115 private static final int GPS_POSITION_MODE_MS_ASSISTED = 2;
116
Mike Lockwood04598b62010-04-14 17:17:24 -0400117 // these need to match GpsPositionRecurrence enum in gps.h
118 private static final int GPS_POSITION_RECURRENCE_PERIODIC = 0;
119 private static final int GPS_POSITION_RECURRENCE_SINGLE = 1;
120
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800121 // these need to match GpsStatusValue defines in gps.h
122 private static final int GPS_STATUS_NONE = 0;
123 private static final int GPS_STATUS_SESSION_BEGIN = 1;
124 private static final int GPS_STATUS_SESSION_END = 2;
125 private static final int GPS_STATUS_ENGINE_ON = 3;
126 private static final int GPS_STATUS_ENGINE_OFF = 4;
127
Mike Lockwoode3635c92009-05-11 08:38:02 -0400128 // these need to match GpsApgsStatusValue defines in gps.h
129 /** AGPS status event values. */
130 private static final int GPS_REQUEST_AGPS_DATA_CONN = 1;
131 private static final int GPS_RELEASE_AGPS_DATA_CONN = 2;
132 private static final int GPS_AGPS_DATA_CONNECTED = 3;
133 private static final int GPS_AGPS_DATA_CONN_DONE = 4;
134 private static final int GPS_AGPS_DATA_CONN_FAILED = 5;
Mike Lockwood58bda982009-04-14 16:25:07 -0400135
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800136 // these need to match GpsLocationFlags enum in gps.h
137 private static final int LOCATION_INVALID = 0;
138 private static final int LOCATION_HAS_LAT_LONG = 1;
139 private static final int LOCATION_HAS_ALTITUDE = 2;
140 private static final int LOCATION_HAS_SPEED = 4;
141 private static final int LOCATION_HAS_BEARING = 8;
142 private static final int LOCATION_HAS_ACCURACY = 16;
Mike Lockwoode3635c92009-05-11 08:38:02 -0400143
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700144 // IMPORTANT - the GPS_DELETE_* symbols here must match constants in gps.h
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800145 private static final int GPS_DELETE_EPHEMERIS = 0x0001;
146 private static final int GPS_DELETE_ALMANAC = 0x0002;
147 private static final int GPS_DELETE_POSITION = 0x0004;
148 private static final int GPS_DELETE_TIME = 0x0008;
149 private static final int GPS_DELETE_IONO = 0x0010;
150 private static final int GPS_DELETE_UTC = 0x0020;
151 private static final int GPS_DELETE_HEALTH = 0x0040;
152 private static final int GPS_DELETE_SVDIR = 0x0080;
153 private static final int GPS_DELETE_SVSTEER = 0x0100;
154 private static final int GPS_DELETE_SADATA = 0x0200;
155 private static final int GPS_DELETE_RTI = 0x0400;
156 private static final int GPS_DELETE_CELLDB_INFO = 0x8000;
157 private static final int GPS_DELETE_ALL = 0xFFFF;
158
Mike Lockwood04598b62010-04-14 17:17:24 -0400159 // The GPS_CAPABILITY_* flags must match the values in gps.h
160 private static final int GPS_CAPABILITY_SCHEDULING = 0x0000001;
161 private static final int GPS_CAPABILITY_MSB = 0x0000002;
162 private static final int GPS_CAPABILITY_MSA = 0x0000004;
163 private static final int GPS_CAPABILITY_SINGLE_SHOT = 0x0000008;
Mike Lockwood9b9fb5c2011-06-29 15:09:40 -0400164 private static final int GPS_CAPABILITY_ON_DEMAND_TIME = 0x0000010;
destradaa6568d702014-10-27 12:47:41 -0700165 private static final int GPS_CAPABILITY_GEOFENCING = 0x0000020;
166 private static final int GPS_CAPABILITY_MEASUREMENTS = 0x0000040;
167 private static final int GPS_CAPABILITY_NAV_MESSAGES = 0x0000080;
Mike Lockwood04598b62010-04-14 17:17:24 -0400168
Tsuwei Chen462bcd82014-09-17 12:28:49 -0700169 // The AGPS SUPL mode
170 private static final int AGPS_SUPL_MODE_MSA = 0x02;
171 private static final int AGPS_SUPL_MODE_MSB = 0x01;
172
Mike Lockwoode3635c92009-05-11 08:38:02 -0400173 // these need to match AGpsType enum in gps.h
174 private static final int AGPS_TYPE_SUPL = 1;
175 private static final int AGPS_TYPE_C2K = 2;
176
destradaa96a14702014-06-05 11:36:30 -0700177 // these must match the definitions in gps.h
178 private static final int APN_INVALID = 0;
179 private static final int APN_IPV4 = 1;
180 private static final int APN_IPV6 = 2;
181 private static final int APN_IPV4V6 = 3;
182
Mike Lockwoode3635c92009-05-11 08:38:02 -0400183 // for mAGpsDataConnectionState
184 private static final int AGPS_DATA_CONNECTION_CLOSED = 0;
185 private static final int AGPS_DATA_CONNECTION_OPENING = 1;
186 private static final int AGPS_DATA_CONNECTION_OPEN = 2;
Mike Lockwood58bda982009-04-14 16:25:07 -0400187
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400188 // Handler messages
189 private static final int CHECK_LOCATION = 1;
190 private static final int ENABLE = 2;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700191 private static final int SET_REQUEST = 3;
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400192 private static final int UPDATE_NETWORK_STATE = 4;
193 private static final int INJECT_NTP_TIME = 5;
194 private static final int DOWNLOAD_XTRA_DATA = 6;
195 private static final int UPDATE_LOCATION = 7;
196 private static final int ADD_LISTENER = 8;
197 private static final int REMOVE_LISTENER = 9;
Kevin Tang40e1baf2012-01-10 14:32:44 -0800198 private static final int INJECT_NTP_TIME_FINISHED = 10;
199 private static final int DOWNLOAD_XTRA_DATA_FINISHED = 11;
destradaafb23c672015-04-16 14:01:27 -0700200 private static final int SUBSCRIPTION_OR_SIM_CHANGED = 12;
201 private static final int INITIALIZE_HANDLER = 13;
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400202
Miguel Torroja1e84da82010-07-27 07:02:24 +0200203 // Request setid
204 private static final int AGPS_RIL_REQUEST_SETID_IMSI = 1;
205 private static final int AGPS_RIL_REQUEST_SETID_MSISDN = 2;
206
207 // Request ref location
208 private static final int AGPS_RIL_REQUEST_REFLOC_CELLID = 1;
209 private static final int AGPS_RIL_REQUEST_REFLOC_MAC = 2;
210
211 // ref. location info
212 private static final int AGPS_REF_LOCATION_TYPE_GSM_CELLID = 1;
213 private static final int AGPS_REF_LOCATION_TYPE_UMTS_CELLID = 2;
214 private static final int AGPS_REG_LOCATION_TYPE_MAC = 3;
215
216 // set id info
217 private static final int AGPS_SETID_TYPE_NONE = 0;
218 private static final int AGPS_SETID_TYPE_IMSI = 1;
219 private static final int AGPS_SETID_TYPE_MSISDN = 2;
220
Colin Cross7c030ed2014-01-28 09:33:53 -0800221 private static final String PROPERTIES_FILE_PREFIX = "/etc/gps";
222 private static final String PROPERTIES_FILE_SUFFIX = ".conf";
223 private static final String DEFAULT_PROPERTIES_FILE = PROPERTIES_FILE_PREFIX + PROPERTIES_FILE_SUFFIX;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800224
destradaa0682809a2013-08-12 18:50:30 -0700225 private static final int GPS_GEOFENCE_UNAVAILABLE = 1<<0L;
226 private static final int GPS_GEOFENCE_AVAILABLE = 1<<1L;
227
228 // GPS Geofence errors. Should match gps.h constants.
229 private static final int GPS_GEOFENCE_OPERATION_SUCCESS = 0;
230 private static final int GPS_GEOFENCE_ERROR_TOO_MANY_GEOFENCES = 100;
231 private static final int GPS_GEOFENCE_ERROR_ID_EXISTS = -101;
232 private static final int GPS_GEOFENCE_ERROR_ID_UNKNOWN = -102;
233 private static final int GPS_GEOFENCE_ERROR_INVALID_TRANSITION = -103;
234 private static final int GPS_GEOFENCE_ERROR_GENERIC = -149;
235
Tsuwei Chen678c13c2014-09-22 17:48:41 -0700236 // TCP/IP constants.
237 // Valid TCP/UDP port range is (0, 65535].
238 private static final int TCP_MIN_PORT = 0;
239 private static final int TCP_MAX_PORT = 0xffff;
240
David Christied4edf4c2014-08-12 15:22:27 -0700241 // Value of batterySaverGpsMode such that GPS isn't affected by battery saver mode.
242 private static final int BATTERY_SAVER_MODE_NO_CHANGE = 0;
243 // Value of batterySaverGpsMode such that GPS is disabled when battery saver mode
244 // is enabled and the screen is off.
245 private static final int BATTERY_SAVER_MODE_DISABLED_WHEN_SCREEN_OFF = 1;
246 // Secure setting for GPS behavior when battery saver mode is on.
247 private static final String BATTERY_SAVER_GPS_MODE = "batterySaverGpsMode";
248
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700249 /** simpler wrapper for ProviderRequest + Worksource */
250 private static class GpsRequest {
251 public ProviderRequest request;
252 public WorkSource source;
253 public GpsRequest(ProviderRequest request, WorkSource source) {
254 this.request = request;
255 this.source = source;
256 }
257 }
258
259 private Object mLock = new Object();
260
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800261 private int mLocationFlags = LOCATION_INVALID;
262
263 // current status
Mike Lockwood15e3d0f2009-05-01 07:53:28 -0400264 private int mStatus = LocationProvider.TEMPORARILY_UNAVAILABLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800265
266 // time for last status update
267 private long mStatusUpdateTime = SystemClock.elapsedRealtime();
Mike Lockwoodd53ba012010-04-15 20:41:26 -0400268
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800269 // turn off GPS fix icon if we haven't received a fix in 10 seconds
Mike Lockwood04598b62010-04-14 17:17:24 -0400270 private static final long RECENT_FIX_TIMEOUT = 10 * 1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800271
Mike Lockwood0632ca72009-05-14 15:51:03 -0400272 // stop trying if we do not receive a fix within 60 seconds
Mike Lockwood04598b62010-04-14 17:17:24 -0400273 private static final int NO_FIX_TIMEOUT = 60 * 1000;
Mike Lockwood0632ca72009-05-14 15:51:03 -0400274
Nick Pellyb041f232012-05-07 17:12:25 -0700275 // if the fix interval is below this we leave GPS on,
276 // if above then we cycle the GPS driver.
277 // Typical hot TTTF is ~5 seconds, so 10 seconds seems sane.
278 private static final int GPS_POLLING_THRESHOLD_INTERVAL = 10 * 1000;
279
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700280 // how often to request NTP time, in milliseconds
281 // current setting 24 hours
282 private static final long NTP_INTERVAL = 24*60*60*1000;
283 // how long to wait if we have a network error in NTP or XTRA downloading
284 // current setting - 5 minutes
285 private static final long RETRY_INTERVAL = 5*60*1000;
286
287 // true if we are enabled, protected by this
288 private boolean mEnabled;
289
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800290 // true if we have network connectivity
291 private boolean mNetworkAvailable;
292
Kevin Tang40e1baf2012-01-10 14:32:44 -0800293 // states for injecting ntp and downloading xtra data
294 private static final int STATE_PENDING_NETWORK = 0;
295 private static final int STATE_DOWNLOADING = 1;
296 private static final int STATE_IDLE = 2;
297
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400298 // flags to trigger NTP or XTRA data download when network becomes available
299 // initialized to true so we do NTP and XTRA when the network comes up after booting
Kevin Tang40e1baf2012-01-10 14:32:44 -0800300 private int mInjectNtpTimePending = STATE_PENDING_NETWORK;
301 private int mDownloadXtraDataPending = STATE_PENDING_NETWORK;
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400302
Mike Lockwood9b9fb5c2011-06-29 15:09:40 -0400303 // set to true if the GPS engine does not do on-demand NTP time requests
304 private boolean mPeriodicTimeInjection;
305
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800306 // true if GPS is navigating
307 private boolean mNavigating;
Mike Lockwoodcf1d8cb2010-01-20 10:14:54 -0500308
309 // true if GPS engine is on
310 private boolean mEngineOn;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700311
Mike Lockwood04598b62010-04-14 17:17:24 -0400312 // requested frequency of fixes, in milliseconds
313 private int mFixInterval = 1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800314
315 // true if we started navigation
316 private boolean mStarted;
317
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -0700318 // true if single shot request is in progress
319 private boolean mSingleShot;
320
Mike Lockwood04598b62010-04-14 17:17:24 -0400321 // capabilities of the GPS engine
322 private int mEngineCapabilities;
323
Mike Lockwood1a1cd3a2010-08-17 07:42:54 -0400324 // true if XTRA is supported
325 private boolean mSupportsXtra;
326
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800327 // for calculating time to first fix
328 private long mFixRequestTime = 0;
329 // time to first fix for most recent session
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700330 private int mTimeToFirstFix = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800331 // time we received our last fix
332 private long mLastFixTime;
333
Mike Lockwood04598b62010-04-14 17:17:24 -0400334 private int mPositionMode;
335
David Christied4edf4c2014-08-12 15:22:27 -0700336 // Current request from underlying location clients.
337 private ProviderRequest mProviderRequest = null;
338 // Current list of underlying location clients.
339 private WorkSource mWorkSource = null;
340 // True if gps should be disabled (used to support battery saver mode in settings).
341 private boolean mDisableGps = false;
342
destradaafb23c672015-04-16 14:01:27 -0700343 /**
344 * Properties loaded from PROPERTIES_FILE.
345 * It must be accessed only inside {@link #mHandler}.
346 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800347 private Properties mProperties;
destradaafb23c672015-04-16 14:01:27 -0700348
Mike Lockwood734d6032009-07-28 18:30:25 -0700349 private String mSuplServerHost;
Tsuwei Chen678c13c2014-09-22 17:48:41 -0700350 private int mSuplServerPort = TCP_MIN_PORT;
Mike Lockwood734d6032009-07-28 18:30:25 -0700351 private String mC2KServerHost;
352 private int mC2KServerPort;
Tsuwei Chen3324e952014-09-07 01:30:42 -0700353 private boolean mSuplEsEnabled = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800354
Mike Lockwood15e3d0f2009-05-01 07:53:28 -0400355 private final Context mContext;
Jeff Sharkey104344e2011-07-10 14:20:41 -0700356 private final NtpTrustedTime mNtpTime;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700357 private final ILocationManager mILocationManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800358 private Location mLocation = new Location(LocationManager.GPS_PROVIDER);
359 private Bundle mLocationExtras = new Bundle();
destradaa6568d702014-10-27 12:47:41 -0700360 private final GpsStatusListenerHelper mListenerHelper;
361 private final GpsMeasurementsProvider mGpsMeasurementsProvider;
362 private final GpsNavigationMessageProvider mGpsNavigationMessageProvider;
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400363
Victoria Lease5c24fd02012-10-01 11:00:50 -0700364 // Handler for processing events
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400365 private Handler mHandler;
The Android Open Source Project10592532009-03-18 17:39:46 -0700366
Mike Lockwoode3635c92009-05-11 08:38:02 -0400367 private String mAGpsApn;
destradaa96a14702014-06-05 11:36:30 -0700368 private int mApnIpType;
Mike Lockwoode3635c92009-05-11 08:38:02 -0400369 private int mAGpsDataConnectionState;
destradaa96a14702014-06-05 11:36:30 -0700370 private InetAddress mAGpsDataConnectionIpAddr;
Mike Lockwood2f82c4e2009-04-17 08:24:10 -0400371 private final ConnectivityManager mConnMgr;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700372 private final GpsNetInitiatedHandler mNIHandler;
Mike Lockwood2f82c4e2009-04-17 08:24:10 -0400373
Mike Lockwood0528b9b2009-05-07 10:12:54 -0400374 // Wakelocks
375 private final static String WAKELOCK_KEY = "GpsLocationProvider";
376 private final PowerManager.WakeLock mWakeLock;
377
Mike Lockwood29c84342009-05-06 14:01:15 -0400378 // Alarms
379 private final static String ALARM_WAKEUP = "com.android.internal.location.ALARM_WAKEUP";
Mike Lockwood0632ca72009-05-14 15:51:03 -0400380 private final static String ALARM_TIMEOUT = "com.android.internal.location.ALARM_TIMEOUT";
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700381
382 // SIM/Carrier info.
383 private final static String SIM_STATE_CHANGED = "android.intent.action.SIM_STATE_CHANGED";
384
David Christied4edf4c2014-08-12 15:22:27 -0700385 private final PowerManager mPowerManager;
Mike Lockwood29c84342009-05-06 14:01:15 -0400386 private final AlarmManager mAlarmManager;
387 private final PendingIntent mWakeupIntent;
Mike Lockwood0632ca72009-05-14 15:51:03 -0400388 private final PendingIntent mTimeoutIntent;
Mike Lockwood29c84342009-05-06 14:01:15 -0400389
Dianne Hackborna06de0f2012-12-11 16:34:47 -0800390 private final IAppOpsService mAppOpsService;
Mike Lockwood2f82c4e2009-04-17 08:24:10 -0400391 private final IBatteryStats mBatteryStats;
The Android Open Source Project10592532009-03-18 17:39:46 -0700392
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700393 // only modified on handler thread
Dianne Hackborn002a54e2013-01-10 17:34:55 -0800394 private WorkSource mClientSource = new WorkSource();
Mike Lockwoodf1218be2010-01-29 09:20:06 -0500395
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -0700396 private GeofenceHardwareImpl mGeofenceHardwareImpl;
397
Mike Lockwood15e3d0f2009-05-01 07:53:28 -0400398 private final IGpsStatusProvider mGpsStatusProvider = new IGpsStatusProvider.Stub() {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700399 @Override
destradaa13a60b02015-01-15 18:36:01 -0800400 public void addGpsStatusListener(IGpsStatusListener listener) {
destradaaea8a8a62014-06-23 18:19:03 -0700401 mListenerHelper.addListener(listener);
Mike Lockwood15e3d0f2009-05-01 07:53:28 -0400402 }
403
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700404 @Override
Mike Lockwood15e3d0f2009-05-01 07:53:28 -0400405 public void removeGpsStatusListener(IGpsStatusListener listener) {
destradaaea8a8a62014-06-23 18:19:03 -0700406 mListenerHelper.removeListener(listener);
407 }
408 };
Mike Lockwood15e3d0f2009-05-01 07:53:28 -0400409
Mike Lockwood15e3d0f2009-05-01 07:53:28 -0400410 public IGpsStatusProvider getGpsStatusProvider() {
411 return mGpsStatusProvider;
412 }
413
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -0700414 public IGpsGeofenceHardware getGpsGeofenceProxy() {
415 return mGpsGeofenceBinder;
416 }
417
destradaaea8a8a62014-06-23 18:19:03 -0700418 public GpsMeasurementsProvider getGpsMeasurementsProvider() {
419 return mGpsMeasurementsProvider;
420 }
421
destradaa4b3e3932014-07-21 18:01:47 -0700422 public GpsNavigationMessageProvider getGpsNavigationMessageProvider() {
423 return mGpsNavigationMessageProvider;
424 }
425
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700426 private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
The Android Open Source Project10592532009-03-18 17:39:46 -0700427 @Override public void onReceive(Context context, Intent intent) {
428 String action = intent.getAction();
429
Tsuwei Chen48d37f92014-09-05 15:15:34 -0700430 if (DEBUG) Log.d(TAG, "receive broadcast intent, action: " + action);
Mike Lockwood29c84342009-05-06 14:01:15 -0400431 if (action.equals(ALARM_WAKEUP)) {
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -0700432 startNavigating(false);
Mike Lockwood0632ca72009-05-14 15:51:03 -0400433 } else if (action.equals(ALARM_TIMEOUT)) {
Mike Lockwood0632ca72009-05-14 15:51:03 -0400434 hibernate();
Miguel Torroja1e84da82010-07-27 07:02:24 +0200435 } else if (action.equals(Intents.DATA_SMS_RECEIVED_ACTION)) {
436 checkSmsSuplInit(intent);
437 } else if (action.equals(Intents.WAP_PUSH_RECEIVED_ACTION)) {
438 checkWapSuplInit(intent);
Erik Klinef851d6d2015-04-20 16:03:48 +0900439 } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
David Christied4edf4c2014-08-12 15:22:27 -0700440 // retrieve NetworkInfo result for this UID
441 NetworkInfo info =
442 intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
443 ConnectivityManager connManager = (ConnectivityManager)
444 mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
445 info = connManager.getNetworkInfo(info.getType());
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700446
Tsuwei Chend3ef8e22014-10-31 14:58:44 -0700447 int networkState;
448 if (intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false) ||
449 !info.isConnected()) {
450 networkState = LocationProvider.TEMPORARILY_UNAVAILABLE;
451 } else {
452 networkState = LocationProvider.AVAILABLE;
453 }
454
455
David Christied4edf4c2014-08-12 15:22:27 -0700456 updateNetworkState(networkState, info);
457 } else if (PowerManager.ACTION_POWER_SAVE_MODE_CHANGED.equals(action)
458 || Intent.ACTION_SCREEN_OFF.equals(action)
459 || Intent.ACTION_SCREEN_ON.equals(action)) {
460 updateLowPowerMode();
Wink Savillea374c3d2014-11-11 11:48:04 -0800461 } else if (action.equals(SIM_STATE_CHANGED)) {
462 subscriptionOrSimChanged(context);
David Christied4edf4c2014-08-12 15:22:27 -0700463 }
The Android Open Source Project10592532009-03-18 17:39:46 -0700464 }
Mike Lockwood29c84342009-05-06 14:01:15 -0400465 };
The Android Open Source Project10592532009-03-18 17:39:46 -0700466
Wink Savilled09c4ca2014-11-22 10:08:16 -0800467 private final OnSubscriptionsChangedListener mOnSubscriptionsChangedListener =
468 new OnSubscriptionsChangedListener() {
Wink Savillea374c3d2014-11-11 11:48:04 -0800469 @Override
Wink Savilled09c4ca2014-11-22 10:08:16 -0800470 public void onSubscriptionsChanged() {
destradaafb23c672015-04-16 14:01:27 -0700471 sendMessage(SUBSCRIPTION_OR_SIM_CHANGED, 0, null);
Wink Savillea374c3d2014-11-11 11:48:04 -0800472 }
473 };
474
475 private void subscriptionOrSimChanged(Context context) {
476 Log.d(TAG, "received SIM realted action: ");
477 TelephonyManager phone = (TelephonyManager)
478 mContext.getSystemService(Context.TELEPHONY_SERVICE);
479 String mccMnc = phone.getSimOperator();
480 if (!TextUtils.isEmpty(mccMnc)) {
481 Log.d(TAG, "SIM MCC/MNC is available: " + mccMnc);
482 synchronized (mLock) {
483 reloadGpsProperties(context, mProperties);
484 mNIHandler.setSuplEsEnabled(mSuplEsEnabled);
485 }
486 } else {
487 Log.d(TAG, "SIM MCC/MNC is still not available");
488 }
489 }
490
Miguel Torroja1e84da82010-07-27 07:02:24 +0200491 private void checkSmsSuplInit(Intent intent) {
492 SmsMessage[] messages = Intents.getMessagesFromIntent(intent);
493 for (int i=0; i <messages.length; i++) {
494 byte[] supl_init = messages[i].getUserData();
495 native_agps_ni_message(supl_init,supl_init.length);
496 }
497 }
498
499 private void checkWapSuplInit(Intent intent) {
500 byte[] supl_init = (byte[]) intent.getExtra("data");
501 native_agps_ni_message(supl_init,supl_init.length);
502 }
503
David Christied4edf4c2014-08-12 15:22:27 -0700504 private void updateLowPowerMode() {
505 final boolean disableGps;
506 switch (Settings.Secure.getInt(mContext.getContentResolver(), BATTERY_SAVER_GPS_MODE,
507 BATTERY_SAVER_MODE_DISABLED_WHEN_SCREEN_OFF)) {
508 case BATTERY_SAVER_MODE_DISABLED_WHEN_SCREEN_OFF:
509 disableGps = mPowerManager.isPowerSaveMode() && !mPowerManager.isInteractive();
510 break;
511 default:
512 disableGps = false;
513 }
514 if (disableGps != mDisableGps) {
515 mDisableGps = disableGps;
516 updateRequirements();
517 }
518 }
519
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800520 public static boolean isSupported() {
521 return native_is_supported();
522 }
523
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700524 private void reloadGpsProperties(Context context, Properties properties) {
525 Log.d(TAG, "Reset GPS properties, previous size = " + properties.size());
526 loadPropertiesFromResource(context, properties);
527 boolean isPropertiesLoadedFromFile = false;
528 final String gpsHardware = SystemProperties.get("ro.hardware.gps");
529 if (!TextUtils.isEmpty(gpsHardware)) {
530 final String propFilename =
531 PROPERTIES_FILE_PREFIX + "." + gpsHardware + PROPERTIES_FILE_SUFFIX;
532 isPropertiesLoadedFromFile =
533 loadPropertiesFromFile(propFilename, properties);
534 }
535 if (!isPropertiesLoadedFromFile) {
536 loadPropertiesFromFile(DEFAULT_PROPERTIES_FILE, properties);
537 }
538 Log.d(TAG, "GPS properties reloaded, size = " + properties.size());
539
540 // TODO: we should get rid of C2K specific setting.
541 setSuplHostPort(properties.getProperty("SUPL_HOST"),
542 properties.getProperty("SUPL_PORT"));
543 mC2KServerHost = properties.getProperty("C2K_HOST");
544 String portString = properties.getProperty("C2K_PORT");
545 if (mC2KServerHost != null && portString != null) {
546 try {
547 mC2KServerPort = Integer.parseInt(portString);
548 } catch (NumberFormatException e) {
549 Log.e(TAG, "unable to parse C2K_PORT: " + portString);
550 }
551 }
552
553 try {
554 // Convert properties to string contents and send it to HAL.
555 ByteArrayOutputStream baos = new ByteArrayOutputStream(4096);
556 properties.store(baos, null);
557 native_configuration_update(baos.toString());
558 Log.d(TAG, "final config = " + baos.toString());
559 } catch (IOException ex) {
560 Log.w(TAG, "failed to dump properties contents");
561 }
Tsuwei Chen3324e952014-09-07 01:30:42 -0700562
563 // SUPL_ES configuration.
564 String suplESProperty = mProperties.getProperty("SUPL_ES");
565 if (suplESProperty != null) {
566 try {
567 mSuplEsEnabled = (Integer.parseInt(suplESProperty) == 1);
568 } catch (NumberFormatException e) {
569 Log.e(TAG, "unable to parse SUPL_ES: " + suplESProperty);
570 }
571 }
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700572 }
573
574 private void loadPropertiesFromResource(Context context,
575 Properties properties) {
576 String[] configValues = context.getResources().getStringArray(
577 com.android.internal.R.array.config_gpsParameters);
578 for (String item : configValues) {
579 Log.d(TAG, "GpsParamsResource: " + item);
Tsuwei Chen7c485bf2014-09-10 15:33:34 -0700580 // We need to support "KEY =", but not "=VALUE".
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700581 String[] split = item.split("=");
582 if (split.length == 2) {
583 properties.setProperty(split[0].trim().toUpperCase(), split[1]);
584 } else {
585 Log.w(TAG, "malformed contents: " + item);
586 }
587 }
588 }
589
590 private boolean loadPropertiesFromFile(String filename,
591 Properties properties) {
Colin Cross7c030ed2014-01-28 09:33:53 -0800592 try {
593 File file = new File(filename);
594 FileInputStream stream = null;
595 try {
596 stream = new FileInputStream(file);
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700597 properties.load(stream);
Colin Cross7c030ed2014-01-28 09:33:53 -0800598 } finally {
599 IoUtils.closeQuietly(stream);
600 }
601
Colin Cross7c030ed2014-01-28 09:33:53 -0800602 } catch (IOException e) {
603 Log.w(TAG, "Could not open GPS configuration file " + filename);
604 return false;
605 }
606 return true;
607 }
608
Victoria Lease5cd731a2012-12-19 15:04:21 -0800609 public GpsLocationProvider(Context context, ILocationManager ilocationManager,
610 Looper looper) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800611 mContext = context;
Jeff Sharkey104344e2011-07-10 14:20:41 -0700612 mNtpTime = NtpTrustedTime.getInstance(context);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700613 mILocationManager = ilocationManager;
Mike Lockwood63598a02010-02-24 11:52:59 -0500614
615 mLocation.setExtras(mLocationExtras);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800616
Mike Lockwood0528b9b2009-05-07 10:12:54 -0400617 // Create a wake lock
David Christied4edf4c2014-08-12 15:22:27 -0700618 mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
619 mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700620 mWakeLock.setReferenceCounted(true);
Mike Lockwood0528b9b2009-05-07 10:12:54 -0400621
Mike Lockwood29c84342009-05-06 14:01:15 -0400622 mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
623 mWakeupIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_WAKEUP), 0);
Mike Lockwood0632ca72009-05-14 15:51:03 -0400624 mTimeoutIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_TIMEOUT), 0);
Mike Lockwood29c84342009-05-06 14:01:15 -0400625
Mike Lockwood58bda982009-04-14 16:25:07 -0400626 mConnMgr = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
627
Dianne Hackborna06de0f2012-12-11 16:34:47 -0800628 // App ops service to keep track of who is accessing the GPS
629 mAppOpsService = IAppOpsService.Stub.asInterface(ServiceManager.getService(
630 Context.APP_OPS_SERVICE));
631
Mike Lockwood2f82c4e2009-04-17 08:24:10 -0400632 // Battery statistics service to be notified when GPS turns on or off
Dianne Hackborn91268cf2013-06-13 19:06:50 -0700633 mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService(
634 BatteryStats.SERVICE_NAME));
Mike Lockwood2f82c4e2009-04-17 08:24:10 -0400635
destradaafb23c672015-04-16 14:01:27 -0700636 // Construct internal handler
637 mHandler = new ProviderHandler(looper);
638
639 // Load GPS configuration and register listeners in the background:
640 // some operations, such as opening files and registering broadcast receivers, can take a
641 // relative long time, so the ctor() is kept to create objects needed by this instance,
642 // while IO initialization and registration is delegated to our internal handler
643 // this approach is just fine because events are posted to our handler anyway
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700644 mProperties = new Properties();
destradaafb23c672015-04-16 14:01:27 -0700645 sendMessage(INITIALIZE_HANDLER, 0, null);
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400646
Tsuwei Chen3324e952014-09-07 01:30:42 -0700647 // Create a GPS net-initiated handler.
648 mNIHandler = new GpsNetInitiatedHandler(context,
649 mNetInitiatedListener,
650 mSuplEsEnabled);
651
destradaa6568d702014-10-27 12:47:41 -0700652 mListenerHelper = new GpsStatusListenerHelper(mHandler) {
653 @Override
654 protected boolean isAvailableInPlatform() {
destradaa13a60b02015-01-15 18:36:01 -0800655 return isSupported();
destradaa6568d702014-10-27 12:47:41 -0700656 }
657
658 @Override
659 protected boolean isGpsEnabled() {
660 return isEnabled();
661 }
662 };
663
664 mGpsMeasurementsProvider = new GpsMeasurementsProvider(mHandler) {
665 @Override
666 public boolean isAvailableInPlatform() {
667 return native_is_measurement_supported();
668 }
669
670 @Override
671 protected boolean registerWithService() {
672 return native_start_measurement_collection();
673 }
674
675 @Override
676 protected void unregisterFromService() {
677 native_stop_measurement_collection();
678 }
679
680 @Override
681 protected boolean isGpsEnabled() {
682 return isEnabled();
683 }
684 };
685
686 mGpsNavigationMessageProvider = new GpsNavigationMessageProvider(mHandler) {
687 @Override
688 protected boolean isAvailableInPlatform() {
689 return native_is_navigation_message_supported();
690 }
691
692 @Override
693 protected boolean registerWithService() {
694 return native_start_navigation_message_collection();
695 }
696
697 @Override
698 protected void unregisterFromService() {
699 native_stop_navigation_message_collection();
700 }
701
702 @Override
703 protected boolean isGpsEnabled() {
704 return isEnabled();
705 }
706 };
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400707 }
708
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800709 /**
Mike Lockwoodd03ff942010-02-09 08:46:14 -0500710 * Returns the name of this provider.
711 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700712 @Override
Mike Lockwoodd03ff942010-02-09 08:46:14 -0500713 public String getName() {
714 return LocationManager.GPS_PROVIDER;
715 }
716
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700717 @Override
718 public ProviderProperties getProperties() {
719 return PROPERTIES;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800720 }
721
Mike Lockwood03d24672009-10-08 15:45:03 -0400722 public void updateNetworkState(int state, NetworkInfo info) {
Mike Lockwood98e48692010-04-07 16:32:51 -0400723 sendMessage(UPDATE_NETWORK_STATE, state, info);
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400724 }
725
726 private void handleUpdateNetworkState(int state, NetworkInfo info) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800727 mNetworkAvailable = (state == LocationProvider.AVAILABLE);
728
Joe Onoratof5d95cb2010-01-07 21:48:32 -0500729 if (DEBUG) {
Mike Lockwood03d24672009-10-08 15:45:03 -0400730 Log.d(TAG, "updateNetworkState " + (mNetworkAvailable ? "available" : "unavailable")
731 + " info: " + info);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800732 }
Mike Lockwood03d24672009-10-08 15:45:03 -0400733
Mike Lockwood50130bb2010-10-11 06:22:50 -0400734 if (info != null) {
Shishir Agrawal64ce5f82015-02-10 19:02:38 -0800735 boolean dataEnabled = TelephonyManager.getDefault().getDataEnabled();
Kevin Tanga5fe6b22011-06-05 14:25:16 -0700736 boolean networkAvailable = info.isAvailable() && dataEnabled;
737 String defaultApn = getSelectedApn();
738 if (defaultApn == null) {
739 defaultApn = "dummy-apn";
740 }
741
Mike Lockwood50130bb2010-10-11 06:22:50 -0400742 native_update_network_state(info.isConnected(), info.getType(),
Kevin Tanga5fe6b22011-06-05 14:25:16 -0700743 info.isRoaming(), networkAvailable,
744 info.getExtraInfo(), defaultApn);
Mike Lockwood50130bb2010-10-11 06:22:50 -0400745 }
746
Mike Lockwood03d24672009-10-08 15:45:03 -0400747 if (info != null && info.getType() == ConnectivityManager.TYPE_MOBILE_SUPL
748 && mAGpsDataConnectionState == AGPS_DATA_CONNECTION_OPENING) {
Stephen Li83b69712011-01-25 18:47:28 -0800749 if (mNetworkAvailable) {
destradaa96a14702014-06-05 11:36:30 -0700750 String apnName = info.getExtraInfo();
Stephen Li83b69712011-01-25 18:47:28 -0800751 if (apnName == null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700752 /* Assign a dummy value in the case of C2K as otherwise we will have a runtime
Stephen Li83b69712011-01-25 18:47:28 -0800753 exception in the following call to native_agps_data_conn_open*/
754 apnName = "dummy-apn";
755 }
Mike Lockwood03d24672009-10-08 15:45:03 -0400756 mAGpsApn = apnName;
destradaa96a14702014-06-05 11:36:30 -0700757 mApnIpType = getApnIpType(apnName);
758 setRouting();
759 if (DEBUG) {
760 String message = String.format(
761 "native_agps_data_conn_open: mAgpsApn=%s, mApnIpType=%s",
762 mAGpsApn, mApnIpType);
763 Log.d(TAG, message);
Stephen Li8efd74d2011-03-01 20:56:00 -0800764 }
destradaa96a14702014-06-05 11:36:30 -0700765 native_agps_data_conn_open(mAGpsApn, mApnIpType);
Mike Lockwood03d24672009-10-08 15:45:03 -0400766 mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPEN;
767 } else {
destradaa96a14702014-06-05 11:36:30 -0700768 Log.e(TAG, "call native_agps_data_conn_failed, info: " + info);
Mike Lockwood03d24672009-10-08 15:45:03 -0400769 mAGpsApn = null;
destradaa96a14702014-06-05 11:36:30 -0700770 mApnIpType = APN_INVALID;
Mike Lockwood03d24672009-10-08 15:45:03 -0400771 mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED;
772 native_agps_data_conn_failed();
773 }
774 }
775
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400776 if (mNetworkAvailable) {
Kevin Tang40e1baf2012-01-10 14:32:44 -0800777 if (mInjectNtpTimePending == STATE_PENDING_NETWORK) {
Mike Lockwood98e48692010-04-07 16:32:51 -0400778 sendMessage(INJECT_NTP_TIME, 0, null);
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400779 }
Kevin Tang40e1baf2012-01-10 14:32:44 -0800780 if (mDownloadXtraDataPending == STATE_PENDING_NETWORK) {
Mike Lockwood98e48692010-04-07 16:32:51 -0400781 sendMessage(DOWNLOAD_XTRA_DATA, 0, null);
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400782 }
783 }
784 }
785
786 private void handleInjectNtpTime() {
Kevin Tang40e1baf2012-01-10 14:32:44 -0800787 if (mInjectNtpTimePending == STATE_DOWNLOADING) {
788 // already downloading data
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400789 return;
790 }
Kevin Tang40e1baf2012-01-10 14:32:44 -0800791 if (!mNetworkAvailable) {
792 // try again when network is up
793 mInjectNtpTimePending = STATE_PENDING_NETWORK;
794 return;
Jeff Sharkey104344e2011-07-10 14:20:41 -0700795 }
Kevin Tang40e1baf2012-01-10 14:32:44 -0800796 mInjectNtpTimePending = STATE_DOWNLOADING;
Jeff Sharkey104344e2011-07-10 14:20:41 -0700797
Jeff Brown028872f2012-08-25 13:07:01 -0700798 // hold wake lock while task runs
799 mWakeLock.acquire();
Kevin Tang40e1baf2012-01-10 14:32:44 -0800800 AsyncTask.THREAD_POOL_EXECUTOR.execute(new Runnable() {
801 @Override
802 public void run() {
803 long delay;
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400804
Kevin Tang40e1baf2012-01-10 14:32:44 -0800805 // force refresh NTP cache when outdated
806 if (mNtpTime.getCacheAge() >= NTP_INTERVAL) {
807 mNtpTime.forceRefresh();
808 }
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400809
Kevin Tang40e1baf2012-01-10 14:32:44 -0800810 // only update when NTP time is fresh
811 if (mNtpTime.getCacheAge() < NTP_INTERVAL) {
812 long time = mNtpTime.getCachedNtpTime();
813 long timeReference = mNtpTime.getCachedNtpTimeReference();
814 long certainty = mNtpTime.getCacheCertainty();
815 long now = System.currentTimeMillis();
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400816
Kevin Tang40e1baf2012-01-10 14:32:44 -0800817 Log.d(TAG, "NTP server returned: "
818 + time + " (" + new Date(time)
819 + ") reference: " + timeReference
820 + " certainty: " + certainty
821 + " system time offset: " + (time - now));
822
823 native_inject_time(time, timeReference, (int) certainty);
824 delay = NTP_INTERVAL;
825 } else {
826 if (DEBUG) Log.d(TAG, "requestTime failed");
827 delay = RETRY_INTERVAL;
828 }
829
Jeff Brown028872f2012-08-25 13:07:01 -0700830 sendMessage(INJECT_NTP_TIME_FINISHED, 0, null);
Kevin Tang40e1baf2012-01-10 14:32:44 -0800831
832 if (mPeriodicTimeInjection) {
833 // send delayed message for next NTP injection
834 // since this is delayed and not urgent we do not hold a wake lock here
Jeff Brown028872f2012-08-25 13:07:01 -0700835 mHandler.sendEmptyMessageDelayed(INJECT_NTP_TIME, delay);
Kevin Tang40e1baf2012-01-10 14:32:44 -0800836 }
Jeff Brown028872f2012-08-25 13:07:01 -0700837
838 // release wake lock held by task
839 mWakeLock.release();
Kevin Tang40e1baf2012-01-10 14:32:44 -0800840 }
841 });
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400842 }
843
844 private void handleDownloadXtraData() {
Kevin Tang40e1baf2012-01-10 14:32:44 -0800845 if (mDownloadXtraDataPending == STATE_DOWNLOADING) {
846 // already downloading data
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400847 return;
848 }
Kevin Tang40e1baf2012-01-10 14:32:44 -0800849 if (!mNetworkAvailable) {
850 // try again when network is up
851 mDownloadXtraDataPending = STATE_PENDING_NETWORK;
852 return;
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400853 }
Kevin Tang40e1baf2012-01-10 14:32:44 -0800854 mDownloadXtraDataPending = STATE_DOWNLOADING;
855
Jeff Brown028872f2012-08-25 13:07:01 -0700856 // hold wake lock while task runs
857 mWakeLock.acquire();
Kevin Tang40e1baf2012-01-10 14:32:44 -0800858 AsyncTask.THREAD_POOL_EXECUTOR.execute(new Runnable() {
859 @Override
860 public void run() {
Andreas Gampedfdc6ac2014-10-28 20:42:53 -0700861 GpsXtraDownloader xtraDownloader = new GpsXtraDownloader(mProperties);
Kevin Tang40e1baf2012-01-10 14:32:44 -0800862 byte[] data = xtraDownloader.downloadXtraData();
863 if (data != null) {
864 if (DEBUG) {
865 Log.d(TAG, "calling native_inject_xtra_data");
866 }
867 native_inject_xtra_data(data, data.length);
868 }
869
Jeff Brown028872f2012-08-25 13:07:01 -0700870 sendMessage(DOWNLOAD_XTRA_DATA_FINISHED, 0, null);
Kevin Tang40e1baf2012-01-10 14:32:44 -0800871
872 if (data == null) {
873 // try again later
874 // since this is delayed and not urgent we do not hold a wake lock here
Jeff Brown028872f2012-08-25 13:07:01 -0700875 mHandler.sendEmptyMessageDelayed(DOWNLOAD_XTRA_DATA, RETRY_INTERVAL);
Kevin Tang40e1baf2012-01-10 14:32:44 -0800876 }
Kevin Tang40e1baf2012-01-10 14:32:44 -0800877
Jeff Brown028872f2012-08-25 13:07:01 -0700878 // release wake lock held by task
879 mWakeLock.release();
880 }
Kevin Tang40e1baf2012-01-10 14:32:44 -0800881 });
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800882 }
883
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400884 private void handleUpdateLocation(Location location) {
Mike Lockwoodd26ce0d2009-06-11 12:25:46 -0400885 if (location.hasAccuracy()) {
886 native_inject_location(location.getLatitude(), location.getLongitude(),
887 location.getAccuracy());
888 }
Mike Lockwoodfd6e5f02009-05-21 11:28:20 -0400889 }
890
891 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800892 * Enables this provider. When enabled, calls to getStatus()
Mike Lockwood4e50b782009-04-03 08:24:43 -0700893 * must be handled. Hardware may be started up
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800894 * when the provider is enabled.
895 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700896 @Override
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400897 public void enable() {
Laurent Tu7b5aeca2013-01-24 15:10:24 -0800898 synchronized (mLock) {
899 if (mEnabled) return;
900 mEnabled = true;
901 }
902
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700903 sendMessage(ENABLE, 1, null);
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400904 }
905
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700906 private void setSuplHostPort(String hostString, String portString) {
907 if (hostString != null) {
908 mSuplServerHost = hostString;
909 }
910 if (portString != null) {
911 try {
912 mSuplServerPort = Integer.parseInt(portString);
913 } catch (NumberFormatException e) {
914 Log.e(TAG, "unable to parse SUPL_PORT: " + portString);
915 }
916 }
Tsuwei Chen678c13c2014-09-22 17:48:41 -0700917 if (mSuplServerHost != null
918 && mSuplServerPort > TCP_MIN_PORT
919 && mSuplServerPort <= TCP_MAX_PORT) {
920 native_set_agps_server(AGPS_TYPE_SUPL, mSuplServerHost, mSuplServerPort);
921 }
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700922 }
923
Tsuwei Chen462bcd82014-09-17 12:28:49 -0700924 /**
925 * Checks what SUPL mode to use, according to the AGPS mode as well as the
926 * allowed mode from properties.
927 *
928 * @param properties GPS properties
929 * @param agpsEnabled whether AGPS is enabled by settings value
930 * @param singleShot whether "singleshot" is needed
931 * @return SUPL mode (MSA vs MSB vs STANDALONE)
932 */
933 private int getSuplMode(Properties properties, boolean agpsEnabled, boolean singleShot) {
934 if (agpsEnabled) {
935 String modeString = properties.getProperty("SUPL_MODE");
936 int suplMode = 0;
937 if (!TextUtils.isEmpty(modeString)) {
938 try {
939 suplMode = Integer.parseInt(modeString);
940 } catch (NumberFormatException e) {
941 Log.e(TAG, "unable to parse SUPL_MODE: " + modeString);
942 return GPS_POSITION_MODE_STANDALONE;
943 }
944 }
945 if (singleShot
946 && hasCapability(GPS_CAPABILITY_MSA)
947 && (suplMode & AGPS_SUPL_MODE_MSA) != 0) {
948 return GPS_POSITION_MODE_MS_ASSISTED;
949 } else if (hasCapability(GPS_CAPABILITY_MSB)
950 && (suplMode & AGPS_SUPL_MODE_MSB) != 0) {
951 return GPS_POSITION_MODE_MS_BASED;
952 }
953 }
954 return GPS_POSITION_MODE_STANDALONE;
955 }
956
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400957 private void handleEnable() {
958 if (DEBUG) Log.d(TAG, "handleEnable");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800959
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700960 boolean enabled = native_init();
961
962 if (enabled) {
Mike Lockwood1a1cd3a2010-08-17 07:42:54 -0400963 mSupportsXtra = native_supports_xtra();
Tsuwei Chen678c13c2014-09-22 17:48:41 -0700964
965 // TODO: remove the following native calls if we can make sure they are redundant.
Mike Lockwood734d6032009-07-28 18:30:25 -0700966 if (mSuplServerHost != null) {
967 native_set_agps_server(AGPS_TYPE_SUPL, mSuplServerHost, mSuplServerPort);
968 }
969 if (mC2KServerHost != null) {
970 native_set_agps_server(AGPS_TYPE_C2K, mC2KServerHost, mC2KServerPort);
971 }
destradaa13a60b02015-01-15 18:36:01 -0800972
973 mGpsMeasurementsProvider.onGpsEnabledChanged();
974 mGpsNavigationMessageProvider.onGpsEnabledChanged();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800975 } else {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700976 synchronized (mLock) {
977 mEnabled = false;
978 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800979 Log.w(TAG, "Failed to enable location provider");
980 }
981 }
982
983 /**
984 * Disables this provider. When disabled, calls to getStatus()
Mike Lockwood4e50b782009-04-03 08:24:43 -0700985 * need not be handled. Hardware may be shut
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800986 * down while the provider is disabled.
987 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700988 @Override
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400989 public void disable() {
Laurent Tu7b5aeca2013-01-24 15:10:24 -0800990 synchronized (mLock) {
991 if (!mEnabled) return;
992 mEnabled = false;
993 }
994
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700995 sendMessage(ENABLE, 0, null);
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400996 }
997
998 private void handleDisable() {
Mike Lockwood89096312010-03-24 10:14:55 -0400999 if (DEBUG) Log.d(TAG, "handleDisable");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001000
David Christie3bc26142013-12-19 14:53:44 -08001001 updateClientUids(new WorkSource());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001002 stopNavigating();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001003 mAlarmManager.cancel(mWakeupIntent);
1004 mAlarmManager.cancel(mTimeoutIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001005
Mike Lockwoodcf1d8cb2010-01-20 10:14:54 -05001006 // do this before releasing wakelock
1007 native_cleanup();
destradaa13a60b02015-01-15 18:36:01 -08001008
1009 mGpsMeasurementsProvider.onGpsEnabledChanged();
1010 mGpsNavigationMessageProvider.onGpsEnabledChanged();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001011 }
1012
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001013 @Override
Mike Lockwoodd03ff942010-02-09 08:46:14 -05001014 public boolean isEnabled() {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001015 synchronized (mLock) {
1016 return mEnabled;
1017 }
Mike Lockwoodd03ff942010-02-09 08:46:14 -05001018 }
1019
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001020 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001021 public int getStatus(Bundle extras) {
1022 if (extras != null) {
1023 extras.putInt("satellites", mSvCount);
1024 }
1025 return mStatus;
1026 }
1027
1028 private void updateStatus(int status, int svCount) {
1029 if (status != mStatus || svCount != mSvCount) {
1030 mStatus = status;
1031 mSvCount = svCount;
1032 mLocationExtras.putInt("satellites", svCount);
1033 mStatusUpdateTime = SystemClock.elapsedRealtime();
1034 }
1035 }
1036
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001037 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001038 public long getStatusUpdateTime() {
1039 return mStatusUpdateTime;
1040 }
1041
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001042 @Override
1043 public void setRequest(ProviderRequest request, WorkSource source) {
1044 sendMessage(SET_REQUEST, 0, new GpsRequest(request, source));
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001045 }
1046
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001047 private void handleSetRequest(ProviderRequest request, WorkSource source) {
David Christied4edf4c2014-08-12 15:22:27 -07001048 mProviderRequest = request;
1049 mWorkSource = source;
1050 updateRequirements();
1051 }
1052
1053 // Called when the requirements for GPS may have changed
1054 private void updateRequirements() {
1055 if (mProviderRequest == null || mWorkSource == null) {
1056 return;
1057 }
1058
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001059 boolean singleShot = false;
1060
1061 // see if the request is for a single update
David Christied4edf4c2014-08-12 15:22:27 -07001062 if (mProviderRequest.locationRequests != null
1063 && mProviderRequest.locationRequests.size() > 0) {
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001064 // if any request has zero or more than one updates
1065 // requested, then this is not single-shot mode
1066 singleShot = true;
1067
David Christied4edf4c2014-08-12 15:22:27 -07001068 for (LocationRequest lr : mProviderRequest.locationRequests) {
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001069 if (lr.getNumUpdates() != 1) {
1070 singleShot = false;
1071 }
1072 }
1073 }
1074
David Christied4edf4c2014-08-12 15:22:27 -07001075 if (DEBUG) Log.d(TAG, "setRequest " + mProviderRequest);
1076 if (mProviderRequest.reportLocation && !mDisableGps) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001077 // update client uids
David Christied4edf4c2014-08-12 15:22:27 -07001078 updateClientUids(mWorkSource);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001079
David Christied4edf4c2014-08-12 15:22:27 -07001080 mFixInterval = (int) mProviderRequest.interval;
Mike Lockwood03ca2162010-04-01 08:10:09 -07001081
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001082 // check for overflow
David Christied4edf4c2014-08-12 15:22:27 -07001083 if (mFixInterval != mProviderRequest.interval) {
1084 Log.w(TAG, "interval overflow: " + mProviderRequest.interval);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001085 mFixInterval = Integer.MAX_VALUE;
1086 }
Mike Lockwood03ca2162010-04-01 08:10:09 -07001087
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001088 // apply request to GPS engine
Mike Lockwood04598b62010-04-14 17:17:24 -04001089 if (mStarted && hasCapability(GPS_CAPABILITY_SCHEDULING)) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001090 // change period
Mike Lockwood04598b62010-04-14 17:17:24 -04001091 if (!native_set_position_mode(mPositionMode, GPS_POSITION_RECURRENCE_PERIODIC,
1092 mFixInterval, 0, 0)) {
1093 Log.e(TAG, "set_position_mode failed in setMinTime()");
1094 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001095 } else if (!mStarted) {
1096 // start GPS
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001097 startNavigating(singleShot);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001098 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001099 } else {
Dianne Hackborn002a54e2013-01-10 17:34:55 -08001100 updateClientUids(new WorkSource());
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001101
1102 stopNavigating();
1103 mAlarmManager.cancel(mWakeupIntent);
1104 mAlarmManager.cancel(mTimeoutIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001105 }
1106 }
1107
Dianne Hackborn002a54e2013-01-10 17:34:55 -08001108 private void updateClientUids(WorkSource source) {
1109 // Update work source.
1110 WorkSource[] changes = mClientSource.setReturningDiffs(source);
Victoria Leaseea78b852013-01-15 10:39:28 -08001111 if (changes == null) {
1112 return;
1113 }
Dianne Hackborn002a54e2013-01-10 17:34:55 -08001114 WorkSource newWork = changes[0];
1115 WorkSource goneWork = changes[1];
1116
1117 // Update sources that were not previously tracked.
1118 if (newWork != null) {
1119 int lastuid = -1;
1120 for (int i=0; i<newWork.size(); i++) {
Dianne Hackborn2e418422009-06-22 20:00:17 -07001121 try {
Dianne Hackborn002a54e2013-01-10 17:34:55 -08001122 int uid = newWork.get(i);
Dianne Hackborne98f5db2013-07-17 17:23:25 -07001123 mAppOpsService.startOperation(AppOpsManager.getToken(mAppOpsService),
1124 AppOpsManager.OP_GPS, uid, newWork.getName(i));
Dianne Hackborn002a54e2013-01-10 17:34:55 -08001125 if (uid != lastuid) {
1126 lastuid = uid;
1127 mBatteryStats.noteStartGps(uid);
1128 }
Dianne Hackborn2e418422009-06-22 20:00:17 -07001129 } catch (RemoteException e) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001130 Log.w(TAG, "RemoteException", e);
1131 }
1132 }
1133 }
1134
Dianne Hackborn002a54e2013-01-10 17:34:55 -08001135 // Update sources that are no longer tracked.
1136 if (goneWork != null) {
1137 int lastuid = -1;
1138 for (int i=0; i<goneWork.size(); i++) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001139 try {
Dianne Hackborn002a54e2013-01-10 17:34:55 -08001140 int uid = goneWork.get(i);
Dianne Hackborne98f5db2013-07-17 17:23:25 -07001141 mAppOpsService.finishOperation(AppOpsManager.getToken(mAppOpsService),
1142 AppOpsManager.OP_GPS, uid, goneWork.getName(i));
Dianne Hackborn002a54e2013-01-10 17:34:55 -08001143 if (uid != lastuid) {
1144 lastuid = uid;
1145 mBatteryStats.noteStopGps(uid);
1146 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001147 } catch (RemoteException e) {
1148 Log.w(TAG, "RemoteException", e);
Dianne Hackborn2e418422009-06-22 20:00:17 -07001149 }
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001150 }
1151 }
1152 }
1153
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001154 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001155 public boolean sendExtraCommand(String command, Bundle extras) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001156
Mike Lockwood63aa5a62010-04-14 19:21:31 -04001157 long identity = Binder.clearCallingIdentity();
1158 boolean result = false;
1159
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001160 if ("delete_aiding_data".equals(command)) {
Mike Lockwood63aa5a62010-04-14 19:21:31 -04001161 result = deleteAidingData(extras);
1162 } else if ("force_time_injection".equals(command)) {
Mike Lockwood98e48692010-04-07 16:32:51 -04001163 sendMessage(INJECT_NTP_TIME, 0, null);
Mike Lockwood63aa5a62010-04-14 19:21:31 -04001164 result = true;
1165 } else if ("force_xtra_injection".equals(command)) {
Mike Lockwood1a1cd3a2010-08-17 07:42:54 -04001166 if (mSupportsXtra) {
Mike Lockwood93bc44d2009-05-20 16:58:22 -04001167 xtraDownloadRequest();
Mike Lockwood63aa5a62010-04-14 19:21:31 -04001168 result = true;
Mike Lockwood93bc44d2009-05-20 16:58:22 -04001169 }
Mike Lockwood63aa5a62010-04-14 19:21:31 -04001170 } else {
1171 Log.w(TAG, "sendExtraCommand: unknown command " + command);
Mike Lockwood93bc44d2009-05-20 16:58:22 -04001172 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001173
Mike Lockwood63aa5a62010-04-14 19:21:31 -04001174 Binder.restoreCallingIdentity(identity);
1175 return result;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001176 }
1177
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001178 private IGpsGeofenceHardware mGpsGeofenceBinder = new IGpsGeofenceHardware.Stub() {
1179 public boolean isHardwareGeofenceSupported() {
1180 return native_is_geofence_supported();
1181 }
1182
1183 public boolean addCircularHardwareGeofence(int geofenceId, double latitude,
1184 double longitude, double radius, int lastTransition, int monitorTransitions,
1185 int notificationResponsiveness, int unknownTimer) {
1186 return native_add_geofence(geofenceId, latitude, longitude, radius,
1187 lastTransition, monitorTransitions, notificationResponsiveness, unknownTimer);
1188 }
1189
1190 public boolean removeHardwareGeofence(int geofenceId) {
1191 return native_remove_geofence(geofenceId);
1192 }
1193
1194 public boolean pauseHardwareGeofence(int geofenceId) {
1195 return native_pause_geofence(geofenceId);
1196 }
1197
1198 public boolean resumeHardwareGeofence(int geofenceId, int monitorTransition) {
1199 return native_resume_geofence(geofenceId, monitorTransition);
1200 }
1201 };
1202
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001203 private boolean deleteAidingData(Bundle extras) {
1204 int flags;
1205
1206 if (extras == null) {
1207 flags = GPS_DELETE_ALL;
1208 } else {
1209 flags = 0;
1210 if (extras.getBoolean("ephemeris")) flags |= GPS_DELETE_EPHEMERIS;
1211 if (extras.getBoolean("almanac")) flags |= GPS_DELETE_ALMANAC;
1212 if (extras.getBoolean("position")) flags |= GPS_DELETE_POSITION;
1213 if (extras.getBoolean("time")) flags |= GPS_DELETE_TIME;
1214 if (extras.getBoolean("iono")) flags |= GPS_DELETE_IONO;
1215 if (extras.getBoolean("utc")) flags |= GPS_DELETE_UTC;
1216 if (extras.getBoolean("health")) flags |= GPS_DELETE_HEALTH;
1217 if (extras.getBoolean("svdir")) flags |= GPS_DELETE_SVDIR;
1218 if (extras.getBoolean("svsteer")) flags |= GPS_DELETE_SVSTEER;
1219 if (extras.getBoolean("sadata")) flags |= GPS_DELETE_SADATA;
1220 if (extras.getBoolean("rti")) flags |= GPS_DELETE_RTI;
1221 if (extras.getBoolean("celldb-info")) flags |= GPS_DELETE_CELLDB_INFO;
1222 if (extras.getBoolean("all")) flags |= GPS_DELETE_ALL;
1223 }
1224
1225 if (flags != 0) {
1226 native_delete_aiding_data(flags);
1227 return true;
1228 }
1229
1230 return false;
1231 }
1232
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001233 private void startNavigating(boolean singleShot) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001234 if (!mStarted) {
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001235 if (DEBUG) Log.d(TAG, "startNavigating, singleShot is " + singleShot);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001236 mTimeToFirstFix = 0;
1237 mLastFixTime = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001238 mStarted = true;
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001239 mSingleShot = singleShot;
Mike Lockwood03ca2162010-04-01 08:10:09 -07001240 mPositionMode = GPS_POSITION_MODE_STANDALONE;
1241
Tsuwei Chen462bcd82014-09-17 12:28:49 -07001242 boolean agpsEnabled =
1243 (Settings.Global.getInt(mContext.getContentResolver(),
1244 Settings.Global.ASSISTED_GPS_ENABLED, 1) != 0);
1245 mPositionMode = getSuplMode(mProperties, agpsEnabled, singleShot);
Mike Lockwoodbcab8df2009-06-25 16:39:09 -04001246
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001247 if (DEBUG) {
1248 String mode;
1249
1250 switch(mPositionMode) {
1251 case GPS_POSITION_MODE_STANDALONE:
1252 mode = "standalone";
1253 break;
1254 case GPS_POSITION_MODE_MS_ASSISTED:
1255 mode = "MS_ASSISTED";
1256 break;
1257 case GPS_POSITION_MODE_MS_BASED:
1258 mode = "MS_BASED";
1259 break;
1260 default:
1261 mode = "unknown";
1262 break;
1263 }
1264 Log.d(TAG, "setting position_mode to " + mode);
1265 }
1266
Mike Lockwood04598b62010-04-14 17:17:24 -04001267 int interval = (hasCapability(GPS_CAPABILITY_SCHEDULING) ? mFixInterval : 1000);
1268 if (!native_set_position_mode(mPositionMode, GPS_POSITION_RECURRENCE_PERIODIC,
1269 interval, 0, 0)) {
1270 mStarted = false;
1271 Log.e(TAG, "set_position_mode failed in startNavigating()");
1272 return;
1273 }
1274 if (!native_start()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001275 mStarted = false;
1276 Log.e(TAG, "native_start failed in startNavigating()");
Mike Lockwood0632ca72009-05-14 15:51:03 -04001277 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001278 }
1279
1280 // reset SV count to zero
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001281 updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, 0);
Mike Lockwood29c84342009-05-06 14:01:15 -04001282 mFixRequestTime = System.currentTimeMillis();
Mike Lockwood04598b62010-04-14 17:17:24 -04001283 if (!hasCapability(GPS_CAPABILITY_SCHEDULING)) {
1284 // set timer to give up if we do not receive a fix within NO_FIX_TIMEOUT
1285 // and our fix interval is not short
1286 if (mFixInterval >= NO_FIX_TIMEOUT) {
1287 mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
1288 SystemClock.elapsedRealtime() + NO_FIX_TIMEOUT, mTimeoutIntent);
1289 }
Mike Lockwood0632ca72009-05-14 15:51:03 -04001290 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001291 }
1292 }
1293
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001294 private void stopNavigating() {
Mike Lockwood29c84342009-05-06 14:01:15 -04001295 if (DEBUG) Log.d(TAG, "stopNavigating");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001296 if (mStarted) {
1297 mStarted = false;
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001298 mSingleShot = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001299 native_stop();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001300 mTimeToFirstFix = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001301 mLastFixTime = 0;
1302 mLocationFlags = LOCATION_INVALID;
1303
1304 // reset SV count to zero
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001305 updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001306 }
1307 }
1308
Mike Lockwood0632ca72009-05-14 15:51:03 -04001309 private void hibernate() {
1310 // stop GPS until our next fix interval arrives
1311 stopNavigating();
Mike Lockwood0632ca72009-05-14 15:51:03 -04001312 mAlarmManager.cancel(mTimeoutIntent);
1313 mAlarmManager.cancel(mWakeupIntent);
1314 long now = SystemClock.elapsedRealtime();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001315 mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, now + mFixInterval, mWakeupIntent);
Mike Lockwood04598b62010-04-14 17:17:24 -04001316 }
1317
1318 private boolean hasCapability(int capability) {
1319 return ((mEngineCapabilities & capability) != 0);
Mike Lockwood0632ca72009-05-14 15:51:03 -04001320 }
1321
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001322
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001323 /**
1324 * called from native code to update our position.
1325 */
1326 private void reportLocation(int flags, double latitude, double longitude, double altitude,
1327 float speed, float bearing, float accuracy, long timestamp) {
Mike Lockwood29c84342009-05-06 14:01:15 -04001328 if (VERBOSE) Log.v(TAG, "reportLocation lat: " + latitude + " long: " + longitude +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001329 " timestamp: " + timestamp);
1330
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001331 synchronized (mLocation) {
1332 mLocationFlags = flags;
1333 if ((flags & LOCATION_HAS_LAT_LONG) == LOCATION_HAS_LAT_LONG) {
1334 mLocation.setLatitude(latitude);
1335 mLocation.setLongitude(longitude);
1336 mLocation.setTime(timestamp);
Nick Pelly2eeeec22012-07-18 13:13:37 -07001337 // It would be nice to push the elapsed real-time timestamp
1338 // further down the stack, but this is still useful
Philip Milne41180122012-09-26 11:29:25 -07001339 mLocation.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001340 }
1341 if ((flags & LOCATION_HAS_ALTITUDE) == LOCATION_HAS_ALTITUDE) {
1342 mLocation.setAltitude(altitude);
1343 } else {
1344 mLocation.removeAltitude();
1345 }
1346 if ((flags & LOCATION_HAS_SPEED) == LOCATION_HAS_SPEED) {
1347 mLocation.setSpeed(speed);
1348 } else {
1349 mLocation.removeSpeed();
1350 }
1351 if ((flags & LOCATION_HAS_BEARING) == LOCATION_HAS_BEARING) {
1352 mLocation.setBearing(bearing);
1353 } else {
1354 mLocation.removeBearing();
1355 }
1356 if ((flags & LOCATION_HAS_ACCURACY) == LOCATION_HAS_ACCURACY) {
1357 mLocation.setAccuracy(accuracy);
1358 } else {
1359 mLocation.removeAccuracy();
1360 }
Sean Barbeauced2b2c2011-12-19 04:43:07 -05001361 mLocation.setExtras(mLocationExtras);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001362
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001363 try {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001364 mILocationManager.reportLocation(mLocation, false);
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001365 } catch (RemoteException e) {
1366 Log.e(TAG, "RemoteException calling reportLocation");
1367 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001368 }
1369
Hakan Gustavssonfa94ff02010-02-23 09:12:38 +01001370 mLastFixTime = System.currentTimeMillis();
1371 // report time to first fix
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001372 if (mTimeToFirstFix == 0 && (flags & LOCATION_HAS_LAT_LONG) == LOCATION_HAS_LAT_LONG) {
1373 mTimeToFirstFix = (int)(mLastFixTime - mFixRequestTime);
1374 if (DEBUG) Log.d(TAG, "TTFF: " + mTimeToFirstFix);
Hakan Gustavssonfa94ff02010-02-23 09:12:38 +01001375
1376 // notify status listeners
destradaaea8a8a62014-06-23 18:19:03 -07001377 mListenerHelper.onFirstFix(mTimeToFirstFix);
Hakan Gustavssonfa94ff02010-02-23 09:12:38 +01001378 }
1379
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001380 if (mSingleShot) {
1381 stopNavigating();
1382 }
1383
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001384 if (mStarted && mStatus != LocationProvider.AVAILABLE) {
Mike Lockwoodd53ba012010-04-15 20:41:26 -04001385 // we want to time out if we do not receive a fix
Mike Lockwoodb7be5442010-02-24 14:34:50 -05001386 // within the time out and we are requesting infrequent fixes
Mike Lockwood04598b62010-04-14 17:17:24 -04001387 if (!hasCapability(GPS_CAPABILITY_SCHEDULING) && mFixInterval < NO_FIX_TIMEOUT) {
Mike Lockwoodb7be5442010-02-24 14:34:50 -05001388 mAlarmManager.cancel(mTimeoutIntent);
1389 }
1390
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001391 // send an intent to notify that the GPS is receiving fixes.
Mike Lockwood00b74272010-03-26 10:41:48 -04001392 Intent intent = new Intent(LocationManager.GPS_FIX_CHANGE_ACTION);
1393 intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, true);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07001394 mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001395 updateStatus(LocationProvider.AVAILABLE, mSvCount);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001396 }
Mike Lockwood29c84342009-05-06 14:01:15 -04001397
Nick Pellyb041f232012-05-07 17:12:25 -07001398 if (!hasCapability(GPS_CAPABILITY_SCHEDULING) && mStarted &&
1399 mFixInterval > GPS_POLLING_THRESHOLD_INTERVAL) {
Mike Lockwoodd53ba012010-04-15 20:41:26 -04001400 if (DEBUG) Log.d(TAG, "got fix, hibernating");
Mike Lockwood0632ca72009-05-14 15:51:03 -04001401 hibernate();
Mike Lockwood29c84342009-05-06 14:01:15 -04001402 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001403 }
1404
1405 /**
1406 * called from native code to update our status
1407 */
1408 private void reportStatus(int status) {
Mike Lockwoodb8d90332010-10-18 17:59:48 -04001409 if (DEBUG) Log.v(TAG, "reportStatus status: " + status);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001410
destradaaea8a8a62014-06-23 18:19:03 -07001411 boolean wasNavigating = mNavigating;
1412 switch (status) {
1413 case GPS_STATUS_SESSION_BEGIN:
1414 mNavigating = true;
1415 mEngineOn = true;
1416 break;
1417 case GPS_STATUS_SESSION_END:
1418 mNavigating = false;
1419 break;
1420 case GPS_STATUS_ENGINE_ON:
1421 mEngineOn = true;
1422 break;
1423 case GPS_STATUS_ENGINE_OFF:
1424 mEngineOn = false;
1425 mNavigating = false;
1426 break;
1427 }
Mike Lockwooddbd6fd82009-12-07 18:43:36 -05001428
destradaaea8a8a62014-06-23 18:19:03 -07001429 if (wasNavigating != mNavigating) {
destradaa13a60b02015-01-15 18:36:01 -08001430 mListenerHelper.onStatusChanged(mNavigating);
Mike Lockwoodcf1d8cb2010-01-20 10:14:54 -05001431
destradaaea8a8a62014-06-23 18:19:03 -07001432 // send an intent to notify that the GPS has been enabled or disabled
1433 Intent intent = new Intent(LocationManager.GPS_ENABLED_CHANGE_ACTION);
1434 intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, mNavigating);
1435 mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001436 }
1437 }
1438
1439 /**
1440 * called from native code to update SV info
1441 */
1442 private void reportSvStatus() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001443 int svCount = native_read_sv_status(mSvs, mSnrs, mSvElevations, mSvAzimuths, mSvMasks);
destradaaea8a8a62014-06-23 18:19:03 -07001444 mListenerHelper.onSvStatusChanged(
1445 svCount,
1446 mSvs,
1447 mSnrs,
1448 mSvElevations,
1449 mSvAzimuths,
1450 mSvMasks[EPHEMERIS_MASK],
1451 mSvMasks[ALMANAC_MASK],
1452 mSvMasks[USED_FOR_FIX_MASK]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001453
Mike Lockwood29c84342009-05-06 14:01:15 -04001454 if (VERBOSE) {
1455 Log.v(TAG, "SV count: " + svCount +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001456 " ephemerisMask: " + Integer.toHexString(mSvMasks[EPHEMERIS_MASK]) +
1457 " almanacMask: " + Integer.toHexString(mSvMasks[ALMANAC_MASK]));
1458 for (int i = 0; i < svCount; i++) {
Mike Lockwood29c84342009-05-06 14:01:15 -04001459 Log.v(TAG, "sv: " + mSvs[i] +
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001460 " snr: " + mSnrs[i]/10 +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001461 " elev: " + mSvElevations[i] +
1462 " azimuth: " + mSvAzimuths[i] +
1463 ((mSvMasks[EPHEMERIS_MASK] & (1 << (mSvs[i] - 1))) == 0 ? " " : " E") +
1464 ((mSvMasks[ALMANAC_MASK] & (1 << (mSvs[i] - 1))) == 0 ? " " : " A") +
1465 ((mSvMasks[USED_FOR_FIX_MASK] & (1 << (mSvs[i] - 1))) == 0 ? "" : "U"));
1466 }
1467 }
1468
Kevin.KY Tsai0881f4f2010-05-21 15:10:39 -04001469 // return number of sets used in fix instead of total
1470 updateStatus(mStatus, Integer.bitCount(mSvMasks[USED_FOR_FIX_MASK]));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001471
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001472 if (mNavigating && mStatus == LocationProvider.AVAILABLE && mLastFixTime > 0 &&
Mike Lockwood04598b62010-04-14 17:17:24 -04001473 System.currentTimeMillis() - mLastFixTime > RECENT_FIX_TIMEOUT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001474 // send an intent to notify that the GPS is no longer receiving fixes.
Mike Lockwood00b74272010-03-26 10:41:48 -04001475 Intent intent = new Intent(LocationManager.GPS_FIX_CHANGE_ACTION);
1476 intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, false);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07001477 mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001478 updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, mSvCount);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001479 }
1480 }
Mike Lockwood58bda982009-04-14 16:25:07 -04001481
1482 /**
Mike Lockwoode3635c92009-05-11 08:38:02 -04001483 * called from native code to update AGPS status
Mike Lockwood58bda982009-04-14 16:25:07 -04001484 */
destradaa96a14702014-06-05 11:36:30 -07001485 private void reportAGpsStatus(int type, int status, byte[] ipaddr) {
Mike Lockwood58bda982009-04-14 16:25:07 -04001486 switch (status) {
Mike Lockwoode3635c92009-05-11 08:38:02 -04001487 case GPS_REQUEST_AGPS_DATA_CONN:
Mike Lockwoodb6e5fa82010-10-09 20:10:46 -04001488 if (DEBUG) Log.d(TAG, "GPS_REQUEST_AGPS_DATA_CONN");
destradaa931a37f2014-08-12 16:36:59 -07001489 Log.v(TAG, "Received SUPL IP addr[]: " + ipaddr);
Mike Lockwood2acfd342010-09-22 12:13:39 -04001490 // Set mAGpsDataConnectionState before calling startUsingNetworkFeature
1491 // to avoid a race condition with handleUpdateNetworkState()
1492 mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPENING;
1493 int result = mConnMgr.startUsingNetworkFeature(
Mike Lockwood58bda982009-04-14 16:25:07 -04001494 ConnectivityManager.TYPE_MOBILE, Phone.FEATURE_ENABLE_SUPL);
destradaa96a14702014-06-05 11:36:30 -07001495 if (ipaddr != null) {
1496 try {
1497 mAGpsDataConnectionIpAddr = InetAddress.getByAddress(ipaddr);
destradaa931a37f2014-08-12 16:36:59 -07001498 Log.v(TAG, "IP address converted to: " + mAGpsDataConnectionIpAddr);
destradaa96a14702014-06-05 11:36:30 -07001499 } catch (UnknownHostException e) {
1500 Log.e(TAG, "Bad IP Address: " + ipaddr, e);
1501 mAGpsDataConnectionIpAddr = null;
1502 }
1503 }
1504
Wink Savillea639b312012-07-10 12:37:54 -07001505 if (result == PhoneConstants.APN_ALREADY_ACTIVE) {
1506 if (DEBUG) Log.d(TAG, "PhoneConstants.APN_ALREADY_ACTIVE");
Mike Lockwoodb362a9a2009-06-22 16:20:39 -04001507 if (mAGpsApn != null) {
destradaa96a14702014-06-05 11:36:30 -07001508 setRouting();
1509 native_agps_data_conn_open(mAGpsApn, mApnIpType);
Mike Lockwoodb362a9a2009-06-22 16:20:39 -04001510 mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPEN;
1511 } else {
Wink Savillea639b312012-07-10 12:37:54 -07001512 Log.e(TAG, "mAGpsApn not set when receiving PhoneConstants.APN_ALREADY_ACTIVE");
Mike Lockwood2acfd342010-09-22 12:13:39 -04001513 mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED;
Mike Lockwoodb362a9a2009-06-22 16:20:39 -04001514 native_agps_data_conn_failed();
1515 }
Wink Savillea639b312012-07-10 12:37:54 -07001516 } else if (result == PhoneConstants.APN_REQUEST_STARTED) {
1517 if (DEBUG) Log.d(TAG, "PhoneConstants.APN_REQUEST_STARTED");
Mike Lockwood2acfd342010-09-22 12:13:39 -04001518 // Nothing to do here
Mike Lockwood58bda982009-04-14 16:25:07 -04001519 } else {
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001520 if (DEBUG) Log.d(TAG, "startUsingNetworkFeature failed, value is " +
1521 result);
Mike Lockwood2acfd342010-09-22 12:13:39 -04001522 mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED;
Mike Lockwoode3635c92009-05-11 08:38:02 -04001523 native_agps_data_conn_failed();
Mike Lockwood58bda982009-04-14 16:25:07 -04001524 }
1525 break;
Mike Lockwoode3635c92009-05-11 08:38:02 -04001526 case GPS_RELEASE_AGPS_DATA_CONN:
Mike Lockwoodb6e5fa82010-10-09 20:10:46 -04001527 if (DEBUG) Log.d(TAG, "GPS_RELEASE_AGPS_DATA_CONN");
Mike Lockwoode3635c92009-05-11 08:38:02 -04001528 if (mAGpsDataConnectionState != AGPS_DATA_CONNECTION_CLOSED) {
Mike Lockwood58bda982009-04-14 16:25:07 -04001529 mConnMgr.stopUsingNetworkFeature(
1530 ConnectivityManager.TYPE_MOBILE, Phone.FEATURE_ENABLE_SUPL);
Mike Lockwoode3635c92009-05-11 08:38:02 -04001531 native_agps_data_conn_closed();
1532 mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED;
destradaa96a14702014-06-05 11:36:30 -07001533 mAGpsDataConnectionIpAddr = null;
Mike Lockwood58bda982009-04-14 16:25:07 -04001534 }
1535 break;
Mike Lockwoode3635c92009-05-11 08:38:02 -04001536 case GPS_AGPS_DATA_CONNECTED:
Mike Lockwoodb6e5fa82010-10-09 20:10:46 -04001537 if (DEBUG) Log.d(TAG, "GPS_AGPS_DATA_CONNECTED");
Mike Lockwood58bda982009-04-14 16:25:07 -04001538 break;
Mike Lockwoode3635c92009-05-11 08:38:02 -04001539 case GPS_AGPS_DATA_CONN_DONE:
Mike Lockwoodb6e5fa82010-10-09 20:10:46 -04001540 if (DEBUG) Log.d(TAG, "GPS_AGPS_DATA_CONN_DONE");
Mike Lockwood58bda982009-04-14 16:25:07 -04001541 break;
Mike Lockwoode3635c92009-05-11 08:38:02 -04001542 case GPS_AGPS_DATA_CONN_FAILED:
Mike Lockwoodb6e5fa82010-10-09 20:10:46 -04001543 if (DEBUG) Log.d(TAG, "GPS_AGPS_DATA_CONN_FAILED");
Mike Lockwood58bda982009-04-14 16:25:07 -04001544 break;
destradaa931a37f2014-08-12 16:36:59 -07001545 default:
1546 Log.d(TAG, "Received Unknown AGPS status: " + status);
Mike Lockwood58bda982009-04-14 16:25:07 -04001547 }
1548 }
1549
Mike Lockwoodb16e7802009-08-06 09:26:02 -04001550 /**
1551 * called from native code to report NMEA data received
1552 */
Mike Lockwoodf602d362010-06-20 14:28:16 -07001553 private void reportNmea(long timestamp) {
destradaaea8a8a62014-06-23 18:19:03 -07001554 int length = native_read_nmea(mNmeaBuffer, mNmeaBuffer.length);
1555 String nmea = new String(mNmeaBuffer, 0 /* offset */, length);
1556 mListenerHelper.onNmeaReceived(timestamp, nmea);
1557 }
Mike Lockwoodb16e7802009-08-06 09:26:02 -04001558
destradaaea8a8a62014-06-23 18:19:03 -07001559 /**
destradaa4b3e3932014-07-21 18:01:47 -07001560 * called from native code - Gps measurements callback
destradaaea8a8a62014-06-23 18:19:03 -07001561 */
1562 private void reportMeasurementData(GpsMeasurementsEvent event) {
1563 mGpsMeasurementsProvider.onMeasurementsAvailable(event);
Mike Lockwoodb16e7802009-08-06 09:26:02 -04001564 }
1565
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001566 /**
destradaa4b3e3932014-07-21 18:01:47 -07001567 * called from native code - GPS navigation message callback
1568 */
1569 private void reportNavigationMessage(GpsNavigationMessageEvent event) {
1570 mGpsNavigationMessageProvider.onNavigationMessageAvailable(event);
1571 }
1572
1573 /**
Mike Lockwood04598b62010-04-14 17:17:24 -04001574 * called from native code to inform us what the GPS engine capabilities are
1575 */
1576 private void setEngineCapabilities(int capabilities) {
1577 mEngineCapabilities = capabilities;
Mike Lockwood9b9fb5c2011-06-29 15:09:40 -04001578
1579 if (!hasCapability(GPS_CAPABILITY_ON_DEMAND_TIME) && !mPeriodicTimeInjection) {
1580 mPeriodicTimeInjection = true;
1581 requestUtcTime();
1582 }
destradaa6568d702014-10-27 12:47:41 -07001583
1584 mGpsMeasurementsProvider.onCapabilitiesUpdated(
1585 (capabilities & GPS_CAPABILITY_MEASUREMENTS) == GPS_CAPABILITY_MEASUREMENTS);
1586 mGpsNavigationMessageProvider.onCapabilitiesUpdated(
1587 (capabilities & GPS_CAPABILITY_NAV_MESSAGES) == GPS_CAPABILITY_NAV_MESSAGES);
Mike Lockwood04598b62010-04-14 17:17:24 -04001588 }
1589
1590 /**
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001591 * called from native code to request XTRA data
1592 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001593 private void xtraDownloadRequest() {
Joe Onoratof5d95cb2010-01-07 21:48:32 -05001594 if (DEBUG) Log.d(TAG, "xtraDownloadRequest");
Mike Lockwood98e48692010-04-07 16:32:51 -04001595 sendMessage(DOWNLOAD_XTRA_DATA, 0, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001596 }
1597
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001598 /**
destradaa0682809a2013-08-12 18:50:30 -07001599 * Helper method to construct a location object.
1600 */
1601 private Location buildLocation(
1602 int flags,
1603 double latitude,
1604 double longitude,
1605 double altitude,
1606 float speed,
1607 float bearing,
1608 float accuracy,
1609 long timestamp) {
1610 Location location = new Location(LocationManager.GPS_PROVIDER);
1611 if((flags & LOCATION_HAS_LAT_LONG) == LOCATION_HAS_LAT_LONG) {
1612 location.setLatitude(latitude);
1613 location.setLongitude(longitude);
1614 location.setTime(timestamp);
1615 location.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());
1616 }
1617 if((flags & LOCATION_HAS_ALTITUDE) == LOCATION_HAS_ALTITUDE) {
1618 location.setAltitude(altitude);
1619 }
1620 if((flags & LOCATION_HAS_SPEED) == LOCATION_HAS_SPEED) {
1621 location.setSpeed(speed);
1622 }
1623 if((flags & LOCATION_HAS_BEARING) == LOCATION_HAS_BEARING) {
1624 location.setBearing(bearing);
1625 }
1626 if((flags & LOCATION_HAS_ACCURACY) == LOCATION_HAS_ACCURACY) {
1627 location.setAccuracy(accuracy);
1628 }
1629 return location;
1630 }
1631
1632 /**
1633 * Converts the GPS HAL status to the internal Geofence Hardware status.
1634 */
1635 private int getGeofenceStatus(int status) {
1636 switch(status) {
1637 case GPS_GEOFENCE_OPERATION_SUCCESS:
1638 return GeofenceHardware.GEOFENCE_SUCCESS;
1639 case GPS_GEOFENCE_ERROR_GENERIC:
1640 return GeofenceHardware.GEOFENCE_FAILURE;
1641 case GPS_GEOFENCE_ERROR_ID_EXISTS:
1642 return GeofenceHardware.GEOFENCE_ERROR_ID_EXISTS;
1643 case GPS_GEOFENCE_ERROR_INVALID_TRANSITION:
1644 return GeofenceHardware.GEOFENCE_ERROR_INVALID_TRANSITION;
1645 case GPS_GEOFENCE_ERROR_TOO_MANY_GEOFENCES:
1646 return GeofenceHardware.GEOFENCE_ERROR_TOO_MANY_GEOFENCES;
1647 case GPS_GEOFENCE_ERROR_ID_UNKNOWN:
1648 return GeofenceHardware.GEOFENCE_ERROR_ID_UNKNOWN;
1649 default:
1650 return -1;
1651 }
1652 }
1653
1654 /**
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001655 * Called from native to report GPS Geofence transition
1656 * All geofence callbacks are called on the same thread
1657 */
1658 private void reportGeofenceTransition(int geofenceId, int flags, double latitude,
1659 double longitude, double altitude, float speed, float bearing, float accuracy,
1660 long timestamp, int transition, long transitionTimestamp) {
1661 if (mGeofenceHardwareImpl == null) {
1662 mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
1663 }
destradaa0682809a2013-08-12 18:50:30 -07001664 Location location = buildLocation(
1665 flags,
1666 latitude,
1667 longitude,
1668 altitude,
1669 speed,
1670 bearing,
1671 accuracy,
1672 timestamp);
1673 mGeofenceHardwareImpl.reportGeofenceTransition(
1674 geofenceId,
1675 location,
1676 transition,
1677 transitionTimestamp,
1678 GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE,
1679 FusedBatchOptions.SourceTechnologies.GNSS);
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001680 }
1681
1682 /**
1683 * called from native code to report GPS status change.
1684 */
1685 private void reportGeofenceStatus(int status, int flags, double latitude,
1686 double longitude, double altitude, float speed, float bearing, float accuracy,
1687 long timestamp) {
1688 if (mGeofenceHardwareImpl == null) {
1689 mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
1690 }
destradaa0682809a2013-08-12 18:50:30 -07001691 Location location = buildLocation(
1692 flags,
1693 latitude,
1694 longitude,
1695 altitude,
1696 speed,
1697 bearing,
1698 accuracy,
1699 timestamp);
1700 int monitorStatus = GeofenceHardware.MONITOR_CURRENTLY_UNAVAILABLE;
1701 if(status == GPS_GEOFENCE_AVAILABLE) {
1702 monitorStatus = GeofenceHardware.MONITOR_CURRENTLY_AVAILABLE;
1703 }
1704 mGeofenceHardwareImpl.reportGeofenceMonitorStatus(
1705 GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE,
1706 monitorStatus,
1707 location,
1708 FusedBatchOptions.SourceTechnologies.GNSS);
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001709 }
1710
1711 /**
1712 * called from native code - Geofence Add callback
1713 */
1714 private void reportGeofenceAddStatus(int geofenceId, int status) {
1715 if (mGeofenceHardwareImpl == null) {
1716 mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
1717 }
destradaa0682809a2013-08-12 18:50:30 -07001718 mGeofenceHardwareImpl.reportGeofenceAddStatus(geofenceId, getGeofenceStatus(status));
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001719 }
1720
1721 /**
1722 * called from native code - Geofence Remove callback
1723 */
1724 private void reportGeofenceRemoveStatus(int geofenceId, int status) {
1725 if (mGeofenceHardwareImpl == null) {
1726 mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
1727 }
destradaa0682809a2013-08-12 18:50:30 -07001728 mGeofenceHardwareImpl.reportGeofenceRemoveStatus(geofenceId, getGeofenceStatus(status));
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001729 }
1730
1731 /**
1732 * called from native code - Geofence Pause callback
1733 */
1734 private void reportGeofencePauseStatus(int geofenceId, int status) {
1735 if (mGeofenceHardwareImpl == null) {
1736 mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
1737 }
destradaa0682809a2013-08-12 18:50:30 -07001738 mGeofenceHardwareImpl.reportGeofencePauseStatus(geofenceId, getGeofenceStatus(status));
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001739 }
1740
1741 /**
1742 * called from native code - Geofence Resume callback
1743 */
1744 private void reportGeofenceResumeStatus(int geofenceId, int status) {
1745 if (mGeofenceHardwareImpl == null) {
1746 mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
1747 }
destradaa0682809a2013-08-12 18:50:30 -07001748 mGeofenceHardwareImpl.reportGeofenceResumeStatus(geofenceId, getGeofenceStatus(status));
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001749 }
1750
Danke Xie22d1f9f2009-08-18 18:28:45 -04001751 //=============================================================
1752 // NI Client support
Miguel Torroja1e84da82010-07-27 07:02:24 +02001753 //=============================================================
Danke Xie22d1f9f2009-08-18 18:28:45 -04001754 private final INetInitiatedListener mNetInitiatedListener = new INetInitiatedListener.Stub() {
Miguel Torroja1e84da82010-07-27 07:02:24 +02001755 // Sends a response for an NI reqeust to HAL.
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001756 @Override
Miguel Torroja1e84da82010-07-27 07:02:24 +02001757 public boolean sendNiResponse(int notificationId, int userResponse)
1758 {
1759 // TODO Add Permission check
Danke Xie22d1f9f2009-08-18 18:28:45 -04001760
Miguel Torroja1e84da82010-07-27 07:02:24 +02001761 if (DEBUG) Log.d(TAG, "sendNiResponse, notifId: " + notificationId +
1762 ", response: " + userResponse);
1763 native_send_ni_response(notificationId, userResponse);
1764 return true;
1765 }
Danke Xie22d1f9f2009-08-18 18:28:45 -04001766 };
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001767
Danke Xie22d1f9f2009-08-18 18:28:45 -04001768 public INetInitiatedListener getNetInitiatedListener() {
1769 return mNetInitiatedListener;
1770 }
1771
1772 // Called by JNI function to report an NI request.
Miguel Torroja1e84da82010-07-27 07:02:24 +02001773 public void reportNiNotification(
1774 int notificationId,
1775 int niType,
1776 int notifyFlags,
1777 int timeout,
1778 int defaultResponse,
1779 String requestorId,
1780 String text,
1781 int requestorIdEncoding,
1782 int textEncoding,
1783 String extras // Encoded extra data
Danke Xie22d1f9f2009-08-18 18:28:45 -04001784 )
Miguel Torroja1e84da82010-07-27 07:02:24 +02001785 {
1786 Log.i(TAG, "reportNiNotification: entered");
1787 Log.i(TAG, "notificationId: " + notificationId +
1788 ", niType: " + niType +
1789 ", notifyFlags: " + notifyFlags +
1790 ", timeout: " + timeout +
1791 ", defaultResponse: " + defaultResponse);
1792
1793 Log.i(TAG, "requestorId: " + requestorId +
1794 ", text: " + text +
1795 ", requestorIdEncoding: " + requestorIdEncoding +
1796 ", textEncoding: " + textEncoding);
1797
1798 GpsNiNotification notification = new GpsNiNotification();
1799
1800 notification.notificationId = notificationId;
1801 notification.niType = niType;
1802 notification.needNotify = (notifyFlags & GpsNetInitiatedHandler.GPS_NI_NEED_NOTIFY) != 0;
1803 notification.needVerify = (notifyFlags & GpsNetInitiatedHandler.GPS_NI_NEED_VERIFY) != 0;
1804 notification.privacyOverride = (notifyFlags & GpsNetInitiatedHandler.GPS_NI_PRIVACY_OVERRIDE) != 0;
1805 notification.timeout = timeout;
1806 notification.defaultResponse = defaultResponse;
1807 notification.requestorId = requestorId;
1808 notification.text = text;
1809 notification.requestorIdEncoding = requestorIdEncoding;
1810 notification.textEncoding = textEncoding;
1811
1812 // Process extras, assuming the format is
1813 // one of more lines of "key = value"
1814 Bundle bundle = new Bundle();
1815
1816 if (extras == null) extras = "";
1817 Properties extraProp = new Properties();
1818
1819 try {
Jeff Sharkey104344e2011-07-10 14:20:41 -07001820 extraProp.load(new StringReader(extras));
Miguel Torroja1e84da82010-07-27 07:02:24 +02001821 }
1822 catch (IOException e)
1823 {
1824 Log.e(TAG, "reportNiNotification cannot parse extras data: " + extras);
1825 }
1826
1827 for (Entry<Object, Object> ent : extraProp.entrySet())
1828 {
1829 bundle.putString((String) ent.getKey(), (String) ent.getValue());
1830 }
1831
1832 notification.extras = bundle;
1833
1834 mNIHandler.handleNiNotification(notification);
1835 }
1836
1837 /**
1838 * Called from native code to request set id info.
1839 * We should be careful about receiving null string from the TelephonyManager,
1840 * because sending null String to JNI function would cause a crash.
1841 */
1842
1843 private void requestSetID(int flags) {
1844 TelephonyManager phone = (TelephonyManager)
1845 mContext.getSystemService(Context.TELEPHONY_SERVICE);
1846 int type = AGPS_SETID_TYPE_NONE;
1847 String data = "";
1848
1849 if ((flags & AGPS_RIL_REQUEST_SETID_IMSI) == AGPS_RIL_REQUEST_SETID_IMSI) {
1850 String data_temp = phone.getSubscriberId();
1851 if (data_temp == null) {
1852 // This means the framework does not have the SIM card ready.
1853 } else {
1854 // This means the framework has the SIM card.
1855 data = data_temp;
1856 type = AGPS_SETID_TYPE_IMSI;
1857 }
1858 }
1859 else if ((flags & AGPS_RIL_REQUEST_SETID_MSISDN) == AGPS_RIL_REQUEST_SETID_MSISDN) {
1860 String data_temp = phone.getLine1Number();
1861 if (data_temp == null) {
1862 // This means the framework does not have the SIM card ready.
1863 } else {
1864 // This means the framework has the SIM card.
1865 data = data_temp;
1866 type = AGPS_SETID_TYPE_MSISDN;
1867 }
1868 }
1869 native_agps_set_id(type, data);
1870 }
1871
1872 /**
Mike Lockwood9b9fb5c2011-06-29 15:09:40 -04001873 * Called from native code to request utc time info
1874 */
1875
1876 private void requestUtcTime() {
1877 sendMessage(INJECT_NTP_TIME, 0, null);
1878 }
1879
1880 /**
Miguel Torroja1e84da82010-07-27 07:02:24 +02001881 * Called from native code to request reference location info
1882 */
1883
1884 private void requestRefLocation(int flags) {
1885 TelephonyManager phone = (TelephonyManager)
1886 mContext.getSystemService(Context.TELEPHONY_SERVICE);
Victoria Leased50d0c32012-10-29 13:16:17 -07001887 final int phoneType = phone.getPhoneType();
1888 if (phoneType == TelephonyManager.PHONE_TYPE_GSM) {
Miguel Torroja1e84da82010-07-27 07:02:24 +02001889 GsmCellLocation gsm_cell = (GsmCellLocation) phone.getCellLocation();
Victoria Leased50d0c32012-10-29 13:16:17 -07001890 if ((gsm_cell != null) && (phone.getNetworkOperator() != null)
1891 && (phone.getNetworkOperator().length() > 3)) {
Miguel Torroja1e84da82010-07-27 07:02:24 +02001892 int type;
1893 int mcc = Integer.parseInt(phone.getNetworkOperator().substring(0,3));
1894 int mnc = Integer.parseInt(phone.getNetworkOperator().substring(3));
Mike Lockwoodedc0f3872010-10-22 09:16:17 -04001895 int networkType = phone.getNetworkType();
1896 if (networkType == TelephonyManager.NETWORK_TYPE_UMTS
1897 || networkType == TelephonyManager.NETWORK_TYPE_HSDPA
1898 || networkType == TelephonyManager.NETWORK_TYPE_HSUPA
Arun Ravindran58d46122012-07-30 17:50:21 +03001899 || networkType == TelephonyManager.NETWORK_TYPE_HSPA
1900 || networkType == TelephonyManager.NETWORK_TYPE_HSPAP) {
Miguel Torroja1e84da82010-07-27 07:02:24 +02001901 type = AGPS_REF_LOCATION_TYPE_UMTS_CELLID;
Mike Lockwoodedc0f3872010-10-22 09:16:17 -04001902 } else {
Miguel Torroja1e84da82010-07-27 07:02:24 +02001903 type = AGPS_REF_LOCATION_TYPE_GSM_CELLID;
Mike Lockwoodedc0f3872010-10-22 09:16:17 -04001904 }
Miguel Torroja1e84da82010-07-27 07:02:24 +02001905 native_agps_set_ref_location_cellid(type, mcc, mnc,
1906 gsm_cell.getLac(), gsm_cell.getCid());
Mike Lockwoodedc0f3872010-10-22 09:16:17 -04001907 } else {
Miguel Torroja1e84da82010-07-27 07:02:24 +02001908 Log.e(TAG,"Error getting cell location info.");
Mike Lockwoodedc0f3872010-10-22 09:16:17 -04001909 }
Victoria Leased50d0c32012-10-29 13:16:17 -07001910 } else if (phoneType == TelephonyManager.PHONE_TYPE_CDMA) {
1911 Log.e(TAG, "CDMA not supported.");
Mike Lockwoodedc0f3872010-10-22 09:16:17 -04001912 }
Miguel Torroja1e84da82010-07-27 07:02:24 +02001913 }
Danke Xie22d1f9f2009-08-18 18:28:45 -04001914
Mike Lockwood98e48692010-04-07 16:32:51 -04001915 private void sendMessage(int message, int arg, Object obj) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001916 // hold a wake lock until this message is delivered
Jeff Brown028872f2012-08-25 13:07:01 -07001917 // note that this assumes the message will not be removed from the queue before
1918 // it is handled (otherwise the wake lock would be leaked).
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001919 mWakeLock.acquire();
1920 mHandler.obtainMessage(message, arg, 1, obj).sendToTarget();
Mike Lockwood98e48692010-04-07 16:32:51 -04001921 }
1922
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001923 private final class ProviderHandler extends Handler {
Victoria Lease5cd731a2012-12-19 15:04:21 -08001924 public ProviderHandler(Looper looper) {
1925 super(looper, null, true /*async*/);
Jeff Brown028872f2012-08-25 13:07:01 -07001926 }
1927
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001928 @Override
Mike Lockwood4a7b65e2010-10-25 16:35:55 -04001929 public void handleMessage(Message msg) {
Mike Lockwood98e48692010-04-07 16:32:51 -04001930 int message = msg.what;
1931 switch (message) {
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001932 case ENABLE:
1933 if (msg.arg1 == 1) {
1934 handleEnable();
1935 } else {
1936 handleDisable();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001937 }
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001938 break;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001939 case SET_REQUEST:
1940 GpsRequest gpsRequest = (GpsRequest) msg.obj;
1941 handleSetRequest(gpsRequest.request, gpsRequest.source);
Mike Lockwood03ca2162010-04-01 08:10:09 -07001942 break;
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001943 case UPDATE_NETWORK_STATE:
1944 handleUpdateNetworkState(msg.arg1, (NetworkInfo)msg.obj);
1945 break;
1946 case INJECT_NTP_TIME:
1947 handleInjectNtpTime();
1948 break;
1949 case DOWNLOAD_XTRA_DATA:
Mike Lockwood1a1cd3a2010-08-17 07:42:54 -04001950 if (mSupportsXtra) {
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001951 handleDownloadXtraData();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001952 }
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001953 break;
Kevin Tang40e1baf2012-01-10 14:32:44 -08001954 case INJECT_NTP_TIME_FINISHED:
1955 mInjectNtpTimePending = STATE_IDLE;
1956 break;
1957 case DOWNLOAD_XTRA_DATA_FINISHED:
1958 mDownloadXtraDataPending = STATE_IDLE;
1959 break;
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001960 case UPDATE_LOCATION:
1961 handleUpdateLocation((Location)msg.obj);
1962 break;
destradaafb23c672015-04-16 14:01:27 -07001963 case SUBSCRIPTION_OR_SIM_CHANGED:
1964 subscriptionOrSimChanged(mContext);
1965 break;
1966 case INITIALIZE_HANDLER:
1967 initialize();
1968 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001969 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001970 if (msg.arg2 == 1) {
1971 // wakelock was taken for this message, release it
1972 mWakeLock.release();
Mike Lockwood98e48692010-04-07 16:32:51 -04001973 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001974 }
destradaafb23c672015-04-16 14:01:27 -07001975
1976 /**
1977 * This method is bound to {@link #GpsLocationProvider(Context, ILocationManager, Looper)}.
1978 * It is in charge of loading properties and registering for events that will be posted to
1979 * this handler.
1980 */
1981 private void initialize() {
1982 // load default GPS configuration
1983 // (this configuration might change in the future based on SIM changes)
1984 reloadGpsProperties(mContext, mProperties);
1985
1986 // TODO: When this object "finishes" we should unregister by invoking
1987 // SubscriptionManager.getInstance(mContext).unregister(mOnSubscriptionsChangedListener);
1988 // This is not strictly necessary because it will be unregistered if the
1989 // notification fails but it is good form.
1990
1991 // Register for SubscriptionInfo list changes which is guaranteed
1992 // to invoke onSubscriptionsChanged the first time.
1993 SubscriptionManager.from(mContext)
1994 .addOnSubscriptionsChangedListener(mOnSubscriptionsChangedListener);
1995
1996 // listen for events
1997 IntentFilter intentFilter = new IntentFilter();
1998 intentFilter.addAction(Intents.DATA_SMS_RECEIVED_ACTION);
1999 intentFilter.addDataScheme("sms");
2000 intentFilter.addDataAuthority("localhost","7275");
2001 mContext.registerReceiver(mBroadcastReceiver, intentFilter, null, this);
2002
2003 intentFilter = new IntentFilter();
2004 intentFilter.addAction(Intents.WAP_PUSH_RECEIVED_ACTION);
2005 try {
2006 intentFilter.addDataType("application/vnd.omaloc-supl-init");
2007 } catch (IntentFilter.MalformedMimeTypeException e) {
2008 Log.w(TAG, "Malformed SUPL init mime type");
2009 }
2010 mContext.registerReceiver(mBroadcastReceiver, intentFilter, null, this);
2011
2012 intentFilter = new IntentFilter();
2013 intentFilter.addAction(ALARM_WAKEUP);
2014 intentFilter.addAction(ALARM_TIMEOUT);
Erik Kline32830cc2015-04-21 13:09:15 +09002015 intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
destradaafb23c672015-04-16 14:01:27 -07002016 intentFilter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED);
2017 intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
2018 intentFilter.addAction(Intent.ACTION_SCREEN_ON);
2019 intentFilter.addAction(SIM_STATE_CHANGED);
2020 mContext.registerReceiver(mBroadcastReceiver, intentFilter, null, this);
2021
2022 // listen for PASSIVE_PROVIDER updates
2023 LocationManager locManager =
2024 (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
2025 long minTime = 0;
2026 float minDistance = 0;
2027 boolean oneShot = false;
2028 LocationRequest request = LocationRequest.createFromDeprecatedProvider(
2029 LocationManager.PASSIVE_PROVIDER,
2030 minTime,
2031 minDistance,
2032 oneShot);
2033 // Don't keep track of this request since it's done on behalf of other clients
2034 // (which are kept track of separately).
2035 request.setHideFromAppOps(true);
2036 locManager.requestLocationUpdates(
2037 request,
2038 new NetworkLocationListener(),
2039 getLooper());
2040 }
2041 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002042
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002043 private final class NetworkLocationListener implements LocationListener {
2044 @Override
2045 public void onLocationChanged(Location location) {
2046 // this callback happens on mHandler looper
2047 if (LocationManager.NETWORK_PROVIDER.equals(location.getProvider())) {
2048 handleUpdateLocation(location);
2049 }
2050 }
2051 @Override
2052 public void onStatusChanged(String provider, int status, Bundle extras) { }
2053 @Override
2054 public void onProviderEnabled(String provider) { }
2055 @Override
2056 public void onProviderDisabled(String provider) { }
2057 }
2058
Kevin Tanga5fe6b22011-06-05 14:25:16 -07002059 private String getSelectedApn() {
2060 Uri uri = Uri.parse("content://telephony/carriers/preferapn");
destradaa96a14702014-06-05 11:36:30 -07002061 Cursor cursor = null;
2062 try {
2063 cursor = mContext.getContentResolver().query(
2064 uri,
2065 new String[] { "apn" },
2066 null /* selection */,
2067 null /* selectionArgs */,
2068 Carriers.DEFAULT_SORT_ORDER);
2069 if (cursor != null && cursor.moveToFirst()) {
2070 return cursor.getString(0);
2071 } else {
2072 Log.e(TAG, "No APN found to select.");
2073 }
2074 } catch (Exception e) {
destradaaea8a8a62014-06-23 18:19:03 -07002075 Log.e(TAG, "Error encountered on selecting the APN.", e);
destradaa96a14702014-06-05 11:36:30 -07002076 } finally {
2077 if (cursor != null) {
Kevin Tanga5fe6b22011-06-05 14:25:16 -07002078 cursor.close();
2079 }
2080 }
destradaa96a14702014-06-05 11:36:30 -07002081
2082 return null;
2083 }
2084
2085 private int getApnIpType(String apn) {
2086 if (apn == null) {
2087 return APN_INVALID;
2088 }
2089
2090 // look for cached data to use
2091 if (apn.equals(mAGpsApn) && mApnIpType != APN_INVALID) {
2092 return mApnIpType;
2093 }
2094
2095 String selection = String.format("current = 1 and apn = '%s' and carrier_enabled = 1", apn);
2096 Cursor cursor = null;
2097 try {
2098 cursor = mContext.getContentResolver().query(
2099 Carriers.CONTENT_URI,
2100 new String[] { Carriers.PROTOCOL },
2101 selection,
2102 null,
2103 Carriers.DEFAULT_SORT_ORDER);
2104
2105 if (null != cursor && cursor.moveToFirst()) {
2106 return translateToApnIpType(cursor.getString(0), apn);
2107 } else {
2108 Log.e(TAG, "No entry found in query for APN: " + apn);
2109 }
2110 } catch (Exception e) {
2111 Log.e(TAG, "Error encountered on APN query for: " + apn, e);
2112 } finally {
2113 if (cursor != null) {
2114 cursor.close();
2115 }
2116 }
2117
2118 return APN_INVALID;
2119 }
2120
2121 private int translateToApnIpType(String ipProtocol, String apn) {
2122 if ("IP".equals(ipProtocol)) {
2123 return APN_IPV4;
2124 }
2125 if ("IPV6".equals(ipProtocol)) {
2126 return APN_IPV6;
2127 }
2128 if ("IPV4V6".equals(ipProtocol)) {
2129 return APN_IPV4V6;
2130 }
2131
2132 // we hit the default case so the ipProtocol is not recognized
2133 String message = String.format("Unknown IP Protocol: %s, for APN: %s", ipProtocol, apn);
2134 Log.e(TAG, message);
2135 return APN_INVALID;
2136 }
2137
2138 private void setRouting() {
2139 if (mAGpsDataConnectionIpAddr == null) {
2140 return;
2141 }
2142
2143 boolean result = mConnMgr.requestRouteToHostAddress(
2144 ConnectivityManager.TYPE_MOBILE_SUPL,
2145 mAGpsDataConnectionIpAddr);
2146
2147 if (!result) {
2148 Log.e(TAG, "Error requesting route to host: " + mAGpsDataConnectionIpAddr);
2149 } else if (DEBUG) {
2150 Log.d(TAG, "Successfully requested route to host: " + mAGpsDataConnectionIpAddr);
2151 }
Kevin Tanga5fe6b22011-06-05 14:25:16 -07002152 }
2153
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002154 @Override
2155 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
2156 StringBuilder s = new StringBuilder();
2157 s.append(" mFixInterval=").append(mFixInterval).append("\n");
David Christied4edf4c2014-08-12 15:22:27 -07002158 s.append(" mDisableGps (battery saver mode)=").append(mDisableGps).append("\n");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002159 s.append(" mEngineCapabilities=0x").append(Integer.toHexString(mEngineCapabilities)).append(" (");
2160 if (hasCapability(GPS_CAPABILITY_SCHEDULING)) s.append("SCHED ");
2161 if (hasCapability(GPS_CAPABILITY_MSB)) s.append("MSB ");
2162 if (hasCapability(GPS_CAPABILITY_MSA)) s.append("MSA ");
2163 if (hasCapability(GPS_CAPABILITY_SINGLE_SHOT)) s.append("SINGLE_SHOT ");
2164 if (hasCapability(GPS_CAPABILITY_ON_DEMAND_TIME)) s.append("ON_DEMAND_TIME ");
2165 s.append(")\n");
2166
2167 s.append(native_get_internal_state());
2168 pw.append(s);
2169 }
2170
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002171 // for GPS SV statistics
2172 private static final int MAX_SVS = 32;
2173 private static final int EPHEMERIS_MASK = 0;
2174 private static final int ALMANAC_MASK = 1;
2175 private static final int USED_FOR_FIX_MASK = 2;
2176
2177 // preallocated arrays, to avoid memory allocation in reportStatus()
2178 private int mSvs[] = new int[MAX_SVS];
2179 private float mSnrs[] = new float[MAX_SVS];
2180 private float mSvElevations[] = new float[MAX_SVS];
2181 private float mSvAzimuths[] = new float[MAX_SVS];
2182 private int mSvMasks[] = new int[3];
2183 private int mSvCount;
Mike Lockwoodb16e7802009-08-06 09:26:02 -04002184 // preallocated to avoid memory allocation in reportNmea()
2185 private byte[] mNmeaBuffer = new byte[120];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002186
2187 static { class_init_native(); }
2188 private static native void class_init_native();
2189 private static native boolean native_is_supported();
2190
2191 private native boolean native_init();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002192 private native void native_cleanup();
Mike Lockwood04598b62010-04-14 17:17:24 -04002193 private native boolean native_set_position_mode(int mode, int recurrence, int min_interval,
2194 int preferred_accuracy, int preferred_time);
2195 private native boolean native_start();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002196 private native boolean native_stop();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002197 private native void native_delete_aiding_data(int flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002198 // returns number of SVs
2199 // mask[0] is ephemeris mask and mask[1] is almanac mask
2200 private native int native_read_sv_status(int[] svs, float[] snrs,
2201 float[] elevations, float[] azimuths, int[] masks);
Mike Lockwoodf602d362010-06-20 14:28:16 -07002202 private native int native_read_nmea(byte[] buffer, int bufferSize);
Mike Lockwoodd26ce0d2009-06-11 12:25:46 -04002203 private native void native_inject_location(double latitude, double longitude, float accuracy);
2204
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -06002205 // XTRA Support
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002206 private native void native_inject_time(long time, long timeReference, int uncertainty);
2207 private native boolean native_supports_xtra();
2208 private native void native_inject_xtra_data(byte[] data, int length);
The Android Open Source Project10592532009-03-18 17:39:46 -07002209
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -06002210 // DEBUG Support
2211 private native String native_get_internal_state();
2212
2213 // AGPS Support
destradaa96a14702014-06-05 11:36:30 -07002214 private native void native_agps_data_conn_open(String apn, int apnIpType);
Mike Lockwoode3635c92009-05-11 08:38:02 -04002215 private native void native_agps_data_conn_closed();
2216 private native void native_agps_data_conn_failed();
Miguel Torroja1e84da82010-07-27 07:02:24 +02002217 private native void native_agps_ni_message(byte [] msg, int length);
Mike Lockwooda9e54612009-06-19 14:54:42 -04002218 private native void native_set_agps_server(int type, String hostname, int port);
Danke Xie22d1f9f2009-08-18 18:28:45 -04002219
2220 // Network-initiated (NI) Support
2221 private native void native_send_ni_response(int notificationId, int userResponse);
Miguel Torroja1e84da82010-07-27 07:02:24 +02002222
2223 // AGPS ril suport
2224 private native void native_agps_set_ref_location_cellid(int type, int mcc, int mnc,
2225 int lac, int cid);
2226 private native void native_agps_set_id(int type, String setid);
Mike Lockwood50130bb2010-10-11 06:22:50 -04002227
2228 private native void native_update_network_state(boolean connected, int type,
Kevin Tanga5fe6b22011-06-05 14:25:16 -07002229 boolean roaming, boolean available, String extraInfo, String defaultAPN);
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07002230
2231 // Hardware Geofence support.
2232 private static native boolean native_is_geofence_supported();
2233 private static native boolean native_add_geofence(int geofenceId, double latitude,
2234 double longitude, double radius, int lastTransition,int monitorTransitions,
2235 int notificationResponsivenes, int unknownTimer);
2236 private static native boolean native_remove_geofence(int geofenceId);
2237 private static native boolean native_resume_geofence(int geofenceId, int transitions);
2238 private static native boolean native_pause_geofence(int geofenceId);
destradaaea8a8a62014-06-23 18:19:03 -07002239
2240 // Gps Hal measurements support.
2241 private static native boolean native_is_measurement_supported();
destradaa4b3e3932014-07-21 18:01:47 -07002242 private native boolean native_start_measurement_collection();
2243 private native boolean native_stop_measurement_collection();
2244
2245 // Gps Navigation message support.
2246 private static native boolean native_is_navigation_message_supported();
2247 private native boolean native_start_navigation_message_collection();
2248 private native boolean native_stop_navigation_message_collection();
Tsuwei Chen52617bb2014-08-25 11:49:11 -07002249
2250 // GNSS Configuration
2251 private static native void native_configuration_update(String configData);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002252}
David Christied4edf4c2014-08-12 15:22:27 -07002253