blob: 7c41abbc33409d85e53807941caa1711e6f1a135 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Mike Lockwood00b74272010-03-26 10:41:48 -040017package com.android.server.location;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080018
destradaaea8a8a62014-06-23 18:19:03 -070019import com.android.internal.app.IAppOpsService;
20import com.android.internal.app.IBatteryStats;
21import com.android.internal.location.GpsNetInitiatedHandler;
22import com.android.internal.location.GpsNetInitiatedHandler.GpsNiNotification;
23import com.android.internal.location.ProviderProperties;
24import com.android.internal.location.ProviderRequest;
25import com.android.internal.telephony.Phone;
26import com.android.internal.telephony.PhoneConstants;
27
Mike Lockwood29c84342009-05-06 14:01:15 -040028import android.app.AlarmManager;
Dianne Hackborna06de0f2012-12-11 16:34:47 -080029import android.app.AppOpsManager;
Mike Lockwood29c84342009-05-06 14:01:15 -040030import android.app.PendingIntent;
The Android Open Source Project10592532009-03-18 17:39:46 -070031import android.content.BroadcastReceiver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080032import android.content.Context;
33import android.content.Intent;
The Android Open Source Project10592532009-03-18 17:39:46 -070034import android.content.IntentFilter;
Kevin Tanga5fe6b22011-06-05 14:25:16 -070035import android.database.Cursor;
destradaa0682809a2013-08-12 18:50:30 -070036import android.hardware.location.GeofenceHardware;
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -070037import android.hardware.location.GeofenceHardwareImpl;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080038import android.location.Criteria;
destradaa0682809a2013-08-12 18:50:30 -070039import android.location.FusedBatchOptions;
destradaaea8a8a62014-06-23 18:19:03 -070040import android.location.GpsMeasurementsEvent;
destradaa4b3e3932014-07-21 18:01:47 -070041import android.location.GpsNavigationMessageEvent;
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -070042import android.location.IGpsGeofenceHardware;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080043import android.location.IGpsStatusListener;
Mike Lockwood15e3d0f2009-05-01 07:53:28 -040044import android.location.IGpsStatusProvider;
Mike Lockwood4e50b782009-04-03 08:24:43 -070045import android.location.ILocationManager;
Danke Xie22d1f9f2009-08-18 18:28:45 -040046import android.location.INetInitiatedListener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080047import android.location.Location;
Nick Pelly6fa9ad42012-07-16 12:18:23 -070048import android.location.LocationListener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080049import android.location.LocationManager;
50import android.location.LocationProvider;
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -070051import android.location.LocationRequest;
Mike Lockwood58bda982009-04-14 16:25:07 -040052import android.net.ConnectivityManager;
Mike Lockwood03d24672009-10-08 15:45:03 -040053import android.net.NetworkInfo;
Kevin Tanga5fe6b22011-06-05 14:25:16 -070054import android.net.Uri;
Kevin Tang40e1baf2012-01-10 14:32:44 -080055import android.os.AsyncTask;
Dianne Hackborn91268cf2013-06-13 19:06:50 -070056import android.os.BatteryStats;
Mike Lockwood63aa5a62010-04-14 19:21:31 -040057import android.os.Binder;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080058import android.os.Bundle;
Mike Lockwood62a8fc12010-03-22 14:23:26 -040059import android.os.Handler;
Victoria Lease5cd731a2012-12-19 15:04:21 -080060import android.os.Looper;
Mike Lockwood62a8fc12010-03-22 14:23:26 -040061import android.os.Message;
Mike Lockwood0528b9b2009-05-07 10:12:54 -040062import android.os.PowerManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080063import android.os.RemoteException;
Mike Lockwood2f82c4e2009-04-17 08:24:10 -040064import android.os.ServiceManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080065import android.os.SystemClock;
Colin Cross7c030ed2014-01-28 09:33:53 -080066import android.os.SystemProperties;
Dianne Hackborn5ac72a22012-08-29 18:32:08 -070067import android.os.UserHandle;
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -070068import android.os.WorkSource;
Mike Lockwoodbcab8df2009-06-25 16:39:09 -040069import android.provider.Settings;
Kevin Tanga5fe6b22011-06-05 14:25:16 -070070import android.provider.Telephony.Carriers;
Miguel Torroja1e84da82010-07-27 07:02:24 +020071import android.provider.Telephony.Sms.Intents;
Jake Hambyb49a73d2011-03-15 20:09:46 -070072import android.telephony.SmsMessage;
Wink Savillea374c3d2014-11-11 11:48:04 -080073import android.telephony.SubscriptionManager;
Wink Savilled09c4ca2014-11-22 10:08:16 -080074import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
Miguel Torroja1e84da82010-07-27 07:02:24 +020075import android.telephony.TelephonyManager;
76import android.telephony.gsm.GsmCellLocation;
Colin Cross7c030ed2014-01-28 09:33:53 -080077import android.text.TextUtils;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080078import android.util.Log;
Jeff Sharkey104344e2011-07-10 14:20:41 -070079import android.util.NtpTrustedTime;
Dianne Hackborna06de0f2012-12-11 16:34:47 -080080
Tsuwei Chen52617bb2014-08-25 11:49:11 -070081import java.io.ByteArrayOutputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080082import java.io.File;
Nick Pelly6fa9ad42012-07-16 12:18:23 -070083import java.io.FileDescriptor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080084import java.io.FileInputStream;
85import java.io.IOException;
Nick Pelly6fa9ad42012-07-16 12:18:23 -070086import java.io.PrintWriter;
Jeff Sharkey104344e2011-07-10 14:20:41 -070087import java.io.StringReader;
destradaaea8a8a62014-06-23 18:19:03 -070088import java.net.InetAddress;
89import java.net.UnknownHostException;
Mike Lockwoodf1218be2010-01-29 09:20:06 -050090import java.util.Date;
Danke Xie22d1f9f2009-08-18 18:28:45 -040091import java.util.Map.Entry;
Jake Hambyb49a73d2011-03-15 20:09:46 -070092import java.util.Properties;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080093
Colin Cross7c030ed2014-01-28 09:33:53 -080094import libcore.io.IoUtils;
95
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080096/**
97 * A GPS implementation of LocationProvider used by LocationManager.
98 *
99 * {@hide}
100 */
Mike Lockwood89096312010-03-24 10:14:55 -0400101public class GpsLocationProvider implements LocationProviderInterface {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800102
103 private static final String TAG = "GpsLocationProvider";
Mike Lockwood29c84342009-05-06 14:01:15 -0400104
Brian Muramatsu1715cb32012-08-08 17:32:21 -0700105 private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
106 private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400107
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700108 private static final ProviderProperties PROPERTIES = new ProviderProperties(
109 true, true, false, false, true, true, true,
110 Criteria.POWER_HIGH, Criteria.ACCURACY_FINE);
111
The Android Open Source Project10592532009-03-18 17:39:46 -0700112 // these need to match GpsPositionMode enum in gps.h
113 private static final int GPS_POSITION_MODE_STANDALONE = 0;
114 private static final int GPS_POSITION_MODE_MS_BASED = 1;
115 private static final int GPS_POSITION_MODE_MS_ASSISTED = 2;
116
Mike Lockwood04598b62010-04-14 17:17:24 -0400117 // these need to match GpsPositionRecurrence enum in gps.h
118 private static final int GPS_POSITION_RECURRENCE_PERIODIC = 0;
119 private static final int GPS_POSITION_RECURRENCE_SINGLE = 1;
120
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800121 // these need to match GpsStatusValue defines in gps.h
122 private static final int GPS_STATUS_NONE = 0;
123 private static final int GPS_STATUS_SESSION_BEGIN = 1;
124 private static final int GPS_STATUS_SESSION_END = 2;
125 private static final int GPS_STATUS_ENGINE_ON = 3;
126 private static final int GPS_STATUS_ENGINE_OFF = 4;
127
Mike Lockwoode3635c92009-05-11 08:38:02 -0400128 // these need to match GpsApgsStatusValue defines in gps.h
129 /** AGPS status event values. */
130 private static final int GPS_REQUEST_AGPS_DATA_CONN = 1;
131 private static final int GPS_RELEASE_AGPS_DATA_CONN = 2;
132 private static final int GPS_AGPS_DATA_CONNECTED = 3;
133 private static final int GPS_AGPS_DATA_CONN_DONE = 4;
134 private static final int GPS_AGPS_DATA_CONN_FAILED = 5;
Mike Lockwood58bda982009-04-14 16:25:07 -0400135
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800136 // these need to match GpsLocationFlags enum in gps.h
137 private static final int LOCATION_INVALID = 0;
138 private static final int LOCATION_HAS_LAT_LONG = 1;
139 private static final int LOCATION_HAS_ALTITUDE = 2;
140 private static final int LOCATION_HAS_SPEED = 4;
141 private static final int LOCATION_HAS_BEARING = 8;
142 private static final int LOCATION_HAS_ACCURACY = 16;
Mike Lockwoode3635c92009-05-11 08:38:02 -0400143
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700144 // IMPORTANT - the GPS_DELETE_* symbols here must match constants in gps.h
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800145 private static final int GPS_DELETE_EPHEMERIS = 0x0001;
146 private static final int GPS_DELETE_ALMANAC = 0x0002;
147 private static final int GPS_DELETE_POSITION = 0x0004;
148 private static final int GPS_DELETE_TIME = 0x0008;
149 private static final int GPS_DELETE_IONO = 0x0010;
150 private static final int GPS_DELETE_UTC = 0x0020;
151 private static final int GPS_DELETE_HEALTH = 0x0040;
152 private static final int GPS_DELETE_SVDIR = 0x0080;
153 private static final int GPS_DELETE_SVSTEER = 0x0100;
154 private static final int GPS_DELETE_SADATA = 0x0200;
155 private static final int GPS_DELETE_RTI = 0x0400;
156 private static final int GPS_DELETE_CELLDB_INFO = 0x8000;
157 private static final int GPS_DELETE_ALL = 0xFFFF;
158
Mike Lockwood04598b62010-04-14 17:17:24 -0400159 // The GPS_CAPABILITY_* flags must match the values in gps.h
160 private static final int GPS_CAPABILITY_SCHEDULING = 0x0000001;
161 private static final int GPS_CAPABILITY_MSB = 0x0000002;
162 private static final int GPS_CAPABILITY_MSA = 0x0000004;
163 private static final int GPS_CAPABILITY_SINGLE_SHOT = 0x0000008;
Mike Lockwood9b9fb5c2011-06-29 15:09:40 -0400164 private static final int GPS_CAPABILITY_ON_DEMAND_TIME = 0x0000010;
destradaa6568d702014-10-27 12:47:41 -0700165 private static final int GPS_CAPABILITY_GEOFENCING = 0x0000020;
166 private static final int GPS_CAPABILITY_MEASUREMENTS = 0x0000040;
167 private static final int GPS_CAPABILITY_NAV_MESSAGES = 0x0000080;
Mike Lockwood04598b62010-04-14 17:17:24 -0400168
Tsuwei Chen462bcd82014-09-17 12:28:49 -0700169 // The AGPS SUPL mode
170 private static final int AGPS_SUPL_MODE_MSA = 0x02;
171 private static final int AGPS_SUPL_MODE_MSB = 0x01;
172
Mike Lockwoode3635c92009-05-11 08:38:02 -0400173 // these need to match AGpsType enum in gps.h
174 private static final int AGPS_TYPE_SUPL = 1;
175 private static final int AGPS_TYPE_C2K = 2;
176
destradaa96a14702014-06-05 11:36:30 -0700177 // these must match the definitions in gps.h
178 private static final int APN_INVALID = 0;
179 private static final int APN_IPV4 = 1;
180 private static final int APN_IPV6 = 2;
181 private static final int APN_IPV4V6 = 3;
182
Mike Lockwoode3635c92009-05-11 08:38:02 -0400183 // for mAGpsDataConnectionState
184 private static final int AGPS_DATA_CONNECTION_CLOSED = 0;
185 private static final int AGPS_DATA_CONNECTION_OPENING = 1;
186 private static final int AGPS_DATA_CONNECTION_OPEN = 2;
Mike Lockwood58bda982009-04-14 16:25:07 -0400187
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400188 // Handler messages
189 private static final int CHECK_LOCATION = 1;
190 private static final int ENABLE = 2;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700191 private static final int SET_REQUEST = 3;
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400192 private static final int UPDATE_NETWORK_STATE = 4;
193 private static final int INJECT_NTP_TIME = 5;
194 private static final int DOWNLOAD_XTRA_DATA = 6;
195 private static final int UPDATE_LOCATION = 7;
196 private static final int ADD_LISTENER = 8;
197 private static final int REMOVE_LISTENER = 9;
Kevin Tang40e1baf2012-01-10 14:32:44 -0800198 private static final int INJECT_NTP_TIME_FINISHED = 10;
199 private static final int DOWNLOAD_XTRA_DATA_FINISHED = 11;
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400200
Miguel Torroja1e84da82010-07-27 07:02:24 +0200201 // Request setid
202 private static final int AGPS_RIL_REQUEST_SETID_IMSI = 1;
203 private static final int AGPS_RIL_REQUEST_SETID_MSISDN = 2;
204
205 // Request ref location
206 private static final int AGPS_RIL_REQUEST_REFLOC_CELLID = 1;
207 private static final int AGPS_RIL_REQUEST_REFLOC_MAC = 2;
208
209 // ref. location info
210 private static final int AGPS_REF_LOCATION_TYPE_GSM_CELLID = 1;
211 private static final int AGPS_REF_LOCATION_TYPE_UMTS_CELLID = 2;
212 private static final int AGPS_REG_LOCATION_TYPE_MAC = 3;
213
214 // set id info
215 private static final int AGPS_SETID_TYPE_NONE = 0;
216 private static final int AGPS_SETID_TYPE_IMSI = 1;
217 private static final int AGPS_SETID_TYPE_MSISDN = 2;
218
Colin Cross7c030ed2014-01-28 09:33:53 -0800219 private static final String PROPERTIES_FILE_PREFIX = "/etc/gps";
220 private static final String PROPERTIES_FILE_SUFFIX = ".conf";
221 private static final String DEFAULT_PROPERTIES_FILE = PROPERTIES_FILE_PREFIX + PROPERTIES_FILE_SUFFIX;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800222
destradaa0682809a2013-08-12 18:50:30 -0700223 private static final int GPS_GEOFENCE_UNAVAILABLE = 1<<0L;
224 private static final int GPS_GEOFENCE_AVAILABLE = 1<<1L;
225
226 // GPS Geofence errors. Should match gps.h constants.
227 private static final int GPS_GEOFENCE_OPERATION_SUCCESS = 0;
228 private static final int GPS_GEOFENCE_ERROR_TOO_MANY_GEOFENCES = 100;
229 private static final int GPS_GEOFENCE_ERROR_ID_EXISTS = -101;
230 private static final int GPS_GEOFENCE_ERROR_ID_UNKNOWN = -102;
231 private static final int GPS_GEOFENCE_ERROR_INVALID_TRANSITION = -103;
232 private static final int GPS_GEOFENCE_ERROR_GENERIC = -149;
233
Tsuwei Chen678c13c2014-09-22 17:48:41 -0700234 // TCP/IP constants.
235 // Valid TCP/UDP port range is (0, 65535].
236 private static final int TCP_MIN_PORT = 0;
237 private static final int TCP_MAX_PORT = 0xffff;
238
David Christied4edf4c2014-08-12 15:22:27 -0700239 // Value of batterySaverGpsMode such that GPS isn't affected by battery saver mode.
240 private static final int BATTERY_SAVER_MODE_NO_CHANGE = 0;
241 // Value of batterySaverGpsMode such that GPS is disabled when battery saver mode
242 // is enabled and the screen is off.
243 private static final int BATTERY_SAVER_MODE_DISABLED_WHEN_SCREEN_OFF = 1;
244 // Secure setting for GPS behavior when battery saver mode is on.
245 private static final String BATTERY_SAVER_GPS_MODE = "batterySaverGpsMode";
246
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700247 /** simpler wrapper for ProviderRequest + Worksource */
248 private static class GpsRequest {
249 public ProviderRequest request;
250 public WorkSource source;
251 public GpsRequest(ProviderRequest request, WorkSource source) {
252 this.request = request;
253 this.source = source;
254 }
255 }
256
257 private Object mLock = new Object();
258
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800259 private int mLocationFlags = LOCATION_INVALID;
260
261 // current status
Mike Lockwood15e3d0f2009-05-01 07:53:28 -0400262 private int mStatus = LocationProvider.TEMPORARILY_UNAVAILABLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800263
264 // time for last status update
265 private long mStatusUpdateTime = SystemClock.elapsedRealtime();
Mike Lockwoodd53ba012010-04-15 20:41:26 -0400266
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800267 // turn off GPS fix icon if we haven't received a fix in 10 seconds
Mike Lockwood04598b62010-04-14 17:17:24 -0400268 private static final long RECENT_FIX_TIMEOUT = 10 * 1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800269
Mike Lockwood0632ca72009-05-14 15:51:03 -0400270 // stop trying if we do not receive a fix within 60 seconds
Mike Lockwood04598b62010-04-14 17:17:24 -0400271 private static final int NO_FIX_TIMEOUT = 60 * 1000;
Mike Lockwood0632ca72009-05-14 15:51:03 -0400272
Nick Pellyb041f232012-05-07 17:12:25 -0700273 // if the fix interval is below this we leave GPS on,
274 // if above then we cycle the GPS driver.
275 // Typical hot TTTF is ~5 seconds, so 10 seconds seems sane.
276 private static final int GPS_POLLING_THRESHOLD_INTERVAL = 10 * 1000;
277
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700278 // how often to request NTP time, in milliseconds
279 // current setting 24 hours
280 private static final long NTP_INTERVAL = 24*60*60*1000;
281 // how long to wait if we have a network error in NTP or XTRA downloading
282 // current setting - 5 minutes
283 private static final long RETRY_INTERVAL = 5*60*1000;
284
285 // true if we are enabled, protected by this
286 private boolean mEnabled;
287
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800288 // true if we have network connectivity
289 private boolean mNetworkAvailable;
290
Kevin Tang40e1baf2012-01-10 14:32:44 -0800291 // states for injecting ntp and downloading xtra data
292 private static final int STATE_PENDING_NETWORK = 0;
293 private static final int STATE_DOWNLOADING = 1;
294 private static final int STATE_IDLE = 2;
295
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400296 // flags to trigger NTP or XTRA data download when network becomes available
297 // initialized to true so we do NTP and XTRA when the network comes up after booting
Kevin Tang40e1baf2012-01-10 14:32:44 -0800298 private int mInjectNtpTimePending = STATE_PENDING_NETWORK;
299 private int mDownloadXtraDataPending = STATE_PENDING_NETWORK;
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400300
Mike Lockwood9b9fb5c2011-06-29 15:09:40 -0400301 // set to true if the GPS engine does not do on-demand NTP time requests
302 private boolean mPeriodicTimeInjection;
303
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800304 // true if GPS is navigating
305 private boolean mNavigating;
Mike Lockwoodcf1d8cb2010-01-20 10:14:54 -0500306
307 // true if GPS engine is on
308 private boolean mEngineOn;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700309
Mike Lockwood04598b62010-04-14 17:17:24 -0400310 // requested frequency of fixes, in milliseconds
311 private int mFixInterval = 1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800312
313 // true if we started navigation
314 private boolean mStarted;
315
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -0700316 // true if single shot request is in progress
317 private boolean mSingleShot;
318
Mike Lockwood04598b62010-04-14 17:17:24 -0400319 // capabilities of the GPS engine
320 private int mEngineCapabilities;
321
Mike Lockwood1a1cd3a2010-08-17 07:42:54 -0400322 // true if XTRA is supported
323 private boolean mSupportsXtra;
324
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800325 // for calculating time to first fix
326 private long mFixRequestTime = 0;
327 // time to first fix for most recent session
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700328 private int mTimeToFirstFix = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800329 // time we received our last fix
330 private long mLastFixTime;
331
Mike Lockwood04598b62010-04-14 17:17:24 -0400332 private int mPositionMode;
333
David Christied4edf4c2014-08-12 15:22:27 -0700334 // Current request from underlying location clients.
335 private ProviderRequest mProviderRequest = null;
336 // Current list of underlying location clients.
337 private WorkSource mWorkSource = null;
338 // True if gps should be disabled (used to support battery saver mode in settings).
339 private boolean mDisableGps = false;
340
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800341 // properties loaded from PROPERTIES_FILE
342 private Properties mProperties;
Mike Lockwood734d6032009-07-28 18:30:25 -0700343 private String mSuplServerHost;
Tsuwei Chen678c13c2014-09-22 17:48:41 -0700344 private int mSuplServerPort = TCP_MIN_PORT;
Mike Lockwood734d6032009-07-28 18:30:25 -0700345 private String mC2KServerHost;
346 private int mC2KServerPort;
Tsuwei Chen3324e952014-09-07 01:30:42 -0700347 private boolean mSuplEsEnabled = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800348
Mike Lockwood15e3d0f2009-05-01 07:53:28 -0400349 private final Context mContext;
Jeff Sharkey104344e2011-07-10 14:20:41 -0700350 private final NtpTrustedTime mNtpTime;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700351 private final ILocationManager mILocationManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800352 private Location mLocation = new Location(LocationManager.GPS_PROVIDER);
353 private Bundle mLocationExtras = new Bundle();
destradaa6568d702014-10-27 12:47:41 -0700354 private final GpsStatusListenerHelper mListenerHelper;
355 private final GpsMeasurementsProvider mGpsMeasurementsProvider;
356 private final GpsNavigationMessageProvider mGpsNavigationMessageProvider;
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400357
Victoria Lease5c24fd02012-10-01 11:00:50 -0700358 // Handler for processing events
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400359 private Handler mHandler;
The Android Open Source Project10592532009-03-18 17:39:46 -0700360
Mike Lockwoode3635c92009-05-11 08:38:02 -0400361 private String mAGpsApn;
destradaa96a14702014-06-05 11:36:30 -0700362 private int mApnIpType;
Mike Lockwoode3635c92009-05-11 08:38:02 -0400363 private int mAGpsDataConnectionState;
destradaa96a14702014-06-05 11:36:30 -0700364 private InetAddress mAGpsDataConnectionIpAddr;
Mike Lockwood2f82c4e2009-04-17 08:24:10 -0400365 private final ConnectivityManager mConnMgr;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700366 private final GpsNetInitiatedHandler mNIHandler;
Mike Lockwood2f82c4e2009-04-17 08:24:10 -0400367
Mike Lockwood0528b9b2009-05-07 10:12:54 -0400368 // Wakelocks
369 private final static String WAKELOCK_KEY = "GpsLocationProvider";
370 private final PowerManager.WakeLock mWakeLock;
371
Mike Lockwood29c84342009-05-06 14:01:15 -0400372 // Alarms
373 private final static String ALARM_WAKEUP = "com.android.internal.location.ALARM_WAKEUP";
Mike Lockwood0632ca72009-05-14 15:51:03 -0400374 private final static String ALARM_TIMEOUT = "com.android.internal.location.ALARM_TIMEOUT";
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700375
376 // SIM/Carrier info.
377 private final static String SIM_STATE_CHANGED = "android.intent.action.SIM_STATE_CHANGED";
378
David Christied4edf4c2014-08-12 15:22:27 -0700379 private final PowerManager mPowerManager;
Mike Lockwood29c84342009-05-06 14:01:15 -0400380 private final AlarmManager mAlarmManager;
381 private final PendingIntent mWakeupIntent;
Mike Lockwood0632ca72009-05-14 15:51:03 -0400382 private final PendingIntent mTimeoutIntent;
Mike Lockwood29c84342009-05-06 14:01:15 -0400383
Dianne Hackborna06de0f2012-12-11 16:34:47 -0800384 private final IAppOpsService mAppOpsService;
Mike Lockwood2f82c4e2009-04-17 08:24:10 -0400385 private final IBatteryStats mBatteryStats;
The Android Open Source Project10592532009-03-18 17:39:46 -0700386
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700387 // only modified on handler thread
Dianne Hackborn002a54e2013-01-10 17:34:55 -0800388 private WorkSource mClientSource = new WorkSource();
Mike Lockwoodf1218be2010-01-29 09:20:06 -0500389
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -0700390 private GeofenceHardwareImpl mGeofenceHardwareImpl;
391
Mike Lockwood15e3d0f2009-05-01 07:53:28 -0400392 private final IGpsStatusProvider mGpsStatusProvider = new IGpsStatusProvider.Stub() {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700393 @Override
destradaa13a60b02015-01-15 18:36:01 -0800394 public void addGpsStatusListener(IGpsStatusListener listener) {
destradaaea8a8a62014-06-23 18:19:03 -0700395 mListenerHelper.addListener(listener);
Mike Lockwood15e3d0f2009-05-01 07:53:28 -0400396 }
397
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700398 @Override
Mike Lockwood15e3d0f2009-05-01 07:53:28 -0400399 public void removeGpsStatusListener(IGpsStatusListener listener) {
destradaaea8a8a62014-06-23 18:19:03 -0700400 mListenerHelper.removeListener(listener);
401 }
402 };
Mike Lockwood15e3d0f2009-05-01 07:53:28 -0400403
Mike Lockwood15e3d0f2009-05-01 07:53:28 -0400404 public IGpsStatusProvider getGpsStatusProvider() {
405 return mGpsStatusProvider;
406 }
407
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -0700408 public IGpsGeofenceHardware getGpsGeofenceProxy() {
409 return mGpsGeofenceBinder;
410 }
411
destradaaea8a8a62014-06-23 18:19:03 -0700412 public GpsMeasurementsProvider getGpsMeasurementsProvider() {
413 return mGpsMeasurementsProvider;
414 }
415
destradaa4b3e3932014-07-21 18:01:47 -0700416 public GpsNavigationMessageProvider getGpsNavigationMessageProvider() {
417 return mGpsNavigationMessageProvider;
418 }
419
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700420 private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
The Android Open Source Project10592532009-03-18 17:39:46 -0700421 @Override public void onReceive(Context context, Intent intent) {
422 String action = intent.getAction();
423
Tsuwei Chen48d37f92014-09-05 15:15:34 -0700424 if (DEBUG) Log.d(TAG, "receive broadcast intent, action: " + action);
Mike Lockwood29c84342009-05-06 14:01:15 -0400425 if (action.equals(ALARM_WAKEUP)) {
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -0700426 startNavigating(false);
Mike Lockwood0632ca72009-05-14 15:51:03 -0400427 } else if (action.equals(ALARM_TIMEOUT)) {
Mike Lockwood0632ca72009-05-14 15:51:03 -0400428 hibernate();
Miguel Torroja1e84da82010-07-27 07:02:24 +0200429 } else if (action.equals(Intents.DATA_SMS_RECEIVED_ACTION)) {
430 checkSmsSuplInit(intent);
431 } else if (action.equals(Intents.WAP_PUSH_RECEIVED_ACTION)) {
432 checkWapSuplInit(intent);
Tsuwei Chend3ef8e22014-10-31 14:58:44 -0700433 } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE)) {
David Christied4edf4c2014-08-12 15:22:27 -0700434 // retrieve NetworkInfo result for this UID
435 NetworkInfo info =
436 intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
437 ConnectivityManager connManager = (ConnectivityManager)
438 mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
439 info = connManager.getNetworkInfo(info.getType());
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700440
Tsuwei Chend3ef8e22014-10-31 14:58:44 -0700441 int networkState;
442 if (intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false) ||
443 !info.isConnected()) {
444 networkState = LocationProvider.TEMPORARILY_UNAVAILABLE;
445 } else {
446 networkState = LocationProvider.AVAILABLE;
447 }
448
449
David Christied4edf4c2014-08-12 15:22:27 -0700450 updateNetworkState(networkState, info);
451 } else if (PowerManager.ACTION_POWER_SAVE_MODE_CHANGED.equals(action)
452 || Intent.ACTION_SCREEN_OFF.equals(action)
453 || Intent.ACTION_SCREEN_ON.equals(action)) {
454 updateLowPowerMode();
Wink Savillea374c3d2014-11-11 11:48:04 -0800455 } else if (action.equals(SIM_STATE_CHANGED)) {
456 subscriptionOrSimChanged(context);
David Christied4edf4c2014-08-12 15:22:27 -0700457 }
The Android Open Source Project10592532009-03-18 17:39:46 -0700458 }
Mike Lockwood29c84342009-05-06 14:01:15 -0400459 };
The Android Open Source Project10592532009-03-18 17:39:46 -0700460
Wink Savilled09c4ca2014-11-22 10:08:16 -0800461 private final OnSubscriptionsChangedListener mOnSubscriptionsChangedListener =
462 new OnSubscriptionsChangedListener() {
Wink Savillea374c3d2014-11-11 11:48:04 -0800463 @Override
Wink Savilled09c4ca2014-11-22 10:08:16 -0800464 public void onSubscriptionsChanged() {
Wink Savillea374c3d2014-11-11 11:48:04 -0800465 subscriptionOrSimChanged(mContext);
466 }
467 };
468
469 private void subscriptionOrSimChanged(Context context) {
470 Log.d(TAG, "received SIM realted action: ");
471 TelephonyManager phone = (TelephonyManager)
472 mContext.getSystemService(Context.TELEPHONY_SERVICE);
473 String mccMnc = phone.getSimOperator();
474 if (!TextUtils.isEmpty(mccMnc)) {
475 Log.d(TAG, "SIM MCC/MNC is available: " + mccMnc);
476 synchronized (mLock) {
477 reloadGpsProperties(context, mProperties);
478 mNIHandler.setSuplEsEnabled(mSuplEsEnabled);
479 }
480 } else {
481 Log.d(TAG, "SIM MCC/MNC is still not available");
482 }
483 }
484
Miguel Torroja1e84da82010-07-27 07:02:24 +0200485 private void checkSmsSuplInit(Intent intent) {
486 SmsMessage[] messages = Intents.getMessagesFromIntent(intent);
487 for (int i=0; i <messages.length; i++) {
488 byte[] supl_init = messages[i].getUserData();
489 native_agps_ni_message(supl_init,supl_init.length);
490 }
491 }
492
493 private void checkWapSuplInit(Intent intent) {
494 byte[] supl_init = (byte[]) intent.getExtra("data");
495 native_agps_ni_message(supl_init,supl_init.length);
496 }
497
David Christied4edf4c2014-08-12 15:22:27 -0700498 private void updateLowPowerMode() {
499 final boolean disableGps;
500 switch (Settings.Secure.getInt(mContext.getContentResolver(), BATTERY_SAVER_GPS_MODE,
501 BATTERY_SAVER_MODE_DISABLED_WHEN_SCREEN_OFF)) {
502 case BATTERY_SAVER_MODE_DISABLED_WHEN_SCREEN_OFF:
503 disableGps = mPowerManager.isPowerSaveMode() && !mPowerManager.isInteractive();
504 break;
505 default:
506 disableGps = false;
507 }
508 if (disableGps != mDisableGps) {
509 mDisableGps = disableGps;
510 updateRequirements();
511 }
512 }
513
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800514 public static boolean isSupported() {
515 return native_is_supported();
516 }
517
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700518 private void reloadGpsProperties(Context context, Properties properties) {
519 Log.d(TAG, "Reset GPS properties, previous size = " + properties.size());
520 loadPropertiesFromResource(context, properties);
521 boolean isPropertiesLoadedFromFile = false;
522 final String gpsHardware = SystemProperties.get("ro.hardware.gps");
523 if (!TextUtils.isEmpty(gpsHardware)) {
524 final String propFilename =
525 PROPERTIES_FILE_PREFIX + "." + gpsHardware + PROPERTIES_FILE_SUFFIX;
526 isPropertiesLoadedFromFile =
527 loadPropertiesFromFile(propFilename, properties);
528 }
529 if (!isPropertiesLoadedFromFile) {
530 loadPropertiesFromFile(DEFAULT_PROPERTIES_FILE, properties);
531 }
532 Log.d(TAG, "GPS properties reloaded, size = " + properties.size());
533
534 // TODO: we should get rid of C2K specific setting.
535 setSuplHostPort(properties.getProperty("SUPL_HOST"),
536 properties.getProperty("SUPL_PORT"));
537 mC2KServerHost = properties.getProperty("C2K_HOST");
538 String portString = properties.getProperty("C2K_PORT");
539 if (mC2KServerHost != null && portString != null) {
540 try {
541 mC2KServerPort = Integer.parseInt(portString);
542 } catch (NumberFormatException e) {
543 Log.e(TAG, "unable to parse C2K_PORT: " + portString);
544 }
545 }
546
547 try {
548 // Convert properties to string contents and send it to HAL.
549 ByteArrayOutputStream baos = new ByteArrayOutputStream(4096);
550 properties.store(baos, null);
551 native_configuration_update(baos.toString());
552 Log.d(TAG, "final config = " + baos.toString());
553 } catch (IOException ex) {
554 Log.w(TAG, "failed to dump properties contents");
555 }
Tsuwei Chen3324e952014-09-07 01:30:42 -0700556
557 // SUPL_ES configuration.
558 String suplESProperty = mProperties.getProperty("SUPL_ES");
559 if (suplESProperty != null) {
560 try {
561 mSuplEsEnabled = (Integer.parseInt(suplESProperty) == 1);
562 } catch (NumberFormatException e) {
563 Log.e(TAG, "unable to parse SUPL_ES: " + suplESProperty);
564 }
565 }
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700566 }
567
568 private void loadPropertiesFromResource(Context context,
569 Properties properties) {
570 String[] configValues = context.getResources().getStringArray(
571 com.android.internal.R.array.config_gpsParameters);
572 for (String item : configValues) {
573 Log.d(TAG, "GpsParamsResource: " + item);
Tsuwei Chen7c485bf2014-09-10 15:33:34 -0700574 // We need to support "KEY =", but not "=VALUE".
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700575 String[] split = item.split("=");
576 if (split.length == 2) {
577 properties.setProperty(split[0].trim().toUpperCase(), split[1]);
578 } else {
579 Log.w(TAG, "malformed contents: " + item);
580 }
581 }
582 }
583
584 private boolean loadPropertiesFromFile(String filename,
585 Properties properties) {
Colin Cross7c030ed2014-01-28 09:33:53 -0800586 try {
587 File file = new File(filename);
588 FileInputStream stream = null;
589 try {
590 stream = new FileInputStream(file);
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700591 properties.load(stream);
Colin Cross7c030ed2014-01-28 09:33:53 -0800592 } finally {
593 IoUtils.closeQuietly(stream);
594 }
595
Colin Cross7c030ed2014-01-28 09:33:53 -0800596 } catch (IOException e) {
597 Log.w(TAG, "Could not open GPS configuration file " + filename);
598 return false;
599 }
600 return true;
601 }
602
Victoria Lease5cd731a2012-12-19 15:04:21 -0800603 public GpsLocationProvider(Context context, ILocationManager ilocationManager,
604 Looper looper) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800605 mContext = context;
Jeff Sharkey104344e2011-07-10 14:20:41 -0700606 mNtpTime = NtpTrustedTime.getInstance(context);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700607 mILocationManager = ilocationManager;
Mike Lockwood63598a02010-02-24 11:52:59 -0500608
609 mLocation.setExtras(mLocationExtras);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800610
Mike Lockwood0528b9b2009-05-07 10:12:54 -0400611 // Create a wake lock
David Christied4edf4c2014-08-12 15:22:27 -0700612 mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
613 mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700614 mWakeLock.setReferenceCounted(true);
Mike Lockwood0528b9b2009-05-07 10:12:54 -0400615
Mike Lockwood29c84342009-05-06 14:01:15 -0400616 mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
617 mWakeupIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_WAKEUP), 0);
Mike Lockwood0632ca72009-05-14 15:51:03 -0400618 mTimeoutIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_TIMEOUT), 0);
Mike Lockwood29c84342009-05-06 14:01:15 -0400619
Mike Lockwood58bda982009-04-14 16:25:07 -0400620 mConnMgr = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
621
Dianne Hackborna06de0f2012-12-11 16:34:47 -0800622 // App ops service to keep track of who is accessing the GPS
623 mAppOpsService = IAppOpsService.Stub.asInterface(ServiceManager.getService(
624 Context.APP_OPS_SERVICE));
625
Mike Lockwood2f82c4e2009-04-17 08:24:10 -0400626 // Battery statistics service to be notified when GPS turns on or off
Dianne Hackborn91268cf2013-06-13 19:06:50 -0700627 mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService(
628 BatteryStats.SERVICE_NAME));
Mike Lockwood2f82c4e2009-04-17 08:24:10 -0400629
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700630 // Load GPS configuration.
631 mProperties = new Properties();
632 reloadGpsProperties(mContext, mProperties);
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400633
Tsuwei Chen3324e952014-09-07 01:30:42 -0700634 // Create a GPS net-initiated handler.
635 mNIHandler = new GpsNetInitiatedHandler(context,
636 mNetInitiatedListener,
637 mSuplEsEnabled);
638
Wink Savillea374c3d2014-11-11 11:48:04 -0800639 // TODO: When this object "finishes" we should unregister by invoking
Wink Savilled09c4ca2014-11-22 10:08:16 -0800640 // SubscriptionManager.getInstance(mContext).unregister(mOnSubscriptionsChangedListener);
Wink Savillea374c3d2014-11-11 11:48:04 -0800641 // This is not strictly necessary because it will be unregistered if the
642 // notification fails but it is good form.
643
644 // Register for SubscriptionInfo list changes which is guaranteed
Wink Savilled09c4ca2014-11-22 10:08:16 -0800645 // to invoke onSubscriptionsChanged the first time.
646 SubscriptionManager.from(mContext)
Wink Saville071743f2015-01-12 17:11:04 -0800647 .addOnSubscriptionsChangedListener(mOnSubscriptionsChangedListener);
Wink Savillea374c3d2014-11-11 11:48:04 -0800648
Victoria Lease5c24fd02012-10-01 11:00:50 -0700649 // construct handler, listen for events
Victoria Lease5cd731a2012-12-19 15:04:21 -0800650 mHandler = new ProviderHandler(looper);
Victoria Lease5c24fd02012-10-01 11:00:50 -0700651 listenForBroadcasts();
652
653 // also listen for PASSIVE_PROVIDER updates
654 mHandler.post(new Runnable() {
655 @Override
656 public void run() {
657 LocationManager locManager =
658 (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
David Christie9e9ce922013-09-12 13:04:32 -0700659 final long minTime = 0;
660 final float minDistance = 0;
661 final boolean oneShot = false;
662 LocationRequest request = LocationRequest.createFromDeprecatedProvider(
663 LocationManager.PASSIVE_PROVIDER,
664 minTime,
665 minDistance,
666 oneShot);
667 // Don't keep track of this request since it's done on behalf of other clients
668 // (which are kept track of separately).
669 request.setHideFromAppOps(true);
670 locManager.requestLocationUpdates(
671 request,
672 new NetworkLocationListener(),
673 mHandler.getLooper());
Mike Lockwood89096312010-03-24 10:14:55 -0400674 }
Victoria Lease5c24fd02012-10-01 11:00:50 -0700675 });
destradaa6568d702014-10-27 12:47:41 -0700676
677 mListenerHelper = new GpsStatusListenerHelper(mHandler) {
678 @Override
679 protected boolean isAvailableInPlatform() {
destradaa13a60b02015-01-15 18:36:01 -0800680 return isSupported();
destradaa6568d702014-10-27 12:47:41 -0700681 }
682
683 @Override
684 protected boolean isGpsEnabled() {
685 return isEnabled();
686 }
687 };
688
689 mGpsMeasurementsProvider = new GpsMeasurementsProvider(mHandler) {
690 @Override
691 public boolean isAvailableInPlatform() {
692 return native_is_measurement_supported();
693 }
694
695 @Override
696 protected boolean registerWithService() {
697 return native_start_measurement_collection();
698 }
699
700 @Override
701 protected void unregisterFromService() {
702 native_stop_measurement_collection();
703 }
704
705 @Override
706 protected boolean isGpsEnabled() {
707 return isEnabled();
708 }
709 };
710
711 mGpsNavigationMessageProvider = new GpsNavigationMessageProvider(mHandler) {
712 @Override
713 protected boolean isAvailableInPlatform() {
714 return native_is_navigation_message_supported();
715 }
716
717 @Override
718 protected boolean registerWithService() {
719 return native_start_navigation_message_collection();
720 }
721
722 @Override
723 protected void unregisterFromService() {
724 native_stop_navigation_message_collection();
725 }
726
727 @Override
728 protected boolean isGpsEnabled() {
729 return isEnabled();
730 }
731 };
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400732 }
733
Victoria Lease5c24fd02012-10-01 11:00:50 -0700734 private void listenForBroadcasts() {
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400735 IntentFilter intentFilter = new IntentFilter();
Victoria Lease5c24fd02012-10-01 11:00:50 -0700736 intentFilter.addAction(Intents.DATA_SMS_RECEIVED_ACTION);
737 intentFilter.addDataScheme("sms");
738 intentFilter.addDataAuthority("localhost","7275");
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700739 mContext.registerReceiver(mBroadcastReceiver, intentFilter, null, mHandler);
Victoria Lease5c24fd02012-10-01 11:00:50 -0700740
741 intentFilter = new IntentFilter();
742 intentFilter.addAction(Intents.WAP_PUSH_RECEIVED_ACTION);
743 try {
744 intentFilter.addDataType("application/vnd.omaloc-supl-init");
745 } catch (IntentFilter.MalformedMimeTypeException e) {
746 Log.w(TAG, "Malformed SUPL init mime type");
747 }
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700748 mContext.registerReceiver(mBroadcastReceiver, intentFilter, null, mHandler);
Victoria Lease5c24fd02012-10-01 11:00:50 -0700749
750 intentFilter = new IntentFilter();
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400751 intentFilter.addAction(ALARM_WAKEUP);
752 intentFilter.addAction(ALARM_TIMEOUT);
Tsuwei Chend3ef8e22014-10-31 14:58:44 -0700753 intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE);
David Christied4edf4c2014-08-12 15:22:27 -0700754 intentFilter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED);
755 intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
756 intentFilter.addAction(Intent.ACTION_SCREEN_ON);
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700757 intentFilter.addAction(SIM_STATE_CHANGED);
758 mContext.registerReceiver(mBroadcastReceiver, intentFilter, null, mHandler);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800759 }
760
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800761 /**
Mike Lockwoodd03ff942010-02-09 08:46:14 -0500762 * Returns the name of this provider.
763 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700764 @Override
Mike Lockwoodd03ff942010-02-09 08:46:14 -0500765 public String getName() {
766 return LocationManager.GPS_PROVIDER;
767 }
768
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700769 @Override
770 public ProviderProperties getProperties() {
771 return PROPERTIES;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800772 }
773
Mike Lockwood03d24672009-10-08 15:45:03 -0400774 public void updateNetworkState(int state, NetworkInfo info) {
Mike Lockwood98e48692010-04-07 16:32:51 -0400775 sendMessage(UPDATE_NETWORK_STATE, state, info);
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400776 }
777
778 private void handleUpdateNetworkState(int state, NetworkInfo info) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800779 mNetworkAvailable = (state == LocationProvider.AVAILABLE);
780
Joe Onoratof5d95cb2010-01-07 21:48:32 -0500781 if (DEBUG) {
Mike Lockwood03d24672009-10-08 15:45:03 -0400782 Log.d(TAG, "updateNetworkState " + (mNetworkAvailable ? "available" : "unavailable")
783 + " info: " + info);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800784 }
Mike Lockwood03d24672009-10-08 15:45:03 -0400785
Mike Lockwood50130bb2010-10-11 06:22:50 -0400786 if (info != null) {
Shishir Agrawal64ce5f82015-02-10 19:02:38 -0800787 boolean dataEnabled = TelephonyManager.getDefault().getDataEnabled();
Kevin Tanga5fe6b22011-06-05 14:25:16 -0700788 boolean networkAvailable = info.isAvailable() && dataEnabled;
789 String defaultApn = getSelectedApn();
790 if (defaultApn == null) {
791 defaultApn = "dummy-apn";
792 }
793
Mike Lockwood50130bb2010-10-11 06:22:50 -0400794 native_update_network_state(info.isConnected(), info.getType(),
Kevin Tanga5fe6b22011-06-05 14:25:16 -0700795 info.isRoaming(), networkAvailable,
796 info.getExtraInfo(), defaultApn);
Mike Lockwood50130bb2010-10-11 06:22:50 -0400797 }
798
Mike Lockwood03d24672009-10-08 15:45:03 -0400799 if (info != null && info.getType() == ConnectivityManager.TYPE_MOBILE_SUPL
800 && mAGpsDataConnectionState == AGPS_DATA_CONNECTION_OPENING) {
Stephen Li83b69712011-01-25 18:47:28 -0800801 if (mNetworkAvailable) {
destradaa96a14702014-06-05 11:36:30 -0700802 String apnName = info.getExtraInfo();
Stephen Li83b69712011-01-25 18:47:28 -0800803 if (apnName == null) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700804 /* Assign a dummy value in the case of C2K as otherwise we will have a runtime
Stephen Li83b69712011-01-25 18:47:28 -0800805 exception in the following call to native_agps_data_conn_open*/
806 apnName = "dummy-apn";
807 }
Mike Lockwood03d24672009-10-08 15:45:03 -0400808 mAGpsApn = apnName;
destradaa96a14702014-06-05 11:36:30 -0700809 mApnIpType = getApnIpType(apnName);
810 setRouting();
811 if (DEBUG) {
812 String message = String.format(
813 "native_agps_data_conn_open: mAgpsApn=%s, mApnIpType=%s",
814 mAGpsApn, mApnIpType);
815 Log.d(TAG, message);
Stephen Li8efd74d2011-03-01 20:56:00 -0800816 }
destradaa96a14702014-06-05 11:36:30 -0700817 native_agps_data_conn_open(mAGpsApn, mApnIpType);
Mike Lockwood03d24672009-10-08 15:45:03 -0400818 mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPEN;
819 } else {
destradaa96a14702014-06-05 11:36:30 -0700820 Log.e(TAG, "call native_agps_data_conn_failed, info: " + info);
Mike Lockwood03d24672009-10-08 15:45:03 -0400821 mAGpsApn = null;
destradaa96a14702014-06-05 11:36:30 -0700822 mApnIpType = APN_INVALID;
Mike Lockwood03d24672009-10-08 15:45:03 -0400823 mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED;
824 native_agps_data_conn_failed();
825 }
826 }
827
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400828 if (mNetworkAvailable) {
Kevin Tang40e1baf2012-01-10 14:32:44 -0800829 if (mInjectNtpTimePending == STATE_PENDING_NETWORK) {
Mike Lockwood98e48692010-04-07 16:32:51 -0400830 sendMessage(INJECT_NTP_TIME, 0, null);
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400831 }
Kevin Tang40e1baf2012-01-10 14:32:44 -0800832 if (mDownloadXtraDataPending == STATE_PENDING_NETWORK) {
Mike Lockwood98e48692010-04-07 16:32:51 -0400833 sendMessage(DOWNLOAD_XTRA_DATA, 0, null);
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400834 }
835 }
836 }
837
838 private void handleInjectNtpTime() {
Kevin Tang40e1baf2012-01-10 14:32:44 -0800839 if (mInjectNtpTimePending == STATE_DOWNLOADING) {
840 // already downloading data
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400841 return;
842 }
Kevin Tang40e1baf2012-01-10 14:32:44 -0800843 if (!mNetworkAvailable) {
844 // try again when network is up
845 mInjectNtpTimePending = STATE_PENDING_NETWORK;
846 return;
Jeff Sharkey104344e2011-07-10 14:20:41 -0700847 }
Kevin Tang40e1baf2012-01-10 14:32:44 -0800848 mInjectNtpTimePending = STATE_DOWNLOADING;
Jeff Sharkey104344e2011-07-10 14:20:41 -0700849
Jeff Brown028872f2012-08-25 13:07:01 -0700850 // hold wake lock while task runs
851 mWakeLock.acquire();
Kevin Tang40e1baf2012-01-10 14:32:44 -0800852 AsyncTask.THREAD_POOL_EXECUTOR.execute(new Runnable() {
853 @Override
854 public void run() {
855 long delay;
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400856
Kevin Tang40e1baf2012-01-10 14:32:44 -0800857 // force refresh NTP cache when outdated
858 if (mNtpTime.getCacheAge() >= NTP_INTERVAL) {
859 mNtpTime.forceRefresh();
860 }
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400861
Kevin Tang40e1baf2012-01-10 14:32:44 -0800862 // only update when NTP time is fresh
863 if (mNtpTime.getCacheAge() < NTP_INTERVAL) {
864 long time = mNtpTime.getCachedNtpTime();
865 long timeReference = mNtpTime.getCachedNtpTimeReference();
866 long certainty = mNtpTime.getCacheCertainty();
867 long now = System.currentTimeMillis();
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400868
Kevin Tang40e1baf2012-01-10 14:32:44 -0800869 Log.d(TAG, "NTP server returned: "
870 + time + " (" + new Date(time)
871 + ") reference: " + timeReference
872 + " certainty: " + certainty
873 + " system time offset: " + (time - now));
874
875 native_inject_time(time, timeReference, (int) certainty);
876 delay = NTP_INTERVAL;
877 } else {
878 if (DEBUG) Log.d(TAG, "requestTime failed");
879 delay = RETRY_INTERVAL;
880 }
881
Jeff Brown028872f2012-08-25 13:07:01 -0700882 sendMessage(INJECT_NTP_TIME_FINISHED, 0, null);
Kevin Tang40e1baf2012-01-10 14:32:44 -0800883
884 if (mPeriodicTimeInjection) {
885 // send delayed message for next NTP injection
886 // since this is delayed and not urgent we do not hold a wake lock here
Jeff Brown028872f2012-08-25 13:07:01 -0700887 mHandler.sendEmptyMessageDelayed(INJECT_NTP_TIME, delay);
Kevin Tang40e1baf2012-01-10 14:32:44 -0800888 }
Jeff Brown028872f2012-08-25 13:07:01 -0700889
890 // release wake lock held by task
891 mWakeLock.release();
Kevin Tang40e1baf2012-01-10 14:32:44 -0800892 }
893 });
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400894 }
895
896 private void handleDownloadXtraData() {
Kevin Tang40e1baf2012-01-10 14:32:44 -0800897 if (mDownloadXtraDataPending == STATE_DOWNLOADING) {
898 // already downloading data
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400899 return;
900 }
Kevin Tang40e1baf2012-01-10 14:32:44 -0800901 if (!mNetworkAvailable) {
902 // try again when network is up
903 mDownloadXtraDataPending = STATE_PENDING_NETWORK;
904 return;
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400905 }
Kevin Tang40e1baf2012-01-10 14:32:44 -0800906 mDownloadXtraDataPending = STATE_DOWNLOADING;
907
Jeff Brown028872f2012-08-25 13:07:01 -0700908 // hold wake lock while task runs
909 mWakeLock.acquire();
Kevin Tang40e1baf2012-01-10 14:32:44 -0800910 AsyncTask.THREAD_POOL_EXECUTOR.execute(new Runnable() {
911 @Override
912 public void run() {
Andreas Gampedfdc6ac2014-10-28 20:42:53 -0700913 GpsXtraDownloader xtraDownloader = new GpsXtraDownloader(mProperties);
Kevin Tang40e1baf2012-01-10 14:32:44 -0800914 byte[] data = xtraDownloader.downloadXtraData();
915 if (data != null) {
916 if (DEBUG) {
917 Log.d(TAG, "calling native_inject_xtra_data");
918 }
919 native_inject_xtra_data(data, data.length);
920 }
921
Jeff Brown028872f2012-08-25 13:07:01 -0700922 sendMessage(DOWNLOAD_XTRA_DATA_FINISHED, 0, null);
Kevin Tang40e1baf2012-01-10 14:32:44 -0800923
924 if (data == null) {
925 // try again later
926 // since this is delayed and not urgent we do not hold a wake lock here
Jeff Brown028872f2012-08-25 13:07:01 -0700927 mHandler.sendEmptyMessageDelayed(DOWNLOAD_XTRA_DATA, RETRY_INTERVAL);
Kevin Tang40e1baf2012-01-10 14:32:44 -0800928 }
Kevin Tang40e1baf2012-01-10 14:32:44 -0800929
Jeff Brown028872f2012-08-25 13:07:01 -0700930 // release wake lock held by task
931 mWakeLock.release();
932 }
Kevin Tang40e1baf2012-01-10 14:32:44 -0800933 });
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800934 }
935
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400936 private void handleUpdateLocation(Location location) {
Mike Lockwoodd26ce0d2009-06-11 12:25:46 -0400937 if (location.hasAccuracy()) {
938 native_inject_location(location.getLatitude(), location.getLongitude(),
939 location.getAccuracy());
940 }
Mike Lockwoodfd6e5f02009-05-21 11:28:20 -0400941 }
942
943 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800944 * Enables this provider. When enabled, calls to getStatus()
Mike Lockwood4e50b782009-04-03 08:24:43 -0700945 * must be handled. Hardware may be started up
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800946 * when the provider is enabled.
947 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700948 @Override
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400949 public void enable() {
Laurent Tu7b5aeca2013-01-24 15:10:24 -0800950 synchronized (mLock) {
951 if (mEnabled) return;
952 mEnabled = true;
953 }
954
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700955 sendMessage(ENABLE, 1, null);
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400956 }
957
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700958 private void setSuplHostPort(String hostString, String portString) {
959 if (hostString != null) {
960 mSuplServerHost = hostString;
961 }
962 if (portString != null) {
963 try {
964 mSuplServerPort = Integer.parseInt(portString);
965 } catch (NumberFormatException e) {
966 Log.e(TAG, "unable to parse SUPL_PORT: " + portString);
967 }
968 }
Tsuwei Chen678c13c2014-09-22 17:48:41 -0700969 if (mSuplServerHost != null
970 && mSuplServerPort > TCP_MIN_PORT
971 && mSuplServerPort <= TCP_MAX_PORT) {
972 native_set_agps_server(AGPS_TYPE_SUPL, mSuplServerHost, mSuplServerPort);
973 }
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700974 }
975
Tsuwei Chen462bcd82014-09-17 12:28:49 -0700976 /**
977 * Checks what SUPL mode to use, according to the AGPS mode as well as the
978 * allowed mode from properties.
979 *
980 * @param properties GPS properties
981 * @param agpsEnabled whether AGPS is enabled by settings value
982 * @param singleShot whether "singleshot" is needed
983 * @return SUPL mode (MSA vs MSB vs STANDALONE)
984 */
985 private int getSuplMode(Properties properties, boolean agpsEnabled, boolean singleShot) {
986 if (agpsEnabled) {
987 String modeString = properties.getProperty("SUPL_MODE");
988 int suplMode = 0;
989 if (!TextUtils.isEmpty(modeString)) {
990 try {
991 suplMode = Integer.parseInt(modeString);
992 } catch (NumberFormatException e) {
993 Log.e(TAG, "unable to parse SUPL_MODE: " + modeString);
994 return GPS_POSITION_MODE_STANDALONE;
995 }
996 }
997 if (singleShot
998 && hasCapability(GPS_CAPABILITY_MSA)
999 && (suplMode & AGPS_SUPL_MODE_MSA) != 0) {
1000 return GPS_POSITION_MODE_MS_ASSISTED;
1001 } else if (hasCapability(GPS_CAPABILITY_MSB)
1002 && (suplMode & AGPS_SUPL_MODE_MSB) != 0) {
1003 return GPS_POSITION_MODE_MS_BASED;
1004 }
1005 }
1006 return GPS_POSITION_MODE_STANDALONE;
1007 }
1008
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001009 private void handleEnable() {
1010 if (DEBUG) Log.d(TAG, "handleEnable");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001011
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001012 boolean enabled = native_init();
1013
1014 if (enabled) {
Mike Lockwood1a1cd3a2010-08-17 07:42:54 -04001015 mSupportsXtra = native_supports_xtra();
Tsuwei Chen678c13c2014-09-22 17:48:41 -07001016
1017 // TODO: remove the following native calls if we can make sure they are redundant.
Mike Lockwood734d6032009-07-28 18:30:25 -07001018 if (mSuplServerHost != null) {
1019 native_set_agps_server(AGPS_TYPE_SUPL, mSuplServerHost, mSuplServerPort);
1020 }
1021 if (mC2KServerHost != null) {
1022 native_set_agps_server(AGPS_TYPE_C2K, mC2KServerHost, mC2KServerPort);
1023 }
destradaa13a60b02015-01-15 18:36:01 -08001024
1025 mGpsMeasurementsProvider.onGpsEnabledChanged();
1026 mGpsNavigationMessageProvider.onGpsEnabledChanged();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001027 } else {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001028 synchronized (mLock) {
1029 mEnabled = false;
1030 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001031 Log.w(TAG, "Failed to enable location provider");
1032 }
1033 }
1034
1035 /**
1036 * Disables this provider. When disabled, calls to getStatus()
Mike Lockwood4e50b782009-04-03 08:24:43 -07001037 * need not be handled. Hardware may be shut
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001038 * down while the provider is disabled.
1039 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001040 @Override
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001041 public void disable() {
Laurent Tu7b5aeca2013-01-24 15:10:24 -08001042 synchronized (mLock) {
1043 if (!mEnabled) return;
1044 mEnabled = false;
1045 }
1046
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001047 sendMessage(ENABLE, 0, null);
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001048 }
1049
1050 private void handleDisable() {
Mike Lockwood89096312010-03-24 10:14:55 -04001051 if (DEBUG) Log.d(TAG, "handleDisable");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001052
David Christie3bc26142013-12-19 14:53:44 -08001053 updateClientUids(new WorkSource());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001054 stopNavigating();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001055 mAlarmManager.cancel(mWakeupIntent);
1056 mAlarmManager.cancel(mTimeoutIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001057
Mike Lockwoodcf1d8cb2010-01-20 10:14:54 -05001058 // do this before releasing wakelock
1059 native_cleanup();
destradaa13a60b02015-01-15 18:36:01 -08001060
1061 mGpsMeasurementsProvider.onGpsEnabledChanged();
1062 mGpsNavigationMessageProvider.onGpsEnabledChanged();
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) {
destradaa13a60b02015-01-15 18:36:01 -08001482 mListenerHelper.onStatusChanged(mNavigating);
Mike Lockwoodcf1d8cb2010-01-20 10:14:54 -05001483
destradaaea8a8a62014-06-23 18:19:03 -07001484 // send an intent to notify that the GPS has been enabled or disabled
1485 Intent intent = new Intent(LocationManager.GPS_ENABLED_CHANGE_ACTION);
1486 intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, mNavigating);
1487 mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001488 }
1489 }
1490
1491 /**
1492 * called from native code to update SV info
1493 */
1494 private void reportSvStatus() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001495 int svCount = native_read_sv_status(mSvs, mSnrs, mSvElevations, mSvAzimuths, mSvMasks);
destradaaea8a8a62014-06-23 18:19:03 -07001496 mListenerHelper.onSvStatusChanged(
1497 svCount,
1498 mSvs,
1499 mSnrs,
1500 mSvElevations,
1501 mSvAzimuths,
1502 mSvMasks[EPHEMERIS_MASK],
1503 mSvMasks[ALMANAC_MASK],
1504 mSvMasks[USED_FOR_FIX_MASK]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001505
Mike Lockwood29c84342009-05-06 14:01:15 -04001506 if (VERBOSE) {
1507 Log.v(TAG, "SV count: " + svCount +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001508 " ephemerisMask: " + Integer.toHexString(mSvMasks[EPHEMERIS_MASK]) +
1509 " almanacMask: " + Integer.toHexString(mSvMasks[ALMANAC_MASK]));
1510 for (int i = 0; i < svCount; i++) {
Mike Lockwood29c84342009-05-06 14:01:15 -04001511 Log.v(TAG, "sv: " + mSvs[i] +
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001512 " snr: " + mSnrs[i]/10 +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001513 " elev: " + mSvElevations[i] +
1514 " azimuth: " + mSvAzimuths[i] +
1515 ((mSvMasks[EPHEMERIS_MASK] & (1 << (mSvs[i] - 1))) == 0 ? " " : " E") +
1516 ((mSvMasks[ALMANAC_MASK] & (1 << (mSvs[i] - 1))) == 0 ? " " : " A") +
1517 ((mSvMasks[USED_FOR_FIX_MASK] & (1 << (mSvs[i] - 1))) == 0 ? "" : "U"));
1518 }
1519 }
1520
Kevin.KY Tsai0881f4f2010-05-21 15:10:39 -04001521 // return number of sets used in fix instead of total
1522 updateStatus(mStatus, Integer.bitCount(mSvMasks[USED_FOR_FIX_MASK]));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001523
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001524 if (mNavigating && mStatus == LocationProvider.AVAILABLE && mLastFixTime > 0 &&
Mike Lockwood04598b62010-04-14 17:17:24 -04001525 System.currentTimeMillis() - mLastFixTime > RECENT_FIX_TIMEOUT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001526 // send an intent to notify that the GPS is no longer receiving fixes.
Mike Lockwood00b74272010-03-26 10:41:48 -04001527 Intent intent = new Intent(LocationManager.GPS_FIX_CHANGE_ACTION);
1528 intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, false);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07001529 mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001530 updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, mSvCount);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001531 }
1532 }
Mike Lockwood58bda982009-04-14 16:25:07 -04001533
1534 /**
Mike Lockwoode3635c92009-05-11 08:38:02 -04001535 * called from native code to update AGPS status
Mike Lockwood58bda982009-04-14 16:25:07 -04001536 */
destradaa96a14702014-06-05 11:36:30 -07001537 private void reportAGpsStatus(int type, int status, byte[] ipaddr) {
Mike Lockwood58bda982009-04-14 16:25:07 -04001538 switch (status) {
Mike Lockwoode3635c92009-05-11 08:38:02 -04001539 case GPS_REQUEST_AGPS_DATA_CONN:
Mike Lockwoodb6e5fa82010-10-09 20:10:46 -04001540 if (DEBUG) Log.d(TAG, "GPS_REQUEST_AGPS_DATA_CONN");
destradaa931a37f2014-08-12 16:36:59 -07001541 Log.v(TAG, "Received SUPL IP addr[]: " + ipaddr);
Mike Lockwood2acfd342010-09-22 12:13:39 -04001542 // Set mAGpsDataConnectionState before calling startUsingNetworkFeature
1543 // to avoid a race condition with handleUpdateNetworkState()
1544 mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPENING;
1545 int result = mConnMgr.startUsingNetworkFeature(
Mike Lockwood58bda982009-04-14 16:25:07 -04001546 ConnectivityManager.TYPE_MOBILE, Phone.FEATURE_ENABLE_SUPL);
destradaa96a14702014-06-05 11:36:30 -07001547 if (ipaddr != null) {
1548 try {
1549 mAGpsDataConnectionIpAddr = InetAddress.getByAddress(ipaddr);
destradaa931a37f2014-08-12 16:36:59 -07001550 Log.v(TAG, "IP address converted to: " + mAGpsDataConnectionIpAddr);
destradaa96a14702014-06-05 11:36:30 -07001551 } catch (UnknownHostException e) {
1552 Log.e(TAG, "Bad IP Address: " + ipaddr, e);
1553 mAGpsDataConnectionIpAddr = null;
1554 }
1555 }
1556
Wink Savillea639b312012-07-10 12:37:54 -07001557 if (result == PhoneConstants.APN_ALREADY_ACTIVE) {
1558 if (DEBUG) Log.d(TAG, "PhoneConstants.APN_ALREADY_ACTIVE");
Mike Lockwoodb362a9a2009-06-22 16:20:39 -04001559 if (mAGpsApn != null) {
destradaa96a14702014-06-05 11:36:30 -07001560 setRouting();
1561 native_agps_data_conn_open(mAGpsApn, mApnIpType);
Mike Lockwoodb362a9a2009-06-22 16:20:39 -04001562 mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPEN;
1563 } else {
Wink Savillea639b312012-07-10 12:37:54 -07001564 Log.e(TAG, "mAGpsApn not set when receiving PhoneConstants.APN_ALREADY_ACTIVE");
Mike Lockwood2acfd342010-09-22 12:13:39 -04001565 mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED;
Mike Lockwoodb362a9a2009-06-22 16:20:39 -04001566 native_agps_data_conn_failed();
1567 }
Wink Savillea639b312012-07-10 12:37:54 -07001568 } else if (result == PhoneConstants.APN_REQUEST_STARTED) {
1569 if (DEBUG) Log.d(TAG, "PhoneConstants.APN_REQUEST_STARTED");
Mike Lockwood2acfd342010-09-22 12:13:39 -04001570 // Nothing to do here
Mike Lockwood58bda982009-04-14 16:25:07 -04001571 } else {
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001572 if (DEBUG) Log.d(TAG, "startUsingNetworkFeature failed, value is " +
1573 result);
Mike Lockwood2acfd342010-09-22 12:13:39 -04001574 mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED;
Mike Lockwoode3635c92009-05-11 08:38:02 -04001575 native_agps_data_conn_failed();
Mike Lockwood58bda982009-04-14 16:25:07 -04001576 }
1577 break;
Mike Lockwoode3635c92009-05-11 08:38:02 -04001578 case GPS_RELEASE_AGPS_DATA_CONN:
Mike Lockwoodb6e5fa82010-10-09 20:10:46 -04001579 if (DEBUG) Log.d(TAG, "GPS_RELEASE_AGPS_DATA_CONN");
Mike Lockwoode3635c92009-05-11 08:38:02 -04001580 if (mAGpsDataConnectionState != AGPS_DATA_CONNECTION_CLOSED) {
Mike Lockwood58bda982009-04-14 16:25:07 -04001581 mConnMgr.stopUsingNetworkFeature(
1582 ConnectivityManager.TYPE_MOBILE, Phone.FEATURE_ENABLE_SUPL);
Mike Lockwoode3635c92009-05-11 08:38:02 -04001583 native_agps_data_conn_closed();
1584 mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED;
destradaa96a14702014-06-05 11:36:30 -07001585 mAGpsDataConnectionIpAddr = null;
Mike Lockwood58bda982009-04-14 16:25:07 -04001586 }
1587 break;
Mike Lockwoode3635c92009-05-11 08:38:02 -04001588 case GPS_AGPS_DATA_CONNECTED:
Mike Lockwoodb6e5fa82010-10-09 20:10:46 -04001589 if (DEBUG) Log.d(TAG, "GPS_AGPS_DATA_CONNECTED");
Mike Lockwood58bda982009-04-14 16:25:07 -04001590 break;
Mike Lockwoode3635c92009-05-11 08:38:02 -04001591 case GPS_AGPS_DATA_CONN_DONE:
Mike Lockwoodb6e5fa82010-10-09 20:10:46 -04001592 if (DEBUG) Log.d(TAG, "GPS_AGPS_DATA_CONN_DONE");
Mike Lockwood58bda982009-04-14 16:25:07 -04001593 break;
Mike Lockwoode3635c92009-05-11 08:38:02 -04001594 case GPS_AGPS_DATA_CONN_FAILED:
Mike Lockwoodb6e5fa82010-10-09 20:10:46 -04001595 if (DEBUG) Log.d(TAG, "GPS_AGPS_DATA_CONN_FAILED");
Mike Lockwood58bda982009-04-14 16:25:07 -04001596 break;
destradaa931a37f2014-08-12 16:36:59 -07001597 default:
1598 Log.d(TAG, "Received Unknown AGPS status: " + status);
Mike Lockwood58bda982009-04-14 16:25:07 -04001599 }
1600 }
1601
Mike Lockwoodb16e7802009-08-06 09:26:02 -04001602 /**
1603 * called from native code to report NMEA data received
1604 */
Mike Lockwoodf602d362010-06-20 14:28:16 -07001605 private void reportNmea(long timestamp) {
destradaaea8a8a62014-06-23 18:19:03 -07001606 int length = native_read_nmea(mNmeaBuffer, mNmeaBuffer.length);
1607 String nmea = new String(mNmeaBuffer, 0 /* offset */, length);
1608 mListenerHelper.onNmeaReceived(timestamp, nmea);
1609 }
Mike Lockwoodb16e7802009-08-06 09:26:02 -04001610
destradaaea8a8a62014-06-23 18:19:03 -07001611 /**
destradaa4b3e3932014-07-21 18:01:47 -07001612 * called from native code - Gps measurements callback
destradaaea8a8a62014-06-23 18:19:03 -07001613 */
1614 private void reportMeasurementData(GpsMeasurementsEvent event) {
1615 mGpsMeasurementsProvider.onMeasurementsAvailable(event);
Mike Lockwoodb16e7802009-08-06 09:26:02 -04001616 }
1617
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001618 /**
destradaa4b3e3932014-07-21 18:01:47 -07001619 * called from native code - GPS navigation message callback
1620 */
1621 private void reportNavigationMessage(GpsNavigationMessageEvent event) {
1622 mGpsNavigationMessageProvider.onNavigationMessageAvailable(event);
1623 }
1624
1625 /**
Mike Lockwood04598b62010-04-14 17:17:24 -04001626 * called from native code to inform us what the GPS engine capabilities are
1627 */
1628 private void setEngineCapabilities(int capabilities) {
1629 mEngineCapabilities = capabilities;
Mike Lockwood9b9fb5c2011-06-29 15:09:40 -04001630
1631 if (!hasCapability(GPS_CAPABILITY_ON_DEMAND_TIME) && !mPeriodicTimeInjection) {
1632 mPeriodicTimeInjection = true;
1633 requestUtcTime();
1634 }
destradaa6568d702014-10-27 12:47:41 -07001635
1636 mGpsMeasurementsProvider.onCapabilitiesUpdated(
1637 (capabilities & GPS_CAPABILITY_MEASUREMENTS) == GPS_CAPABILITY_MEASUREMENTS);
1638 mGpsNavigationMessageProvider.onCapabilitiesUpdated(
1639 (capabilities & GPS_CAPABILITY_NAV_MESSAGES) == GPS_CAPABILITY_NAV_MESSAGES);
Mike Lockwood04598b62010-04-14 17:17:24 -04001640 }
1641
1642 /**
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001643 * called from native code to request XTRA data
1644 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001645 private void xtraDownloadRequest() {
Joe Onoratof5d95cb2010-01-07 21:48:32 -05001646 if (DEBUG) Log.d(TAG, "xtraDownloadRequest");
Mike Lockwood98e48692010-04-07 16:32:51 -04001647 sendMessage(DOWNLOAD_XTRA_DATA, 0, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001648 }
1649
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001650 /**
destradaa0682809a2013-08-12 18:50:30 -07001651 * Helper method to construct a location object.
1652 */
1653 private Location buildLocation(
1654 int flags,
1655 double latitude,
1656 double longitude,
1657 double altitude,
1658 float speed,
1659 float bearing,
1660 float accuracy,
1661 long timestamp) {
1662 Location location = new Location(LocationManager.GPS_PROVIDER);
1663 if((flags & LOCATION_HAS_LAT_LONG) == LOCATION_HAS_LAT_LONG) {
1664 location.setLatitude(latitude);
1665 location.setLongitude(longitude);
1666 location.setTime(timestamp);
1667 location.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());
1668 }
1669 if((flags & LOCATION_HAS_ALTITUDE) == LOCATION_HAS_ALTITUDE) {
1670 location.setAltitude(altitude);
1671 }
1672 if((flags & LOCATION_HAS_SPEED) == LOCATION_HAS_SPEED) {
1673 location.setSpeed(speed);
1674 }
1675 if((flags & LOCATION_HAS_BEARING) == LOCATION_HAS_BEARING) {
1676 location.setBearing(bearing);
1677 }
1678 if((flags & LOCATION_HAS_ACCURACY) == LOCATION_HAS_ACCURACY) {
1679 location.setAccuracy(accuracy);
1680 }
1681 return location;
1682 }
1683
1684 /**
1685 * Converts the GPS HAL status to the internal Geofence Hardware status.
1686 */
1687 private int getGeofenceStatus(int status) {
1688 switch(status) {
1689 case GPS_GEOFENCE_OPERATION_SUCCESS:
1690 return GeofenceHardware.GEOFENCE_SUCCESS;
1691 case GPS_GEOFENCE_ERROR_GENERIC:
1692 return GeofenceHardware.GEOFENCE_FAILURE;
1693 case GPS_GEOFENCE_ERROR_ID_EXISTS:
1694 return GeofenceHardware.GEOFENCE_ERROR_ID_EXISTS;
1695 case GPS_GEOFENCE_ERROR_INVALID_TRANSITION:
1696 return GeofenceHardware.GEOFENCE_ERROR_INVALID_TRANSITION;
1697 case GPS_GEOFENCE_ERROR_TOO_MANY_GEOFENCES:
1698 return GeofenceHardware.GEOFENCE_ERROR_TOO_MANY_GEOFENCES;
1699 case GPS_GEOFENCE_ERROR_ID_UNKNOWN:
1700 return GeofenceHardware.GEOFENCE_ERROR_ID_UNKNOWN;
1701 default:
1702 return -1;
1703 }
1704 }
1705
1706 /**
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001707 * Called from native to report GPS Geofence transition
1708 * All geofence callbacks are called on the same thread
1709 */
1710 private void reportGeofenceTransition(int geofenceId, int flags, double latitude,
1711 double longitude, double altitude, float speed, float bearing, float accuracy,
1712 long timestamp, int transition, long transitionTimestamp) {
1713 if (mGeofenceHardwareImpl == null) {
1714 mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
1715 }
destradaa0682809a2013-08-12 18:50:30 -07001716 Location location = buildLocation(
1717 flags,
1718 latitude,
1719 longitude,
1720 altitude,
1721 speed,
1722 bearing,
1723 accuracy,
1724 timestamp);
1725 mGeofenceHardwareImpl.reportGeofenceTransition(
1726 geofenceId,
1727 location,
1728 transition,
1729 transitionTimestamp,
1730 GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE,
1731 FusedBatchOptions.SourceTechnologies.GNSS);
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001732 }
1733
1734 /**
1735 * called from native code to report GPS status change.
1736 */
1737 private void reportGeofenceStatus(int status, int flags, double latitude,
1738 double longitude, double altitude, float speed, float bearing, float accuracy,
1739 long timestamp) {
1740 if (mGeofenceHardwareImpl == null) {
1741 mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
1742 }
destradaa0682809a2013-08-12 18:50:30 -07001743 Location location = buildLocation(
1744 flags,
1745 latitude,
1746 longitude,
1747 altitude,
1748 speed,
1749 bearing,
1750 accuracy,
1751 timestamp);
1752 int monitorStatus = GeofenceHardware.MONITOR_CURRENTLY_UNAVAILABLE;
1753 if(status == GPS_GEOFENCE_AVAILABLE) {
1754 monitorStatus = GeofenceHardware.MONITOR_CURRENTLY_AVAILABLE;
1755 }
1756 mGeofenceHardwareImpl.reportGeofenceMonitorStatus(
1757 GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE,
1758 monitorStatus,
1759 location,
1760 FusedBatchOptions.SourceTechnologies.GNSS);
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001761 }
1762
1763 /**
1764 * called from native code - Geofence Add callback
1765 */
1766 private void reportGeofenceAddStatus(int geofenceId, int status) {
1767 if (mGeofenceHardwareImpl == null) {
1768 mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
1769 }
destradaa0682809a2013-08-12 18:50:30 -07001770 mGeofenceHardwareImpl.reportGeofenceAddStatus(geofenceId, getGeofenceStatus(status));
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001771 }
1772
1773 /**
1774 * called from native code - Geofence Remove callback
1775 */
1776 private void reportGeofenceRemoveStatus(int geofenceId, int status) {
1777 if (mGeofenceHardwareImpl == null) {
1778 mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
1779 }
destradaa0682809a2013-08-12 18:50:30 -07001780 mGeofenceHardwareImpl.reportGeofenceRemoveStatus(geofenceId, getGeofenceStatus(status));
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001781 }
1782
1783 /**
1784 * called from native code - Geofence Pause callback
1785 */
1786 private void reportGeofencePauseStatus(int geofenceId, int status) {
1787 if (mGeofenceHardwareImpl == null) {
1788 mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
1789 }
destradaa0682809a2013-08-12 18:50:30 -07001790 mGeofenceHardwareImpl.reportGeofencePauseStatus(geofenceId, getGeofenceStatus(status));
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001791 }
1792
1793 /**
1794 * called from native code - Geofence Resume callback
1795 */
1796 private void reportGeofenceResumeStatus(int geofenceId, int status) {
1797 if (mGeofenceHardwareImpl == null) {
1798 mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
1799 }
destradaa0682809a2013-08-12 18:50:30 -07001800 mGeofenceHardwareImpl.reportGeofenceResumeStatus(geofenceId, getGeofenceStatus(status));
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001801 }
1802
Danke Xie22d1f9f2009-08-18 18:28:45 -04001803 //=============================================================
1804 // NI Client support
Miguel Torroja1e84da82010-07-27 07:02:24 +02001805 //=============================================================
Danke Xie22d1f9f2009-08-18 18:28:45 -04001806 private final INetInitiatedListener mNetInitiatedListener = new INetInitiatedListener.Stub() {
Miguel Torroja1e84da82010-07-27 07:02:24 +02001807 // Sends a response for an NI reqeust to HAL.
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001808 @Override
Miguel Torroja1e84da82010-07-27 07:02:24 +02001809 public boolean sendNiResponse(int notificationId, int userResponse)
1810 {
1811 // TODO Add Permission check
Danke Xie22d1f9f2009-08-18 18:28:45 -04001812
Miguel Torroja1e84da82010-07-27 07:02:24 +02001813 if (DEBUG) Log.d(TAG, "sendNiResponse, notifId: " + notificationId +
1814 ", response: " + userResponse);
1815 native_send_ni_response(notificationId, userResponse);
1816 return true;
1817 }
Danke Xie22d1f9f2009-08-18 18:28:45 -04001818 };
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001819
Danke Xie22d1f9f2009-08-18 18:28:45 -04001820 public INetInitiatedListener getNetInitiatedListener() {
1821 return mNetInitiatedListener;
1822 }
1823
1824 // Called by JNI function to report an NI request.
Miguel Torroja1e84da82010-07-27 07:02:24 +02001825 public void reportNiNotification(
1826 int notificationId,
1827 int niType,
1828 int notifyFlags,
1829 int timeout,
1830 int defaultResponse,
1831 String requestorId,
1832 String text,
1833 int requestorIdEncoding,
1834 int textEncoding,
1835 String extras // Encoded extra data
Danke Xie22d1f9f2009-08-18 18:28:45 -04001836 )
Miguel Torroja1e84da82010-07-27 07:02:24 +02001837 {
1838 Log.i(TAG, "reportNiNotification: entered");
1839 Log.i(TAG, "notificationId: " + notificationId +
1840 ", niType: " + niType +
1841 ", notifyFlags: " + notifyFlags +
1842 ", timeout: " + timeout +
1843 ", defaultResponse: " + defaultResponse);
1844
1845 Log.i(TAG, "requestorId: " + requestorId +
1846 ", text: " + text +
1847 ", requestorIdEncoding: " + requestorIdEncoding +
1848 ", textEncoding: " + textEncoding);
1849
1850 GpsNiNotification notification = new GpsNiNotification();
1851
1852 notification.notificationId = notificationId;
1853 notification.niType = niType;
1854 notification.needNotify = (notifyFlags & GpsNetInitiatedHandler.GPS_NI_NEED_NOTIFY) != 0;
1855 notification.needVerify = (notifyFlags & GpsNetInitiatedHandler.GPS_NI_NEED_VERIFY) != 0;
1856 notification.privacyOverride = (notifyFlags & GpsNetInitiatedHandler.GPS_NI_PRIVACY_OVERRIDE) != 0;
1857 notification.timeout = timeout;
1858 notification.defaultResponse = defaultResponse;
1859 notification.requestorId = requestorId;
1860 notification.text = text;
1861 notification.requestorIdEncoding = requestorIdEncoding;
1862 notification.textEncoding = textEncoding;
1863
1864 // Process extras, assuming the format is
1865 // one of more lines of "key = value"
1866 Bundle bundle = new Bundle();
1867
1868 if (extras == null) extras = "";
1869 Properties extraProp = new Properties();
1870
1871 try {
Jeff Sharkey104344e2011-07-10 14:20:41 -07001872 extraProp.load(new StringReader(extras));
Miguel Torroja1e84da82010-07-27 07:02:24 +02001873 }
1874 catch (IOException e)
1875 {
1876 Log.e(TAG, "reportNiNotification cannot parse extras data: " + extras);
1877 }
1878
1879 for (Entry<Object, Object> ent : extraProp.entrySet())
1880 {
1881 bundle.putString((String) ent.getKey(), (String) ent.getValue());
1882 }
1883
1884 notification.extras = bundle;
1885
1886 mNIHandler.handleNiNotification(notification);
1887 }
1888
1889 /**
1890 * Called from native code to request set id info.
1891 * We should be careful about receiving null string from the TelephonyManager,
1892 * because sending null String to JNI function would cause a crash.
1893 */
1894
1895 private void requestSetID(int flags) {
1896 TelephonyManager phone = (TelephonyManager)
1897 mContext.getSystemService(Context.TELEPHONY_SERVICE);
1898 int type = AGPS_SETID_TYPE_NONE;
1899 String data = "";
1900
1901 if ((flags & AGPS_RIL_REQUEST_SETID_IMSI) == AGPS_RIL_REQUEST_SETID_IMSI) {
1902 String data_temp = phone.getSubscriberId();
1903 if (data_temp == null) {
1904 // This means the framework does not have the SIM card ready.
1905 } else {
1906 // This means the framework has the SIM card.
1907 data = data_temp;
1908 type = AGPS_SETID_TYPE_IMSI;
1909 }
1910 }
1911 else if ((flags & AGPS_RIL_REQUEST_SETID_MSISDN) == AGPS_RIL_REQUEST_SETID_MSISDN) {
1912 String data_temp = phone.getLine1Number();
1913 if (data_temp == null) {
1914 // This means the framework does not have the SIM card ready.
1915 } else {
1916 // This means the framework has the SIM card.
1917 data = data_temp;
1918 type = AGPS_SETID_TYPE_MSISDN;
1919 }
1920 }
1921 native_agps_set_id(type, data);
1922 }
1923
1924 /**
Mike Lockwood9b9fb5c2011-06-29 15:09:40 -04001925 * Called from native code to request utc time info
1926 */
1927
1928 private void requestUtcTime() {
1929 sendMessage(INJECT_NTP_TIME, 0, null);
1930 }
1931
1932 /**
Miguel Torroja1e84da82010-07-27 07:02:24 +02001933 * Called from native code to request reference location info
1934 */
1935
1936 private void requestRefLocation(int flags) {
1937 TelephonyManager phone = (TelephonyManager)
1938 mContext.getSystemService(Context.TELEPHONY_SERVICE);
Victoria Leased50d0c32012-10-29 13:16:17 -07001939 final int phoneType = phone.getPhoneType();
1940 if (phoneType == TelephonyManager.PHONE_TYPE_GSM) {
Miguel Torroja1e84da82010-07-27 07:02:24 +02001941 GsmCellLocation gsm_cell = (GsmCellLocation) phone.getCellLocation();
Victoria Leased50d0c32012-10-29 13:16:17 -07001942 if ((gsm_cell != null) && (phone.getNetworkOperator() != null)
1943 && (phone.getNetworkOperator().length() > 3)) {
Miguel Torroja1e84da82010-07-27 07:02:24 +02001944 int type;
1945 int mcc = Integer.parseInt(phone.getNetworkOperator().substring(0,3));
1946 int mnc = Integer.parseInt(phone.getNetworkOperator().substring(3));
Mike Lockwoodedc0f3872010-10-22 09:16:17 -04001947 int networkType = phone.getNetworkType();
1948 if (networkType == TelephonyManager.NETWORK_TYPE_UMTS
1949 || networkType == TelephonyManager.NETWORK_TYPE_HSDPA
1950 || networkType == TelephonyManager.NETWORK_TYPE_HSUPA
Arun Ravindran58d46122012-07-30 17:50:21 +03001951 || networkType == TelephonyManager.NETWORK_TYPE_HSPA
1952 || networkType == TelephonyManager.NETWORK_TYPE_HSPAP) {
Miguel Torroja1e84da82010-07-27 07:02:24 +02001953 type = AGPS_REF_LOCATION_TYPE_UMTS_CELLID;
Mike Lockwoodedc0f3872010-10-22 09:16:17 -04001954 } else {
Miguel Torroja1e84da82010-07-27 07:02:24 +02001955 type = AGPS_REF_LOCATION_TYPE_GSM_CELLID;
Mike Lockwoodedc0f3872010-10-22 09:16:17 -04001956 }
Miguel Torroja1e84da82010-07-27 07:02:24 +02001957 native_agps_set_ref_location_cellid(type, mcc, mnc,
1958 gsm_cell.getLac(), gsm_cell.getCid());
Mike Lockwoodedc0f3872010-10-22 09:16:17 -04001959 } else {
Miguel Torroja1e84da82010-07-27 07:02:24 +02001960 Log.e(TAG,"Error getting cell location info.");
Mike Lockwoodedc0f3872010-10-22 09:16:17 -04001961 }
Victoria Leased50d0c32012-10-29 13:16:17 -07001962 } else if (phoneType == TelephonyManager.PHONE_TYPE_CDMA) {
1963 Log.e(TAG, "CDMA not supported.");
Mike Lockwoodedc0f3872010-10-22 09:16:17 -04001964 }
Miguel Torroja1e84da82010-07-27 07:02:24 +02001965 }
Danke Xie22d1f9f2009-08-18 18:28:45 -04001966
Mike Lockwood98e48692010-04-07 16:32:51 -04001967 private void sendMessage(int message, int arg, Object obj) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001968 // hold a wake lock until this message is delivered
Jeff Brown028872f2012-08-25 13:07:01 -07001969 // note that this assumes the message will not be removed from the queue before
1970 // it is handled (otherwise the wake lock would be leaked).
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001971 mWakeLock.acquire();
1972 mHandler.obtainMessage(message, arg, 1, obj).sendToTarget();
Mike Lockwood98e48692010-04-07 16:32:51 -04001973 }
1974
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001975 private final class ProviderHandler extends Handler {
Victoria Lease5cd731a2012-12-19 15:04:21 -08001976 public ProviderHandler(Looper looper) {
1977 super(looper, null, true /*async*/);
Jeff Brown028872f2012-08-25 13:07:01 -07001978 }
1979
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001980 @Override
Mike Lockwood4a7b65e2010-10-25 16:35:55 -04001981 public void handleMessage(Message msg) {
Mike Lockwood98e48692010-04-07 16:32:51 -04001982 int message = msg.what;
1983 switch (message) {
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001984 case ENABLE:
1985 if (msg.arg1 == 1) {
1986 handleEnable();
1987 } else {
1988 handleDisable();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001989 }
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001990 break;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001991 case SET_REQUEST:
1992 GpsRequest gpsRequest = (GpsRequest) msg.obj;
1993 handleSetRequest(gpsRequest.request, gpsRequest.source);
Mike Lockwood03ca2162010-04-01 08:10:09 -07001994 break;
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001995 case UPDATE_NETWORK_STATE:
1996 handleUpdateNetworkState(msg.arg1, (NetworkInfo)msg.obj);
1997 break;
1998 case INJECT_NTP_TIME:
1999 handleInjectNtpTime();
2000 break;
2001 case DOWNLOAD_XTRA_DATA:
Mike Lockwood1a1cd3a2010-08-17 07:42:54 -04002002 if (mSupportsXtra) {
Mike Lockwood62a8fc12010-03-22 14:23:26 -04002003 handleDownloadXtraData();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002004 }
Mike Lockwood62a8fc12010-03-22 14:23:26 -04002005 break;
Kevin Tang40e1baf2012-01-10 14:32:44 -08002006 case INJECT_NTP_TIME_FINISHED:
2007 mInjectNtpTimePending = STATE_IDLE;
2008 break;
2009 case DOWNLOAD_XTRA_DATA_FINISHED:
2010 mDownloadXtraDataPending = STATE_IDLE;
2011 break;
Mike Lockwood62a8fc12010-03-22 14:23:26 -04002012 case UPDATE_LOCATION:
2013 handleUpdateLocation((Location)msg.obj);
2014 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002015 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002016 if (msg.arg2 == 1) {
2017 // wakelock was taken for this message, release it
2018 mWakeLock.release();
Mike Lockwood98e48692010-04-07 16:32:51 -04002019 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002020 }
Mike Lockwood62a8fc12010-03-22 14:23:26 -04002021 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002022
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002023 private final class NetworkLocationListener implements LocationListener {
2024 @Override
2025 public void onLocationChanged(Location location) {
2026 // this callback happens on mHandler looper
2027 if (LocationManager.NETWORK_PROVIDER.equals(location.getProvider())) {
2028 handleUpdateLocation(location);
2029 }
2030 }
2031 @Override
2032 public void onStatusChanged(String provider, int status, Bundle extras) { }
2033 @Override
2034 public void onProviderEnabled(String provider) { }
2035 @Override
2036 public void onProviderDisabled(String provider) { }
2037 }
2038
Kevin Tanga5fe6b22011-06-05 14:25:16 -07002039 private String getSelectedApn() {
2040 Uri uri = Uri.parse("content://telephony/carriers/preferapn");
destradaa96a14702014-06-05 11:36:30 -07002041 Cursor cursor = null;
2042 try {
2043 cursor = mContext.getContentResolver().query(
2044 uri,
2045 new String[] { "apn" },
2046 null /* selection */,
2047 null /* selectionArgs */,
2048 Carriers.DEFAULT_SORT_ORDER);
2049 if (cursor != null && cursor.moveToFirst()) {
2050 return cursor.getString(0);
2051 } else {
2052 Log.e(TAG, "No APN found to select.");
2053 }
2054 } catch (Exception e) {
destradaaea8a8a62014-06-23 18:19:03 -07002055 Log.e(TAG, "Error encountered on selecting the APN.", e);
destradaa96a14702014-06-05 11:36:30 -07002056 } finally {
2057 if (cursor != null) {
Kevin Tanga5fe6b22011-06-05 14:25:16 -07002058 cursor.close();
2059 }
2060 }
destradaa96a14702014-06-05 11:36:30 -07002061
2062 return null;
2063 }
2064
2065 private int getApnIpType(String apn) {
2066 if (apn == null) {
2067 return APN_INVALID;
2068 }
2069
2070 // look for cached data to use
2071 if (apn.equals(mAGpsApn) && mApnIpType != APN_INVALID) {
2072 return mApnIpType;
2073 }
2074
2075 String selection = String.format("current = 1 and apn = '%s' and carrier_enabled = 1", apn);
2076 Cursor cursor = null;
2077 try {
2078 cursor = mContext.getContentResolver().query(
2079 Carriers.CONTENT_URI,
2080 new String[] { Carriers.PROTOCOL },
2081 selection,
2082 null,
2083 Carriers.DEFAULT_SORT_ORDER);
2084
2085 if (null != cursor && cursor.moveToFirst()) {
2086 return translateToApnIpType(cursor.getString(0), apn);
2087 } else {
2088 Log.e(TAG, "No entry found in query for APN: " + apn);
2089 }
2090 } catch (Exception e) {
2091 Log.e(TAG, "Error encountered on APN query for: " + apn, e);
2092 } finally {
2093 if (cursor != null) {
2094 cursor.close();
2095 }
2096 }
2097
2098 return APN_INVALID;
2099 }
2100
2101 private int translateToApnIpType(String ipProtocol, String apn) {
2102 if ("IP".equals(ipProtocol)) {
2103 return APN_IPV4;
2104 }
2105 if ("IPV6".equals(ipProtocol)) {
2106 return APN_IPV6;
2107 }
2108 if ("IPV4V6".equals(ipProtocol)) {
2109 return APN_IPV4V6;
2110 }
2111
2112 // we hit the default case so the ipProtocol is not recognized
2113 String message = String.format("Unknown IP Protocol: %s, for APN: %s", ipProtocol, apn);
2114 Log.e(TAG, message);
2115 return APN_INVALID;
2116 }
2117
2118 private void setRouting() {
2119 if (mAGpsDataConnectionIpAddr == null) {
2120 return;
2121 }
2122
2123 boolean result = mConnMgr.requestRouteToHostAddress(
2124 ConnectivityManager.TYPE_MOBILE_SUPL,
2125 mAGpsDataConnectionIpAddr);
2126
2127 if (!result) {
2128 Log.e(TAG, "Error requesting route to host: " + mAGpsDataConnectionIpAddr);
2129 } else if (DEBUG) {
2130 Log.d(TAG, "Successfully requested route to host: " + mAGpsDataConnectionIpAddr);
2131 }
Kevin Tanga5fe6b22011-06-05 14:25:16 -07002132 }
2133
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002134 @Override
2135 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
2136 StringBuilder s = new StringBuilder();
2137 s.append(" mFixInterval=").append(mFixInterval).append("\n");
David Christied4edf4c2014-08-12 15:22:27 -07002138 s.append(" mDisableGps (battery saver mode)=").append(mDisableGps).append("\n");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002139 s.append(" mEngineCapabilities=0x").append(Integer.toHexString(mEngineCapabilities)).append(" (");
2140 if (hasCapability(GPS_CAPABILITY_SCHEDULING)) s.append("SCHED ");
2141 if (hasCapability(GPS_CAPABILITY_MSB)) s.append("MSB ");
2142 if (hasCapability(GPS_CAPABILITY_MSA)) s.append("MSA ");
2143 if (hasCapability(GPS_CAPABILITY_SINGLE_SHOT)) s.append("SINGLE_SHOT ");
2144 if (hasCapability(GPS_CAPABILITY_ON_DEMAND_TIME)) s.append("ON_DEMAND_TIME ");
2145 s.append(")\n");
2146
2147 s.append(native_get_internal_state());
2148 pw.append(s);
2149 }
2150
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002151 // for GPS SV statistics
2152 private static final int MAX_SVS = 32;
2153 private static final int EPHEMERIS_MASK = 0;
2154 private static final int ALMANAC_MASK = 1;
2155 private static final int USED_FOR_FIX_MASK = 2;
2156
2157 // preallocated arrays, to avoid memory allocation in reportStatus()
2158 private int mSvs[] = new int[MAX_SVS];
2159 private float mSnrs[] = new float[MAX_SVS];
2160 private float mSvElevations[] = new float[MAX_SVS];
2161 private float mSvAzimuths[] = new float[MAX_SVS];
2162 private int mSvMasks[] = new int[3];
2163 private int mSvCount;
Mike Lockwoodb16e7802009-08-06 09:26:02 -04002164 // preallocated to avoid memory allocation in reportNmea()
2165 private byte[] mNmeaBuffer = new byte[120];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002166
2167 static { class_init_native(); }
2168 private static native void class_init_native();
2169 private static native boolean native_is_supported();
2170
2171 private native boolean native_init();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002172 private native void native_cleanup();
Mike Lockwood04598b62010-04-14 17:17:24 -04002173 private native boolean native_set_position_mode(int mode, int recurrence, int min_interval,
2174 int preferred_accuracy, int preferred_time);
2175 private native boolean native_start();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002176 private native boolean native_stop();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002177 private native void native_delete_aiding_data(int flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002178 // returns number of SVs
2179 // mask[0] is ephemeris mask and mask[1] is almanac mask
2180 private native int native_read_sv_status(int[] svs, float[] snrs,
2181 float[] elevations, float[] azimuths, int[] masks);
Mike Lockwoodf602d362010-06-20 14:28:16 -07002182 private native int native_read_nmea(byte[] buffer, int bufferSize);
Mike Lockwoodd26ce0d2009-06-11 12:25:46 -04002183 private native void native_inject_location(double latitude, double longitude, float accuracy);
2184
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -06002185 // XTRA Support
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002186 private native void native_inject_time(long time, long timeReference, int uncertainty);
2187 private native boolean native_supports_xtra();
2188 private native void native_inject_xtra_data(byte[] data, int length);
The Android Open Source Project10592532009-03-18 17:39:46 -07002189
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -06002190 // DEBUG Support
2191 private native String native_get_internal_state();
2192
2193 // AGPS Support
destradaa96a14702014-06-05 11:36:30 -07002194 private native void native_agps_data_conn_open(String apn, int apnIpType);
Mike Lockwoode3635c92009-05-11 08:38:02 -04002195 private native void native_agps_data_conn_closed();
2196 private native void native_agps_data_conn_failed();
Miguel Torroja1e84da82010-07-27 07:02:24 +02002197 private native void native_agps_ni_message(byte [] msg, int length);
Mike Lockwooda9e54612009-06-19 14:54:42 -04002198 private native void native_set_agps_server(int type, String hostname, int port);
Danke Xie22d1f9f2009-08-18 18:28:45 -04002199
2200 // Network-initiated (NI) Support
2201 private native void native_send_ni_response(int notificationId, int userResponse);
Miguel Torroja1e84da82010-07-27 07:02:24 +02002202
2203 // AGPS ril suport
2204 private native void native_agps_set_ref_location_cellid(int type, int mcc, int mnc,
2205 int lac, int cid);
2206 private native void native_agps_set_id(int type, String setid);
Mike Lockwood50130bb2010-10-11 06:22:50 -04002207
2208 private native void native_update_network_state(boolean connected, int type,
Kevin Tanga5fe6b22011-06-05 14:25:16 -07002209 boolean roaming, boolean available, String extraInfo, String defaultAPN);
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07002210
2211 // Hardware Geofence support.
2212 private static native boolean native_is_geofence_supported();
2213 private static native boolean native_add_geofence(int geofenceId, double latitude,
2214 double longitude, double radius, int lastTransition,int monitorTransitions,
2215 int notificationResponsivenes, int unknownTimer);
2216 private static native boolean native_remove_geofence(int geofenceId);
2217 private static native boolean native_resume_geofence(int geofenceId, int transitions);
2218 private static native boolean native_pause_geofence(int geofenceId);
destradaaea8a8a62014-06-23 18:19:03 -07002219
2220 // Gps Hal measurements support.
2221 private static native boolean native_is_measurement_supported();
destradaa4b3e3932014-07-21 18:01:47 -07002222 private native boolean native_start_measurement_collection();
2223 private native boolean native_stop_measurement_collection();
2224
2225 // Gps Navigation message support.
2226 private static native boolean native_is_navigation_message_supported();
2227 private native boolean native_start_navigation_message_collection();
2228 private native boolean native_stop_navigation_message_collection();
Tsuwei Chen52617bb2014-08-25 11:49:11 -07002229
2230 // GNSS Configuration
2231 private static native void native_configuration_update(String configData);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002232}
David Christied4edf4c2014-08-12 15:22:27 -07002233