blob: 9c0f9874b5bc1c858f38b4d02f45a452837ee4ea [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;
Tsuwei Chen52617bb2014-08-25 11:49:11 -070025import com.android.internal.R;
destradaaea8a8a62014-06-23 18:19:03 -070026import com.android.internal.telephony.Phone;
27import com.android.internal.telephony.PhoneConstants;
Tsuwei Chen678c13c2014-09-22 17:48:41 -070028import com.android.internal.telephony.TelephonyIntents;
destradaaea8a8a62014-06-23 18:19:03 -070029
Mike Lockwood29c84342009-05-06 14:01:15 -040030import android.app.AlarmManager;
Dianne Hackborna06de0f2012-12-11 16:34:47 -080031import android.app.AppOpsManager;
Mike Lockwood29c84342009-05-06 14:01:15 -040032import android.app.PendingIntent;
The Android Open Source Project10592532009-03-18 17:39:46 -070033import android.content.BroadcastReceiver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080034import android.content.Context;
35import android.content.Intent;
The Android Open Source Project10592532009-03-18 17:39:46 -070036import android.content.IntentFilter;
Kevin Tanga5fe6b22011-06-05 14:25:16 -070037import android.database.Cursor;
destradaa0682809a2013-08-12 18:50:30 -070038import android.hardware.location.GeofenceHardware;
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -070039import android.hardware.location.GeofenceHardwareImpl;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080040import android.location.Criteria;
destradaa0682809a2013-08-12 18:50:30 -070041import android.location.FusedBatchOptions;
destradaaea8a8a62014-06-23 18:19:03 -070042import android.location.GpsMeasurementsEvent;
destradaa4b3e3932014-07-21 18:01:47 -070043import android.location.GpsNavigationMessageEvent;
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -070044import android.location.IGpsGeofenceHardware;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080045import android.location.IGpsStatusListener;
Mike Lockwood15e3d0f2009-05-01 07:53:28 -040046import android.location.IGpsStatusProvider;
Mike Lockwood4e50b782009-04-03 08:24:43 -070047import android.location.ILocationManager;
Danke Xie22d1f9f2009-08-18 18:28:45 -040048import android.location.INetInitiatedListener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080049import android.location.Location;
Nick Pelly6fa9ad42012-07-16 12:18:23 -070050import android.location.LocationListener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080051import android.location.LocationManager;
52import android.location.LocationProvider;
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -070053import android.location.LocationRequest;
Mike Lockwood58bda982009-04-14 16:25:07 -040054import android.net.ConnectivityManager;
Mike Lockwood03d24672009-10-08 15:45:03 -040055import android.net.NetworkInfo;
Kevin Tanga5fe6b22011-06-05 14:25:16 -070056import android.net.Uri;
Kevin Tang40e1baf2012-01-10 14:32:44 -080057import android.os.AsyncTask;
Dianne Hackborn91268cf2013-06-13 19:06:50 -070058import android.os.BatteryStats;
Mike Lockwood63aa5a62010-04-14 19:21:31 -040059import android.os.Binder;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080060import android.os.Bundle;
Mike Lockwood62a8fc12010-03-22 14:23:26 -040061import android.os.Handler;
Victoria Lease5cd731a2012-12-19 15:04:21 -080062import android.os.Looper;
Mike Lockwood62a8fc12010-03-22 14:23:26 -040063import android.os.Message;
Mike Lockwood0528b9b2009-05-07 10:12:54 -040064import android.os.PowerManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080065import android.os.RemoteException;
Mike Lockwood2f82c4e2009-04-17 08:24:10 -040066import android.os.ServiceManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080067import android.os.SystemClock;
Colin Cross7c030ed2014-01-28 09:33:53 -080068import android.os.SystemProperties;
Dianne Hackborn5ac72a22012-08-29 18:32:08 -070069import android.os.UserHandle;
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -070070import android.os.WorkSource;
Mike Lockwoodbcab8df2009-06-25 16:39:09 -040071import android.provider.Settings;
Kevin Tanga5fe6b22011-06-05 14:25:16 -070072import android.provider.Telephony.Carriers;
Miguel Torroja1e84da82010-07-27 07:02:24 +020073import android.provider.Telephony.Sms.Intents;
Jake Hambyb49a73d2011-03-15 20:09:46 -070074import android.telephony.SmsMessage;
Wink Savillea374c3d2014-11-11 11:48:04 -080075import android.telephony.SubscriptionInfo;
Wink Savillea374c3d2014-11-11 11:48:04 -080076import android.telephony.SubscriptionManager;
Wink Savilled09c4ca2014-11-22 10:08:16 -080077import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
Miguel Torroja1e84da82010-07-27 07:02:24 +020078import android.telephony.TelephonyManager;
79import android.telephony.gsm.GsmCellLocation;
Colin Cross7c030ed2014-01-28 09:33:53 -080080import android.text.TextUtils;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080081import android.util.Log;
Jeff Sharkey104344e2011-07-10 14:20:41 -070082import android.util.NtpTrustedTime;
Dianne Hackborna06de0f2012-12-11 16:34:47 -080083
Tsuwei Chen52617bb2014-08-25 11:49:11 -070084import java.io.ByteArrayOutputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080085import java.io.File;
Nick Pelly6fa9ad42012-07-16 12:18:23 -070086import java.io.FileDescriptor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080087import java.io.FileInputStream;
88import java.io.IOException;
Nick Pelly6fa9ad42012-07-16 12:18:23 -070089import java.io.PrintWriter;
Jeff Sharkey104344e2011-07-10 14:20:41 -070090import java.io.StringReader;
destradaaea8a8a62014-06-23 18:19:03 -070091import java.net.InetAddress;
92import java.net.UnknownHostException;
Mike Lockwoodf1218be2010-01-29 09:20:06 -050093import java.util.Date;
Wink Savillea374c3d2014-11-11 11:48:04 -080094import java.util.List;
Danke Xie22d1f9f2009-08-18 18:28:45 -040095import java.util.Map.Entry;
Jake Hambyb49a73d2011-03-15 20:09:46 -070096import java.util.Properties;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080097
Colin Cross7c030ed2014-01-28 09:33:53 -080098import libcore.io.IoUtils;
99
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800100/**
101 * A GPS implementation of LocationProvider used by LocationManager.
102 *
103 * {@hide}
104 */
Mike Lockwood89096312010-03-24 10:14:55 -0400105public class GpsLocationProvider implements LocationProviderInterface {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800106
107 private static final String TAG = "GpsLocationProvider";
Mike Lockwood29c84342009-05-06 14:01:15 -0400108
Brian Muramatsu1715cb32012-08-08 17:32:21 -0700109 private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
110 private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400111
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700112 private static final ProviderProperties PROPERTIES = new ProviderProperties(
113 true, true, false, false, true, true, true,
114 Criteria.POWER_HIGH, Criteria.ACCURACY_FINE);
115
The Android Open Source Project10592532009-03-18 17:39:46 -0700116 // these need to match GpsPositionMode enum in gps.h
117 private static final int GPS_POSITION_MODE_STANDALONE = 0;
118 private static final int GPS_POSITION_MODE_MS_BASED = 1;
119 private static final int GPS_POSITION_MODE_MS_ASSISTED = 2;
120
Mike Lockwood04598b62010-04-14 17:17:24 -0400121 // these need to match GpsPositionRecurrence enum in gps.h
122 private static final int GPS_POSITION_RECURRENCE_PERIODIC = 0;
123 private static final int GPS_POSITION_RECURRENCE_SINGLE = 1;
124
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800125 // these need to match GpsStatusValue defines in gps.h
126 private static final int GPS_STATUS_NONE = 0;
127 private static final int GPS_STATUS_SESSION_BEGIN = 1;
128 private static final int GPS_STATUS_SESSION_END = 2;
129 private static final int GPS_STATUS_ENGINE_ON = 3;
130 private static final int GPS_STATUS_ENGINE_OFF = 4;
131
Mike Lockwoode3635c92009-05-11 08:38:02 -0400132 // these need to match GpsApgsStatusValue defines in gps.h
133 /** AGPS status event values. */
134 private static final int GPS_REQUEST_AGPS_DATA_CONN = 1;
135 private static final int GPS_RELEASE_AGPS_DATA_CONN = 2;
136 private static final int GPS_AGPS_DATA_CONNECTED = 3;
137 private static final int GPS_AGPS_DATA_CONN_DONE = 4;
138 private static final int GPS_AGPS_DATA_CONN_FAILED = 5;
Mike Lockwood58bda982009-04-14 16:25:07 -0400139
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800140 // these need to match GpsLocationFlags enum in gps.h
141 private static final int LOCATION_INVALID = 0;
142 private static final int LOCATION_HAS_LAT_LONG = 1;
143 private static final int LOCATION_HAS_ALTITUDE = 2;
144 private static final int LOCATION_HAS_SPEED = 4;
145 private static final int LOCATION_HAS_BEARING = 8;
146 private static final int LOCATION_HAS_ACCURACY = 16;
Mike Lockwoode3635c92009-05-11 08:38:02 -0400147
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700148 // IMPORTANT - the GPS_DELETE_* symbols here must match constants in gps.h
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800149 private static final int GPS_DELETE_EPHEMERIS = 0x0001;
150 private static final int GPS_DELETE_ALMANAC = 0x0002;
151 private static final int GPS_DELETE_POSITION = 0x0004;
152 private static final int GPS_DELETE_TIME = 0x0008;
153 private static final int GPS_DELETE_IONO = 0x0010;
154 private static final int GPS_DELETE_UTC = 0x0020;
155 private static final int GPS_DELETE_HEALTH = 0x0040;
156 private static final int GPS_DELETE_SVDIR = 0x0080;
157 private static final int GPS_DELETE_SVSTEER = 0x0100;
158 private static final int GPS_DELETE_SADATA = 0x0200;
159 private static final int GPS_DELETE_RTI = 0x0400;
160 private static final int GPS_DELETE_CELLDB_INFO = 0x8000;
161 private static final int GPS_DELETE_ALL = 0xFFFF;
162
Mike Lockwood04598b62010-04-14 17:17:24 -0400163 // The GPS_CAPABILITY_* flags must match the values in gps.h
164 private static final int GPS_CAPABILITY_SCHEDULING = 0x0000001;
165 private static final int GPS_CAPABILITY_MSB = 0x0000002;
166 private static final int GPS_CAPABILITY_MSA = 0x0000004;
167 private static final int GPS_CAPABILITY_SINGLE_SHOT = 0x0000008;
Mike Lockwood9b9fb5c2011-06-29 15:09:40 -0400168 private static final int GPS_CAPABILITY_ON_DEMAND_TIME = 0x0000010;
destradaa6568d702014-10-27 12:47:41 -0700169 private static final int GPS_CAPABILITY_GEOFENCING = 0x0000020;
170 private static final int GPS_CAPABILITY_MEASUREMENTS = 0x0000040;
171 private static final int GPS_CAPABILITY_NAV_MESSAGES = 0x0000080;
Mike Lockwood04598b62010-04-14 17:17:24 -0400172
Tsuwei Chen462bcd82014-09-17 12:28:49 -0700173 // The AGPS SUPL mode
174 private static final int AGPS_SUPL_MODE_MSA = 0x02;
175 private static final int AGPS_SUPL_MODE_MSB = 0x01;
176
Mike Lockwoode3635c92009-05-11 08:38:02 -0400177 // these need to match AGpsType enum in gps.h
178 private static final int AGPS_TYPE_SUPL = 1;
179 private static final int AGPS_TYPE_C2K = 2;
180
destradaa96a14702014-06-05 11:36:30 -0700181 // these must match the definitions in gps.h
182 private static final int APN_INVALID = 0;
183 private static final int APN_IPV4 = 1;
184 private static final int APN_IPV6 = 2;
185 private static final int APN_IPV4V6 = 3;
186
Mike Lockwoode3635c92009-05-11 08:38:02 -0400187 // for mAGpsDataConnectionState
188 private static final int AGPS_DATA_CONNECTION_CLOSED = 0;
189 private static final int AGPS_DATA_CONNECTION_OPENING = 1;
190 private static final int AGPS_DATA_CONNECTION_OPEN = 2;
Mike Lockwood58bda982009-04-14 16:25:07 -0400191
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400192 // Handler messages
193 private static final int CHECK_LOCATION = 1;
194 private static final int ENABLE = 2;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700195 private static final int SET_REQUEST = 3;
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400196 private static final int UPDATE_NETWORK_STATE = 4;
197 private static final int INJECT_NTP_TIME = 5;
198 private static final int DOWNLOAD_XTRA_DATA = 6;
199 private static final int UPDATE_LOCATION = 7;
200 private static final int ADD_LISTENER = 8;
201 private static final int REMOVE_LISTENER = 9;
Kevin Tang40e1baf2012-01-10 14:32:44 -0800202 private static final int INJECT_NTP_TIME_FINISHED = 10;
203 private static final int DOWNLOAD_XTRA_DATA_FINISHED = 11;
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400204
Miguel Torroja1e84da82010-07-27 07:02:24 +0200205 // Request setid
206 private static final int AGPS_RIL_REQUEST_SETID_IMSI = 1;
207 private static final int AGPS_RIL_REQUEST_SETID_MSISDN = 2;
208
209 // Request ref location
210 private static final int AGPS_RIL_REQUEST_REFLOC_CELLID = 1;
211 private static final int AGPS_RIL_REQUEST_REFLOC_MAC = 2;
212
213 // ref. location info
214 private static final int AGPS_REF_LOCATION_TYPE_GSM_CELLID = 1;
215 private static final int AGPS_REF_LOCATION_TYPE_UMTS_CELLID = 2;
216 private static final int AGPS_REG_LOCATION_TYPE_MAC = 3;
217
218 // set id info
219 private static final int AGPS_SETID_TYPE_NONE = 0;
220 private static final int AGPS_SETID_TYPE_IMSI = 1;
221 private static final int AGPS_SETID_TYPE_MSISDN = 2;
222
Colin Cross7c030ed2014-01-28 09:33:53 -0800223 private static final String PROPERTIES_FILE_PREFIX = "/etc/gps";
224 private static final String PROPERTIES_FILE_SUFFIX = ".conf";
225 private static final String DEFAULT_PROPERTIES_FILE = PROPERTIES_FILE_PREFIX + PROPERTIES_FILE_SUFFIX;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800226
destradaa0682809a2013-08-12 18:50:30 -0700227 private static final int GPS_GEOFENCE_UNAVAILABLE = 1<<0L;
228 private static final int GPS_GEOFENCE_AVAILABLE = 1<<1L;
229
230 // GPS Geofence errors. Should match gps.h constants.
231 private static final int GPS_GEOFENCE_OPERATION_SUCCESS = 0;
232 private static final int GPS_GEOFENCE_ERROR_TOO_MANY_GEOFENCES = 100;
233 private static final int GPS_GEOFENCE_ERROR_ID_EXISTS = -101;
234 private static final int GPS_GEOFENCE_ERROR_ID_UNKNOWN = -102;
235 private static final int GPS_GEOFENCE_ERROR_INVALID_TRANSITION = -103;
236 private static final int GPS_GEOFENCE_ERROR_GENERIC = -149;
237
Tsuwei Chen678c13c2014-09-22 17:48:41 -0700238 // TCP/IP constants.
239 // Valid TCP/UDP port range is (0, 65535].
240 private static final int TCP_MIN_PORT = 0;
241 private static final int TCP_MAX_PORT = 0xffff;
242
David Christied4edf4c2014-08-12 15:22:27 -0700243 // Value of batterySaverGpsMode such that GPS isn't affected by battery saver mode.
244 private static final int BATTERY_SAVER_MODE_NO_CHANGE = 0;
245 // Value of batterySaverGpsMode such that GPS is disabled when battery saver mode
246 // is enabled and the screen is off.
247 private static final int BATTERY_SAVER_MODE_DISABLED_WHEN_SCREEN_OFF = 1;
248 // Secure setting for GPS behavior when battery saver mode is on.
249 private static final String BATTERY_SAVER_GPS_MODE = "batterySaverGpsMode";
250
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700251 /** simpler wrapper for ProviderRequest + Worksource */
252 private static class GpsRequest {
253 public ProviderRequest request;
254 public WorkSource source;
255 public GpsRequest(ProviderRequest request, WorkSource source) {
256 this.request = request;
257 this.source = source;
258 }
259 }
260
261 private Object mLock = new Object();
262
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800263 private int mLocationFlags = LOCATION_INVALID;
264
265 // current status
Mike Lockwood15e3d0f2009-05-01 07:53:28 -0400266 private int mStatus = LocationProvider.TEMPORARILY_UNAVAILABLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800267
268 // time for last status update
269 private long mStatusUpdateTime = SystemClock.elapsedRealtime();
Mike Lockwoodd53ba012010-04-15 20:41:26 -0400270
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800271 // turn off GPS fix icon if we haven't received a fix in 10 seconds
Mike Lockwood04598b62010-04-14 17:17:24 -0400272 private static final long RECENT_FIX_TIMEOUT = 10 * 1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800273
Mike Lockwood0632ca72009-05-14 15:51:03 -0400274 // stop trying if we do not receive a fix within 60 seconds
Mike Lockwood04598b62010-04-14 17:17:24 -0400275 private static final int NO_FIX_TIMEOUT = 60 * 1000;
Mike Lockwood0632ca72009-05-14 15:51:03 -0400276
Nick Pellyb041f232012-05-07 17:12:25 -0700277 // if the fix interval is below this we leave GPS on,
278 // if above then we cycle the GPS driver.
279 // Typical hot TTTF is ~5 seconds, so 10 seconds seems sane.
280 private static final int GPS_POLLING_THRESHOLD_INTERVAL = 10 * 1000;
281
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700282 // how often to request NTP time, in milliseconds
283 // current setting 24 hours
284 private static final long NTP_INTERVAL = 24*60*60*1000;
285 // how long to wait if we have a network error in NTP or XTRA downloading
286 // current setting - 5 minutes
287 private static final long RETRY_INTERVAL = 5*60*1000;
288
289 // true if we are enabled, protected by this
290 private boolean mEnabled;
291
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800292 // true if we have network connectivity
293 private boolean mNetworkAvailable;
294
Kevin Tang40e1baf2012-01-10 14:32:44 -0800295 // states for injecting ntp and downloading xtra data
296 private static final int STATE_PENDING_NETWORK = 0;
297 private static final int STATE_DOWNLOADING = 1;
298 private static final int STATE_IDLE = 2;
299
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400300 // flags to trigger NTP or XTRA data download when network becomes available
301 // initialized to true so we do NTP and XTRA when the network comes up after booting
Kevin Tang40e1baf2012-01-10 14:32:44 -0800302 private int mInjectNtpTimePending = STATE_PENDING_NETWORK;
303 private int mDownloadXtraDataPending = STATE_PENDING_NETWORK;
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400304
Mike Lockwood9b9fb5c2011-06-29 15:09:40 -0400305 // set to true if the GPS engine does not do on-demand NTP time requests
306 private boolean mPeriodicTimeInjection;
307
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800308 // true if GPS is navigating
309 private boolean mNavigating;
Mike Lockwoodcf1d8cb2010-01-20 10:14:54 -0500310
311 // true if GPS engine is on
312 private boolean mEngineOn;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700313
Mike Lockwood04598b62010-04-14 17:17:24 -0400314 // requested frequency of fixes, in milliseconds
315 private int mFixInterval = 1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800316
317 // true if we started navigation
318 private boolean mStarted;
319
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -0700320 // true if single shot request is in progress
321 private boolean mSingleShot;
322
Mike Lockwood04598b62010-04-14 17:17:24 -0400323 // capabilities of the GPS engine
324 private int mEngineCapabilities;
325
Mike Lockwood1a1cd3a2010-08-17 07:42:54 -0400326 // true if XTRA is supported
327 private boolean mSupportsXtra;
328
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800329 // for calculating time to first fix
330 private long mFixRequestTime = 0;
331 // time to first fix for most recent session
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700332 private int mTimeToFirstFix = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800333 // time we received our last fix
334 private long mLastFixTime;
335
Mike Lockwood04598b62010-04-14 17:17:24 -0400336 private int mPositionMode;
337
David Christied4edf4c2014-08-12 15:22:27 -0700338 // Current request from underlying location clients.
339 private ProviderRequest mProviderRequest = null;
340 // Current list of underlying location clients.
341 private WorkSource mWorkSource = null;
342 // True if gps should be disabled (used to support battery saver mode in settings).
343 private boolean mDisableGps = false;
344
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800345 // properties loaded from PROPERTIES_FILE
346 private Properties mProperties;
Mike Lockwood734d6032009-07-28 18:30:25 -0700347 private String mSuplServerHost;
Tsuwei Chen678c13c2014-09-22 17:48:41 -0700348 private int mSuplServerPort = TCP_MIN_PORT;
Mike Lockwood734d6032009-07-28 18:30:25 -0700349 private String mC2KServerHost;
350 private int mC2KServerPort;
Tsuwei Chen3324e952014-09-07 01:30:42 -0700351 private boolean mSuplEsEnabled = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800352
Mike Lockwood15e3d0f2009-05-01 07:53:28 -0400353 private final Context mContext;
Jeff Sharkey104344e2011-07-10 14:20:41 -0700354 private final NtpTrustedTime mNtpTime;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700355 private final ILocationManager mILocationManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800356 private Location mLocation = new Location(LocationManager.GPS_PROVIDER);
357 private Bundle mLocationExtras = new Bundle();
destradaa6568d702014-10-27 12:47:41 -0700358 private final GpsStatusListenerHelper mListenerHelper;
359 private final GpsMeasurementsProvider mGpsMeasurementsProvider;
360 private final GpsNavigationMessageProvider mGpsNavigationMessageProvider;
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400361
Victoria Lease5c24fd02012-10-01 11:00:50 -0700362 // Handler for processing events
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400363 private Handler mHandler;
The Android Open Source Project10592532009-03-18 17:39:46 -0700364
Mike Lockwoode3635c92009-05-11 08:38:02 -0400365 private String mAGpsApn;
destradaa96a14702014-06-05 11:36:30 -0700366 private int mApnIpType;
Mike Lockwoode3635c92009-05-11 08:38:02 -0400367 private int mAGpsDataConnectionState;
destradaa96a14702014-06-05 11:36:30 -0700368 private InetAddress mAGpsDataConnectionIpAddr;
Mike Lockwood2f82c4e2009-04-17 08:24:10 -0400369 private final ConnectivityManager mConnMgr;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700370 private final GpsNetInitiatedHandler mNIHandler;
Mike Lockwood2f82c4e2009-04-17 08:24:10 -0400371
Mike Lockwood0528b9b2009-05-07 10:12:54 -0400372 // Wakelocks
373 private final static String WAKELOCK_KEY = "GpsLocationProvider";
374 private final PowerManager.WakeLock mWakeLock;
375
Mike Lockwood29c84342009-05-06 14:01:15 -0400376 // Alarms
377 private final static String ALARM_WAKEUP = "com.android.internal.location.ALARM_WAKEUP";
Mike Lockwood0632ca72009-05-14 15:51:03 -0400378 private final static String ALARM_TIMEOUT = "com.android.internal.location.ALARM_TIMEOUT";
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700379
380 // SIM/Carrier info.
381 private final static String SIM_STATE_CHANGED = "android.intent.action.SIM_STATE_CHANGED";
382
David Christied4edf4c2014-08-12 15:22:27 -0700383 private final PowerManager mPowerManager;
Mike Lockwood29c84342009-05-06 14:01:15 -0400384 private final AlarmManager mAlarmManager;
385 private final PendingIntent mWakeupIntent;
Mike Lockwood0632ca72009-05-14 15:51:03 -0400386 private final PendingIntent mTimeoutIntent;
Mike Lockwood29c84342009-05-06 14:01:15 -0400387
Dianne Hackborna06de0f2012-12-11 16:34:47 -0800388 private final IAppOpsService mAppOpsService;
Mike Lockwood2f82c4e2009-04-17 08:24:10 -0400389 private final IBatteryStats mBatteryStats;
The Android Open Source Project10592532009-03-18 17:39:46 -0700390
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700391 // only modified on handler thread
Dianne Hackborn002a54e2013-01-10 17:34:55 -0800392 private WorkSource mClientSource = new WorkSource();
Mike Lockwoodf1218be2010-01-29 09:20:06 -0500393
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -0700394 private GeofenceHardwareImpl mGeofenceHardwareImpl;
395
Mike Lockwood15e3d0f2009-05-01 07:53:28 -0400396 private final IGpsStatusProvider mGpsStatusProvider = new IGpsStatusProvider.Stub() {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700397 @Override
Mike Lockwood15e3d0f2009-05-01 07:53:28 -0400398 public void addGpsStatusListener(IGpsStatusListener listener) throws RemoteException {
destradaaea8a8a62014-06-23 18:19:03 -0700399 mListenerHelper.addListener(listener);
Mike Lockwood15e3d0f2009-05-01 07:53:28 -0400400 }
401
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700402 @Override
Mike Lockwood15e3d0f2009-05-01 07:53:28 -0400403 public void removeGpsStatusListener(IGpsStatusListener listener) {
destradaaea8a8a62014-06-23 18:19:03 -0700404 mListenerHelper.removeListener(listener);
405 }
406 };
Mike Lockwood15e3d0f2009-05-01 07:53:28 -0400407
Mike Lockwood15e3d0f2009-05-01 07:53:28 -0400408 public IGpsStatusProvider getGpsStatusProvider() {
409 return mGpsStatusProvider;
410 }
411
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -0700412 public IGpsGeofenceHardware getGpsGeofenceProxy() {
413 return mGpsGeofenceBinder;
414 }
415
destradaaea8a8a62014-06-23 18:19:03 -0700416 public GpsMeasurementsProvider getGpsMeasurementsProvider() {
417 return mGpsMeasurementsProvider;
418 }
419
destradaa4b3e3932014-07-21 18:01:47 -0700420 public GpsNavigationMessageProvider getGpsNavigationMessageProvider() {
421 return mGpsNavigationMessageProvider;
422 }
423
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700424 private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
The Android Open Source Project10592532009-03-18 17:39:46 -0700425 @Override public void onReceive(Context context, Intent intent) {
426 String action = intent.getAction();
427
Tsuwei Chen48d37f92014-09-05 15:15:34 -0700428 if (DEBUG) Log.d(TAG, "receive broadcast intent, action: " + action);
Mike Lockwood29c84342009-05-06 14:01:15 -0400429 if (action.equals(ALARM_WAKEUP)) {
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -0700430 startNavigating(false);
Mike Lockwood0632ca72009-05-14 15:51:03 -0400431 } else if (action.equals(ALARM_TIMEOUT)) {
Mike Lockwood0632ca72009-05-14 15:51:03 -0400432 hibernate();
Miguel Torroja1e84da82010-07-27 07:02:24 +0200433 } else if (action.equals(Intents.DATA_SMS_RECEIVED_ACTION)) {
434 checkSmsSuplInit(intent);
435 } else if (action.equals(Intents.WAP_PUSH_RECEIVED_ACTION)) {
436 checkWapSuplInit(intent);
Tsuwei Chend3ef8e22014-10-31 14:58:44 -0700437 } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE)) {
David Christied4edf4c2014-08-12 15:22:27 -0700438 // retrieve NetworkInfo result for this UID
439 NetworkInfo info =
440 intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
441 ConnectivityManager connManager = (ConnectivityManager)
442 mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
443 info = connManager.getNetworkInfo(info.getType());
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700444
Tsuwei Chend3ef8e22014-10-31 14:58:44 -0700445 int networkState;
446 if (intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false) ||
447 !info.isConnected()) {
448 networkState = LocationProvider.TEMPORARILY_UNAVAILABLE;
449 } else {
450 networkState = LocationProvider.AVAILABLE;
451 }
452
453
David Christied4edf4c2014-08-12 15:22:27 -0700454 updateNetworkState(networkState, info);
455 } else if (PowerManager.ACTION_POWER_SAVE_MODE_CHANGED.equals(action)
456 || Intent.ACTION_SCREEN_OFF.equals(action)
457 || Intent.ACTION_SCREEN_ON.equals(action)) {
458 updateLowPowerMode();
Wink Savillea374c3d2014-11-11 11:48:04 -0800459 } else if (action.equals(SIM_STATE_CHANGED)) {
460 subscriptionOrSimChanged(context);
David Christied4edf4c2014-08-12 15:22:27 -0700461 }
The Android Open Source Project10592532009-03-18 17:39:46 -0700462 }
Mike Lockwood29c84342009-05-06 14:01:15 -0400463 };
The Android Open Source Project10592532009-03-18 17:39:46 -0700464
Wink Savilled09c4ca2014-11-22 10:08:16 -0800465 private final OnSubscriptionsChangedListener mOnSubscriptionsChangedListener =
466 new OnSubscriptionsChangedListener() {
Wink Savillea374c3d2014-11-11 11:48:04 -0800467 @Override
Wink Savilled09c4ca2014-11-22 10:08:16 -0800468 public void onSubscriptionsChanged() {
Wink Savillea374c3d2014-11-11 11:48:04 -0800469 subscriptionOrSimChanged(mContext);
470 }
471 };
472
473 private void subscriptionOrSimChanged(Context context) {
474 Log.d(TAG, "received SIM realted action: ");
475 TelephonyManager phone = (TelephonyManager)
476 mContext.getSystemService(Context.TELEPHONY_SERVICE);
477 String mccMnc = phone.getSimOperator();
478 if (!TextUtils.isEmpty(mccMnc)) {
479 Log.d(TAG, "SIM MCC/MNC is available: " + mccMnc);
480 synchronized (mLock) {
481 reloadGpsProperties(context, mProperties);
482 mNIHandler.setSuplEsEnabled(mSuplEsEnabled);
483 }
484 } else {
485 Log.d(TAG, "SIM MCC/MNC is still not available");
486 }
487 }
488
Miguel Torroja1e84da82010-07-27 07:02:24 +0200489 private void checkSmsSuplInit(Intent intent) {
490 SmsMessage[] messages = Intents.getMessagesFromIntent(intent);
491 for (int i=0; i <messages.length; i++) {
492 byte[] supl_init = messages[i].getUserData();
493 native_agps_ni_message(supl_init,supl_init.length);
494 }
495 }
496
497 private void checkWapSuplInit(Intent intent) {
498 byte[] supl_init = (byte[]) intent.getExtra("data");
499 native_agps_ni_message(supl_init,supl_init.length);
500 }
501
David Christied4edf4c2014-08-12 15:22:27 -0700502 private void updateLowPowerMode() {
503 final boolean disableGps;
504 switch (Settings.Secure.getInt(mContext.getContentResolver(), BATTERY_SAVER_GPS_MODE,
505 BATTERY_SAVER_MODE_DISABLED_WHEN_SCREEN_OFF)) {
506 case BATTERY_SAVER_MODE_DISABLED_WHEN_SCREEN_OFF:
507 disableGps = mPowerManager.isPowerSaveMode() && !mPowerManager.isInteractive();
508 break;
509 default:
510 disableGps = false;
511 }
512 if (disableGps != mDisableGps) {
513 mDisableGps = disableGps;
514 updateRequirements();
515 }
516 }
517
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800518 public static boolean isSupported() {
519 return native_is_supported();
520 }
521
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700522 private void reloadGpsProperties(Context context, Properties properties) {
523 Log.d(TAG, "Reset GPS properties, previous size = " + properties.size());
524 loadPropertiesFromResource(context, properties);
525 boolean isPropertiesLoadedFromFile = false;
526 final String gpsHardware = SystemProperties.get("ro.hardware.gps");
527 if (!TextUtils.isEmpty(gpsHardware)) {
528 final String propFilename =
529 PROPERTIES_FILE_PREFIX + "." + gpsHardware + PROPERTIES_FILE_SUFFIX;
530 isPropertiesLoadedFromFile =
531 loadPropertiesFromFile(propFilename, properties);
532 }
533 if (!isPropertiesLoadedFromFile) {
534 loadPropertiesFromFile(DEFAULT_PROPERTIES_FILE, properties);
535 }
536 Log.d(TAG, "GPS properties reloaded, size = " + properties.size());
537
538 // TODO: we should get rid of C2K specific setting.
539 setSuplHostPort(properties.getProperty("SUPL_HOST"),
540 properties.getProperty("SUPL_PORT"));
541 mC2KServerHost = properties.getProperty("C2K_HOST");
542 String portString = properties.getProperty("C2K_PORT");
543 if (mC2KServerHost != null && portString != null) {
544 try {
545 mC2KServerPort = Integer.parseInt(portString);
546 } catch (NumberFormatException e) {
547 Log.e(TAG, "unable to parse C2K_PORT: " + portString);
548 }
549 }
550
551 try {
552 // Convert properties to string contents and send it to HAL.
553 ByteArrayOutputStream baos = new ByteArrayOutputStream(4096);
554 properties.store(baos, null);
555 native_configuration_update(baos.toString());
556 Log.d(TAG, "final config = " + baos.toString());
557 } catch (IOException ex) {
558 Log.w(TAG, "failed to dump properties contents");
559 }
Tsuwei Chen3324e952014-09-07 01:30:42 -0700560
561 // SUPL_ES configuration.
562 String suplESProperty = mProperties.getProperty("SUPL_ES");
563 if (suplESProperty != null) {
564 try {
565 mSuplEsEnabled = (Integer.parseInt(suplESProperty) == 1);
566 } catch (NumberFormatException e) {
567 Log.e(TAG, "unable to parse SUPL_ES: " + suplESProperty);
568 }
569 }
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700570 }
571
572 private void loadPropertiesFromResource(Context context,
573 Properties properties) {
574 String[] configValues = context.getResources().getStringArray(
575 com.android.internal.R.array.config_gpsParameters);
576 for (String item : configValues) {
577 Log.d(TAG, "GpsParamsResource: " + item);
Tsuwei Chen7c485bf2014-09-10 15:33:34 -0700578 // We need to support "KEY =", but not "=VALUE".
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700579 String[] split = item.split("=");
580 if (split.length == 2) {
581 properties.setProperty(split[0].trim().toUpperCase(), split[1]);
582 } else {
583 Log.w(TAG, "malformed contents: " + item);
584 }
585 }
586 }
587
588 private boolean loadPropertiesFromFile(String filename,
589 Properties properties) {
Colin Cross7c030ed2014-01-28 09:33:53 -0800590 try {
591 File file = new File(filename);
592 FileInputStream stream = null;
593 try {
594 stream = new FileInputStream(file);
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700595 properties.load(stream);
Colin Cross7c030ed2014-01-28 09:33:53 -0800596 } finally {
597 IoUtils.closeQuietly(stream);
598 }
599
Colin Cross7c030ed2014-01-28 09:33:53 -0800600 } catch (IOException e) {
601 Log.w(TAG, "Could not open GPS configuration file " + filename);
602 return false;
603 }
604 return true;
605 }
606
Victoria Lease5cd731a2012-12-19 15:04:21 -0800607 public GpsLocationProvider(Context context, ILocationManager ilocationManager,
608 Looper looper) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800609 mContext = context;
Jeff Sharkey104344e2011-07-10 14:20:41 -0700610 mNtpTime = NtpTrustedTime.getInstance(context);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700611 mILocationManager = ilocationManager;
Mike Lockwood63598a02010-02-24 11:52:59 -0500612
613 mLocation.setExtras(mLocationExtras);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800614
Mike Lockwood0528b9b2009-05-07 10:12:54 -0400615 // Create a wake lock
David Christied4edf4c2014-08-12 15:22:27 -0700616 mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
617 mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700618 mWakeLock.setReferenceCounted(true);
Mike Lockwood0528b9b2009-05-07 10:12:54 -0400619
Mike Lockwood29c84342009-05-06 14:01:15 -0400620 mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
621 mWakeupIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_WAKEUP), 0);
Mike Lockwood0632ca72009-05-14 15:51:03 -0400622 mTimeoutIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_TIMEOUT), 0);
Mike Lockwood29c84342009-05-06 14:01:15 -0400623
Mike Lockwood58bda982009-04-14 16:25:07 -0400624 mConnMgr = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
625
Dianne Hackborna06de0f2012-12-11 16:34:47 -0800626 // App ops service to keep track of who is accessing the GPS
627 mAppOpsService = IAppOpsService.Stub.asInterface(ServiceManager.getService(
628 Context.APP_OPS_SERVICE));
629
Mike Lockwood2f82c4e2009-04-17 08:24:10 -0400630 // Battery statistics service to be notified when GPS turns on or off
Dianne Hackborn91268cf2013-06-13 19:06:50 -0700631 mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService(
632 BatteryStats.SERVICE_NAME));
Mike Lockwood2f82c4e2009-04-17 08:24:10 -0400633
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700634 // Load GPS configuration.
635 mProperties = new Properties();
636 reloadGpsProperties(mContext, mProperties);
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400637
Tsuwei Chen3324e952014-09-07 01:30:42 -0700638 // Create a GPS net-initiated handler.
639 mNIHandler = new GpsNetInitiatedHandler(context,
640 mNetInitiatedListener,
641 mSuplEsEnabled);
642
Wink Savillea374c3d2014-11-11 11:48:04 -0800643 // TODO: When this object "finishes" we should unregister by invoking
Wink Savilled09c4ca2014-11-22 10:08:16 -0800644 // SubscriptionManager.getInstance(mContext).unregister(mOnSubscriptionsChangedListener);
Wink Savillea374c3d2014-11-11 11:48:04 -0800645 // This is not strictly necessary because it will be unregistered if the
646 // notification fails but it is good form.
647
648 // Register for SubscriptionInfo list changes which is guaranteed
Wink Savilled09c4ca2014-11-22 10:08:16 -0800649 // to invoke onSubscriptionsChanged the first time.
650 SubscriptionManager.from(mContext)
651 .registerOnSubscriptionsChangedListener(mOnSubscriptionsChangedListener);
Wink Savillea374c3d2014-11-11 11:48:04 -0800652
Victoria Lease5c24fd02012-10-01 11:00:50 -0700653 // construct handler, listen for events
Victoria Lease5cd731a2012-12-19 15:04:21 -0800654 mHandler = new ProviderHandler(looper);
Victoria Lease5c24fd02012-10-01 11:00:50 -0700655 listenForBroadcasts();
656
657 // also listen for PASSIVE_PROVIDER updates
658 mHandler.post(new Runnable() {
659 @Override
660 public void run() {
661 LocationManager locManager =
662 (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
David Christie9e9ce922013-09-12 13:04:32 -0700663 final long minTime = 0;
664 final float minDistance = 0;
665 final boolean oneShot = false;
666 LocationRequest request = LocationRequest.createFromDeprecatedProvider(
667 LocationManager.PASSIVE_PROVIDER,
668 minTime,
669 minDistance,
670 oneShot);
671 // Don't keep track of this request since it's done on behalf of other clients
672 // (which are kept track of separately).
673 request.setHideFromAppOps(true);
674 locManager.requestLocationUpdates(
675 request,
676 new NetworkLocationListener(),
677 mHandler.getLooper());
Mike Lockwood89096312010-03-24 10:14:55 -0400678 }
Victoria Lease5c24fd02012-10-01 11:00:50 -0700679 });
destradaa6568d702014-10-27 12:47:41 -0700680
681 mListenerHelper = new GpsStatusListenerHelper(mHandler) {
682 @Override
683 protected boolean isAvailableInPlatform() {
684 return GpsLocationProvider.isSupported();
685 }
686
687 @Override
688 protected boolean isGpsEnabled() {
689 return isEnabled();
690 }
691 };
692
693 mGpsMeasurementsProvider = new GpsMeasurementsProvider(mHandler) {
694 @Override
695 public boolean isAvailableInPlatform() {
696 return native_is_measurement_supported();
697 }
698
699 @Override
700 protected boolean registerWithService() {
701 return native_start_measurement_collection();
702 }
703
704 @Override
705 protected void unregisterFromService() {
706 native_stop_measurement_collection();
707 }
708
709 @Override
710 protected boolean isGpsEnabled() {
711 return isEnabled();
712 }
713 };
714
715 mGpsNavigationMessageProvider = new GpsNavigationMessageProvider(mHandler) {
716 @Override
717 protected boolean isAvailableInPlatform() {
718 return native_is_navigation_message_supported();
719 }
720
721 @Override
722 protected boolean registerWithService() {
723 return native_start_navigation_message_collection();
724 }
725
726 @Override
727 protected void unregisterFromService() {
728 native_stop_navigation_message_collection();
729 }
730
731 @Override
732 protected boolean isGpsEnabled() {
733 return isEnabled();
734 }
735 };
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400736 }
737
Victoria Lease5c24fd02012-10-01 11:00:50 -0700738 private void listenForBroadcasts() {
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400739 IntentFilter intentFilter = new IntentFilter();
Victoria Lease5c24fd02012-10-01 11:00:50 -0700740 intentFilter.addAction(Intents.DATA_SMS_RECEIVED_ACTION);
741 intentFilter.addDataScheme("sms");
742 intentFilter.addDataAuthority("localhost","7275");
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700743 mContext.registerReceiver(mBroadcastReceiver, intentFilter, null, mHandler);
Victoria Lease5c24fd02012-10-01 11:00:50 -0700744
745 intentFilter = new IntentFilter();
746 intentFilter.addAction(Intents.WAP_PUSH_RECEIVED_ACTION);
747 try {
748 intentFilter.addDataType("application/vnd.omaloc-supl-init");
749 } catch (IntentFilter.MalformedMimeTypeException e) {
750 Log.w(TAG, "Malformed SUPL init mime type");
751 }
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700752 mContext.registerReceiver(mBroadcastReceiver, intentFilter, null, mHandler);
Victoria Lease5c24fd02012-10-01 11:00:50 -0700753
754 intentFilter = new IntentFilter();
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400755 intentFilter.addAction(ALARM_WAKEUP);
756 intentFilter.addAction(ALARM_TIMEOUT);
Tsuwei Chend3ef8e22014-10-31 14:58:44 -0700757 intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE);
David Christied4edf4c2014-08-12 15:22:27 -0700758 intentFilter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED);
759 intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
760 intentFilter.addAction(Intent.ACTION_SCREEN_ON);
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700761 intentFilter.addAction(SIM_STATE_CHANGED);
762 mContext.registerReceiver(mBroadcastReceiver, intentFilter, null, mHandler);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800763 }
764
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800765 /**
Mike Lockwoodd03ff942010-02-09 08:46:14 -0500766 * Returns the name of this provider.
767 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700768 @Override
Mike Lockwoodd03ff942010-02-09 08:46:14 -0500769 public String getName() {
770 return LocationManager.GPS_PROVIDER;
771 }
772
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700773 @Override
774 public ProviderProperties getProperties() {
775 return PROPERTIES;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800776 }
777
Mike Lockwood03d24672009-10-08 15:45:03 -0400778 public void updateNetworkState(int state, NetworkInfo info) {
Mike Lockwood98e48692010-04-07 16:32:51 -0400779 sendMessage(UPDATE_NETWORK_STATE, state, info);
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400780 }
781
782 private void handleUpdateNetworkState(int state, NetworkInfo info) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800783 mNetworkAvailable = (state == LocationProvider.AVAILABLE);
784
Joe Onoratof5d95cb2010-01-07 21:48:32 -0500785 if (DEBUG) {
Mike Lockwood03d24672009-10-08 15:45:03 -0400786 Log.d(TAG, "updateNetworkState " + (mNetworkAvailable ? "available" : "unavailable")
787 + " info: " + info);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800788 }
Mike Lockwood03d24672009-10-08 15:45:03 -0400789
Mike Lockwood50130bb2010-10-11 06:22:50 -0400790 if (info != null) {
Amit Mahajan421a5392014-11-20 11:42:19 -0800791 boolean dataEnabled = TelephonyManager.getIntWithSubId(mContext.getContentResolver(),
792 Settings.Global.MOBILE_DATA, SubscriptionManager.getDefaultSubId(),
793 1) == 1;
Kevin Tanga5fe6b22011-06-05 14:25:16 -0700794 boolean networkAvailable = info.isAvailable() && dataEnabled;
795 String defaultApn = getSelectedApn();
796 if (defaultApn == null) {
797 defaultApn = "dummy-apn";
798 }
799
Mike Lockwood50130bb2010-10-11 06:22:50 -0400800 native_update_network_state(info.isConnected(), info.getType(),
Kevin Tanga5fe6b22011-06-05 14:25:16 -0700801 info.isRoaming(), networkAvailable,
802 info.getExtraInfo(), defaultApn);
Mike Lockwood50130bb2010-10-11 06:22:50 -0400803 }
804
Mike Lockwood03d24672009-10-08 15:45:03 -0400805 if (info != null && info.getType() == ConnectivityManager.TYPE_MOBILE_SUPL
806 && mAGpsDataConnectionState == AGPS_DATA_CONNECTION_OPENING) {
Stephen Li83b69712011-01-25 18:47:28 -0800807 if (mNetworkAvailable) {
destradaa96a14702014-06-05 11:36:30 -0700808 String apnName = info.getExtraInfo();
Stephen Li83b69712011-01-25 18:47:28 -0800809 if (apnName == null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700810 /* Assign a dummy value in the case of C2K as otherwise we will have a runtime
Stephen Li83b69712011-01-25 18:47:28 -0800811 exception in the following call to native_agps_data_conn_open*/
812 apnName = "dummy-apn";
813 }
Mike Lockwood03d24672009-10-08 15:45:03 -0400814 mAGpsApn = apnName;
destradaa96a14702014-06-05 11:36:30 -0700815 mApnIpType = getApnIpType(apnName);
816 setRouting();
817 if (DEBUG) {
818 String message = String.format(
819 "native_agps_data_conn_open: mAgpsApn=%s, mApnIpType=%s",
820 mAGpsApn, mApnIpType);
821 Log.d(TAG, message);
Stephen Li8efd74d2011-03-01 20:56:00 -0800822 }
destradaa96a14702014-06-05 11:36:30 -0700823 native_agps_data_conn_open(mAGpsApn, mApnIpType);
Mike Lockwood03d24672009-10-08 15:45:03 -0400824 mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPEN;
825 } else {
destradaa96a14702014-06-05 11:36:30 -0700826 Log.e(TAG, "call native_agps_data_conn_failed, info: " + info);
Mike Lockwood03d24672009-10-08 15:45:03 -0400827 mAGpsApn = null;
destradaa96a14702014-06-05 11:36:30 -0700828 mApnIpType = APN_INVALID;
Mike Lockwood03d24672009-10-08 15:45:03 -0400829 mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED;
830 native_agps_data_conn_failed();
831 }
832 }
833
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400834 if (mNetworkAvailable) {
Kevin Tang40e1baf2012-01-10 14:32:44 -0800835 if (mInjectNtpTimePending == STATE_PENDING_NETWORK) {
Mike Lockwood98e48692010-04-07 16:32:51 -0400836 sendMessage(INJECT_NTP_TIME, 0, null);
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400837 }
Kevin Tang40e1baf2012-01-10 14:32:44 -0800838 if (mDownloadXtraDataPending == STATE_PENDING_NETWORK) {
Mike Lockwood98e48692010-04-07 16:32:51 -0400839 sendMessage(DOWNLOAD_XTRA_DATA, 0, null);
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400840 }
841 }
842 }
843
844 private void handleInjectNtpTime() {
Kevin Tang40e1baf2012-01-10 14:32:44 -0800845 if (mInjectNtpTimePending == 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 mInjectNtpTimePending = STATE_PENDING_NETWORK;
852 return;
Jeff Sharkey104344e2011-07-10 14:20:41 -0700853 }
Kevin Tang40e1baf2012-01-10 14:32:44 -0800854 mInjectNtpTimePending = STATE_DOWNLOADING;
Jeff Sharkey104344e2011-07-10 14:20:41 -0700855
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() {
861 long delay;
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400862
Kevin Tang40e1baf2012-01-10 14:32:44 -0800863 // force refresh NTP cache when outdated
864 if (mNtpTime.getCacheAge() >= NTP_INTERVAL) {
865 mNtpTime.forceRefresh();
866 }
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400867
Kevin Tang40e1baf2012-01-10 14:32:44 -0800868 // only update when NTP time is fresh
869 if (mNtpTime.getCacheAge() < NTP_INTERVAL) {
870 long time = mNtpTime.getCachedNtpTime();
871 long timeReference = mNtpTime.getCachedNtpTimeReference();
872 long certainty = mNtpTime.getCacheCertainty();
873 long now = System.currentTimeMillis();
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400874
Kevin Tang40e1baf2012-01-10 14:32:44 -0800875 Log.d(TAG, "NTP server returned: "
876 + time + " (" + new Date(time)
877 + ") reference: " + timeReference
878 + " certainty: " + certainty
879 + " system time offset: " + (time - now));
880
881 native_inject_time(time, timeReference, (int) certainty);
882 delay = NTP_INTERVAL;
883 } else {
884 if (DEBUG) Log.d(TAG, "requestTime failed");
885 delay = RETRY_INTERVAL;
886 }
887
Jeff Brown028872f2012-08-25 13:07:01 -0700888 sendMessage(INJECT_NTP_TIME_FINISHED, 0, null);
Kevin Tang40e1baf2012-01-10 14:32:44 -0800889
890 if (mPeriodicTimeInjection) {
891 // send delayed message for next NTP injection
892 // since this is delayed and not urgent we do not hold a wake lock here
Jeff Brown028872f2012-08-25 13:07:01 -0700893 mHandler.sendEmptyMessageDelayed(INJECT_NTP_TIME, delay);
Kevin Tang40e1baf2012-01-10 14:32:44 -0800894 }
Jeff Brown028872f2012-08-25 13:07:01 -0700895
896 // release wake lock held by task
897 mWakeLock.release();
Kevin Tang40e1baf2012-01-10 14:32:44 -0800898 }
899 });
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400900 }
901
902 private void handleDownloadXtraData() {
Kevin Tang40e1baf2012-01-10 14:32:44 -0800903 if (mDownloadXtraDataPending == STATE_DOWNLOADING) {
904 // already downloading data
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400905 return;
906 }
Kevin Tang40e1baf2012-01-10 14:32:44 -0800907 if (!mNetworkAvailable) {
908 // try again when network is up
909 mDownloadXtraDataPending = STATE_PENDING_NETWORK;
910 return;
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400911 }
Kevin Tang40e1baf2012-01-10 14:32:44 -0800912 mDownloadXtraDataPending = STATE_DOWNLOADING;
913
Jeff Brown028872f2012-08-25 13:07:01 -0700914 // hold wake lock while task runs
915 mWakeLock.acquire();
Kevin Tang40e1baf2012-01-10 14:32:44 -0800916 AsyncTask.THREAD_POOL_EXECUTOR.execute(new Runnable() {
917 @Override
918 public void run() {
919 GpsXtraDownloader xtraDownloader = new GpsXtraDownloader(mContext, mProperties);
920 byte[] data = xtraDownloader.downloadXtraData();
921 if (data != null) {
922 if (DEBUG) {
923 Log.d(TAG, "calling native_inject_xtra_data");
924 }
925 native_inject_xtra_data(data, data.length);
926 }
927
Jeff Brown028872f2012-08-25 13:07:01 -0700928 sendMessage(DOWNLOAD_XTRA_DATA_FINISHED, 0, null);
Kevin Tang40e1baf2012-01-10 14:32:44 -0800929
930 if (data == null) {
931 // try again later
932 // since this is delayed and not urgent we do not hold a wake lock here
Jeff Brown028872f2012-08-25 13:07:01 -0700933 mHandler.sendEmptyMessageDelayed(DOWNLOAD_XTRA_DATA, RETRY_INTERVAL);
Kevin Tang40e1baf2012-01-10 14:32:44 -0800934 }
Kevin Tang40e1baf2012-01-10 14:32:44 -0800935
Jeff Brown028872f2012-08-25 13:07:01 -0700936 // release wake lock held by task
937 mWakeLock.release();
938 }
Kevin Tang40e1baf2012-01-10 14:32:44 -0800939 });
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800940 }
941
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400942 private void handleUpdateLocation(Location location) {
Mike Lockwoodd26ce0d2009-06-11 12:25:46 -0400943 if (location.hasAccuracy()) {
944 native_inject_location(location.getLatitude(), location.getLongitude(),
945 location.getAccuracy());
946 }
Mike Lockwoodfd6e5f02009-05-21 11:28:20 -0400947 }
948
949 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800950 * Enables this provider. When enabled, calls to getStatus()
Mike Lockwood4e50b782009-04-03 08:24:43 -0700951 * must be handled. Hardware may be started up
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800952 * when the provider is enabled.
953 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700954 @Override
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400955 public void enable() {
Laurent Tu7b5aeca2013-01-24 15:10:24 -0800956 synchronized (mLock) {
957 if (mEnabled) return;
958 mEnabled = true;
959 }
960
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700961 sendMessage(ENABLE, 1, null);
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400962 }
963
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700964 private void setSuplHostPort(String hostString, String portString) {
965 if (hostString != null) {
966 mSuplServerHost = hostString;
967 }
968 if (portString != null) {
969 try {
970 mSuplServerPort = Integer.parseInt(portString);
971 } catch (NumberFormatException e) {
972 Log.e(TAG, "unable to parse SUPL_PORT: " + portString);
973 }
974 }
Tsuwei Chen678c13c2014-09-22 17:48:41 -0700975 if (mSuplServerHost != null
976 && mSuplServerPort > TCP_MIN_PORT
977 && mSuplServerPort <= TCP_MAX_PORT) {
978 native_set_agps_server(AGPS_TYPE_SUPL, mSuplServerHost, mSuplServerPort);
979 }
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700980 }
981
Tsuwei Chen462bcd82014-09-17 12:28:49 -0700982 /**
983 * Checks what SUPL mode to use, according to the AGPS mode as well as the
984 * allowed mode from properties.
985 *
986 * @param properties GPS properties
987 * @param agpsEnabled whether AGPS is enabled by settings value
988 * @param singleShot whether "singleshot" is needed
989 * @return SUPL mode (MSA vs MSB vs STANDALONE)
990 */
991 private int getSuplMode(Properties properties, boolean agpsEnabled, boolean singleShot) {
992 if (agpsEnabled) {
993 String modeString = properties.getProperty("SUPL_MODE");
994 int suplMode = 0;
995 if (!TextUtils.isEmpty(modeString)) {
996 try {
997 suplMode = Integer.parseInt(modeString);
998 } catch (NumberFormatException e) {
999 Log.e(TAG, "unable to parse SUPL_MODE: " + modeString);
1000 return GPS_POSITION_MODE_STANDALONE;
1001 }
1002 }
1003 if (singleShot
1004 && hasCapability(GPS_CAPABILITY_MSA)
1005 && (suplMode & AGPS_SUPL_MODE_MSA) != 0) {
1006 return GPS_POSITION_MODE_MS_ASSISTED;
1007 } else if (hasCapability(GPS_CAPABILITY_MSB)
1008 && (suplMode & AGPS_SUPL_MODE_MSB) != 0) {
1009 return GPS_POSITION_MODE_MS_BASED;
1010 }
1011 }
1012 return GPS_POSITION_MODE_STANDALONE;
1013 }
1014
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001015 private void handleEnable() {
1016 if (DEBUG) Log.d(TAG, "handleEnable");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001017
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001018 boolean enabled = native_init();
1019
1020 if (enabled) {
Mike Lockwood1a1cd3a2010-08-17 07:42:54 -04001021 mSupportsXtra = native_supports_xtra();
Tsuwei Chen678c13c2014-09-22 17:48:41 -07001022
1023 // TODO: remove the following native calls if we can make sure they are redundant.
Mike Lockwood734d6032009-07-28 18:30:25 -07001024 if (mSuplServerHost != null) {
1025 native_set_agps_server(AGPS_TYPE_SUPL, mSuplServerHost, mSuplServerPort);
1026 }
1027 if (mC2KServerHost != null) {
1028 native_set_agps_server(AGPS_TYPE_C2K, mC2KServerHost, mC2KServerPort);
1029 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001030 } else {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001031 synchronized (mLock) {
1032 mEnabled = false;
1033 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001034 Log.w(TAG, "Failed to enable location provider");
1035 }
1036 }
1037
1038 /**
1039 * Disables this provider. When disabled, calls to getStatus()
Mike Lockwood4e50b782009-04-03 08:24:43 -07001040 * need not be handled. Hardware may be shut
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001041 * down while the provider is disabled.
1042 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001043 @Override
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001044 public void disable() {
Laurent Tu7b5aeca2013-01-24 15:10:24 -08001045 synchronized (mLock) {
1046 if (!mEnabled) return;
1047 mEnabled = false;
1048 }
1049
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001050 sendMessage(ENABLE, 0, null);
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001051 }
1052
1053 private void handleDisable() {
Mike Lockwood89096312010-03-24 10:14:55 -04001054 if (DEBUG) Log.d(TAG, "handleDisable");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001055
David Christie3bc26142013-12-19 14:53:44 -08001056 updateClientUids(new WorkSource());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001057 stopNavigating();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001058 mAlarmManager.cancel(mWakeupIntent);
1059 mAlarmManager.cancel(mTimeoutIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001060
Mike Lockwoodcf1d8cb2010-01-20 10:14:54 -05001061 // do this before releasing wakelock
1062 native_cleanup();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001063 }
1064
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001065 @Override
Mike Lockwoodd03ff942010-02-09 08:46:14 -05001066 public boolean isEnabled() {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001067 synchronized (mLock) {
1068 return mEnabled;
1069 }
Mike Lockwoodd03ff942010-02-09 08:46:14 -05001070 }
1071
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001072 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001073 public int getStatus(Bundle extras) {
1074 if (extras != null) {
1075 extras.putInt("satellites", mSvCount);
1076 }
1077 return mStatus;
1078 }
1079
1080 private void updateStatus(int status, int svCount) {
1081 if (status != mStatus || svCount != mSvCount) {
1082 mStatus = status;
1083 mSvCount = svCount;
1084 mLocationExtras.putInt("satellites", svCount);
1085 mStatusUpdateTime = SystemClock.elapsedRealtime();
1086 }
1087 }
1088
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001089 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001090 public long getStatusUpdateTime() {
1091 return mStatusUpdateTime;
1092 }
1093
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001094 @Override
1095 public void setRequest(ProviderRequest request, WorkSource source) {
1096 sendMessage(SET_REQUEST, 0, new GpsRequest(request, source));
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001097 }
1098
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001099 private void handleSetRequest(ProviderRequest request, WorkSource source) {
David Christied4edf4c2014-08-12 15:22:27 -07001100 mProviderRequest = request;
1101 mWorkSource = source;
1102 updateRequirements();
1103 }
1104
1105 // Called when the requirements for GPS may have changed
1106 private void updateRequirements() {
1107 if (mProviderRequest == null || mWorkSource == null) {
1108 return;
1109 }
1110
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001111 boolean singleShot = false;
1112
1113 // see if the request is for a single update
David Christied4edf4c2014-08-12 15:22:27 -07001114 if (mProviderRequest.locationRequests != null
1115 && mProviderRequest.locationRequests.size() > 0) {
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001116 // if any request has zero or more than one updates
1117 // requested, then this is not single-shot mode
1118 singleShot = true;
1119
David Christied4edf4c2014-08-12 15:22:27 -07001120 for (LocationRequest lr : mProviderRequest.locationRequests) {
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001121 if (lr.getNumUpdates() != 1) {
1122 singleShot = false;
1123 }
1124 }
1125 }
1126
David Christied4edf4c2014-08-12 15:22:27 -07001127 if (DEBUG) Log.d(TAG, "setRequest " + mProviderRequest);
1128 if (mProviderRequest.reportLocation && !mDisableGps) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001129 // update client uids
David Christied4edf4c2014-08-12 15:22:27 -07001130 updateClientUids(mWorkSource);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001131
David Christied4edf4c2014-08-12 15:22:27 -07001132 mFixInterval = (int) mProviderRequest.interval;
Mike Lockwood03ca2162010-04-01 08:10:09 -07001133
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001134 // check for overflow
David Christied4edf4c2014-08-12 15:22:27 -07001135 if (mFixInterval != mProviderRequest.interval) {
1136 Log.w(TAG, "interval overflow: " + mProviderRequest.interval);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001137 mFixInterval = Integer.MAX_VALUE;
1138 }
Mike Lockwood03ca2162010-04-01 08:10:09 -07001139
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001140 // apply request to GPS engine
Mike Lockwood04598b62010-04-14 17:17:24 -04001141 if (mStarted && hasCapability(GPS_CAPABILITY_SCHEDULING)) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001142 // change period
Mike Lockwood04598b62010-04-14 17:17:24 -04001143 if (!native_set_position_mode(mPositionMode, GPS_POSITION_RECURRENCE_PERIODIC,
1144 mFixInterval, 0, 0)) {
1145 Log.e(TAG, "set_position_mode failed in setMinTime()");
1146 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001147 } else if (!mStarted) {
1148 // start GPS
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001149 startNavigating(singleShot);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001150 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001151 } else {
Dianne Hackborn002a54e2013-01-10 17:34:55 -08001152 updateClientUids(new WorkSource());
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001153
1154 stopNavigating();
1155 mAlarmManager.cancel(mWakeupIntent);
1156 mAlarmManager.cancel(mTimeoutIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001157 }
1158 }
1159
Dianne Hackborn002a54e2013-01-10 17:34:55 -08001160 private void updateClientUids(WorkSource source) {
1161 // Update work source.
1162 WorkSource[] changes = mClientSource.setReturningDiffs(source);
Victoria Leaseea78b852013-01-15 10:39:28 -08001163 if (changes == null) {
1164 return;
1165 }
Dianne Hackborn002a54e2013-01-10 17:34:55 -08001166 WorkSource newWork = changes[0];
1167 WorkSource goneWork = changes[1];
1168
1169 // Update sources that were not previously tracked.
1170 if (newWork != null) {
1171 int lastuid = -1;
1172 for (int i=0; i<newWork.size(); i++) {
Dianne Hackborn2e418422009-06-22 20:00:17 -07001173 try {
Dianne Hackborn002a54e2013-01-10 17:34:55 -08001174 int uid = newWork.get(i);
Dianne Hackborne98f5db2013-07-17 17:23:25 -07001175 mAppOpsService.startOperation(AppOpsManager.getToken(mAppOpsService),
1176 AppOpsManager.OP_GPS, uid, newWork.getName(i));
Dianne Hackborn002a54e2013-01-10 17:34:55 -08001177 if (uid != lastuid) {
1178 lastuid = uid;
1179 mBatteryStats.noteStartGps(uid);
1180 }
Dianne Hackborn2e418422009-06-22 20:00:17 -07001181 } catch (RemoteException e) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001182 Log.w(TAG, "RemoteException", e);
1183 }
1184 }
1185 }
1186
Dianne Hackborn002a54e2013-01-10 17:34:55 -08001187 // Update sources that are no longer tracked.
1188 if (goneWork != null) {
1189 int lastuid = -1;
1190 for (int i=0; i<goneWork.size(); i++) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001191 try {
Dianne Hackborn002a54e2013-01-10 17:34:55 -08001192 int uid = goneWork.get(i);
Dianne Hackborne98f5db2013-07-17 17:23:25 -07001193 mAppOpsService.finishOperation(AppOpsManager.getToken(mAppOpsService),
1194 AppOpsManager.OP_GPS, uid, goneWork.getName(i));
Dianne Hackborn002a54e2013-01-10 17:34:55 -08001195 if (uid != lastuid) {
1196 lastuid = uid;
1197 mBatteryStats.noteStopGps(uid);
1198 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001199 } catch (RemoteException e) {
1200 Log.w(TAG, "RemoteException", e);
Dianne Hackborn2e418422009-06-22 20:00:17 -07001201 }
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001202 }
1203 }
1204 }
1205
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001206 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001207 public boolean sendExtraCommand(String command, Bundle extras) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001208
Mike Lockwood63aa5a62010-04-14 19:21:31 -04001209 long identity = Binder.clearCallingIdentity();
1210 boolean result = false;
1211
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001212 if ("delete_aiding_data".equals(command)) {
Mike Lockwood63aa5a62010-04-14 19:21:31 -04001213 result = deleteAidingData(extras);
1214 } else if ("force_time_injection".equals(command)) {
Mike Lockwood98e48692010-04-07 16:32:51 -04001215 sendMessage(INJECT_NTP_TIME, 0, null);
Mike Lockwood63aa5a62010-04-14 19:21:31 -04001216 result = true;
1217 } else if ("force_xtra_injection".equals(command)) {
Mike Lockwood1a1cd3a2010-08-17 07:42:54 -04001218 if (mSupportsXtra) {
Mike Lockwood93bc44d2009-05-20 16:58:22 -04001219 xtraDownloadRequest();
Mike Lockwood63aa5a62010-04-14 19:21:31 -04001220 result = true;
Mike Lockwood93bc44d2009-05-20 16:58:22 -04001221 }
Mike Lockwood63aa5a62010-04-14 19:21:31 -04001222 } else {
1223 Log.w(TAG, "sendExtraCommand: unknown command " + command);
Mike Lockwood93bc44d2009-05-20 16:58:22 -04001224 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001225
Mike Lockwood63aa5a62010-04-14 19:21:31 -04001226 Binder.restoreCallingIdentity(identity);
1227 return result;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001228 }
1229
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001230 private IGpsGeofenceHardware mGpsGeofenceBinder = new IGpsGeofenceHardware.Stub() {
1231 public boolean isHardwareGeofenceSupported() {
1232 return native_is_geofence_supported();
1233 }
1234
1235 public boolean addCircularHardwareGeofence(int geofenceId, double latitude,
1236 double longitude, double radius, int lastTransition, int monitorTransitions,
1237 int notificationResponsiveness, int unknownTimer) {
1238 return native_add_geofence(geofenceId, latitude, longitude, radius,
1239 lastTransition, monitorTransitions, notificationResponsiveness, unknownTimer);
1240 }
1241
1242 public boolean removeHardwareGeofence(int geofenceId) {
1243 return native_remove_geofence(geofenceId);
1244 }
1245
1246 public boolean pauseHardwareGeofence(int geofenceId) {
1247 return native_pause_geofence(geofenceId);
1248 }
1249
1250 public boolean resumeHardwareGeofence(int geofenceId, int monitorTransition) {
1251 return native_resume_geofence(geofenceId, monitorTransition);
1252 }
1253 };
1254
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001255 private boolean deleteAidingData(Bundle extras) {
1256 int flags;
1257
1258 if (extras == null) {
1259 flags = GPS_DELETE_ALL;
1260 } else {
1261 flags = 0;
1262 if (extras.getBoolean("ephemeris")) flags |= GPS_DELETE_EPHEMERIS;
1263 if (extras.getBoolean("almanac")) flags |= GPS_DELETE_ALMANAC;
1264 if (extras.getBoolean("position")) flags |= GPS_DELETE_POSITION;
1265 if (extras.getBoolean("time")) flags |= GPS_DELETE_TIME;
1266 if (extras.getBoolean("iono")) flags |= GPS_DELETE_IONO;
1267 if (extras.getBoolean("utc")) flags |= GPS_DELETE_UTC;
1268 if (extras.getBoolean("health")) flags |= GPS_DELETE_HEALTH;
1269 if (extras.getBoolean("svdir")) flags |= GPS_DELETE_SVDIR;
1270 if (extras.getBoolean("svsteer")) flags |= GPS_DELETE_SVSTEER;
1271 if (extras.getBoolean("sadata")) flags |= GPS_DELETE_SADATA;
1272 if (extras.getBoolean("rti")) flags |= GPS_DELETE_RTI;
1273 if (extras.getBoolean("celldb-info")) flags |= GPS_DELETE_CELLDB_INFO;
1274 if (extras.getBoolean("all")) flags |= GPS_DELETE_ALL;
1275 }
1276
1277 if (flags != 0) {
1278 native_delete_aiding_data(flags);
1279 return true;
1280 }
1281
1282 return false;
1283 }
1284
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001285 private void startNavigating(boolean singleShot) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001286 if (!mStarted) {
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001287 if (DEBUG) Log.d(TAG, "startNavigating, singleShot is " + singleShot);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001288 mTimeToFirstFix = 0;
1289 mLastFixTime = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001290 mStarted = true;
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001291 mSingleShot = singleShot;
Mike Lockwood03ca2162010-04-01 08:10:09 -07001292 mPositionMode = GPS_POSITION_MODE_STANDALONE;
1293
Tsuwei Chen462bcd82014-09-17 12:28:49 -07001294 boolean agpsEnabled =
1295 (Settings.Global.getInt(mContext.getContentResolver(),
1296 Settings.Global.ASSISTED_GPS_ENABLED, 1) != 0);
1297 mPositionMode = getSuplMode(mProperties, agpsEnabled, singleShot);
Mike Lockwoodbcab8df2009-06-25 16:39:09 -04001298
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001299 if (DEBUG) {
1300 String mode;
1301
1302 switch(mPositionMode) {
1303 case GPS_POSITION_MODE_STANDALONE:
1304 mode = "standalone";
1305 break;
1306 case GPS_POSITION_MODE_MS_ASSISTED:
1307 mode = "MS_ASSISTED";
1308 break;
1309 case GPS_POSITION_MODE_MS_BASED:
1310 mode = "MS_BASED";
1311 break;
1312 default:
1313 mode = "unknown";
1314 break;
1315 }
1316 Log.d(TAG, "setting position_mode to " + mode);
1317 }
1318
Mike Lockwood04598b62010-04-14 17:17:24 -04001319 int interval = (hasCapability(GPS_CAPABILITY_SCHEDULING) ? mFixInterval : 1000);
1320 if (!native_set_position_mode(mPositionMode, GPS_POSITION_RECURRENCE_PERIODIC,
1321 interval, 0, 0)) {
1322 mStarted = false;
1323 Log.e(TAG, "set_position_mode failed in startNavigating()");
1324 return;
1325 }
1326 if (!native_start()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001327 mStarted = false;
1328 Log.e(TAG, "native_start failed in startNavigating()");
Mike Lockwood0632ca72009-05-14 15:51:03 -04001329 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001330 }
1331
1332 // reset SV count to zero
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001333 updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, 0);
Mike Lockwood29c84342009-05-06 14:01:15 -04001334 mFixRequestTime = System.currentTimeMillis();
Mike Lockwood04598b62010-04-14 17:17:24 -04001335 if (!hasCapability(GPS_CAPABILITY_SCHEDULING)) {
1336 // set timer to give up if we do not receive a fix within NO_FIX_TIMEOUT
1337 // and our fix interval is not short
1338 if (mFixInterval >= NO_FIX_TIMEOUT) {
1339 mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
1340 SystemClock.elapsedRealtime() + NO_FIX_TIMEOUT, mTimeoutIntent);
1341 }
Mike Lockwood0632ca72009-05-14 15:51:03 -04001342 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001343 }
1344 }
1345
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001346 private void stopNavigating() {
Mike Lockwood29c84342009-05-06 14:01:15 -04001347 if (DEBUG) Log.d(TAG, "stopNavigating");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001348 if (mStarted) {
1349 mStarted = false;
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001350 mSingleShot = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001351 native_stop();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001352 mTimeToFirstFix = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001353 mLastFixTime = 0;
1354 mLocationFlags = LOCATION_INVALID;
1355
1356 // reset SV count to zero
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001357 updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001358 }
1359 }
1360
Mike Lockwood0632ca72009-05-14 15:51:03 -04001361 private void hibernate() {
1362 // stop GPS until our next fix interval arrives
1363 stopNavigating();
Mike Lockwood0632ca72009-05-14 15:51:03 -04001364 mAlarmManager.cancel(mTimeoutIntent);
1365 mAlarmManager.cancel(mWakeupIntent);
1366 long now = SystemClock.elapsedRealtime();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001367 mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, now + mFixInterval, mWakeupIntent);
Mike Lockwood04598b62010-04-14 17:17:24 -04001368 }
1369
1370 private boolean hasCapability(int capability) {
1371 return ((mEngineCapabilities & capability) != 0);
Mike Lockwood0632ca72009-05-14 15:51:03 -04001372 }
1373
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001374
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001375 /**
1376 * called from native code to update our position.
1377 */
1378 private void reportLocation(int flags, double latitude, double longitude, double altitude,
1379 float speed, float bearing, float accuracy, long timestamp) {
Mike Lockwood29c84342009-05-06 14:01:15 -04001380 if (VERBOSE) Log.v(TAG, "reportLocation lat: " + latitude + " long: " + longitude +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001381 " timestamp: " + timestamp);
1382
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001383 synchronized (mLocation) {
1384 mLocationFlags = flags;
1385 if ((flags & LOCATION_HAS_LAT_LONG) == LOCATION_HAS_LAT_LONG) {
1386 mLocation.setLatitude(latitude);
1387 mLocation.setLongitude(longitude);
1388 mLocation.setTime(timestamp);
Nick Pelly2eeeec22012-07-18 13:13:37 -07001389 // It would be nice to push the elapsed real-time timestamp
1390 // further down the stack, but this is still useful
Philip Milne41180122012-09-26 11:29:25 -07001391 mLocation.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001392 }
1393 if ((flags & LOCATION_HAS_ALTITUDE) == LOCATION_HAS_ALTITUDE) {
1394 mLocation.setAltitude(altitude);
1395 } else {
1396 mLocation.removeAltitude();
1397 }
1398 if ((flags & LOCATION_HAS_SPEED) == LOCATION_HAS_SPEED) {
1399 mLocation.setSpeed(speed);
1400 } else {
1401 mLocation.removeSpeed();
1402 }
1403 if ((flags & LOCATION_HAS_BEARING) == LOCATION_HAS_BEARING) {
1404 mLocation.setBearing(bearing);
1405 } else {
1406 mLocation.removeBearing();
1407 }
1408 if ((flags & LOCATION_HAS_ACCURACY) == LOCATION_HAS_ACCURACY) {
1409 mLocation.setAccuracy(accuracy);
1410 } else {
1411 mLocation.removeAccuracy();
1412 }
Sean Barbeauced2b2c2011-12-19 04:43:07 -05001413 mLocation.setExtras(mLocationExtras);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001414
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001415 try {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001416 mILocationManager.reportLocation(mLocation, false);
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001417 } catch (RemoteException e) {
1418 Log.e(TAG, "RemoteException calling reportLocation");
1419 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001420 }
1421
Hakan Gustavssonfa94ff02010-02-23 09:12:38 +01001422 mLastFixTime = System.currentTimeMillis();
1423 // report time to first fix
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001424 if (mTimeToFirstFix == 0 && (flags & LOCATION_HAS_LAT_LONG) == LOCATION_HAS_LAT_LONG) {
1425 mTimeToFirstFix = (int)(mLastFixTime - mFixRequestTime);
1426 if (DEBUG) Log.d(TAG, "TTFF: " + mTimeToFirstFix);
Hakan Gustavssonfa94ff02010-02-23 09:12:38 +01001427
1428 // notify status listeners
destradaaea8a8a62014-06-23 18:19:03 -07001429 mListenerHelper.onFirstFix(mTimeToFirstFix);
Hakan Gustavssonfa94ff02010-02-23 09:12:38 +01001430 }
1431
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001432 if (mSingleShot) {
1433 stopNavigating();
1434 }
1435
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001436 if (mStarted && mStatus != LocationProvider.AVAILABLE) {
Mike Lockwoodd53ba012010-04-15 20:41:26 -04001437 // we want to time out if we do not receive a fix
Mike Lockwoodb7be5442010-02-24 14:34:50 -05001438 // within the time out and we are requesting infrequent fixes
Mike Lockwood04598b62010-04-14 17:17:24 -04001439 if (!hasCapability(GPS_CAPABILITY_SCHEDULING) && mFixInterval < NO_FIX_TIMEOUT) {
Mike Lockwoodb7be5442010-02-24 14:34:50 -05001440 mAlarmManager.cancel(mTimeoutIntent);
1441 }
1442
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001443 // send an intent to notify that the GPS is receiving fixes.
Mike Lockwood00b74272010-03-26 10:41:48 -04001444 Intent intent = new Intent(LocationManager.GPS_FIX_CHANGE_ACTION);
1445 intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, true);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07001446 mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001447 updateStatus(LocationProvider.AVAILABLE, mSvCount);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001448 }
Mike Lockwood29c84342009-05-06 14:01:15 -04001449
Nick Pellyb041f232012-05-07 17:12:25 -07001450 if (!hasCapability(GPS_CAPABILITY_SCHEDULING) && mStarted &&
1451 mFixInterval > GPS_POLLING_THRESHOLD_INTERVAL) {
Mike Lockwoodd53ba012010-04-15 20:41:26 -04001452 if (DEBUG) Log.d(TAG, "got fix, hibernating");
Mike Lockwood0632ca72009-05-14 15:51:03 -04001453 hibernate();
Mike Lockwood29c84342009-05-06 14:01:15 -04001454 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001455 }
1456
1457 /**
1458 * called from native code to update our status
1459 */
1460 private void reportStatus(int status) {
Mike Lockwoodb8d90332010-10-18 17:59:48 -04001461 if (DEBUG) Log.v(TAG, "reportStatus status: " + status);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001462
destradaaea8a8a62014-06-23 18:19:03 -07001463 boolean wasNavigating = mNavigating;
1464 switch (status) {
1465 case GPS_STATUS_SESSION_BEGIN:
1466 mNavigating = true;
1467 mEngineOn = true;
1468 break;
1469 case GPS_STATUS_SESSION_END:
1470 mNavigating = false;
1471 break;
1472 case GPS_STATUS_ENGINE_ON:
1473 mEngineOn = true;
1474 break;
1475 case GPS_STATUS_ENGINE_OFF:
1476 mEngineOn = false;
1477 mNavigating = false;
1478 break;
1479 }
Mike Lockwooddbd6fd82009-12-07 18:43:36 -05001480
destradaaea8a8a62014-06-23 18:19:03 -07001481 if (wasNavigating != mNavigating) {
destradaa6568d702014-10-27 12:47:41 -07001482 mListenerHelper.onGpsEnabledChanged(mNavigating);
1483 mGpsMeasurementsProvider.onGpsEnabledChanged(mNavigating);
1484 mGpsNavigationMessageProvider.onGpsEnabledChanged(mNavigating);
Mike Lockwoodcf1d8cb2010-01-20 10:14:54 -05001485
destradaaea8a8a62014-06-23 18:19:03 -07001486 // send an intent to notify that the GPS has been enabled or disabled
1487 Intent intent = new Intent(LocationManager.GPS_ENABLED_CHANGE_ACTION);
1488 intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, mNavigating);
1489 mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001490 }
1491 }
1492
1493 /**
1494 * called from native code to update SV info
1495 */
1496 private void reportSvStatus() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001497 int svCount = native_read_sv_status(mSvs, mSnrs, mSvElevations, mSvAzimuths, mSvMasks);
destradaaea8a8a62014-06-23 18:19:03 -07001498 mListenerHelper.onSvStatusChanged(
1499 svCount,
1500 mSvs,
1501 mSnrs,
1502 mSvElevations,
1503 mSvAzimuths,
1504 mSvMasks[EPHEMERIS_MASK],
1505 mSvMasks[ALMANAC_MASK],
1506 mSvMasks[USED_FOR_FIX_MASK]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001507
Mike Lockwood29c84342009-05-06 14:01:15 -04001508 if (VERBOSE) {
1509 Log.v(TAG, "SV count: " + svCount +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001510 " ephemerisMask: " + Integer.toHexString(mSvMasks[EPHEMERIS_MASK]) +
1511 " almanacMask: " + Integer.toHexString(mSvMasks[ALMANAC_MASK]));
1512 for (int i = 0; i < svCount; i++) {
Mike Lockwood29c84342009-05-06 14:01:15 -04001513 Log.v(TAG, "sv: " + mSvs[i] +
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001514 " snr: " + mSnrs[i]/10 +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001515 " elev: " + mSvElevations[i] +
1516 " azimuth: " + mSvAzimuths[i] +
1517 ((mSvMasks[EPHEMERIS_MASK] & (1 << (mSvs[i] - 1))) == 0 ? " " : " E") +
1518 ((mSvMasks[ALMANAC_MASK] & (1 << (mSvs[i] - 1))) == 0 ? " " : " A") +
1519 ((mSvMasks[USED_FOR_FIX_MASK] & (1 << (mSvs[i] - 1))) == 0 ? "" : "U"));
1520 }
1521 }
1522
Kevin.KY Tsai0881f4f2010-05-21 15:10:39 -04001523 // return number of sets used in fix instead of total
1524 updateStatus(mStatus, Integer.bitCount(mSvMasks[USED_FOR_FIX_MASK]));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001525
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001526 if (mNavigating && mStatus == LocationProvider.AVAILABLE && mLastFixTime > 0 &&
Mike Lockwood04598b62010-04-14 17:17:24 -04001527 System.currentTimeMillis() - mLastFixTime > RECENT_FIX_TIMEOUT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001528 // send an intent to notify that the GPS is no longer receiving fixes.
Mike Lockwood00b74272010-03-26 10:41:48 -04001529 Intent intent = new Intent(LocationManager.GPS_FIX_CHANGE_ACTION);
1530 intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, false);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07001531 mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001532 updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, mSvCount);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001533 }
1534 }
Mike Lockwood58bda982009-04-14 16:25:07 -04001535
1536 /**
Mike Lockwoode3635c92009-05-11 08:38:02 -04001537 * called from native code to update AGPS status
Mike Lockwood58bda982009-04-14 16:25:07 -04001538 */
destradaa96a14702014-06-05 11:36:30 -07001539 private void reportAGpsStatus(int type, int status, byte[] ipaddr) {
Mike Lockwood58bda982009-04-14 16:25:07 -04001540 switch (status) {
Mike Lockwoode3635c92009-05-11 08:38:02 -04001541 case GPS_REQUEST_AGPS_DATA_CONN:
Mike Lockwoodb6e5fa82010-10-09 20:10:46 -04001542 if (DEBUG) Log.d(TAG, "GPS_REQUEST_AGPS_DATA_CONN");
destradaa931a37f2014-08-12 16:36:59 -07001543 Log.v(TAG, "Received SUPL IP addr[]: " + ipaddr);
Mike Lockwood2acfd342010-09-22 12:13:39 -04001544 // Set mAGpsDataConnectionState before calling startUsingNetworkFeature
1545 // to avoid a race condition with handleUpdateNetworkState()
1546 mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPENING;
1547 int result = mConnMgr.startUsingNetworkFeature(
Mike Lockwood58bda982009-04-14 16:25:07 -04001548 ConnectivityManager.TYPE_MOBILE, Phone.FEATURE_ENABLE_SUPL);
destradaa96a14702014-06-05 11:36:30 -07001549 if (ipaddr != null) {
1550 try {
1551 mAGpsDataConnectionIpAddr = InetAddress.getByAddress(ipaddr);
destradaa931a37f2014-08-12 16:36:59 -07001552 Log.v(TAG, "IP address converted to: " + mAGpsDataConnectionIpAddr);
destradaa96a14702014-06-05 11:36:30 -07001553 } catch (UnknownHostException e) {
1554 Log.e(TAG, "Bad IP Address: " + ipaddr, e);
1555 mAGpsDataConnectionIpAddr = null;
1556 }
1557 }
1558
Wink Savillea639b312012-07-10 12:37:54 -07001559 if (result == PhoneConstants.APN_ALREADY_ACTIVE) {
1560 if (DEBUG) Log.d(TAG, "PhoneConstants.APN_ALREADY_ACTIVE");
Mike Lockwoodb362a9a2009-06-22 16:20:39 -04001561 if (mAGpsApn != null) {
destradaa96a14702014-06-05 11:36:30 -07001562 setRouting();
1563 native_agps_data_conn_open(mAGpsApn, mApnIpType);
Mike Lockwoodb362a9a2009-06-22 16:20:39 -04001564 mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPEN;
1565 } else {
Wink Savillea639b312012-07-10 12:37:54 -07001566 Log.e(TAG, "mAGpsApn not set when receiving PhoneConstants.APN_ALREADY_ACTIVE");
Mike Lockwood2acfd342010-09-22 12:13:39 -04001567 mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED;
Mike Lockwoodb362a9a2009-06-22 16:20:39 -04001568 native_agps_data_conn_failed();
1569 }
Wink Savillea639b312012-07-10 12:37:54 -07001570 } else if (result == PhoneConstants.APN_REQUEST_STARTED) {
1571 if (DEBUG) Log.d(TAG, "PhoneConstants.APN_REQUEST_STARTED");
Mike Lockwood2acfd342010-09-22 12:13:39 -04001572 // Nothing to do here
Mike Lockwood58bda982009-04-14 16:25:07 -04001573 } else {
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001574 if (DEBUG) Log.d(TAG, "startUsingNetworkFeature failed, value is " +
1575 result);
Mike Lockwood2acfd342010-09-22 12:13:39 -04001576 mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED;
Mike Lockwoode3635c92009-05-11 08:38:02 -04001577 native_agps_data_conn_failed();
Mike Lockwood58bda982009-04-14 16:25:07 -04001578 }
1579 break;
Mike Lockwoode3635c92009-05-11 08:38:02 -04001580 case GPS_RELEASE_AGPS_DATA_CONN:
Mike Lockwoodb6e5fa82010-10-09 20:10:46 -04001581 if (DEBUG) Log.d(TAG, "GPS_RELEASE_AGPS_DATA_CONN");
Mike Lockwoode3635c92009-05-11 08:38:02 -04001582 if (mAGpsDataConnectionState != AGPS_DATA_CONNECTION_CLOSED) {
Mike Lockwood58bda982009-04-14 16:25:07 -04001583 mConnMgr.stopUsingNetworkFeature(
1584 ConnectivityManager.TYPE_MOBILE, Phone.FEATURE_ENABLE_SUPL);
Mike Lockwoode3635c92009-05-11 08:38:02 -04001585 native_agps_data_conn_closed();
1586 mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED;
destradaa96a14702014-06-05 11:36:30 -07001587 mAGpsDataConnectionIpAddr = null;
Mike Lockwood58bda982009-04-14 16:25:07 -04001588 }
1589 break;
Mike Lockwoode3635c92009-05-11 08:38:02 -04001590 case GPS_AGPS_DATA_CONNECTED:
Mike Lockwoodb6e5fa82010-10-09 20:10:46 -04001591 if (DEBUG) Log.d(TAG, "GPS_AGPS_DATA_CONNECTED");
Mike Lockwood58bda982009-04-14 16:25:07 -04001592 break;
Mike Lockwoode3635c92009-05-11 08:38:02 -04001593 case GPS_AGPS_DATA_CONN_DONE:
Mike Lockwoodb6e5fa82010-10-09 20:10:46 -04001594 if (DEBUG) Log.d(TAG, "GPS_AGPS_DATA_CONN_DONE");
Mike Lockwood58bda982009-04-14 16:25:07 -04001595 break;
Mike Lockwoode3635c92009-05-11 08:38:02 -04001596 case GPS_AGPS_DATA_CONN_FAILED:
Mike Lockwoodb6e5fa82010-10-09 20:10:46 -04001597 if (DEBUG) Log.d(TAG, "GPS_AGPS_DATA_CONN_FAILED");
Mike Lockwood58bda982009-04-14 16:25:07 -04001598 break;
destradaa931a37f2014-08-12 16:36:59 -07001599 default:
1600 Log.d(TAG, "Received Unknown AGPS status: " + status);
Mike Lockwood58bda982009-04-14 16:25:07 -04001601 }
1602 }
1603
Mike Lockwoodb16e7802009-08-06 09:26:02 -04001604 /**
1605 * called from native code to report NMEA data received
1606 */
Mike Lockwoodf602d362010-06-20 14:28:16 -07001607 private void reportNmea(long timestamp) {
destradaaea8a8a62014-06-23 18:19:03 -07001608 int length = native_read_nmea(mNmeaBuffer, mNmeaBuffer.length);
1609 String nmea = new String(mNmeaBuffer, 0 /* offset */, length);
1610 mListenerHelper.onNmeaReceived(timestamp, nmea);
1611 }
Mike Lockwoodb16e7802009-08-06 09:26:02 -04001612
destradaaea8a8a62014-06-23 18:19:03 -07001613 /**
destradaa4b3e3932014-07-21 18:01:47 -07001614 * called from native code - Gps measurements callback
destradaaea8a8a62014-06-23 18:19:03 -07001615 */
1616 private void reportMeasurementData(GpsMeasurementsEvent event) {
1617 mGpsMeasurementsProvider.onMeasurementsAvailable(event);
Mike Lockwoodb16e7802009-08-06 09:26:02 -04001618 }
1619
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001620 /**
destradaa4b3e3932014-07-21 18:01:47 -07001621 * called from native code - GPS navigation message callback
1622 */
1623 private void reportNavigationMessage(GpsNavigationMessageEvent event) {
1624 mGpsNavigationMessageProvider.onNavigationMessageAvailable(event);
1625 }
1626
1627 /**
Mike Lockwood04598b62010-04-14 17:17:24 -04001628 * called from native code to inform us what the GPS engine capabilities are
1629 */
1630 private void setEngineCapabilities(int capabilities) {
1631 mEngineCapabilities = capabilities;
Mike Lockwood9b9fb5c2011-06-29 15:09:40 -04001632
1633 if (!hasCapability(GPS_CAPABILITY_ON_DEMAND_TIME) && !mPeriodicTimeInjection) {
1634 mPeriodicTimeInjection = true;
1635 requestUtcTime();
1636 }
destradaa6568d702014-10-27 12:47:41 -07001637
1638 mGpsMeasurementsProvider.onCapabilitiesUpdated(
1639 (capabilities & GPS_CAPABILITY_MEASUREMENTS) == GPS_CAPABILITY_MEASUREMENTS);
1640 mGpsNavigationMessageProvider.onCapabilitiesUpdated(
1641 (capabilities & GPS_CAPABILITY_NAV_MESSAGES) == GPS_CAPABILITY_NAV_MESSAGES);
Mike Lockwood04598b62010-04-14 17:17:24 -04001642 }
1643
1644 /**
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001645 * called from native code to request XTRA data
1646 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001647 private void xtraDownloadRequest() {
Joe Onoratof5d95cb2010-01-07 21:48:32 -05001648 if (DEBUG) Log.d(TAG, "xtraDownloadRequest");
Mike Lockwood98e48692010-04-07 16:32:51 -04001649 sendMessage(DOWNLOAD_XTRA_DATA, 0, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001650 }
1651
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001652 /**
destradaa0682809a2013-08-12 18:50:30 -07001653 * Helper method to construct a location object.
1654 */
1655 private Location buildLocation(
1656 int flags,
1657 double latitude,
1658 double longitude,
1659 double altitude,
1660 float speed,
1661 float bearing,
1662 float accuracy,
1663 long timestamp) {
1664 Location location = new Location(LocationManager.GPS_PROVIDER);
1665 if((flags & LOCATION_HAS_LAT_LONG) == LOCATION_HAS_LAT_LONG) {
1666 location.setLatitude(latitude);
1667 location.setLongitude(longitude);
1668 location.setTime(timestamp);
1669 location.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());
1670 }
1671 if((flags & LOCATION_HAS_ALTITUDE) == LOCATION_HAS_ALTITUDE) {
1672 location.setAltitude(altitude);
1673 }
1674 if((flags & LOCATION_HAS_SPEED) == LOCATION_HAS_SPEED) {
1675 location.setSpeed(speed);
1676 }
1677 if((flags & LOCATION_HAS_BEARING) == LOCATION_HAS_BEARING) {
1678 location.setBearing(bearing);
1679 }
1680 if((flags & LOCATION_HAS_ACCURACY) == LOCATION_HAS_ACCURACY) {
1681 location.setAccuracy(accuracy);
1682 }
1683 return location;
1684 }
1685
1686 /**
1687 * Converts the GPS HAL status to the internal Geofence Hardware status.
1688 */
1689 private int getGeofenceStatus(int status) {
1690 switch(status) {
1691 case GPS_GEOFENCE_OPERATION_SUCCESS:
1692 return GeofenceHardware.GEOFENCE_SUCCESS;
1693 case GPS_GEOFENCE_ERROR_GENERIC:
1694 return GeofenceHardware.GEOFENCE_FAILURE;
1695 case GPS_GEOFENCE_ERROR_ID_EXISTS:
1696 return GeofenceHardware.GEOFENCE_ERROR_ID_EXISTS;
1697 case GPS_GEOFENCE_ERROR_INVALID_TRANSITION:
1698 return GeofenceHardware.GEOFENCE_ERROR_INVALID_TRANSITION;
1699 case GPS_GEOFENCE_ERROR_TOO_MANY_GEOFENCES:
1700 return GeofenceHardware.GEOFENCE_ERROR_TOO_MANY_GEOFENCES;
1701 case GPS_GEOFENCE_ERROR_ID_UNKNOWN:
1702 return GeofenceHardware.GEOFENCE_ERROR_ID_UNKNOWN;
1703 default:
1704 return -1;
1705 }
1706 }
1707
1708 /**
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001709 * Called from native to report GPS Geofence transition
1710 * All geofence callbacks are called on the same thread
1711 */
1712 private void reportGeofenceTransition(int geofenceId, int flags, double latitude,
1713 double longitude, double altitude, float speed, float bearing, float accuracy,
1714 long timestamp, int transition, long transitionTimestamp) {
1715 if (mGeofenceHardwareImpl == null) {
1716 mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
1717 }
destradaa0682809a2013-08-12 18:50:30 -07001718 Location location = buildLocation(
1719 flags,
1720 latitude,
1721 longitude,
1722 altitude,
1723 speed,
1724 bearing,
1725 accuracy,
1726 timestamp);
1727 mGeofenceHardwareImpl.reportGeofenceTransition(
1728 geofenceId,
1729 location,
1730 transition,
1731 transitionTimestamp,
1732 GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE,
1733 FusedBatchOptions.SourceTechnologies.GNSS);
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001734 }
1735
1736 /**
1737 * called from native code to report GPS status change.
1738 */
1739 private void reportGeofenceStatus(int status, int flags, double latitude,
1740 double longitude, double altitude, float speed, float bearing, float accuracy,
1741 long timestamp) {
1742 if (mGeofenceHardwareImpl == null) {
1743 mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
1744 }
destradaa0682809a2013-08-12 18:50:30 -07001745 Location location = buildLocation(
1746 flags,
1747 latitude,
1748 longitude,
1749 altitude,
1750 speed,
1751 bearing,
1752 accuracy,
1753 timestamp);
1754 int monitorStatus = GeofenceHardware.MONITOR_CURRENTLY_UNAVAILABLE;
1755 if(status == GPS_GEOFENCE_AVAILABLE) {
1756 monitorStatus = GeofenceHardware.MONITOR_CURRENTLY_AVAILABLE;
1757 }
1758 mGeofenceHardwareImpl.reportGeofenceMonitorStatus(
1759 GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE,
1760 monitorStatus,
1761 location,
1762 FusedBatchOptions.SourceTechnologies.GNSS);
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001763 }
1764
1765 /**
1766 * called from native code - Geofence Add callback
1767 */
1768 private void reportGeofenceAddStatus(int geofenceId, int status) {
1769 if (mGeofenceHardwareImpl == null) {
1770 mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
1771 }
destradaa0682809a2013-08-12 18:50:30 -07001772 mGeofenceHardwareImpl.reportGeofenceAddStatus(geofenceId, getGeofenceStatus(status));
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001773 }
1774
1775 /**
1776 * called from native code - Geofence Remove callback
1777 */
1778 private void reportGeofenceRemoveStatus(int geofenceId, int status) {
1779 if (mGeofenceHardwareImpl == null) {
1780 mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
1781 }
destradaa0682809a2013-08-12 18:50:30 -07001782 mGeofenceHardwareImpl.reportGeofenceRemoveStatus(geofenceId, getGeofenceStatus(status));
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001783 }
1784
1785 /**
1786 * called from native code - Geofence Pause callback
1787 */
1788 private void reportGeofencePauseStatus(int geofenceId, int status) {
1789 if (mGeofenceHardwareImpl == null) {
1790 mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
1791 }
destradaa0682809a2013-08-12 18:50:30 -07001792 mGeofenceHardwareImpl.reportGeofencePauseStatus(geofenceId, getGeofenceStatus(status));
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001793 }
1794
1795 /**
1796 * called from native code - Geofence Resume callback
1797 */
1798 private void reportGeofenceResumeStatus(int geofenceId, int status) {
1799 if (mGeofenceHardwareImpl == null) {
1800 mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
1801 }
destradaa0682809a2013-08-12 18:50:30 -07001802 mGeofenceHardwareImpl.reportGeofenceResumeStatus(geofenceId, getGeofenceStatus(status));
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001803 }
1804
Danke Xie22d1f9f2009-08-18 18:28:45 -04001805 //=============================================================
1806 // NI Client support
Miguel Torroja1e84da82010-07-27 07:02:24 +02001807 //=============================================================
Danke Xie22d1f9f2009-08-18 18:28:45 -04001808 private final INetInitiatedListener mNetInitiatedListener = new INetInitiatedListener.Stub() {
Miguel Torroja1e84da82010-07-27 07:02:24 +02001809 // Sends a response for an NI reqeust to HAL.
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001810 @Override
Miguel Torroja1e84da82010-07-27 07:02:24 +02001811 public boolean sendNiResponse(int notificationId, int userResponse)
1812 {
1813 // TODO Add Permission check
Danke Xie22d1f9f2009-08-18 18:28:45 -04001814
Miguel Torroja1e84da82010-07-27 07:02:24 +02001815 if (DEBUG) Log.d(TAG, "sendNiResponse, notifId: " + notificationId +
1816 ", response: " + userResponse);
1817 native_send_ni_response(notificationId, userResponse);
1818 return true;
1819 }
Danke Xie22d1f9f2009-08-18 18:28:45 -04001820 };
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001821
Danke Xie22d1f9f2009-08-18 18:28:45 -04001822 public INetInitiatedListener getNetInitiatedListener() {
1823 return mNetInitiatedListener;
1824 }
1825
1826 // Called by JNI function to report an NI request.
Miguel Torroja1e84da82010-07-27 07:02:24 +02001827 public void reportNiNotification(
1828 int notificationId,
1829 int niType,
1830 int notifyFlags,
1831 int timeout,
1832 int defaultResponse,
1833 String requestorId,
1834 String text,
1835 int requestorIdEncoding,
1836 int textEncoding,
1837 String extras // Encoded extra data
Danke Xie22d1f9f2009-08-18 18:28:45 -04001838 )
Miguel Torroja1e84da82010-07-27 07:02:24 +02001839 {
1840 Log.i(TAG, "reportNiNotification: entered");
1841 Log.i(TAG, "notificationId: " + notificationId +
1842 ", niType: " + niType +
1843 ", notifyFlags: " + notifyFlags +
1844 ", timeout: " + timeout +
1845 ", defaultResponse: " + defaultResponse);
1846
1847 Log.i(TAG, "requestorId: " + requestorId +
1848 ", text: " + text +
1849 ", requestorIdEncoding: " + requestorIdEncoding +
1850 ", textEncoding: " + textEncoding);
1851
1852 GpsNiNotification notification = new GpsNiNotification();
1853
1854 notification.notificationId = notificationId;
1855 notification.niType = niType;
1856 notification.needNotify = (notifyFlags & GpsNetInitiatedHandler.GPS_NI_NEED_NOTIFY) != 0;
1857 notification.needVerify = (notifyFlags & GpsNetInitiatedHandler.GPS_NI_NEED_VERIFY) != 0;
1858 notification.privacyOverride = (notifyFlags & GpsNetInitiatedHandler.GPS_NI_PRIVACY_OVERRIDE) != 0;
1859 notification.timeout = timeout;
1860 notification.defaultResponse = defaultResponse;
1861 notification.requestorId = requestorId;
1862 notification.text = text;
1863 notification.requestorIdEncoding = requestorIdEncoding;
1864 notification.textEncoding = textEncoding;
1865
1866 // Process extras, assuming the format is
1867 // one of more lines of "key = value"
1868 Bundle bundle = new Bundle();
1869
1870 if (extras == null) extras = "";
1871 Properties extraProp = new Properties();
1872
1873 try {
Jeff Sharkey104344e2011-07-10 14:20:41 -07001874 extraProp.load(new StringReader(extras));
Miguel Torroja1e84da82010-07-27 07:02:24 +02001875 }
1876 catch (IOException e)
1877 {
1878 Log.e(TAG, "reportNiNotification cannot parse extras data: " + extras);
1879 }
1880
1881 for (Entry<Object, Object> ent : extraProp.entrySet())
1882 {
1883 bundle.putString((String) ent.getKey(), (String) ent.getValue());
1884 }
1885
1886 notification.extras = bundle;
1887
1888 mNIHandler.handleNiNotification(notification);
1889 }
1890
1891 /**
1892 * Called from native code to request set id info.
1893 * We should be careful about receiving null string from the TelephonyManager,
1894 * because sending null String to JNI function would cause a crash.
1895 */
1896
1897 private void requestSetID(int flags) {
1898 TelephonyManager phone = (TelephonyManager)
1899 mContext.getSystemService(Context.TELEPHONY_SERVICE);
1900 int type = AGPS_SETID_TYPE_NONE;
1901 String data = "";
1902
1903 if ((flags & AGPS_RIL_REQUEST_SETID_IMSI) == AGPS_RIL_REQUEST_SETID_IMSI) {
1904 String data_temp = phone.getSubscriberId();
1905 if (data_temp == null) {
1906 // This means the framework does not have the SIM card ready.
1907 } else {
1908 // This means the framework has the SIM card.
1909 data = data_temp;
1910 type = AGPS_SETID_TYPE_IMSI;
1911 }
1912 }
1913 else if ((flags & AGPS_RIL_REQUEST_SETID_MSISDN) == AGPS_RIL_REQUEST_SETID_MSISDN) {
1914 String data_temp = phone.getLine1Number();
1915 if (data_temp == null) {
1916 // This means the framework does not have the SIM card ready.
1917 } else {
1918 // This means the framework has the SIM card.
1919 data = data_temp;
1920 type = AGPS_SETID_TYPE_MSISDN;
1921 }
1922 }
1923 native_agps_set_id(type, data);
1924 }
1925
1926 /**
Mike Lockwood9b9fb5c2011-06-29 15:09:40 -04001927 * Called from native code to request utc time info
1928 */
1929
1930 private void requestUtcTime() {
1931 sendMessage(INJECT_NTP_TIME, 0, null);
1932 }
1933
1934 /**
Miguel Torroja1e84da82010-07-27 07:02:24 +02001935 * Called from native code to request reference location info
1936 */
1937
1938 private void requestRefLocation(int flags) {
1939 TelephonyManager phone = (TelephonyManager)
1940 mContext.getSystemService(Context.TELEPHONY_SERVICE);
Victoria Leased50d0c32012-10-29 13:16:17 -07001941 final int phoneType = phone.getPhoneType();
1942 if (phoneType == TelephonyManager.PHONE_TYPE_GSM) {
Miguel Torroja1e84da82010-07-27 07:02:24 +02001943 GsmCellLocation gsm_cell = (GsmCellLocation) phone.getCellLocation();
Victoria Leased50d0c32012-10-29 13:16:17 -07001944 if ((gsm_cell != null) && (phone.getNetworkOperator() != null)
1945 && (phone.getNetworkOperator().length() > 3)) {
Miguel Torroja1e84da82010-07-27 07:02:24 +02001946 int type;
1947 int mcc = Integer.parseInt(phone.getNetworkOperator().substring(0,3));
1948 int mnc = Integer.parseInt(phone.getNetworkOperator().substring(3));
Mike Lockwoodedc0f3872010-10-22 09:16:17 -04001949 int networkType = phone.getNetworkType();
1950 if (networkType == TelephonyManager.NETWORK_TYPE_UMTS
1951 || networkType == TelephonyManager.NETWORK_TYPE_HSDPA
1952 || networkType == TelephonyManager.NETWORK_TYPE_HSUPA
Arun Ravindran58d46122012-07-30 17:50:21 +03001953 || networkType == TelephonyManager.NETWORK_TYPE_HSPA
1954 || networkType == TelephonyManager.NETWORK_TYPE_HSPAP) {
Miguel Torroja1e84da82010-07-27 07:02:24 +02001955 type = AGPS_REF_LOCATION_TYPE_UMTS_CELLID;
Mike Lockwoodedc0f3872010-10-22 09:16:17 -04001956 } else {
Miguel Torroja1e84da82010-07-27 07:02:24 +02001957 type = AGPS_REF_LOCATION_TYPE_GSM_CELLID;
Mike Lockwoodedc0f3872010-10-22 09:16:17 -04001958 }
Miguel Torroja1e84da82010-07-27 07:02:24 +02001959 native_agps_set_ref_location_cellid(type, mcc, mnc,
1960 gsm_cell.getLac(), gsm_cell.getCid());
Mike Lockwoodedc0f3872010-10-22 09:16:17 -04001961 } else {
Miguel Torroja1e84da82010-07-27 07:02:24 +02001962 Log.e(TAG,"Error getting cell location info.");
Mike Lockwoodedc0f3872010-10-22 09:16:17 -04001963 }
Victoria Leased50d0c32012-10-29 13:16:17 -07001964 } else if (phoneType == TelephonyManager.PHONE_TYPE_CDMA) {
1965 Log.e(TAG, "CDMA not supported.");
Mike Lockwoodedc0f3872010-10-22 09:16:17 -04001966 }
Miguel Torroja1e84da82010-07-27 07:02:24 +02001967 }
Danke Xie22d1f9f2009-08-18 18:28:45 -04001968
Mike Lockwood98e48692010-04-07 16:32:51 -04001969 private void sendMessage(int message, int arg, Object obj) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001970 // hold a wake lock until this message is delivered
Jeff Brown028872f2012-08-25 13:07:01 -07001971 // note that this assumes the message will not be removed from the queue before
1972 // it is handled (otherwise the wake lock would be leaked).
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001973 mWakeLock.acquire();
1974 mHandler.obtainMessage(message, arg, 1, obj).sendToTarget();
Mike Lockwood98e48692010-04-07 16:32:51 -04001975 }
1976
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001977 private final class ProviderHandler extends Handler {
Victoria Lease5cd731a2012-12-19 15:04:21 -08001978 public ProviderHandler(Looper looper) {
1979 super(looper, null, true /*async*/);
Jeff Brown028872f2012-08-25 13:07:01 -07001980 }
1981
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001982 @Override
Mike Lockwood4a7b65e2010-10-25 16:35:55 -04001983 public void handleMessage(Message msg) {
Mike Lockwood98e48692010-04-07 16:32:51 -04001984 int message = msg.what;
1985 switch (message) {
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001986 case ENABLE:
1987 if (msg.arg1 == 1) {
1988 handleEnable();
1989 } else {
1990 handleDisable();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001991 }
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001992 break;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001993 case SET_REQUEST:
1994 GpsRequest gpsRequest = (GpsRequest) msg.obj;
1995 handleSetRequest(gpsRequest.request, gpsRequest.source);
Mike Lockwood03ca2162010-04-01 08:10:09 -07001996 break;
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001997 case UPDATE_NETWORK_STATE:
1998 handleUpdateNetworkState(msg.arg1, (NetworkInfo)msg.obj);
1999 break;
2000 case INJECT_NTP_TIME:
2001 handleInjectNtpTime();
2002 break;
2003 case DOWNLOAD_XTRA_DATA:
Mike Lockwood1a1cd3a2010-08-17 07:42:54 -04002004 if (mSupportsXtra) {
Mike Lockwood62a8fc12010-03-22 14:23:26 -04002005 handleDownloadXtraData();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002006 }
Mike Lockwood62a8fc12010-03-22 14:23:26 -04002007 break;
Kevin Tang40e1baf2012-01-10 14:32:44 -08002008 case INJECT_NTP_TIME_FINISHED:
2009 mInjectNtpTimePending = STATE_IDLE;
2010 break;
2011 case DOWNLOAD_XTRA_DATA_FINISHED:
2012 mDownloadXtraDataPending = STATE_IDLE;
2013 break;
Mike Lockwood62a8fc12010-03-22 14:23:26 -04002014 case UPDATE_LOCATION:
2015 handleUpdateLocation((Location)msg.obj);
2016 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002017 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002018 if (msg.arg2 == 1) {
2019 // wakelock was taken for this message, release it
2020 mWakeLock.release();
Mike Lockwood98e48692010-04-07 16:32:51 -04002021 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002022 }
Mike Lockwood62a8fc12010-03-22 14:23:26 -04002023 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002024
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002025 private final class NetworkLocationListener implements LocationListener {
2026 @Override
2027 public void onLocationChanged(Location location) {
2028 // this callback happens on mHandler looper
2029 if (LocationManager.NETWORK_PROVIDER.equals(location.getProvider())) {
2030 handleUpdateLocation(location);
2031 }
2032 }
2033 @Override
2034 public void onStatusChanged(String provider, int status, Bundle extras) { }
2035 @Override
2036 public void onProviderEnabled(String provider) { }
2037 @Override
2038 public void onProviderDisabled(String provider) { }
2039 }
2040
Kevin Tanga5fe6b22011-06-05 14:25:16 -07002041 private String getSelectedApn() {
2042 Uri uri = Uri.parse("content://telephony/carriers/preferapn");
destradaa96a14702014-06-05 11:36:30 -07002043 Cursor cursor = null;
2044 try {
2045 cursor = mContext.getContentResolver().query(
2046 uri,
2047 new String[] { "apn" },
2048 null /* selection */,
2049 null /* selectionArgs */,
2050 Carriers.DEFAULT_SORT_ORDER);
2051 if (cursor != null && cursor.moveToFirst()) {
2052 return cursor.getString(0);
2053 } else {
2054 Log.e(TAG, "No APN found to select.");
2055 }
2056 } catch (Exception e) {
destradaaea8a8a62014-06-23 18:19:03 -07002057 Log.e(TAG, "Error encountered on selecting the APN.", e);
destradaa96a14702014-06-05 11:36:30 -07002058 } finally {
2059 if (cursor != null) {
Kevin Tanga5fe6b22011-06-05 14:25:16 -07002060 cursor.close();
2061 }
2062 }
destradaa96a14702014-06-05 11:36:30 -07002063
2064 return null;
2065 }
2066
2067 private int getApnIpType(String apn) {
2068 if (apn == null) {
2069 return APN_INVALID;
2070 }
2071
2072 // look for cached data to use
2073 if (apn.equals(mAGpsApn) && mApnIpType != APN_INVALID) {
2074 return mApnIpType;
2075 }
2076
2077 String selection = String.format("current = 1 and apn = '%s' and carrier_enabled = 1", apn);
2078 Cursor cursor = null;
2079 try {
2080 cursor = mContext.getContentResolver().query(
2081 Carriers.CONTENT_URI,
2082 new String[] { Carriers.PROTOCOL },
2083 selection,
2084 null,
2085 Carriers.DEFAULT_SORT_ORDER);
2086
2087 if (null != cursor && cursor.moveToFirst()) {
2088 return translateToApnIpType(cursor.getString(0), apn);
2089 } else {
2090 Log.e(TAG, "No entry found in query for APN: " + apn);
2091 }
2092 } catch (Exception e) {
2093 Log.e(TAG, "Error encountered on APN query for: " + apn, e);
2094 } finally {
2095 if (cursor != null) {
2096 cursor.close();
2097 }
2098 }
2099
2100 return APN_INVALID;
2101 }
2102
2103 private int translateToApnIpType(String ipProtocol, String apn) {
2104 if ("IP".equals(ipProtocol)) {
2105 return APN_IPV4;
2106 }
2107 if ("IPV6".equals(ipProtocol)) {
2108 return APN_IPV6;
2109 }
2110 if ("IPV4V6".equals(ipProtocol)) {
2111 return APN_IPV4V6;
2112 }
2113
2114 // we hit the default case so the ipProtocol is not recognized
2115 String message = String.format("Unknown IP Protocol: %s, for APN: %s", ipProtocol, apn);
2116 Log.e(TAG, message);
2117 return APN_INVALID;
2118 }
2119
2120 private void setRouting() {
2121 if (mAGpsDataConnectionIpAddr == null) {
2122 return;
2123 }
2124
2125 boolean result = mConnMgr.requestRouteToHostAddress(
2126 ConnectivityManager.TYPE_MOBILE_SUPL,
2127 mAGpsDataConnectionIpAddr);
2128
2129 if (!result) {
2130 Log.e(TAG, "Error requesting route to host: " + mAGpsDataConnectionIpAddr);
2131 } else if (DEBUG) {
2132 Log.d(TAG, "Successfully requested route to host: " + mAGpsDataConnectionIpAddr);
2133 }
Kevin Tanga5fe6b22011-06-05 14:25:16 -07002134 }
2135
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002136 @Override
2137 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
2138 StringBuilder s = new StringBuilder();
2139 s.append(" mFixInterval=").append(mFixInterval).append("\n");
David Christied4edf4c2014-08-12 15:22:27 -07002140 s.append(" mDisableGps (battery saver mode)=").append(mDisableGps).append("\n");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002141 s.append(" mEngineCapabilities=0x").append(Integer.toHexString(mEngineCapabilities)).append(" (");
2142 if (hasCapability(GPS_CAPABILITY_SCHEDULING)) s.append("SCHED ");
2143 if (hasCapability(GPS_CAPABILITY_MSB)) s.append("MSB ");
2144 if (hasCapability(GPS_CAPABILITY_MSA)) s.append("MSA ");
2145 if (hasCapability(GPS_CAPABILITY_SINGLE_SHOT)) s.append("SINGLE_SHOT ");
2146 if (hasCapability(GPS_CAPABILITY_ON_DEMAND_TIME)) s.append("ON_DEMAND_TIME ");
2147 s.append(")\n");
2148
2149 s.append(native_get_internal_state());
2150 pw.append(s);
2151 }
2152
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002153 // for GPS SV statistics
2154 private static final int MAX_SVS = 32;
2155 private static final int EPHEMERIS_MASK = 0;
2156 private static final int ALMANAC_MASK = 1;
2157 private static final int USED_FOR_FIX_MASK = 2;
2158
2159 // preallocated arrays, to avoid memory allocation in reportStatus()
2160 private int mSvs[] = new int[MAX_SVS];
2161 private float mSnrs[] = new float[MAX_SVS];
2162 private float mSvElevations[] = new float[MAX_SVS];
2163 private float mSvAzimuths[] = new float[MAX_SVS];
2164 private int mSvMasks[] = new int[3];
2165 private int mSvCount;
Mike Lockwoodb16e7802009-08-06 09:26:02 -04002166 // preallocated to avoid memory allocation in reportNmea()
2167 private byte[] mNmeaBuffer = new byte[120];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002168
2169 static { class_init_native(); }
2170 private static native void class_init_native();
2171 private static native boolean native_is_supported();
2172
2173 private native boolean native_init();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002174 private native void native_cleanup();
Mike Lockwood04598b62010-04-14 17:17:24 -04002175 private native boolean native_set_position_mode(int mode, int recurrence, int min_interval,
2176 int preferred_accuracy, int preferred_time);
2177 private native boolean native_start();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002178 private native boolean native_stop();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002179 private native void native_delete_aiding_data(int flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002180 // returns number of SVs
2181 // mask[0] is ephemeris mask and mask[1] is almanac mask
2182 private native int native_read_sv_status(int[] svs, float[] snrs,
2183 float[] elevations, float[] azimuths, int[] masks);
Mike Lockwoodf602d362010-06-20 14:28:16 -07002184 private native int native_read_nmea(byte[] buffer, int bufferSize);
Mike Lockwoodd26ce0d2009-06-11 12:25:46 -04002185 private native void native_inject_location(double latitude, double longitude, float accuracy);
2186
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -06002187 // XTRA Support
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002188 private native void native_inject_time(long time, long timeReference, int uncertainty);
2189 private native boolean native_supports_xtra();
2190 private native void native_inject_xtra_data(byte[] data, int length);
The Android Open Source Project10592532009-03-18 17:39:46 -07002191
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -06002192 // DEBUG Support
2193 private native String native_get_internal_state();
2194
2195 // AGPS Support
destradaa96a14702014-06-05 11:36:30 -07002196 private native void native_agps_data_conn_open(String apn, int apnIpType);
Mike Lockwoode3635c92009-05-11 08:38:02 -04002197 private native void native_agps_data_conn_closed();
2198 private native void native_agps_data_conn_failed();
Miguel Torroja1e84da82010-07-27 07:02:24 +02002199 private native void native_agps_ni_message(byte [] msg, int length);
Mike Lockwooda9e54612009-06-19 14:54:42 -04002200 private native void native_set_agps_server(int type, String hostname, int port);
Danke Xie22d1f9f2009-08-18 18:28:45 -04002201
2202 // Network-initiated (NI) Support
2203 private native void native_send_ni_response(int notificationId, int userResponse);
Miguel Torroja1e84da82010-07-27 07:02:24 +02002204
2205 // AGPS ril suport
2206 private native void native_agps_set_ref_location_cellid(int type, int mcc, int mnc,
2207 int lac, int cid);
2208 private native void native_agps_set_id(int type, String setid);
Mike Lockwood50130bb2010-10-11 06:22:50 -04002209
2210 private native void native_update_network_state(boolean connected, int type,
Kevin Tanga5fe6b22011-06-05 14:25:16 -07002211 boolean roaming, boolean available, String extraInfo, String defaultAPN);
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07002212
2213 // Hardware Geofence support.
2214 private static native boolean native_is_geofence_supported();
2215 private static native boolean native_add_geofence(int geofenceId, double latitude,
2216 double longitude, double radius, int lastTransition,int monitorTransitions,
2217 int notificationResponsivenes, int unknownTimer);
2218 private static native boolean native_remove_geofence(int geofenceId);
2219 private static native boolean native_resume_geofence(int geofenceId, int transitions);
2220 private static native boolean native_pause_geofence(int geofenceId);
destradaaea8a8a62014-06-23 18:19:03 -07002221
2222 // Gps Hal measurements support.
2223 private static native boolean native_is_measurement_supported();
destradaa4b3e3932014-07-21 18:01:47 -07002224 private native boolean native_start_measurement_collection();
2225 private native boolean native_stop_measurement_collection();
2226
2227 // Gps Navigation message support.
2228 private static native boolean native_is_navigation_message_supported();
2229 private native boolean native_start_navigation_message_collection();
2230 private native boolean native_stop_navigation_message_collection();
Tsuwei Chen52617bb2014-08-25 11:49:11 -07002231
2232 // GNSS Configuration
2233 private static native void native_configuration_update(String configData);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002234}
David Christied4edf4c2014-08-12 15:22:27 -07002235