blob: eb8f8fc9af96d3fe154a57bd9e5251cce2566890 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Mike Lockwood00b74272010-03-26 10:41:48 -040017package com.android.server.location;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080018
destradaaea8a8a62014-06-23 18:19:03 -070019import com.android.internal.app.IAppOpsService;
20import com.android.internal.app.IBatteryStats;
21import com.android.internal.location.GpsNetInitiatedHandler;
22import com.android.internal.location.GpsNetInitiatedHandler.GpsNiNotification;
23import com.android.internal.location.ProviderProperties;
24import com.android.internal.location.ProviderRequest;
destradaaea8a8a62014-06-23 18:19:03 -070025
Mike Lockwood29c84342009-05-06 14:01:15 -040026import android.app.AlarmManager;
Dianne Hackborna06de0f2012-12-11 16:34:47 -080027import android.app.AppOpsManager;
Mike Lockwood29c84342009-05-06 14:01:15 -040028import android.app.PendingIntent;
The Android Open Source Project10592532009-03-18 17:39:46 -070029import android.content.BroadcastReceiver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080030import android.content.Context;
31import android.content.Intent;
The Android Open Source Project10592532009-03-18 17:39:46 -070032import android.content.IntentFilter;
Kevin Tanga5fe6b22011-06-05 14:25:16 -070033import android.database.Cursor;
destradaa0682809a2013-08-12 18:50:30 -070034import android.hardware.location.GeofenceHardware;
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -070035import android.hardware.location.GeofenceHardwareImpl;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080036import android.location.Criteria;
destradaa0682809a2013-08-12 18:50:30 -070037import android.location.FusedBatchOptions;
Lifu Tang30f95a72016-01-07 23:20:38 -080038import android.location.GnssStatus;
39import android.location.IGnssStatusListener;
40import android.location.IGnssStatusProvider;
Lifu Tang818aa2c2016-02-01 01:52:00 -080041import android.location.GnssMeasurementsEvent;
Lifu Tange8abe8e2016-04-01 10:32:05 -070042import android.location.GnssNavigationMessage;
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -070043import android.location.IGpsGeofenceHardware;
Mike Lockwood4e50b782009-04-03 08:24:43 -070044import android.location.ILocationManager;
Danke Xie22d1f9f2009-08-18 18:28:45 -040045import android.location.INetInitiatedListener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080046import android.location.Location;
Nick Pelly6fa9ad42012-07-16 12:18:23 -070047import android.location.LocationListener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080048import android.location.LocationManager;
49import android.location.LocationProvider;
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -070050import android.location.LocationRequest;
Mike Lockwood58bda982009-04-14 16:25:07 -040051import android.net.ConnectivityManager;
destradaae21252a2015-09-08 12:32:59 -070052import android.net.Network;
53import android.net.NetworkCapabilities;
Mike Lockwood03d24672009-10-08 15:45:03 -040054import android.net.NetworkInfo;
destradaae21252a2015-09-08 12:32:59 -070055import android.net.NetworkRequest;
Kevin Tanga5fe6b22011-06-05 14:25:16 -070056import android.net.Uri;
Kevin Tang40e1baf2012-01-10 14:32:44 -080057import android.os.AsyncTask;
Dianne Hackborn91268cf2013-06-13 19:06:50 -070058import android.os.BatteryStats;
Mike Lockwood63aa5a62010-04-14 19:21:31 -040059import android.os.Binder;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080060import android.os.Bundle;
Ecco Park4fa1ab72016-10-24 13:04:52 -070061import android.os.PersistableBundle;
Mike Lockwood62a8fc12010-03-22 14:23:26 -040062import android.os.Handler;
Victoria Lease5cd731a2012-12-19 15:04:21 -080063import android.os.Looper;
Mike Lockwood62a8fc12010-03-22 14:23:26 -040064import android.os.Message;
Mike Lockwood0528b9b2009-05-07 10:12:54 -040065import android.os.PowerManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080066import android.os.RemoteException;
Mike Lockwood2f82c4e2009-04-17 08:24:10 -040067import android.os.ServiceManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080068import android.os.SystemClock;
Colin Cross7c030ed2014-01-28 09:33:53 -080069import android.os.SystemProperties;
Dianne Hackborn5ac72a22012-08-29 18:32:08 -070070import android.os.UserHandle;
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -070071import android.os.WorkSource;
Mike Lockwoodbcab8df2009-06-25 16:39:09 -040072import android.provider.Settings;
Kevin Tanga5fe6b22011-06-05 14:25:16 -070073import android.provider.Telephony.Carriers;
Miguel Torroja1e84da82010-07-27 07:02:24 +020074import android.provider.Telephony.Sms.Intents;
Jake Hambyb49a73d2011-03-15 20:09:46 -070075import android.telephony.SmsMessage;
Wink Savillea374c3d2014-11-11 11:48:04 -080076import android.telephony.SubscriptionManager;
Wink Savilled09c4ca2014-11-22 10:08:16 -080077import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
Miguel Torroja1e84da82010-07-27 07:02:24 +020078import android.telephony.TelephonyManager;
Ecco Park4fa1ab72016-10-24 13:04:52 -070079import android.telephony.CarrierConfigManager;
Miguel Torroja1e84da82010-07-27 07:02:24 +020080import android.telephony.gsm.GsmCellLocation;
Colin Cross7c030ed2014-01-28 09:33:53 -080081import android.text.TextUtils;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080082import android.util.Log;
Jeff Sharkey104344e2011-07-10 14:20:41 -070083import android.util.NtpTrustedTime;
Dianne Hackborna06de0f2012-12-11 16:34:47 -080084
Tsuwei Chen52617bb2014-08-25 11:49:11 -070085import java.io.ByteArrayOutputStream;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080086import java.io.File;
Nick Pelly6fa9ad42012-07-16 12:18:23 -070087import java.io.FileDescriptor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080088import java.io.FileInputStream;
89import java.io.IOException;
Nick Pelly6fa9ad42012-07-16 12:18:23 -070090import java.io.PrintWriter;
Jeff Sharkey104344e2011-07-10 14:20:41 -070091import java.io.StringReader;
destradaaea8a8a62014-06-23 18:19:03 -070092import java.net.InetAddress;
93import java.net.UnknownHostException;
Andreas Gampee6748ce2015-12-11 18:00:38 -080094import java.util.Arrays;
Mike Lockwoodf1218be2010-01-29 09:20:06 -050095import java.util.Date;
Danke Xie22d1f9f2009-08-18 18:28:45 -040096import java.util.Map.Entry;
Jake Hambyb49a73d2011-03-15 20:09:46 -070097import java.util.Properties;
Hridya Valsaraju2ea29602016-09-13 08:38:09 -070098import java.util.Map;
99import java.util.HashMap;
Colin Cross7c030ed2014-01-28 09:33:53 -0800100import libcore.io.IoUtils;
101
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800102/**
gomo4402af62017-01-11 13:20:13 -0800103 * A GNSS implementation of LocationProvider used by LocationManager.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800104 *
105 * {@hide}
106 */
Lifu Tang30f95a72016-01-07 23:20:38 -0800107public class GnssLocationProvider implements LocationProviderInterface {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800108
Lifu Tang30f95a72016-01-07 23:20:38 -0800109 private static final String TAG = "GnssLocationProvider";
Mike Lockwood29c84342009-05-06 14:01:15 -0400110
Brian Muramatsu1715cb32012-08-08 17:32:21 -0700111 private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
112 private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400113
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700114 private static final ProviderProperties PROPERTIES = new ProviderProperties(
115 true, true, false, false, true, true, true,
116 Criteria.POWER_HIGH, Criteria.ACCURACY_FINE);
117
gomo4402af62017-01-11 13:20:13 -0800118 // these need to match GnssPositionMode enum in IGnss.hal
The Android Open Source Project10592532009-03-18 17:39:46 -0700119 private static final int GPS_POSITION_MODE_STANDALONE = 0;
120 private static final int GPS_POSITION_MODE_MS_BASED = 1;
121 private static final int GPS_POSITION_MODE_MS_ASSISTED = 2;
122
gomo4402af62017-01-11 13:20:13 -0800123 // these need to match GnssPositionRecurrence enum in IGnss.hal
Mike Lockwood04598b62010-04-14 17:17:24 -0400124 private static final int GPS_POSITION_RECURRENCE_PERIODIC = 0;
125 private static final int GPS_POSITION_RECURRENCE_SINGLE = 1;
126
gomo4402af62017-01-11 13:20:13 -0800127 // these need to match GnssStatusValue enum in IGnssCallback.hal
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800128 private static final int GPS_STATUS_NONE = 0;
129 private static final int GPS_STATUS_SESSION_BEGIN = 1;
130 private static final int GPS_STATUS_SESSION_END = 2;
131 private static final int GPS_STATUS_ENGINE_ON = 3;
132 private static final int GPS_STATUS_ENGINE_OFF = 4;
133
gomo4402af62017-01-11 13:20:13 -0800134 // these need to match AGnssStatusValue enum in IAGnssCallback.hal
Mike Lockwoode3635c92009-05-11 08:38:02 -0400135 /** AGPS status event values. */
136 private static final int GPS_REQUEST_AGPS_DATA_CONN = 1;
137 private static final int GPS_RELEASE_AGPS_DATA_CONN = 2;
138 private static final int GPS_AGPS_DATA_CONNECTED = 3;
139 private static final int GPS_AGPS_DATA_CONN_DONE = 4;
140 private static final int GPS_AGPS_DATA_CONN_FAILED = 5;
Mike Lockwood58bda982009-04-14 16:25:07 -0400141
gomo4402af62017-01-11 13:20:13 -0800142 // these need to match GnssLocationFlags enum in types.hal
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800143 private static final int LOCATION_INVALID = 0;
144 private static final int LOCATION_HAS_LAT_LONG = 1;
145 private static final int LOCATION_HAS_ALTITUDE = 2;
146 private static final int LOCATION_HAS_SPEED = 4;
147 private static final int LOCATION_HAS_BEARING = 8;
gomo4402af62017-01-11 13:20:13 -0800148 private static final int LOCATION_HAS_HORIZONTAL_ACCURACY = 16;
149 private static final int LOCATION_HAS_VERTICAL_ACCURACY = 32;
150 private static final int LOCATION_HAS_SPEED_ACCURACY = 64;
151 private static final int LOCATION_HAS_BEARING_ACCURACY = 128;
Mike Lockwoode3635c92009-05-11 08:38:02 -0400152
gomo4402af62017-01-11 13:20:13 -0800153
154 // IMPORTANT - the GPS_DELETE_* symbols here must match GnssAidingData enum in IGnss.hal
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800155 private static final int GPS_DELETE_EPHEMERIS = 0x0001;
156 private static final int GPS_DELETE_ALMANAC = 0x0002;
157 private static final int GPS_DELETE_POSITION = 0x0004;
158 private static final int GPS_DELETE_TIME = 0x0008;
159 private static final int GPS_DELETE_IONO = 0x0010;
160 private static final int GPS_DELETE_UTC = 0x0020;
161 private static final int GPS_DELETE_HEALTH = 0x0040;
162 private static final int GPS_DELETE_SVDIR = 0x0080;
163 private static final int GPS_DELETE_SVSTEER = 0x0100;
164 private static final int GPS_DELETE_SADATA = 0x0200;
165 private static final int GPS_DELETE_RTI = 0x0400;
166 private static final int GPS_DELETE_CELLDB_INFO = 0x8000;
167 private static final int GPS_DELETE_ALL = 0xFFFF;
168
gomo4402af62017-01-11 13:20:13 -0800169 // The GPS_CAPABILITY_* flags must match Capabilities enum in IGnssCallback.hal
Mike Lockwood04598b62010-04-14 17:17:24 -0400170 private static final int GPS_CAPABILITY_SCHEDULING = 0x0000001;
171 private static final int GPS_CAPABILITY_MSB = 0x0000002;
172 private static final int GPS_CAPABILITY_MSA = 0x0000004;
173 private static final int GPS_CAPABILITY_SINGLE_SHOT = 0x0000008;
Mike Lockwood9b9fb5c2011-06-29 15:09:40 -0400174 private static final int GPS_CAPABILITY_ON_DEMAND_TIME = 0x0000010;
destradaa6568d702014-10-27 12:47:41 -0700175 private static final int GPS_CAPABILITY_GEOFENCING = 0x0000020;
176 private static final int GPS_CAPABILITY_MEASUREMENTS = 0x0000040;
177 private static final int GPS_CAPABILITY_NAV_MESSAGES = 0x0000080;
Mike Lockwood04598b62010-04-14 17:17:24 -0400178
Tsuwei Chen462bcd82014-09-17 12:28:49 -0700179 // The AGPS SUPL mode
180 private static final int AGPS_SUPL_MODE_MSA = 0x02;
181 private static final int AGPS_SUPL_MODE_MSB = 0x01;
182
gomo4402af62017-01-11 13:20:13 -0800183 // these need to match AGnssType enum in IAGnssCallback.hal
Mike Lockwoode3635c92009-05-11 08:38:02 -0400184 private static final int AGPS_TYPE_SUPL = 1;
185 private static final int AGPS_TYPE_C2K = 2;
186
gomo4402af62017-01-11 13:20:13 -0800187 // these must match the ApnIpType enum in IAGnss.hal
destradaa96a14702014-06-05 11:36:30 -0700188 private static final int APN_INVALID = 0;
189 private static final int APN_IPV4 = 1;
190 private static final int APN_IPV6 = 2;
191 private static final int APN_IPV4V6 = 3;
192
Mike Lockwoode3635c92009-05-11 08:38:02 -0400193 // for mAGpsDataConnectionState
194 private static final int AGPS_DATA_CONNECTION_CLOSED = 0;
195 private static final int AGPS_DATA_CONNECTION_OPENING = 1;
196 private static final int AGPS_DATA_CONNECTION_OPEN = 2;
Mike Lockwood58bda982009-04-14 16:25:07 -0400197
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400198 // Handler messages
199 private static final int CHECK_LOCATION = 1;
200 private static final int ENABLE = 2;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700201 private static final int SET_REQUEST = 3;
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400202 private static final int UPDATE_NETWORK_STATE = 4;
203 private static final int INJECT_NTP_TIME = 5;
204 private static final int DOWNLOAD_XTRA_DATA = 6;
205 private static final int UPDATE_LOCATION = 7;
206 private static final int ADD_LISTENER = 8;
207 private static final int REMOVE_LISTENER = 9;
Kevin Tang40e1baf2012-01-10 14:32:44 -0800208 private static final int INJECT_NTP_TIME_FINISHED = 10;
209 private static final int DOWNLOAD_XTRA_DATA_FINISHED = 11;
destradaafb23c672015-04-16 14:01:27 -0700210 private static final int SUBSCRIPTION_OR_SIM_CHANGED = 12;
211 private static final int INITIALIZE_HANDLER = 13;
destradaae21252a2015-09-08 12:32:59 -0700212 private static final int REQUEST_SUPL_CONNECTION = 14;
213 private static final int RELEASE_SUPL_CONNECTION = 15;
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400214
Miguel Torroja1e84da82010-07-27 07:02:24 +0200215 // Request setid
216 private static final int AGPS_RIL_REQUEST_SETID_IMSI = 1;
217 private static final int AGPS_RIL_REQUEST_SETID_MSISDN = 2;
218
Hridya Valsaraju2ea29602016-09-13 08:38:09 -0700219 //TODO(b/33112647): Create gps_debug.conf with commented career parameters.
220 private static final String DEBUG_PROPERTIES_FILE = "/etc/gps_debug.conf";
Miguel Torroja1e84da82010-07-27 07:02:24 +0200221
222 // ref. location info
223 private static final int AGPS_REF_LOCATION_TYPE_GSM_CELLID = 1;
224 private static final int AGPS_REF_LOCATION_TYPE_UMTS_CELLID = 2;
Miguel Torroja1e84da82010-07-27 07:02:24 +0200225
226 // set id info
227 private static final int AGPS_SETID_TYPE_NONE = 0;
228 private static final int AGPS_SETID_TYPE_IMSI = 1;
229 private static final int AGPS_SETID_TYPE_MSISDN = 2;
230
destradaa0682809a2013-08-12 18:50:30 -0700231 private static final int GPS_GEOFENCE_UNAVAILABLE = 1<<0L;
232 private static final int GPS_GEOFENCE_AVAILABLE = 1<<1L;
233
gomo4402af62017-01-11 13:20:13 -0800234 // GPS Geofence errors. Should match GeofenceStatus enum in IGnssGeofenceCallback.hal.
destradaa0682809a2013-08-12 18:50:30 -0700235 private static final int GPS_GEOFENCE_OPERATION_SUCCESS = 0;
236 private static final int GPS_GEOFENCE_ERROR_TOO_MANY_GEOFENCES = 100;
237 private static final int GPS_GEOFENCE_ERROR_ID_EXISTS = -101;
238 private static final int GPS_GEOFENCE_ERROR_ID_UNKNOWN = -102;
239 private static final int GPS_GEOFENCE_ERROR_INVALID_TRANSITION = -103;
240 private static final int GPS_GEOFENCE_ERROR_GENERIC = -149;
241
Tsuwei Chen678c13c2014-09-22 17:48:41 -0700242 // TCP/IP constants.
243 // Valid TCP/UDP port range is (0, 65535].
244 private static final int TCP_MIN_PORT = 0;
245 private static final int TCP_MAX_PORT = 0xffff;
246
David Christied4edf4c2014-08-12 15:22:27 -0700247 // Value of batterySaverGpsMode such that GPS isn't affected by battery saver mode.
248 private static final int BATTERY_SAVER_MODE_NO_CHANGE = 0;
249 // Value of batterySaverGpsMode such that GPS is disabled when battery saver mode
250 // is enabled and the screen is off.
251 private static final int BATTERY_SAVER_MODE_DISABLED_WHEN_SCREEN_OFF = 1;
252 // Secure setting for GPS behavior when battery saver mode is on.
253 private static final String BATTERY_SAVER_GPS_MODE = "batterySaverGpsMode";
254
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700255 /** simpler wrapper for ProviderRequest + Worksource */
256 private static class GpsRequest {
257 public ProviderRequest request;
258 public WorkSource source;
259 public GpsRequest(ProviderRequest request, WorkSource source) {
260 this.request = request;
261 this.source = source;
262 }
263 }
264
265 private Object mLock = new Object();
266
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800267 private int mLocationFlags = LOCATION_INVALID;
268
269 // current status
Mike Lockwood15e3d0f2009-05-01 07:53:28 -0400270 private int mStatus = LocationProvider.TEMPORARILY_UNAVAILABLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800271
272 // time for last status update
273 private long mStatusUpdateTime = SystemClock.elapsedRealtime();
Mike Lockwoodd53ba012010-04-15 20:41:26 -0400274
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800275 // turn off GPS fix icon if we haven't received a fix in 10 seconds
Mike Lockwood04598b62010-04-14 17:17:24 -0400276 private static final long RECENT_FIX_TIMEOUT = 10 * 1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800277
Mike Lockwood0632ca72009-05-14 15:51:03 -0400278 // stop trying if we do not receive a fix within 60 seconds
Mike Lockwood04598b62010-04-14 17:17:24 -0400279 private static final int NO_FIX_TIMEOUT = 60 * 1000;
Mike Lockwood0632ca72009-05-14 15:51:03 -0400280
Nick Pellyb041f232012-05-07 17:12:25 -0700281 // if the fix interval is below this we leave GPS on,
282 // if above then we cycle the GPS driver.
283 // Typical hot TTTF is ~5 seconds, so 10 seconds seems sane.
284 private static final int GPS_POLLING_THRESHOLD_INTERVAL = 10 * 1000;
285
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700286 // how often to request NTP time, in milliseconds
287 // current setting 24 hours
288 private static final long NTP_INTERVAL = 24*60*60*1000;
289 // how long to wait if we have a network error in NTP or XTRA downloading
Wei Liu6f6326b2015-06-24 23:47:50 -0700290 // the initial value of the exponential backoff
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700291 // current setting - 5 minutes
292 private static final long RETRY_INTERVAL = 5*60*1000;
Wei Liu6f6326b2015-06-24 23:47:50 -0700293 // how long to wait if we have a network error in NTP or XTRA downloading
294 // the max value of the exponential backoff
295 // current setting - 4 hours
296 private static final long MAX_RETRY_INTERVAL = 4*60*60*1000;
297
298 private BackOff mNtpBackOff = new BackOff(RETRY_INTERVAL, MAX_RETRY_INTERVAL);
299 private BackOff mXtraBackOff = new BackOff(RETRY_INTERVAL, MAX_RETRY_INTERVAL);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700300
301 // true if we are enabled, protected by this
302 private boolean mEnabled;
303
Kevin Tang40e1baf2012-01-10 14:32:44 -0800304 // states for injecting ntp and downloading xtra data
305 private static final int STATE_PENDING_NETWORK = 0;
306 private static final int STATE_DOWNLOADING = 1;
307 private static final int STATE_IDLE = 2;
308
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400309 // flags to trigger NTP or XTRA data download when network becomes available
310 // initialized to true so we do NTP and XTRA when the network comes up after booting
Kevin Tang40e1baf2012-01-10 14:32:44 -0800311 private int mInjectNtpTimePending = STATE_PENDING_NETWORK;
312 private int mDownloadXtraDataPending = STATE_PENDING_NETWORK;
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400313
destradaa56b47f82015-07-24 10:56:18 -0700314 // set to true if the GPS engine requested on-demand NTP time requests
315 private boolean mOnDemandTimeInjection;
Mike Lockwood9b9fb5c2011-06-29 15:09:40 -0400316
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800317 // true if GPS is navigating
318 private boolean mNavigating;
Mike Lockwoodcf1d8cb2010-01-20 10:14:54 -0500319
320 // true if GPS engine is on
321 private boolean mEngineOn;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700322
Mike Lockwood04598b62010-04-14 17:17:24 -0400323 // requested frequency of fixes, in milliseconds
324 private int mFixInterval = 1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800325
326 // true if we started navigation
327 private boolean mStarted;
328
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -0700329 // true if single shot request is in progress
330 private boolean mSingleShot;
331
Mike Lockwood04598b62010-04-14 17:17:24 -0400332 // capabilities of the GPS engine
333 private int mEngineCapabilities;
334
Mike Lockwood1a1cd3a2010-08-17 07:42:54 -0400335 // true if XTRA is supported
336 private boolean mSupportsXtra;
337
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800338 // for calculating time to first fix
339 private long mFixRequestTime = 0;
340 // time to first fix for most recent session
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700341 private int mTimeToFirstFix = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800342 // time we received our last fix
343 private long mLastFixTime;
344
Mike Lockwood04598b62010-04-14 17:17:24 -0400345 private int mPositionMode;
346
David Christied4edf4c2014-08-12 15:22:27 -0700347 // Current request from underlying location clients.
348 private ProviderRequest mProviderRequest = null;
349 // Current list of underlying location clients.
350 private WorkSource mWorkSource = null;
351 // True if gps should be disabled (used to support battery saver mode in settings).
352 private boolean mDisableGps = false;
353
destradaafb23c672015-04-16 14:01:27 -0700354 /**
355 * Properties loaded from PROPERTIES_FILE.
356 * It must be accessed only inside {@link #mHandler}.
357 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800358 private Properties mProperties;
destradaafb23c672015-04-16 14:01:27 -0700359
Mike Lockwood734d6032009-07-28 18:30:25 -0700360 private String mSuplServerHost;
Tsuwei Chen678c13c2014-09-22 17:48:41 -0700361 private int mSuplServerPort = TCP_MIN_PORT;
Mike Lockwood734d6032009-07-28 18:30:25 -0700362 private String mC2KServerHost;
363 private int mC2KServerPort;
Tsuwei Chen3324e952014-09-07 01:30:42 -0700364 private boolean mSuplEsEnabled = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800365
Mike Lockwood15e3d0f2009-05-01 07:53:28 -0400366 private final Context mContext;
Jeff Sharkey104344e2011-07-10 14:20:41 -0700367 private final NtpTrustedTime mNtpTime;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700368 private final ILocationManager mILocationManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800369 private Location mLocation = new Location(LocationManager.GPS_PROVIDER);
370 private Bundle mLocationExtras = new Bundle();
Lifu Tang30f95a72016-01-07 23:20:38 -0800371 private final GnssStatusListenerHelper mListenerHelper;
Lifu Tang818aa2c2016-02-01 01:52:00 -0800372 private final GnssMeasurementsProvider mGnssMeasurementsProvider;
373 private final GnssNavigationMessageProvider mGnssNavigationMessageProvider;
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400374
Victoria Lease5c24fd02012-10-01 11:00:50 -0700375 // Handler for processing events
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400376 private Handler mHandler;
The Android Open Source Project10592532009-03-18 17:39:46 -0700377
destradaae21252a2015-09-08 12:32:59 -0700378 /** It must be accessed only inside {@link #mHandler}. */
Mike Lockwoode3635c92009-05-11 08:38:02 -0400379 private int mAGpsDataConnectionState;
destradaae21252a2015-09-08 12:32:59 -0700380 /** It must be accessed only inside {@link #mHandler}. */
destradaa96a14702014-06-05 11:36:30 -0700381 private InetAddress mAGpsDataConnectionIpAddr;
destradaae21252a2015-09-08 12:32:59 -0700382
Mike Lockwood2f82c4e2009-04-17 08:24:10 -0400383 private final ConnectivityManager mConnMgr;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700384 private final GpsNetInitiatedHandler mNIHandler;
Mike Lockwood2f82c4e2009-04-17 08:24:10 -0400385
Mike Lockwood0528b9b2009-05-07 10:12:54 -0400386 // Wakelocks
Lifu Tang30f95a72016-01-07 23:20:38 -0800387 private final static String WAKELOCK_KEY = "GnssLocationProvider";
Mike Lockwood0528b9b2009-05-07 10:12:54 -0400388 private final PowerManager.WakeLock mWakeLock;
389
Mike Lockwood29c84342009-05-06 14:01:15 -0400390 // Alarms
391 private final static String ALARM_WAKEUP = "com.android.internal.location.ALARM_WAKEUP";
Mike Lockwood0632ca72009-05-14 15:51:03 -0400392 private final static String ALARM_TIMEOUT = "com.android.internal.location.ALARM_TIMEOUT";
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700393
394 // SIM/Carrier info.
395 private final static String SIM_STATE_CHANGED = "android.intent.action.SIM_STATE_CHANGED";
396
Ecco Park624ac3c2016-07-18 14:08:05 -0700397 // Persist property for LPP_PROFILE
398 private final static String LPP_PROFILE = "persist.sys.gps.lpp";
399
Ecco Park624ac3c2016-07-18 14:08:05 -0700400
401
David Christied4edf4c2014-08-12 15:22:27 -0700402 private final PowerManager mPowerManager;
Mike Lockwood29c84342009-05-06 14:01:15 -0400403 private final AlarmManager mAlarmManager;
404 private final PendingIntent mWakeupIntent;
Mike Lockwood0632ca72009-05-14 15:51:03 -0400405 private final PendingIntent mTimeoutIntent;
Mike Lockwood29c84342009-05-06 14:01:15 -0400406
Dianne Hackborna06de0f2012-12-11 16:34:47 -0800407 private final IAppOpsService mAppOpsService;
Mike Lockwood2f82c4e2009-04-17 08:24:10 -0400408 private final IBatteryStats mBatteryStats;
The Android Open Source Project10592532009-03-18 17:39:46 -0700409
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700410 // only modified on handler thread
Dianne Hackborn002a54e2013-01-10 17:34:55 -0800411 private WorkSource mClientSource = new WorkSource();
Mike Lockwoodf1218be2010-01-29 09:20:06 -0500412
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -0700413 private GeofenceHardwareImpl mGeofenceHardwareImpl;
414
Lifu Tang82f893d2016-01-21 18:15:33 -0800415 private int mYearOfHardware = 0;
416
Wyatt Riley5d5bac82016-11-01 07:05:16 -0700417 // Set lower than the current ITAR limit of 600m/s to allow this to trigger even if GPS HAL
418 // stops output right at 600m/s, depriving this of the information of a device that reaches
419 // greater than 600m/s, and higher than the speed of sound to avoid impacting most use cases.
420 private static final float ITAR_SPEED_LIMIT_METERS_PER_SECOND = 400.0F;
421 private boolean mItarSpeedLimitExceeded = false;
422
Lifu Tang30f95a72016-01-07 23:20:38 -0800423 private final IGnssStatusProvider mGnssStatusProvider = new IGnssStatusProvider.Stub() {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700424 @Override
Lifu Tang30f95a72016-01-07 23:20:38 -0800425 public void registerGnssStatusCallback(IGnssStatusListener callback) {
426 mListenerHelper.addListener(callback);
Mike Lockwood15e3d0f2009-05-01 07:53:28 -0400427 }
428
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700429 @Override
Lifu Tang30f95a72016-01-07 23:20:38 -0800430 public void unregisterGnssStatusCallback(IGnssStatusListener callback) {
431 mListenerHelper.removeListener(callback);
destradaaea8a8a62014-06-23 18:19:03 -0700432 }
433 };
Mike Lockwood15e3d0f2009-05-01 07:53:28 -0400434
Lifu Tang30f95a72016-01-07 23:20:38 -0800435 public IGnssStatusProvider getGnssStatusProvider() {
436 return mGnssStatusProvider;
Mike Lockwood15e3d0f2009-05-01 07:53:28 -0400437 }
438
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -0700439 public IGpsGeofenceHardware getGpsGeofenceProxy() {
440 return mGpsGeofenceBinder;
441 }
442
Lifu Tang818aa2c2016-02-01 01:52:00 -0800443 public GnssMeasurementsProvider getGnssMeasurementsProvider() {
444 return mGnssMeasurementsProvider;
destradaaea8a8a62014-06-23 18:19:03 -0700445 }
446
Lifu Tang818aa2c2016-02-01 01:52:00 -0800447 public GnssNavigationMessageProvider getGnssNavigationMessageProvider() {
448 return mGnssNavigationMessageProvider;
destradaa4b3e3932014-07-21 18:01:47 -0700449 }
450
destradaae21252a2015-09-08 12:32:59 -0700451 /**
452 * Callback used to listen for data connectivity changes.
453 */
454 private final ConnectivityManager.NetworkCallback mNetworkConnectivityCallback =
455 new ConnectivityManager.NetworkCallback() {
456 @Override
457 public void onAvailable(Network network) {
Wyatt Riley0d6e54e22016-10-05 12:03:03 -0700458 if (mInjectNtpTimePending == STATE_PENDING_NETWORK) {
459 requestUtcTime();
460 }
461 if (mDownloadXtraDataPending == STATE_PENDING_NETWORK) {
462 xtraDownloadRequest();
463 }
Wyatt Riley41f6bce2016-12-13 10:45:29 -0800464 // Always on, notify HAL so it can get data it needs
Wyatt Rileybb9c9902016-12-07 07:16:25 -0800465 sendMessage(UPDATE_NETWORK_STATE, 0 /*arg*/, network);
destradaae21252a2015-09-08 12:32:59 -0700466 }
467 };
468
469 /**
470 * Callback used to listen for availability of a requested SUPL connection.
471 * It is kept as a separate instance from {@link #mNetworkConnectivityCallback} to be able to
472 * manage the registration/un-registration lifetimes separate.
473 */
474 private final ConnectivityManager.NetworkCallback mSuplConnectivityCallback =
475 new ConnectivityManager.NetworkCallback() {
476 @Override
Wyatt Riley41f6bce2016-12-13 10:45:29 -0800477 public void onAvailable(Network network) {
478 // Specific to a change to a SUPL enabled network becoming ready
479 sendMessage(UPDATE_NETWORK_STATE, 0 /*arg*/, network);
480 }
481
482 @Override
destradaae21252a2015-09-08 12:32:59 -0700483 public void onLost(Network network) {
484 releaseSuplConnection(GPS_RELEASE_AGPS_DATA_CONN);
485 }
486
487 @Override
488 public void onUnavailable() {
489 // timeout, it was not possible to establish the required connection
490 releaseSuplConnection(GPS_AGPS_DATA_CONN_FAILED);
491 }
492 };
493
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700494 private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
The Android Open Source Project10592532009-03-18 17:39:46 -0700495 @Override public void onReceive(Context context, Intent intent) {
496 String action = intent.getAction();
Tsuwei Chen48d37f92014-09-05 15:15:34 -0700497 if (DEBUG) Log.d(TAG, "receive broadcast intent, action: " + action);
destradaaee9fd342015-08-31 13:31:17 -0700498 if (action == null) {
499 return;
500 }
501
Mike Lockwood29c84342009-05-06 14:01:15 -0400502 if (action.equals(ALARM_WAKEUP)) {
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -0700503 startNavigating(false);
Mike Lockwood0632ca72009-05-14 15:51:03 -0400504 } else if (action.equals(ALARM_TIMEOUT)) {
Mike Lockwood0632ca72009-05-14 15:51:03 -0400505 hibernate();
David Christied4edf4c2014-08-12 15:22:27 -0700506 } else if (PowerManager.ACTION_POWER_SAVE_MODE_CHANGED.equals(action)
Adam Lesinski87c17df2015-05-27 13:24:13 -0700507 || PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED.equals(action)
David Christied4edf4c2014-08-12 15:22:27 -0700508 || Intent.ACTION_SCREEN_OFF.equals(action)
509 || Intent.ACTION_SCREEN_ON.equals(action)) {
510 updateLowPowerMode();
Wink Savillea374c3d2014-11-11 11:48:04 -0800511 } else if (action.equals(SIM_STATE_CHANGED)) {
512 subscriptionOrSimChanged(context);
David Christied4edf4c2014-08-12 15:22:27 -0700513 }
The Android Open Source Project10592532009-03-18 17:39:46 -0700514 }
Mike Lockwood29c84342009-05-06 14:01:15 -0400515 };
The Android Open Source Project10592532009-03-18 17:39:46 -0700516
Wink Savilled09c4ca2014-11-22 10:08:16 -0800517 private final OnSubscriptionsChangedListener mOnSubscriptionsChangedListener =
518 new OnSubscriptionsChangedListener() {
Wink Savillea374c3d2014-11-11 11:48:04 -0800519 @Override
Wink Savilled09c4ca2014-11-22 10:08:16 -0800520 public void onSubscriptionsChanged() {
destradaafb23c672015-04-16 14:01:27 -0700521 sendMessage(SUBSCRIPTION_OR_SIM_CHANGED, 0, null);
Wink Savillea374c3d2014-11-11 11:48:04 -0800522 }
523 };
524
525 private void subscriptionOrSimChanged(Context context) {
Joe Onorato0c484102016-02-01 18:04:24 -0800526 if (DEBUG) Log.d(TAG, "received SIM related action: ");
Wink Savillea374c3d2014-11-11 11:48:04 -0800527 TelephonyManager phone = (TelephonyManager)
528 mContext.getSystemService(Context.TELEPHONY_SERVICE);
Ecco Park4fa1ab72016-10-24 13:04:52 -0700529 CarrierConfigManager configManager = (CarrierConfigManager)
530 mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE);
Wink Savillea374c3d2014-11-11 11:48:04 -0800531 String mccMnc = phone.getSimOperator();
Ecco Park4fa1ab72016-10-24 13:04:52 -0700532 boolean isKeepLppProfile = false;
Wink Savillea374c3d2014-11-11 11:48:04 -0800533 if (!TextUtils.isEmpty(mccMnc)) {
Joe Onorato0c484102016-02-01 18:04:24 -0800534 if (DEBUG) Log.d(TAG, "SIM MCC/MNC is available: " + mccMnc);
Wink Savillea374c3d2014-11-11 11:48:04 -0800535 synchronized (mLock) {
Ecco Park4fa1ab72016-10-24 13:04:52 -0700536 if (configManager != null) {
537 PersistableBundle b = configManager.getConfig();
538 isKeepLppProfile = b.getBoolean(CarrierConfigManager.KEY_PERSIST_LPP_MODE_BOOL);
539 }
540 if (isKeepLppProfile) {
541 // load current properties for the carrier
542 loadPropertiesFromResource(context, mProperties);
543 String lpp_profile = mProperties.getProperty("LPP_PROFILE");
544 // set the persist property LPP_PROFILE for the value
545 SystemProperties.set(LPP_PROFILE, lpp_profile);
Ecco Park624ac3c2016-07-18 14:08:05 -0700546 } else {
Ecco Park4fa1ab72016-10-24 13:04:52 -0700547 // reset the persist property
548 SystemProperties.set(LPP_PROFILE, "");
Ecco Park624ac3c2016-07-18 14:08:05 -0700549 }
Wink Savillea374c3d2014-11-11 11:48:04 -0800550 reloadGpsProperties(context, mProperties);
551 mNIHandler.setSuplEsEnabled(mSuplEsEnabled);
552 }
553 } else {
Joe Onorato0c484102016-02-01 18:04:24 -0800554 if (DEBUG) Log.d(TAG, "SIM MCC/MNC is still not available");
Wink Savillea374c3d2014-11-11 11:48:04 -0800555 }
556 }
557
David Christied4edf4c2014-08-12 15:22:27 -0700558 private void updateLowPowerMode() {
Adam Lesinski87c17df2015-05-27 13:24:13 -0700559 // Disable GPS if we are in device idle mode.
560 boolean disableGps = mPowerManager.isDeviceIdleMode();
David Christied4edf4c2014-08-12 15:22:27 -0700561 switch (Settings.Secure.getInt(mContext.getContentResolver(), BATTERY_SAVER_GPS_MODE,
562 BATTERY_SAVER_MODE_DISABLED_WHEN_SCREEN_OFF)) {
563 case BATTERY_SAVER_MODE_DISABLED_WHEN_SCREEN_OFF:
Adam Lesinski87c17df2015-05-27 13:24:13 -0700564 // If we are in battery saver mode and the screen is off, disable GPS.
565 disableGps |= mPowerManager.isPowerSaveMode() && !mPowerManager.isInteractive();
David Christied4edf4c2014-08-12 15:22:27 -0700566 break;
David Christied4edf4c2014-08-12 15:22:27 -0700567 }
568 if (disableGps != mDisableGps) {
569 mDisableGps = disableGps;
570 updateRequirements();
571 }
572 }
573
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800574 public static boolean isSupported() {
575 return native_is_supported();
576 }
577
Hridya Valsaraju2ea29602016-09-13 08:38:09 -0700578 interface SetCarrierProperty {
579 public boolean set(int value);
580 }
581
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700582 private void reloadGpsProperties(Context context, Properties properties) {
Joe Onorato0c484102016-02-01 18:04:24 -0800583 if (DEBUG) Log.d(TAG, "Reset GPS properties, previous size = " + properties.size());
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700584 loadPropertiesFromResource(context, properties);
Ecco Park624ac3c2016-07-18 14:08:05 -0700585
Ecco Park624ac3c2016-07-18 14:08:05 -0700586 String lpp_prof = SystemProperties.get(LPP_PROFILE);
587 if (!TextUtils.isEmpty(lpp_prof)) {
588 // override default value of this if lpp_prof is not empty
589 properties.setProperty("LPP_PROFILE", lpp_prof);
590 }
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700591 // TODO: we should get rid of C2K specific setting.
592 setSuplHostPort(properties.getProperty("SUPL_HOST"),
593 properties.getProperty("SUPL_PORT"));
594 mC2KServerHost = properties.getProperty("C2K_HOST");
595 String portString = properties.getProperty("C2K_PORT");
596 if (mC2KServerHost != null && portString != null) {
597 try {
598 mC2KServerPort = Integer.parseInt(portString);
599 } catch (NumberFormatException e) {
600 Log.e(TAG, "unable to parse C2K_PORT: " + portString);
601 }
602 }
Hridya Valsaraju2ea29602016-09-13 08:38:09 -0700603 /*
604 * Allow carrier properties to be loaded from a debug configuration file.
605 */
606 loadPropertiesFromFile(DEBUG_PROPERTIES_FILE, properties);
destradaaef752b62015-04-17 13:10:47 -0700607 if (native_is_gnss_configuration_supported()) {
Hridya Valsaraju2ea29602016-09-13 08:38:09 -0700608 Map<String, SetCarrierProperty> map = new HashMap<String, SetCarrierProperty>() {
609 {
610 put("SUPL_VER", (val) -> native_set_supl_version(val));
611 put("SUPL_MODE", (val) -> native_set_supl_mode(val));
612 put("SUPL_ES", (val) -> native_set_supl_es(val));
613 put("LPP_PROFILE", (val) -> native_set_lpp_profile(val));
614 put("A_GLONASS_POS_PROTOCOL_SELECT", (val) -> native_set_gnss_pos_protocol_select(val));
615 put("USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL", (val) -> native_set_emergency_supl_pdn(val));
616 put("GPS_LOCK", (val) -> native_set_gps_lock(val));
617 }
618 };
619
620 for(Entry<String, SetCarrierProperty> entry : map.entrySet()) {
621 String propertyName = entry.getKey();
622 String propertyValueString = properties.getProperty(propertyName);
623 if (propertyValueString != null) {
624 try {
625 int propertyValueInt = Integer.decode(propertyValueString);
626 boolean result = entry.getValue().set(propertyValueInt);
627 if (result == false) {
628 Log.e(TAG, "Unable to set " + propertyName);
629 }
630 } catch (NumberFormatException e) {
631 Log.e(TAG, "unable to parse propertyName: " + propertyValueString);
632 }
633 }
destradaaef752b62015-04-17 13:10:47 -0700634 }
635 } else if (DEBUG) {
636 Log.d(TAG, "Skipped configuration update because GNSS configuration in GPS HAL is not"
637 + " supported");
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700638 }
Tsuwei Chen3324e952014-09-07 01:30:42 -0700639
640 // SUPL_ES configuration.
641 String suplESProperty = mProperties.getProperty("SUPL_ES");
642 if (suplESProperty != null) {
643 try {
644 mSuplEsEnabled = (Integer.parseInt(suplESProperty) == 1);
645 } catch (NumberFormatException e) {
646 Log.e(TAG, "unable to parse SUPL_ES: " + suplESProperty);
647 }
648 }
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700649 }
650
651 private void loadPropertiesFromResource(Context context,
652 Properties properties) {
653 String[] configValues = context.getResources().getStringArray(
654 com.android.internal.R.array.config_gpsParameters);
655 for (String item : configValues) {
Joe Onorato0c484102016-02-01 18:04:24 -0800656 if (DEBUG) Log.d(TAG, "GpsParamsResource: " + item);
Tsuwei Chen7c485bf2014-09-10 15:33:34 -0700657 // We need to support "KEY =", but not "=VALUE".
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700658 String[] split = item.split("=");
659 if (split.length == 2) {
660 properties.setProperty(split[0].trim().toUpperCase(), split[1]);
661 } else {
662 Log.w(TAG, "malformed contents: " + item);
663 }
664 }
665 }
666
667 private boolean loadPropertiesFromFile(String filename,
668 Properties properties) {
Colin Cross7c030ed2014-01-28 09:33:53 -0800669 try {
670 File file = new File(filename);
671 FileInputStream stream = null;
672 try {
673 stream = new FileInputStream(file);
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700674 properties.load(stream);
Colin Cross7c030ed2014-01-28 09:33:53 -0800675 } finally {
676 IoUtils.closeQuietly(stream);
677 }
678
Colin Cross7c030ed2014-01-28 09:33:53 -0800679 } catch (IOException e) {
Hridya Valsaraju2ea29602016-09-13 08:38:09 -0700680 Log.v(TAG, "Could not open GPS configuration file " + filename);
Colin Cross7c030ed2014-01-28 09:33:53 -0800681 return false;
682 }
683 return true;
684 }
685
Lifu Tang30f95a72016-01-07 23:20:38 -0800686 public GnssLocationProvider(Context context, ILocationManager ilocationManager,
Victoria Lease5cd731a2012-12-19 15:04:21 -0800687 Looper looper) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800688 mContext = context;
Jeff Sharkey104344e2011-07-10 14:20:41 -0700689 mNtpTime = NtpTrustedTime.getInstance(context);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700690 mILocationManager = ilocationManager;
Mike Lockwood63598a02010-02-24 11:52:59 -0500691
692 mLocation.setExtras(mLocationExtras);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800693
Mike Lockwood0528b9b2009-05-07 10:12:54 -0400694 // Create a wake lock
David Christied4edf4c2014-08-12 15:22:27 -0700695 mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
696 mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700697 mWakeLock.setReferenceCounted(true);
Mike Lockwood0528b9b2009-05-07 10:12:54 -0400698
Mike Lockwood29c84342009-05-06 14:01:15 -0400699 mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
700 mWakeupIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_WAKEUP), 0);
Mike Lockwood0632ca72009-05-14 15:51:03 -0400701 mTimeoutIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_TIMEOUT), 0);
Mike Lockwood29c84342009-05-06 14:01:15 -0400702
Mike Lockwood58bda982009-04-14 16:25:07 -0400703 mConnMgr = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
704
Dianne Hackborna06de0f2012-12-11 16:34:47 -0800705 // App ops service to keep track of who is accessing the GPS
706 mAppOpsService = IAppOpsService.Stub.asInterface(ServiceManager.getService(
707 Context.APP_OPS_SERVICE));
708
Mike Lockwood2f82c4e2009-04-17 08:24:10 -0400709 // Battery statistics service to be notified when GPS turns on or off
Dianne Hackborn91268cf2013-06-13 19:06:50 -0700710 mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService(
711 BatteryStats.SERVICE_NAME));
Mike Lockwood2f82c4e2009-04-17 08:24:10 -0400712
destradaafb23c672015-04-16 14:01:27 -0700713 // Construct internal handler
714 mHandler = new ProviderHandler(looper);
715
716 // Load GPS configuration and register listeners in the background:
717 // some operations, such as opening files and registering broadcast receivers, can take a
718 // relative long time, so the ctor() is kept to create objects needed by this instance,
719 // while IO initialization and registration is delegated to our internal handler
720 // this approach is just fine because events are posted to our handler anyway
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700721 mProperties = new Properties();
destradaafb23c672015-04-16 14:01:27 -0700722 sendMessage(INITIALIZE_HANDLER, 0, null);
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400723
Tsuwei Chen3324e952014-09-07 01:30:42 -0700724 // Create a GPS net-initiated handler.
725 mNIHandler = new GpsNetInitiatedHandler(context,
726 mNetInitiatedListener,
727 mSuplEsEnabled);
728
Lifu Tang30f95a72016-01-07 23:20:38 -0800729 mListenerHelper = new GnssStatusListenerHelper(mHandler) {
destradaa6568d702014-10-27 12:47:41 -0700730 @Override
731 protected boolean isAvailableInPlatform() {
destradaa13a60b02015-01-15 18:36:01 -0800732 return isSupported();
destradaa6568d702014-10-27 12:47:41 -0700733 }
734
735 @Override
736 protected boolean isGpsEnabled() {
737 return isEnabled();
738 }
739 };
740
Lifu Tang818aa2c2016-02-01 01:52:00 -0800741 mGnssMeasurementsProvider = new GnssMeasurementsProvider(mHandler) {
destradaa6568d702014-10-27 12:47:41 -0700742 @Override
743 public boolean isAvailableInPlatform() {
744 return native_is_measurement_supported();
745 }
746
747 @Override
748 protected boolean registerWithService() {
749 return native_start_measurement_collection();
750 }
751
752 @Override
753 protected void unregisterFromService() {
754 native_stop_measurement_collection();
755 }
756
757 @Override
758 protected boolean isGpsEnabled() {
759 return isEnabled();
760 }
761 };
762
Lifu Tang818aa2c2016-02-01 01:52:00 -0800763 mGnssNavigationMessageProvider = new GnssNavigationMessageProvider(mHandler) {
destradaa6568d702014-10-27 12:47:41 -0700764 @Override
765 protected boolean isAvailableInPlatform() {
766 return native_is_navigation_message_supported();
767 }
768
769 @Override
770 protected boolean registerWithService() {
771 return native_start_navigation_message_collection();
772 }
773
774 @Override
775 protected void unregisterFromService() {
776 native_stop_navigation_message_collection();
777 }
778
779 @Override
780 protected boolean isGpsEnabled() {
781 return isEnabled();
782 }
783 };
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400784 }
785
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800786 /**
Mike Lockwoodd03ff942010-02-09 08:46:14 -0500787 * Returns the name of this provider.
788 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700789 @Override
Mike Lockwoodd03ff942010-02-09 08:46:14 -0500790 public String getName() {
791 return LocationManager.GPS_PROVIDER;
792 }
793
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700794 @Override
795 public ProviderProperties getProperties() {
796 return PROPERTIES;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800797 }
798
destradaae21252a2015-09-08 12:32:59 -0700799 private void handleUpdateNetworkState(Network network) {
800 // retrieve NetworkInfo for this UID
801 NetworkInfo info = mConnMgr.getNetworkInfo(network);
802 if (info == null) {
803 return;
804 }
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400805
destradaae21252a2015-09-08 12:32:59 -0700806 boolean isConnected = info.isConnected();
Joe Onoratof5d95cb2010-01-07 21:48:32 -0500807 if (DEBUG) {
destradaae21252a2015-09-08 12:32:59 -0700808 String message = String.format(
809 "UpdateNetworkState, state=%s, connected=%s, info=%s, capabilities=%S",
810 agpsDataConnStateAsString(),
811 isConnected,
812 info,
813 mConnMgr.getNetworkCapabilities(network));
814 Log.d(TAG, message);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800815 }
Mike Lockwood03d24672009-10-08 15:45:03 -0400816
destradaae21252a2015-09-08 12:32:59 -0700817 if (native_is_agps_ril_supported()) {
818 boolean dataEnabled = TelephonyManager.getDefault().getDataEnabled();
819 boolean networkAvailable = info.isAvailable() && dataEnabled;
820 String defaultApn = getSelectedApn();
821 if (defaultApn == null) {
822 defaultApn = "dummy-apn";
destradaaef752b62015-04-17 13:10:47 -0700823 }
destradaae21252a2015-09-08 12:32:59 -0700824
825 native_update_network_state(
826 isConnected,
827 info.getType(),
828 info.isRoaming(),
829 networkAvailable,
830 info.getExtraInfo(),
831 defaultApn);
832 } else if (DEBUG) {
833 Log.d(TAG, "Skipped network state update because GPS HAL AGPS-RIL is not supported");
Mike Lockwood50130bb2010-10-11 06:22:50 -0400834 }
835
destradaae21252a2015-09-08 12:32:59 -0700836 if (mAGpsDataConnectionState == AGPS_DATA_CONNECTION_OPENING) {
837 if (isConnected) {
destradaa96a14702014-06-05 11:36:30 -0700838 String apnName = info.getExtraInfo();
Stephen Li83b69712011-01-25 18:47:28 -0800839 if (apnName == null) {
destradaae21252a2015-09-08 12:32:59 -0700840 // assign a dummy value in the case of C2K as otherwise we will have a runtime
841 // exception in the following call to native_agps_data_conn_open
Stephen Li83b69712011-01-25 18:47:28 -0800842 apnName = "dummy-apn";
843 }
destradaae21252a2015-09-08 12:32:59 -0700844 int apnIpType = getApnIpType(apnName);
destradaa96a14702014-06-05 11:36:30 -0700845 setRouting();
846 if (DEBUG) {
847 String message = String.format(
848 "native_agps_data_conn_open: mAgpsApn=%s, mApnIpType=%s",
destradaae21252a2015-09-08 12:32:59 -0700849 apnName,
850 apnIpType);
destradaa96a14702014-06-05 11:36:30 -0700851 Log.d(TAG, message);
Stephen Li8efd74d2011-03-01 20:56:00 -0800852 }
destradaae21252a2015-09-08 12:32:59 -0700853 native_agps_data_conn_open(apnName, apnIpType);
Mike Lockwood03d24672009-10-08 15:45:03 -0400854 mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPEN;
855 } else {
destradaae21252a2015-09-08 12:32:59 -0700856 handleReleaseSuplConnection(GPS_AGPS_DATA_CONN_FAILED);
Mike Lockwood03d24672009-10-08 15:45:03 -0400857 }
858 }
destradaae21252a2015-09-08 12:32:59 -0700859 }
Mike Lockwood03d24672009-10-08 15:45:03 -0400860
destradaae21252a2015-09-08 12:32:59 -0700861 private void handleRequestSuplConnection(InetAddress address) {
862 if (DEBUG) {
863 String message = String.format(
864 "requestSuplConnection, state=%s, address=%s",
865 agpsDataConnStateAsString(),
866 address);
867 Log.d(TAG, message);
868 }
869
870 if (mAGpsDataConnectionState != AGPS_DATA_CONNECTION_CLOSED) {
871 return;
872 }
873 mAGpsDataConnectionIpAddr = address;
874 mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPENING;
875
876 NetworkRequest.Builder requestBuilder = new NetworkRequest.Builder();
877 requestBuilder.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
878 requestBuilder.addCapability(NetworkCapabilities.NET_CAPABILITY_SUPL);
879 NetworkRequest request = requestBuilder.build();
880 mConnMgr.requestNetwork(
881 request,
882 mSuplConnectivityCallback,
883 ConnectivityManager.MAX_NETWORK_REQUEST_TIMEOUT_MS);
884 }
885
886 private void handleReleaseSuplConnection(int agpsDataConnStatus) {
887 if (DEBUG) {
888 String message = String.format(
889 "releaseSuplConnection, state=%s, status=%s",
890 agpsDataConnStateAsString(),
891 agpsDataConnStatusAsString(agpsDataConnStatus));
892 Log.d(TAG, message);
893 }
894
895 if (mAGpsDataConnectionState == AGPS_DATA_CONNECTION_CLOSED) {
896 return;
897 }
898 mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED;
899
900 mConnMgr.unregisterNetworkCallback(mSuplConnectivityCallback);
901 switch (agpsDataConnStatus) {
902 case GPS_AGPS_DATA_CONN_FAILED:
903 native_agps_data_conn_failed();
904 break;
905 case GPS_RELEASE_AGPS_DATA_CONN:
906 native_agps_data_conn_closed();
907 break;
908 default:
909 Log.e(TAG, "Invalid status to release SUPL connection: " + agpsDataConnStatus);
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400910 }
911 }
912
913 private void handleInjectNtpTime() {
Kevin Tang40e1baf2012-01-10 14:32:44 -0800914 if (mInjectNtpTimePending == STATE_DOWNLOADING) {
915 // already downloading data
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400916 return;
917 }
destradaae21252a2015-09-08 12:32:59 -0700918 if (!isDataNetworkConnected()) {
Kevin Tang40e1baf2012-01-10 14:32:44 -0800919 // try again when network is up
920 mInjectNtpTimePending = STATE_PENDING_NETWORK;
921 return;
Jeff Sharkey104344e2011-07-10 14:20:41 -0700922 }
Kevin Tang40e1baf2012-01-10 14:32:44 -0800923 mInjectNtpTimePending = STATE_DOWNLOADING;
Jeff Sharkey104344e2011-07-10 14:20:41 -0700924
Jeff Brown028872f2012-08-25 13:07:01 -0700925 // hold wake lock while task runs
926 mWakeLock.acquire();
Lifu Tangcbd2a142016-06-22 10:57:55 -0700927 Log.i(TAG, "WakeLock acquired by handleInjectNtpTime()");
Kevin Tang40e1baf2012-01-10 14:32:44 -0800928 AsyncTask.THREAD_POOL_EXECUTOR.execute(new Runnable() {
929 @Override
930 public void run() {
931 long delay;
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400932
Kevin Tang40e1baf2012-01-10 14:32:44 -0800933 // force refresh NTP cache when outdated
destradaa56b47f82015-07-24 10:56:18 -0700934 boolean refreshSuccess = true;
Kevin Tang40e1baf2012-01-10 14:32:44 -0800935 if (mNtpTime.getCacheAge() >= NTP_INTERVAL) {
destradaa56b47f82015-07-24 10:56:18 -0700936 refreshSuccess = mNtpTime.forceRefresh();
Kevin Tang40e1baf2012-01-10 14:32:44 -0800937 }
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400938
Kevin Tang40e1baf2012-01-10 14:32:44 -0800939 // only update when NTP time is fresh
940 if (mNtpTime.getCacheAge() < NTP_INTERVAL) {
941 long time = mNtpTime.getCachedNtpTime();
942 long timeReference = mNtpTime.getCachedNtpTimeReference();
943 long certainty = mNtpTime.getCacheCertainty();
944 long now = System.currentTimeMillis();
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400945
Joe Onorato0c484102016-02-01 18:04:24 -0800946 if (DEBUG) {
947 Log.d(TAG, "NTP server returned: "
948 + time + " (" + new Date(time)
949 + ") reference: " + timeReference
950 + " certainty: " + certainty
951 + " system time offset: " + (time - now));
952 }
Kevin Tang40e1baf2012-01-10 14:32:44 -0800953
954 native_inject_time(time, timeReference, (int) certainty);
955 delay = NTP_INTERVAL;
Wei Liu6f6326b2015-06-24 23:47:50 -0700956 mNtpBackOff.reset();
Kevin Tang40e1baf2012-01-10 14:32:44 -0800957 } else {
destradaa56b47f82015-07-24 10:56:18 -0700958 Log.e(TAG, "requestTime failed");
Wei Liu6f6326b2015-06-24 23:47:50 -0700959 delay = mNtpBackOff.nextBackoffMillis();
Kevin Tang40e1baf2012-01-10 14:32:44 -0800960 }
961
Jeff Brown028872f2012-08-25 13:07:01 -0700962 sendMessage(INJECT_NTP_TIME_FINISHED, 0, null);
Kevin Tang40e1baf2012-01-10 14:32:44 -0800963
destradaa56b47f82015-07-24 10:56:18 -0700964 if (DEBUG) {
965 String message = String.format(
966 "onDemandTimeInjection=%s, refreshSuccess=%s, delay=%s",
967 mOnDemandTimeInjection,
968 refreshSuccess,
969 delay);
970 Log.d(TAG, message);
971 }
972 if (mOnDemandTimeInjection || !refreshSuccess) {
Kevin Tang40e1baf2012-01-10 14:32:44 -0800973 // send delayed message for next NTP injection
974 // since this is delayed and not urgent we do not hold a wake lock here
Jeff Brown028872f2012-08-25 13:07:01 -0700975 mHandler.sendEmptyMessageDelayed(INJECT_NTP_TIME, delay);
Kevin Tang40e1baf2012-01-10 14:32:44 -0800976 }
Jeff Brown028872f2012-08-25 13:07:01 -0700977
978 // release wake lock held by task
979 mWakeLock.release();
Lifu Tangcbd2a142016-06-22 10:57:55 -0700980 Log.i(TAG, "WakeLock released by handleInjectNtpTime()");
Kevin Tang40e1baf2012-01-10 14:32:44 -0800981 }
982 });
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400983 }
984
985 private void handleDownloadXtraData() {
Wyatt Riley0d6e54e22016-10-05 12:03:03 -0700986 if (!mSupportsXtra) {
987 // native code reports xtra not supported, don't try
988 Log.d(TAG, "handleDownloadXtraData() called when Xtra not supported");
989 return;
990 }
Kevin Tang40e1baf2012-01-10 14:32:44 -0800991 if (mDownloadXtraDataPending == STATE_DOWNLOADING) {
992 // already downloading data
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400993 return;
994 }
destradaae21252a2015-09-08 12:32:59 -0700995 if (!isDataNetworkConnected()) {
Kevin Tang40e1baf2012-01-10 14:32:44 -0800996 // try again when network is up
997 mDownloadXtraDataPending = STATE_PENDING_NETWORK;
998 return;
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400999 }
Kevin Tang40e1baf2012-01-10 14:32:44 -08001000 mDownloadXtraDataPending = STATE_DOWNLOADING;
1001
Jeff Brown028872f2012-08-25 13:07:01 -07001002 // hold wake lock while task runs
1003 mWakeLock.acquire();
Lifu Tangcbd2a142016-06-22 10:57:55 -07001004 Log.i(TAG, "WakeLock acquired by handleDownloadXtraData()");
Kevin Tang40e1baf2012-01-10 14:32:44 -08001005 AsyncTask.THREAD_POOL_EXECUTOR.execute(new Runnable() {
1006 @Override
1007 public void run() {
Andreas Gampedfdc6ac2014-10-28 20:42:53 -07001008 GpsXtraDownloader xtraDownloader = new GpsXtraDownloader(mProperties);
Kevin Tang40e1baf2012-01-10 14:32:44 -08001009 byte[] data = xtraDownloader.downloadXtraData();
1010 if (data != null) {
destradaae21252a2015-09-08 12:32:59 -07001011 if (DEBUG) Log.d(TAG, "calling native_inject_xtra_data");
Kevin Tang40e1baf2012-01-10 14:32:44 -08001012 native_inject_xtra_data(data, data.length);
Wei Liu6f6326b2015-06-24 23:47:50 -07001013 mXtraBackOff.reset();
Kevin Tang40e1baf2012-01-10 14:32:44 -08001014 }
1015
Jeff Brown028872f2012-08-25 13:07:01 -07001016 sendMessage(DOWNLOAD_XTRA_DATA_FINISHED, 0, null);
Kevin Tang40e1baf2012-01-10 14:32:44 -08001017
1018 if (data == null) {
1019 // try again later
1020 // since this is delayed and not urgent we do not hold a wake lock here
Wei Liu6f6326b2015-06-24 23:47:50 -07001021 mHandler.sendEmptyMessageDelayed(DOWNLOAD_XTRA_DATA,
1022 mXtraBackOff.nextBackoffMillis());
Kevin Tang40e1baf2012-01-10 14:32:44 -08001023 }
Kevin Tang40e1baf2012-01-10 14:32:44 -08001024
Jeff Brown028872f2012-08-25 13:07:01 -07001025 // release wake lock held by task
1026 mWakeLock.release();
Lifu Tangcbd2a142016-06-22 10:57:55 -07001027 Log.i(TAG, "WakeLock released by handleDownloadXtraData()");
Jeff Brown028872f2012-08-25 13:07:01 -07001028 }
Kevin Tang40e1baf2012-01-10 14:32:44 -08001029 });
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001030 }
1031
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001032 private void handleUpdateLocation(Location location) {
Mike Lockwoodd26ce0d2009-06-11 12:25:46 -04001033 if (location.hasAccuracy()) {
1034 native_inject_location(location.getLatitude(), location.getLongitude(),
1035 location.getAccuracy());
1036 }
Mike Lockwoodfd6e5f02009-05-21 11:28:20 -04001037 }
1038
1039 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001040 * Enables this provider. When enabled, calls to getStatus()
Mike Lockwood4e50b782009-04-03 08:24:43 -07001041 * must be handled. Hardware may be started up
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001042 * when the provider is enabled.
1043 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001044 @Override
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001045 public void enable() {
Laurent Tu7b5aeca2013-01-24 15:10:24 -08001046 synchronized (mLock) {
1047 if (mEnabled) return;
1048 mEnabled = true;
1049 }
1050
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001051 sendMessage(ENABLE, 1, null);
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001052 }
1053
Tsuwei Chen52617bb2014-08-25 11:49:11 -07001054 private void setSuplHostPort(String hostString, String portString) {
1055 if (hostString != null) {
1056 mSuplServerHost = hostString;
1057 }
1058 if (portString != null) {
1059 try {
1060 mSuplServerPort = Integer.parseInt(portString);
1061 } catch (NumberFormatException e) {
1062 Log.e(TAG, "unable to parse SUPL_PORT: " + portString);
1063 }
1064 }
Tsuwei Chen678c13c2014-09-22 17:48:41 -07001065 if (mSuplServerHost != null
1066 && mSuplServerPort > TCP_MIN_PORT
1067 && mSuplServerPort <= TCP_MAX_PORT) {
1068 native_set_agps_server(AGPS_TYPE_SUPL, mSuplServerHost, mSuplServerPort);
1069 }
Tsuwei Chen52617bb2014-08-25 11:49:11 -07001070 }
1071
Tsuwei Chen462bcd82014-09-17 12:28:49 -07001072 /**
1073 * Checks what SUPL mode to use, according to the AGPS mode as well as the
1074 * allowed mode from properties.
1075 *
1076 * @param properties GPS properties
1077 * @param agpsEnabled whether AGPS is enabled by settings value
1078 * @param singleShot whether "singleshot" is needed
1079 * @return SUPL mode (MSA vs MSB vs STANDALONE)
1080 */
1081 private int getSuplMode(Properties properties, boolean agpsEnabled, boolean singleShot) {
1082 if (agpsEnabled) {
1083 String modeString = properties.getProperty("SUPL_MODE");
1084 int suplMode = 0;
1085 if (!TextUtils.isEmpty(modeString)) {
1086 try {
1087 suplMode = Integer.parseInt(modeString);
1088 } catch (NumberFormatException e) {
1089 Log.e(TAG, "unable to parse SUPL_MODE: " + modeString);
1090 return GPS_POSITION_MODE_STANDALONE;
1091 }
1092 }
destradaabfb3bdb2015-04-29 14:42:35 -07001093 // MS-Based is the preferred mode for Assisted-GPS position computation, so we favor
1094 // such mode when it is available
1095 if (hasCapability(GPS_CAPABILITY_MSB) && (suplMode & AGPS_SUPL_MODE_MSB) != 0) {
1096 return GPS_POSITION_MODE_MS_BASED;
1097 }
1098 // for now, just as the legacy code did, we fallback to MS-Assisted if it is available,
1099 // do fallback only for single-shot requests, because it is too expensive to do for
1100 // periodic requests as well
Tsuwei Chen462bcd82014-09-17 12:28:49 -07001101 if (singleShot
1102 && hasCapability(GPS_CAPABILITY_MSA)
1103 && (suplMode & AGPS_SUPL_MODE_MSA) != 0) {
1104 return GPS_POSITION_MODE_MS_ASSISTED;
Tsuwei Chen462bcd82014-09-17 12:28:49 -07001105 }
1106 }
1107 return GPS_POSITION_MODE_STANDALONE;
1108 }
1109
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001110 private void handleEnable() {
1111 if (DEBUG) Log.d(TAG, "handleEnable");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001112
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001113 boolean enabled = native_init();
1114
1115 if (enabled) {
Mike Lockwood1a1cd3a2010-08-17 07:42:54 -04001116 mSupportsXtra = native_supports_xtra();
Tsuwei Chen678c13c2014-09-22 17:48:41 -07001117
1118 // TODO: remove the following native calls if we can make sure they are redundant.
Mike Lockwood734d6032009-07-28 18:30:25 -07001119 if (mSuplServerHost != null) {
1120 native_set_agps_server(AGPS_TYPE_SUPL, mSuplServerHost, mSuplServerPort);
1121 }
1122 if (mC2KServerHost != null) {
1123 native_set_agps_server(AGPS_TYPE_C2K, mC2KServerHost, mC2KServerPort);
1124 }
destradaa13a60b02015-01-15 18:36:01 -08001125
Lifu Tang818aa2c2016-02-01 01:52:00 -08001126 mGnssMeasurementsProvider.onGpsEnabledChanged();
1127 mGnssNavigationMessageProvider.onGpsEnabledChanged();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001128 } else {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001129 synchronized (mLock) {
1130 mEnabled = false;
1131 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001132 Log.w(TAG, "Failed to enable location provider");
1133 }
1134 }
1135
1136 /**
1137 * Disables this provider. When disabled, calls to getStatus()
Mike Lockwood4e50b782009-04-03 08:24:43 -07001138 * need not be handled. Hardware may be shut
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001139 * down while the provider is disabled.
1140 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001141 @Override
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001142 public void disable() {
Laurent Tu7b5aeca2013-01-24 15:10:24 -08001143 synchronized (mLock) {
1144 if (!mEnabled) return;
1145 mEnabled = false;
1146 }
1147
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001148 sendMessage(ENABLE, 0, null);
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001149 }
1150
1151 private void handleDisable() {
Mike Lockwood89096312010-03-24 10:14:55 -04001152 if (DEBUG) Log.d(TAG, "handleDisable");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001153
David Christie3bc26142013-12-19 14:53:44 -08001154 updateClientUids(new WorkSource());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001155 stopNavigating();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001156 mAlarmManager.cancel(mWakeupIntent);
1157 mAlarmManager.cancel(mTimeoutIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001158
Mike Lockwoodcf1d8cb2010-01-20 10:14:54 -05001159 // do this before releasing wakelock
1160 native_cleanup();
destradaa13a60b02015-01-15 18:36:01 -08001161
Lifu Tang818aa2c2016-02-01 01:52:00 -08001162 mGnssMeasurementsProvider.onGpsEnabledChanged();
1163 mGnssNavigationMessageProvider.onGpsEnabledChanged();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001164 }
1165
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001166 @Override
Mike Lockwoodd03ff942010-02-09 08:46:14 -05001167 public boolean isEnabled() {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001168 synchronized (mLock) {
1169 return mEnabled;
1170 }
Mike Lockwoodd03ff942010-02-09 08:46:14 -05001171 }
1172
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001173 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001174 public int getStatus(Bundle extras) {
1175 if (extras != null) {
1176 extras.putInt("satellites", mSvCount);
1177 }
1178 return mStatus;
1179 }
1180
1181 private void updateStatus(int status, int svCount) {
1182 if (status != mStatus || svCount != mSvCount) {
1183 mStatus = status;
1184 mSvCount = svCount;
1185 mLocationExtras.putInt("satellites", svCount);
1186 mStatusUpdateTime = SystemClock.elapsedRealtime();
1187 }
1188 }
1189
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001190 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001191 public long getStatusUpdateTime() {
1192 return mStatusUpdateTime;
1193 }
1194
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001195 @Override
1196 public void setRequest(ProviderRequest request, WorkSource source) {
1197 sendMessage(SET_REQUEST, 0, new GpsRequest(request, source));
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001198 }
1199
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001200 private void handleSetRequest(ProviderRequest request, WorkSource source) {
David Christied4edf4c2014-08-12 15:22:27 -07001201 mProviderRequest = request;
1202 mWorkSource = source;
1203 updateRequirements();
1204 }
1205
1206 // Called when the requirements for GPS may have changed
1207 private void updateRequirements() {
1208 if (mProviderRequest == null || mWorkSource == null) {
1209 return;
1210 }
1211
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001212 boolean singleShot = false;
1213
1214 // see if the request is for a single update
David Christied4edf4c2014-08-12 15:22:27 -07001215 if (mProviderRequest.locationRequests != null
1216 && mProviderRequest.locationRequests.size() > 0) {
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001217 // if any request has zero or more than one updates
1218 // requested, then this is not single-shot mode
1219 singleShot = true;
1220
David Christied4edf4c2014-08-12 15:22:27 -07001221 for (LocationRequest lr : mProviderRequest.locationRequests) {
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001222 if (lr.getNumUpdates() != 1) {
1223 singleShot = false;
1224 }
1225 }
1226 }
1227
David Christied4edf4c2014-08-12 15:22:27 -07001228 if (DEBUG) Log.d(TAG, "setRequest " + mProviderRequest);
Dante Russo260d6672016-06-20 11:11:59 -07001229 if (mProviderRequest.reportLocation && !mDisableGps && isEnabled()) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001230 // update client uids
David Christied4edf4c2014-08-12 15:22:27 -07001231 updateClientUids(mWorkSource);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001232
David Christied4edf4c2014-08-12 15:22:27 -07001233 mFixInterval = (int) mProviderRequest.interval;
Mike Lockwood03ca2162010-04-01 08:10:09 -07001234
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001235 // check for overflow
David Christied4edf4c2014-08-12 15:22:27 -07001236 if (mFixInterval != mProviderRequest.interval) {
1237 Log.w(TAG, "interval overflow: " + mProviderRequest.interval);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001238 mFixInterval = Integer.MAX_VALUE;
1239 }
Mike Lockwood03ca2162010-04-01 08:10:09 -07001240
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001241 // apply request to GPS engine
Mike Lockwood04598b62010-04-14 17:17:24 -04001242 if (mStarted && hasCapability(GPS_CAPABILITY_SCHEDULING)) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001243 // change period
Mike Lockwood04598b62010-04-14 17:17:24 -04001244 if (!native_set_position_mode(mPositionMode, GPS_POSITION_RECURRENCE_PERIODIC,
1245 mFixInterval, 0, 0)) {
1246 Log.e(TAG, "set_position_mode failed in setMinTime()");
1247 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001248 } else if (!mStarted) {
1249 // start GPS
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001250 startNavigating(singleShot);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001251 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001252 } else {
Dianne Hackborn002a54e2013-01-10 17:34:55 -08001253 updateClientUids(new WorkSource());
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001254
1255 stopNavigating();
1256 mAlarmManager.cancel(mWakeupIntent);
1257 mAlarmManager.cancel(mTimeoutIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001258 }
1259 }
1260
Dianne Hackborn002a54e2013-01-10 17:34:55 -08001261 private void updateClientUids(WorkSource source) {
1262 // Update work source.
1263 WorkSource[] changes = mClientSource.setReturningDiffs(source);
Victoria Leaseea78b852013-01-15 10:39:28 -08001264 if (changes == null) {
1265 return;
1266 }
Dianne Hackborn002a54e2013-01-10 17:34:55 -08001267 WorkSource newWork = changes[0];
1268 WorkSource goneWork = changes[1];
1269
1270 // Update sources that were not previously tracked.
1271 if (newWork != null) {
1272 int lastuid = -1;
1273 for (int i=0; i<newWork.size(); i++) {
Dianne Hackborn2e418422009-06-22 20:00:17 -07001274 try {
Dianne Hackborn002a54e2013-01-10 17:34:55 -08001275 int uid = newWork.get(i);
Dianne Hackborne98f5db2013-07-17 17:23:25 -07001276 mAppOpsService.startOperation(AppOpsManager.getToken(mAppOpsService),
1277 AppOpsManager.OP_GPS, uid, newWork.getName(i));
Dianne Hackborn002a54e2013-01-10 17:34:55 -08001278 if (uid != lastuid) {
1279 lastuid = uid;
1280 mBatteryStats.noteStartGps(uid);
1281 }
Dianne Hackborn2e418422009-06-22 20:00:17 -07001282 } catch (RemoteException e) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001283 Log.w(TAG, "RemoteException", e);
1284 }
1285 }
1286 }
1287
Dianne Hackborn002a54e2013-01-10 17:34:55 -08001288 // Update sources that are no longer tracked.
1289 if (goneWork != null) {
1290 int lastuid = -1;
1291 for (int i=0; i<goneWork.size(); i++) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001292 try {
Dianne Hackborn002a54e2013-01-10 17:34:55 -08001293 int uid = goneWork.get(i);
Dianne Hackborne98f5db2013-07-17 17:23:25 -07001294 mAppOpsService.finishOperation(AppOpsManager.getToken(mAppOpsService),
1295 AppOpsManager.OP_GPS, uid, goneWork.getName(i));
Dianne Hackborn002a54e2013-01-10 17:34:55 -08001296 if (uid != lastuid) {
1297 lastuid = uid;
1298 mBatteryStats.noteStopGps(uid);
1299 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001300 } catch (RemoteException e) {
1301 Log.w(TAG, "RemoteException", e);
Dianne Hackborn2e418422009-06-22 20:00:17 -07001302 }
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001303 }
1304 }
1305 }
1306
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001307 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001308 public boolean sendExtraCommand(String command, Bundle extras) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001309
Mike Lockwood63aa5a62010-04-14 19:21:31 -04001310 long identity = Binder.clearCallingIdentity();
1311 boolean result = false;
1312
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001313 if ("delete_aiding_data".equals(command)) {
Mike Lockwood63aa5a62010-04-14 19:21:31 -04001314 result = deleteAidingData(extras);
1315 } else if ("force_time_injection".equals(command)) {
destradaae21252a2015-09-08 12:32:59 -07001316 requestUtcTime();
Mike Lockwood63aa5a62010-04-14 19:21:31 -04001317 result = true;
1318 } else if ("force_xtra_injection".equals(command)) {
Mike Lockwood1a1cd3a2010-08-17 07:42:54 -04001319 if (mSupportsXtra) {
Mike Lockwood93bc44d2009-05-20 16:58:22 -04001320 xtraDownloadRequest();
Mike Lockwood63aa5a62010-04-14 19:21:31 -04001321 result = true;
Mike Lockwood93bc44d2009-05-20 16:58:22 -04001322 }
Mike Lockwood63aa5a62010-04-14 19:21:31 -04001323 } else {
1324 Log.w(TAG, "sendExtraCommand: unknown command " + command);
Mike Lockwood93bc44d2009-05-20 16:58:22 -04001325 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001326
Mike Lockwood63aa5a62010-04-14 19:21:31 -04001327 Binder.restoreCallingIdentity(identity);
1328 return result;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001329 }
1330
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001331 private IGpsGeofenceHardware mGpsGeofenceBinder = new IGpsGeofenceHardware.Stub() {
1332 public boolean isHardwareGeofenceSupported() {
1333 return native_is_geofence_supported();
1334 }
1335
1336 public boolean addCircularHardwareGeofence(int geofenceId, double latitude,
1337 double longitude, double radius, int lastTransition, int monitorTransitions,
1338 int notificationResponsiveness, int unknownTimer) {
1339 return native_add_geofence(geofenceId, latitude, longitude, radius,
1340 lastTransition, monitorTransitions, notificationResponsiveness, unknownTimer);
1341 }
1342
1343 public boolean removeHardwareGeofence(int geofenceId) {
1344 return native_remove_geofence(geofenceId);
1345 }
1346
1347 public boolean pauseHardwareGeofence(int geofenceId) {
1348 return native_pause_geofence(geofenceId);
1349 }
1350
1351 public boolean resumeHardwareGeofence(int geofenceId, int monitorTransition) {
1352 return native_resume_geofence(geofenceId, monitorTransition);
1353 }
1354 };
1355
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001356 private boolean deleteAidingData(Bundle extras) {
1357 int flags;
1358
1359 if (extras == null) {
1360 flags = GPS_DELETE_ALL;
1361 } else {
1362 flags = 0;
1363 if (extras.getBoolean("ephemeris")) flags |= GPS_DELETE_EPHEMERIS;
1364 if (extras.getBoolean("almanac")) flags |= GPS_DELETE_ALMANAC;
1365 if (extras.getBoolean("position")) flags |= GPS_DELETE_POSITION;
1366 if (extras.getBoolean("time")) flags |= GPS_DELETE_TIME;
1367 if (extras.getBoolean("iono")) flags |= GPS_DELETE_IONO;
1368 if (extras.getBoolean("utc")) flags |= GPS_DELETE_UTC;
1369 if (extras.getBoolean("health")) flags |= GPS_DELETE_HEALTH;
1370 if (extras.getBoolean("svdir")) flags |= GPS_DELETE_SVDIR;
1371 if (extras.getBoolean("svsteer")) flags |= GPS_DELETE_SVSTEER;
1372 if (extras.getBoolean("sadata")) flags |= GPS_DELETE_SADATA;
1373 if (extras.getBoolean("rti")) flags |= GPS_DELETE_RTI;
1374 if (extras.getBoolean("celldb-info")) flags |= GPS_DELETE_CELLDB_INFO;
1375 if (extras.getBoolean("all")) flags |= GPS_DELETE_ALL;
1376 }
1377
1378 if (flags != 0) {
1379 native_delete_aiding_data(flags);
1380 return true;
1381 }
1382
1383 return false;
1384 }
1385
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001386 private void startNavigating(boolean singleShot) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001387 if (!mStarted) {
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001388 if (DEBUG) Log.d(TAG, "startNavigating, singleShot is " + singleShot);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001389 mTimeToFirstFix = 0;
1390 mLastFixTime = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001391 mStarted = true;
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001392 mSingleShot = singleShot;
Mike Lockwood03ca2162010-04-01 08:10:09 -07001393 mPositionMode = GPS_POSITION_MODE_STANDALONE;
Wyatt Riley5d5bac82016-11-01 07:05:16 -07001394 // Notify about suppressed output, if speed limit was previously exceeded.
1395 // Elsewhere, we check again with every speed output reported.
1396 if (mItarSpeedLimitExceeded) {
1397 Log.i(TAG, "startNavigating with ITAR limit in place. Output limited " +
1398 "until slow enough speed reported.");
1399 }
Mike Lockwood03ca2162010-04-01 08:10:09 -07001400
Tsuwei Chen462bcd82014-09-17 12:28:49 -07001401 boolean agpsEnabled =
1402 (Settings.Global.getInt(mContext.getContentResolver(),
1403 Settings.Global.ASSISTED_GPS_ENABLED, 1) != 0);
1404 mPositionMode = getSuplMode(mProperties, agpsEnabled, singleShot);
Mike Lockwoodbcab8df2009-06-25 16:39:09 -04001405
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001406 if (DEBUG) {
1407 String mode;
1408
1409 switch(mPositionMode) {
1410 case GPS_POSITION_MODE_STANDALONE:
1411 mode = "standalone";
1412 break;
1413 case GPS_POSITION_MODE_MS_ASSISTED:
1414 mode = "MS_ASSISTED";
1415 break;
1416 case GPS_POSITION_MODE_MS_BASED:
1417 mode = "MS_BASED";
1418 break;
1419 default:
1420 mode = "unknown";
1421 break;
1422 }
1423 Log.d(TAG, "setting position_mode to " + mode);
1424 }
1425
Mike Lockwood04598b62010-04-14 17:17:24 -04001426 int interval = (hasCapability(GPS_CAPABILITY_SCHEDULING) ? mFixInterval : 1000);
1427 if (!native_set_position_mode(mPositionMode, GPS_POSITION_RECURRENCE_PERIODIC,
1428 interval, 0, 0)) {
1429 mStarted = false;
1430 Log.e(TAG, "set_position_mode failed in startNavigating()");
1431 return;
1432 }
1433 if (!native_start()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001434 mStarted = false;
1435 Log.e(TAG, "native_start failed in startNavigating()");
Mike Lockwood0632ca72009-05-14 15:51:03 -04001436 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001437 }
1438
1439 // reset SV count to zero
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001440 updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, 0);
Mike Lockwood29c84342009-05-06 14:01:15 -04001441 mFixRequestTime = System.currentTimeMillis();
Mike Lockwood04598b62010-04-14 17:17:24 -04001442 if (!hasCapability(GPS_CAPABILITY_SCHEDULING)) {
1443 // set timer to give up if we do not receive a fix within NO_FIX_TIMEOUT
1444 // and our fix interval is not short
1445 if (mFixInterval >= NO_FIX_TIMEOUT) {
1446 mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
1447 SystemClock.elapsedRealtime() + NO_FIX_TIMEOUT, mTimeoutIntent);
1448 }
Mike Lockwood0632ca72009-05-14 15:51:03 -04001449 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001450 }
1451 }
1452
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001453 private void stopNavigating() {
Mike Lockwood29c84342009-05-06 14:01:15 -04001454 if (DEBUG) Log.d(TAG, "stopNavigating");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001455 if (mStarted) {
1456 mStarted = false;
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001457 mSingleShot = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001458 native_stop();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001459 mTimeToFirstFix = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001460 mLastFixTime = 0;
1461 mLocationFlags = LOCATION_INVALID;
1462
1463 // reset SV count to zero
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001464 updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001465 }
1466 }
1467
Mike Lockwood0632ca72009-05-14 15:51:03 -04001468 private void hibernate() {
1469 // stop GPS until our next fix interval arrives
1470 stopNavigating();
Mike Lockwood0632ca72009-05-14 15:51:03 -04001471 mAlarmManager.cancel(mTimeoutIntent);
1472 mAlarmManager.cancel(mWakeupIntent);
1473 long now = SystemClock.elapsedRealtime();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001474 mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, now + mFixInterval, mWakeupIntent);
Mike Lockwood04598b62010-04-14 17:17:24 -04001475 }
1476
1477 private boolean hasCapability(int capability) {
1478 return ((mEngineCapabilities & capability) != 0);
Mike Lockwood0632ca72009-05-14 15:51:03 -04001479 }
1480
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001481
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001482 /**
1483 * called from native code to update our position.
1484 */
1485 private void reportLocation(int flags, double latitude, double longitude, double altitude,
gomo4402af62017-01-11 13:20:13 -08001486 float speedMetersPerSecond, float bearing, float horizontalAccuracyMeters,
1487 float verticalAccuracyMeters, float speedAccuracyMetersPerSeconds,
1488 float bearingAccuracyDegrees, long timestamp) {
Wyatt Riley5d5bac82016-11-01 07:05:16 -07001489 if ((flags & LOCATION_HAS_SPEED) == LOCATION_HAS_SPEED) {
1490 mItarSpeedLimitExceeded = speedMetersPerSecond > ITAR_SPEED_LIMIT_METERS_PER_SECOND;
1491 }
1492
1493 if (mItarSpeedLimitExceeded) {
1494 Log.i(TAG, "Hal reported a speed in excess of ITAR limit." +
1495 " GPS/GNSS Navigation output blocked.");
1496 return; // No output of location allowed
1497 }
1498
Mike Lockwood29c84342009-05-06 14:01:15 -04001499 if (VERBOSE) Log.v(TAG, "reportLocation lat: " + latitude + " long: " + longitude +
gomo4402af62017-01-11 13:20:13 -08001500 " timestamp: " + timestamp + " flags: " + flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001501
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001502 synchronized (mLocation) {
1503 mLocationFlags = flags;
1504 if ((flags & LOCATION_HAS_LAT_LONG) == LOCATION_HAS_LAT_LONG) {
1505 mLocation.setLatitude(latitude);
1506 mLocation.setLongitude(longitude);
1507 mLocation.setTime(timestamp);
Nick Pelly2eeeec22012-07-18 13:13:37 -07001508 // It would be nice to push the elapsed real-time timestamp
1509 // further down the stack, but this is still useful
Philip Milne41180122012-09-26 11:29:25 -07001510 mLocation.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001511 }
1512 if ((flags & LOCATION_HAS_ALTITUDE) == LOCATION_HAS_ALTITUDE) {
1513 mLocation.setAltitude(altitude);
1514 } else {
1515 mLocation.removeAltitude();
1516 }
1517 if ((flags & LOCATION_HAS_SPEED) == LOCATION_HAS_SPEED) {
Wyatt Riley5d5bac82016-11-01 07:05:16 -07001518 mLocation.setSpeed(speedMetersPerSecond);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001519 } else {
1520 mLocation.removeSpeed();
1521 }
1522 if ((flags & LOCATION_HAS_BEARING) == LOCATION_HAS_BEARING) {
1523 mLocation.setBearing(bearing);
1524 } else {
1525 mLocation.removeBearing();
1526 }
gomo4402af62017-01-11 13:20:13 -08001527 if ((flags & LOCATION_HAS_HORIZONTAL_ACCURACY) == LOCATION_HAS_HORIZONTAL_ACCURACY) {
1528 mLocation.setAccuracy(horizontalAccuracyMeters);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001529 } else {
1530 mLocation.removeAccuracy();
1531 }
gomo4402af62017-01-11 13:20:13 -08001532 if ((flags & LOCATION_HAS_VERTICAL_ACCURACY) == LOCATION_HAS_VERTICAL_ACCURACY) {
1533 mLocation.setVerticalAccuracyMeters(verticalAccuracyMeters);
1534 } else {
1535 mLocation.removeVerticalAccuracy();
1536 }
1537 if((flags & LOCATION_HAS_SPEED_ACCURACY) == LOCATION_HAS_SPEED_ACCURACY) {
1538 mLocation.setSpeedAccuracyMetersPerSecond(speedAccuracyMetersPerSeconds);
1539 } else {
1540 mLocation.removeSpeedAccuracy();
1541 }
1542 if((flags & LOCATION_HAS_BEARING_ACCURACY) == LOCATION_HAS_BEARING_ACCURACY) {
1543 mLocation.setBearingAccuracyDegrees(bearingAccuracyDegrees);
1544 } else {
1545 mLocation.removeBearingAccuracy();
1546 }
Sean Barbeauced2b2c2011-12-19 04:43:07 -05001547 mLocation.setExtras(mLocationExtras);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001548
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001549 try {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001550 mILocationManager.reportLocation(mLocation, false);
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001551 } catch (RemoteException e) {
1552 Log.e(TAG, "RemoteException calling reportLocation");
1553 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001554 }
1555
Hakan Gustavssonfa94ff02010-02-23 09:12:38 +01001556 mLastFixTime = System.currentTimeMillis();
1557 // report time to first fix
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001558 if (mTimeToFirstFix == 0 && (flags & LOCATION_HAS_LAT_LONG) == LOCATION_HAS_LAT_LONG) {
1559 mTimeToFirstFix = (int)(mLastFixTime - mFixRequestTime);
1560 if (DEBUG) Log.d(TAG, "TTFF: " + mTimeToFirstFix);
Hakan Gustavssonfa94ff02010-02-23 09:12:38 +01001561
1562 // notify status listeners
destradaaea8a8a62014-06-23 18:19:03 -07001563 mListenerHelper.onFirstFix(mTimeToFirstFix);
Hakan Gustavssonfa94ff02010-02-23 09:12:38 +01001564 }
1565
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001566 if (mSingleShot) {
1567 stopNavigating();
1568 }
1569
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001570 if (mStarted && mStatus != LocationProvider.AVAILABLE) {
Mike Lockwoodd53ba012010-04-15 20:41:26 -04001571 // we want to time out if we do not receive a fix
Mike Lockwoodb7be5442010-02-24 14:34:50 -05001572 // within the time out and we are requesting infrequent fixes
Mike Lockwood04598b62010-04-14 17:17:24 -04001573 if (!hasCapability(GPS_CAPABILITY_SCHEDULING) && mFixInterval < NO_FIX_TIMEOUT) {
Mike Lockwoodb7be5442010-02-24 14:34:50 -05001574 mAlarmManager.cancel(mTimeoutIntent);
1575 }
1576
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001577 // send an intent to notify that the GPS is receiving fixes.
Mike Lockwood00b74272010-03-26 10:41:48 -04001578 Intent intent = new Intent(LocationManager.GPS_FIX_CHANGE_ACTION);
1579 intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, true);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07001580 mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001581 updateStatus(LocationProvider.AVAILABLE, mSvCount);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001582 }
Mike Lockwood29c84342009-05-06 14:01:15 -04001583
Nick Pellyb041f232012-05-07 17:12:25 -07001584 if (!hasCapability(GPS_CAPABILITY_SCHEDULING) && mStarted &&
1585 mFixInterval > GPS_POLLING_THRESHOLD_INTERVAL) {
Mike Lockwoodd53ba012010-04-15 20:41:26 -04001586 if (DEBUG) Log.d(TAG, "got fix, hibernating");
Mike Lockwood0632ca72009-05-14 15:51:03 -04001587 hibernate();
Mike Lockwood29c84342009-05-06 14:01:15 -04001588 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001589 }
1590
1591 /**
1592 * called from native code to update our status
1593 */
1594 private void reportStatus(int status) {
Mike Lockwoodb8d90332010-10-18 17:59:48 -04001595 if (DEBUG) Log.v(TAG, "reportStatus status: " + status);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001596
destradaaea8a8a62014-06-23 18:19:03 -07001597 boolean wasNavigating = mNavigating;
1598 switch (status) {
1599 case GPS_STATUS_SESSION_BEGIN:
1600 mNavigating = true;
1601 mEngineOn = true;
1602 break;
1603 case GPS_STATUS_SESSION_END:
1604 mNavigating = false;
1605 break;
1606 case GPS_STATUS_ENGINE_ON:
1607 mEngineOn = true;
1608 break;
1609 case GPS_STATUS_ENGINE_OFF:
1610 mEngineOn = false;
1611 mNavigating = false;
1612 break;
1613 }
Mike Lockwooddbd6fd82009-12-07 18:43:36 -05001614
destradaaea8a8a62014-06-23 18:19:03 -07001615 if (wasNavigating != mNavigating) {
destradaa13a60b02015-01-15 18:36:01 -08001616 mListenerHelper.onStatusChanged(mNavigating);
Mike Lockwoodcf1d8cb2010-01-20 10:14:54 -05001617
destradaaea8a8a62014-06-23 18:19:03 -07001618 // send an intent to notify that the GPS has been enabled or disabled
1619 Intent intent = new Intent(LocationManager.GPS_ENABLED_CHANGE_ACTION);
1620 intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, mNavigating);
1621 mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001622 }
1623 }
1624
1625 /**
1626 * called from native code to update SV info
1627 */
1628 private void reportSvStatus() {
gomo4402af62017-01-11 13:20:13 -08001629 int svCount = native_read_sv_status(mSvidWithFlags,
1630 mCn0s,
1631 mSvElevations,
1632 mSvAzimuths,
1633 mSvCarrierFreqs);
destradaaea8a8a62014-06-23 18:19:03 -07001634 mListenerHelper.onSvStatusChanged(
1635 svCount,
Lifu Tang120480f2016-02-07 18:08:19 -08001636 mSvidWithFlags,
Lifu Tang76a620f2016-02-26 19:53:01 -08001637 mCn0s,
destradaaea8a8a62014-06-23 18:19:03 -07001638 mSvElevations,
gomo4402af62017-01-11 13:20:13 -08001639 mSvAzimuths,
1640 mSvCarrierFreqs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001641
Mike Lockwood29c84342009-05-06 14:01:15 -04001642 if (VERBOSE) {
Lifu Tang30f95a72016-01-07 23:20:38 -08001643 Log.v(TAG, "SV count: " + svCount);
1644 }
1645 // Calculate number of sets used in fix.
1646 int usedInFixCount = 0;
1647 for (int i = 0; i < svCount; i++) {
Lifu Tang120480f2016-02-07 18:08:19 -08001648 if ((mSvidWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_USED_IN_FIX) != 0) {
Lifu Tang30f95a72016-01-07 23:20:38 -08001649 ++usedInFixCount;
1650 }
1651 if (VERBOSE) {
Lifu Tang120480f2016-02-07 18:08:19 -08001652 Log.v(TAG, "svid: " + (mSvidWithFlags[i] >> GnssStatus.SVID_SHIFT_WIDTH) +
Lifu Tang76a620f2016-02-26 19:53:01 -08001653 " cn0: " + mCn0s[i]/10 +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001654 " elev: " + mSvElevations[i] +
1655 " azimuth: " + mSvAzimuths[i] +
gomo4402af62017-01-11 13:20:13 -08001656 " carrier frequency: " + mSvCarrierFreqs[i] +
Lifu Tang120480f2016-02-07 18:08:19 -08001657 ((mSvidWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_HAS_EPHEMERIS_DATA) == 0
Lifu Tang30f95a72016-01-07 23:20:38 -08001658 ? " " : " E") +
Lifu Tang120480f2016-02-07 18:08:19 -08001659 ((mSvidWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_HAS_ALMANAC_DATA) == 0
Lifu Tang30f95a72016-01-07 23:20:38 -08001660 ? " " : " A") +
Lifu Tang120480f2016-02-07 18:08:19 -08001661 ((mSvidWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_USED_IN_FIX) == 0
gomo4402af62017-01-11 13:20:13 -08001662 ? "" : "U") +
1663 ((mSvidWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_HAS_CARRIER_FREQUENCY) == 0
1664 ? "" : "F"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001665 }
1666 }
Kevin.KY Tsai0881f4f2010-05-21 15:10:39 -04001667 // return number of sets used in fix instead of total
Lifu Tang30f95a72016-01-07 23:20:38 -08001668 updateStatus(mStatus, usedInFixCount);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001669
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001670 if (mNavigating && mStatus == LocationProvider.AVAILABLE && mLastFixTime > 0 &&
Mike Lockwood04598b62010-04-14 17:17:24 -04001671 System.currentTimeMillis() - mLastFixTime > RECENT_FIX_TIMEOUT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001672 // send an intent to notify that the GPS is no longer receiving fixes.
Mike Lockwood00b74272010-03-26 10:41:48 -04001673 Intent intent = new Intent(LocationManager.GPS_FIX_CHANGE_ACTION);
1674 intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, false);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07001675 mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001676 updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, mSvCount);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001677 }
1678 }
Mike Lockwood58bda982009-04-14 16:25:07 -04001679
1680 /**
Mike Lockwoode3635c92009-05-11 08:38:02 -04001681 * called from native code to update AGPS status
Mike Lockwood58bda982009-04-14 16:25:07 -04001682 */
destradaa96a14702014-06-05 11:36:30 -07001683 private void reportAGpsStatus(int type, int status, byte[] ipaddr) {
Mike Lockwood58bda982009-04-14 16:25:07 -04001684 switch (status) {
Mike Lockwoode3635c92009-05-11 08:38:02 -04001685 case GPS_REQUEST_AGPS_DATA_CONN:
Mike Lockwoodb6e5fa82010-10-09 20:10:46 -04001686 if (DEBUG) Log.d(TAG, "GPS_REQUEST_AGPS_DATA_CONN");
Andreas Gampee6748ce2015-12-11 18:00:38 -08001687 Log.v(TAG, "Received SUPL IP addr[]: " + Arrays.toString(ipaddr));
destradaae21252a2015-09-08 12:32:59 -07001688 InetAddress connectionIpAddress = null;
destradaa96a14702014-06-05 11:36:30 -07001689 if (ipaddr != null) {
1690 try {
destradaae21252a2015-09-08 12:32:59 -07001691 connectionIpAddress = InetAddress.getByAddress(ipaddr);
1692 if (DEBUG) Log.d(TAG, "IP address converted to: " + connectionIpAddress);
destradaa96a14702014-06-05 11:36:30 -07001693 } catch (UnknownHostException e) {
1694 Log.e(TAG, "Bad IP Address: " + ipaddr, e);
destradaa96a14702014-06-05 11:36:30 -07001695 }
1696 }
destradaae21252a2015-09-08 12:32:59 -07001697 sendMessage(REQUEST_SUPL_CONNECTION, 0 /*arg*/, connectionIpAddress);
Mike Lockwood58bda982009-04-14 16:25:07 -04001698 break;
Mike Lockwoode3635c92009-05-11 08:38:02 -04001699 case GPS_RELEASE_AGPS_DATA_CONN:
Mike Lockwoodb6e5fa82010-10-09 20:10:46 -04001700 if (DEBUG) Log.d(TAG, "GPS_RELEASE_AGPS_DATA_CONN");
destradaae21252a2015-09-08 12:32:59 -07001701 releaseSuplConnection(GPS_RELEASE_AGPS_DATA_CONN);
Mike Lockwood58bda982009-04-14 16:25:07 -04001702 break;
Mike Lockwoode3635c92009-05-11 08:38:02 -04001703 case GPS_AGPS_DATA_CONNECTED:
Mike Lockwoodb6e5fa82010-10-09 20:10:46 -04001704 if (DEBUG) Log.d(TAG, "GPS_AGPS_DATA_CONNECTED");
Mike Lockwood58bda982009-04-14 16:25:07 -04001705 break;
Mike Lockwoode3635c92009-05-11 08:38:02 -04001706 case GPS_AGPS_DATA_CONN_DONE:
Mike Lockwoodb6e5fa82010-10-09 20:10:46 -04001707 if (DEBUG) Log.d(TAG, "GPS_AGPS_DATA_CONN_DONE");
Mike Lockwood58bda982009-04-14 16:25:07 -04001708 break;
Mike Lockwoode3635c92009-05-11 08:38:02 -04001709 case GPS_AGPS_DATA_CONN_FAILED:
Mike Lockwoodb6e5fa82010-10-09 20:10:46 -04001710 if (DEBUG) Log.d(TAG, "GPS_AGPS_DATA_CONN_FAILED");
Mike Lockwood58bda982009-04-14 16:25:07 -04001711 break;
destradaa931a37f2014-08-12 16:36:59 -07001712 default:
Joe Onorato0c484102016-02-01 18:04:24 -08001713 if (DEBUG) Log.d(TAG, "Received Unknown AGPS status: " + status);
Mike Lockwood58bda982009-04-14 16:25:07 -04001714 }
1715 }
1716
destradaae21252a2015-09-08 12:32:59 -07001717 private void releaseSuplConnection(int connStatus) {
1718 sendMessage(RELEASE_SUPL_CONNECTION, connStatus, null /*obj*/);
1719 }
1720
Mike Lockwoodb16e7802009-08-06 09:26:02 -04001721 /**
1722 * called from native code to report NMEA data received
1723 */
Mike Lockwoodf602d362010-06-20 14:28:16 -07001724 private void reportNmea(long timestamp) {
Wyatt Riley5d5bac82016-11-01 07:05:16 -07001725 if (!mItarSpeedLimitExceeded) {
1726 int length = native_read_nmea(mNmeaBuffer, mNmeaBuffer.length);
1727 String nmea = new String(mNmeaBuffer, 0 /* offset */, length);
1728 mListenerHelper.onNmeaReceived(timestamp, nmea);
1729 }
destradaaea8a8a62014-06-23 18:19:03 -07001730 }
Mike Lockwoodb16e7802009-08-06 09:26:02 -04001731
destradaaea8a8a62014-06-23 18:19:03 -07001732 /**
destradaa4b3e3932014-07-21 18:01:47 -07001733 * called from native code - Gps measurements callback
destradaaea8a8a62014-06-23 18:19:03 -07001734 */
Lifu Tang818aa2c2016-02-01 01:52:00 -08001735 private void reportMeasurementData(GnssMeasurementsEvent event) {
Wyatt Riley5d5bac82016-11-01 07:05:16 -07001736 if (!mItarSpeedLimitExceeded) {
1737 mGnssMeasurementsProvider.onMeasurementsAvailable(event);
1738 }
Mike Lockwoodb16e7802009-08-06 09:26:02 -04001739 }
1740
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001741 /**
destradaa4b3e3932014-07-21 18:01:47 -07001742 * called from native code - GPS navigation message callback
1743 */
Lifu Tange8abe8e2016-04-01 10:32:05 -07001744 private void reportNavigationMessage(GnssNavigationMessage event) {
Wyatt Riley5d5bac82016-11-01 07:05:16 -07001745 if (!mItarSpeedLimitExceeded) {
1746 mGnssNavigationMessageProvider.onNavigationMessageAvailable(event);
1747 }
destradaa4b3e3932014-07-21 18:01:47 -07001748 }
1749
1750 /**
Mike Lockwood04598b62010-04-14 17:17:24 -04001751 * called from native code to inform us what the GPS engine capabilities are
1752 */
1753 private void setEngineCapabilities(int capabilities) {
1754 mEngineCapabilities = capabilities;
Mike Lockwood9b9fb5c2011-06-29 15:09:40 -04001755
destradaa56b47f82015-07-24 10:56:18 -07001756 if (hasCapability(GPS_CAPABILITY_ON_DEMAND_TIME)) {
1757 mOnDemandTimeInjection = true;
Mike Lockwood9b9fb5c2011-06-29 15:09:40 -04001758 requestUtcTime();
1759 }
destradaa6568d702014-10-27 12:47:41 -07001760
Lifu Tang818aa2c2016-02-01 01:52:00 -08001761 mGnssMeasurementsProvider.onCapabilitiesUpdated(
destradaa6568d702014-10-27 12:47:41 -07001762 (capabilities & GPS_CAPABILITY_MEASUREMENTS) == GPS_CAPABILITY_MEASUREMENTS);
Lifu Tang818aa2c2016-02-01 01:52:00 -08001763 mGnssNavigationMessageProvider.onCapabilitiesUpdated(
destradaa6568d702014-10-27 12:47:41 -07001764 (capabilities & GPS_CAPABILITY_NAV_MESSAGES) == GPS_CAPABILITY_NAV_MESSAGES);
Mike Lockwood04598b62010-04-14 17:17:24 -04001765 }
1766
1767 /**
Lifu Tang82f893d2016-01-21 18:15:33 -08001768 * Called from native code to inform us the hardware information.
1769 */
Lifu Tang9363b942016-02-16 18:07:00 -08001770 private void setGnssYearOfHardware(int yearOfHardware) {
1771 if (DEBUG) Log.d(TAG, "setGnssYearOfHardware called with " + yearOfHardware);
Lifu Tang82f893d2016-01-21 18:15:33 -08001772 mYearOfHardware = yearOfHardware;
1773 }
1774
Lifu Tang9363b942016-02-16 18:07:00 -08001775 public interface GnssSystemInfoProvider {
Lifu Tang82f893d2016-01-21 18:15:33 -08001776 /**
1777 * Returns the year of GPS hardware.
1778 */
Lifu Tang9363b942016-02-16 18:07:00 -08001779 int getGnssYearOfHardware();
Lifu Tang82f893d2016-01-21 18:15:33 -08001780 }
1781
1782 /**
1783 * @hide
1784 */
Lifu Tang9363b942016-02-16 18:07:00 -08001785 public GnssSystemInfoProvider getGnssSystemInfoProvider() {
1786 return new GnssSystemInfoProvider() {
Lifu Tang82f893d2016-01-21 18:15:33 -08001787 @Override
Lifu Tang9363b942016-02-16 18:07:00 -08001788 public int getGnssYearOfHardware() {
Lifu Tang82f893d2016-01-21 18:15:33 -08001789 return mYearOfHardware;
1790 }
1791 };
1792 }
1793
1794 /**
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001795 * called from native code to request XTRA data
1796 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001797 private void xtraDownloadRequest() {
Joe Onoratof5d95cb2010-01-07 21:48:32 -05001798 if (DEBUG) Log.d(TAG, "xtraDownloadRequest");
Mike Lockwood98e48692010-04-07 16:32:51 -04001799 sendMessage(DOWNLOAD_XTRA_DATA, 0, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001800 }
1801
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001802 /**
destradaa0682809a2013-08-12 18:50:30 -07001803 * Helper method to construct a location object.
1804 */
1805 private Location buildLocation(
1806 int flags,
1807 double latitude,
1808 double longitude,
1809 double altitude,
1810 float speed,
1811 float bearing,
gomo4402af62017-01-11 13:20:13 -08001812 float horizontalAccuracy,
1813 float verticalAccuracy,
1814 float speedAccuracy,
1815 float bearingAccuracy,
destradaa0682809a2013-08-12 18:50:30 -07001816 long timestamp) {
1817 Location location = new Location(LocationManager.GPS_PROVIDER);
1818 if((flags & LOCATION_HAS_LAT_LONG) == LOCATION_HAS_LAT_LONG) {
1819 location.setLatitude(latitude);
1820 location.setLongitude(longitude);
1821 location.setTime(timestamp);
1822 location.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());
1823 }
1824 if((flags & LOCATION_HAS_ALTITUDE) == LOCATION_HAS_ALTITUDE) {
1825 location.setAltitude(altitude);
1826 }
1827 if((flags & LOCATION_HAS_SPEED) == LOCATION_HAS_SPEED) {
1828 location.setSpeed(speed);
1829 }
1830 if((flags & LOCATION_HAS_BEARING) == LOCATION_HAS_BEARING) {
1831 location.setBearing(bearing);
1832 }
gomo4402af62017-01-11 13:20:13 -08001833 if((flags & LOCATION_HAS_HORIZONTAL_ACCURACY) == LOCATION_HAS_HORIZONTAL_ACCURACY) {
1834 location.setAccuracy(horizontalAccuracy);
1835 }
1836 if((flags & LOCATION_HAS_VERTICAL_ACCURACY) == LOCATION_HAS_VERTICAL_ACCURACY) {
1837 location.setVerticalAccuracyMeters(verticalAccuracy);
1838 }
1839 if((flags & LOCATION_HAS_SPEED_ACCURACY) == LOCATION_HAS_SPEED_ACCURACY) {
1840 location.setSpeedAccuracyMetersPerSecond(speedAccuracy);
1841 }
1842 if((flags & LOCATION_HAS_BEARING_ACCURACY) == LOCATION_HAS_BEARING_ACCURACY) {
1843 location.setBearingAccuracyDegrees(bearingAccuracy);
destradaa0682809a2013-08-12 18:50:30 -07001844 }
1845 return location;
1846 }
1847
1848 /**
1849 * Converts the GPS HAL status to the internal Geofence Hardware status.
1850 */
1851 private int getGeofenceStatus(int status) {
1852 switch(status) {
1853 case GPS_GEOFENCE_OPERATION_SUCCESS:
1854 return GeofenceHardware.GEOFENCE_SUCCESS;
1855 case GPS_GEOFENCE_ERROR_GENERIC:
1856 return GeofenceHardware.GEOFENCE_FAILURE;
1857 case GPS_GEOFENCE_ERROR_ID_EXISTS:
1858 return GeofenceHardware.GEOFENCE_ERROR_ID_EXISTS;
1859 case GPS_GEOFENCE_ERROR_INVALID_TRANSITION:
1860 return GeofenceHardware.GEOFENCE_ERROR_INVALID_TRANSITION;
1861 case GPS_GEOFENCE_ERROR_TOO_MANY_GEOFENCES:
1862 return GeofenceHardware.GEOFENCE_ERROR_TOO_MANY_GEOFENCES;
1863 case GPS_GEOFENCE_ERROR_ID_UNKNOWN:
1864 return GeofenceHardware.GEOFENCE_ERROR_ID_UNKNOWN;
1865 default:
1866 return -1;
1867 }
1868 }
1869
1870 /**
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001871 * Called from native to report GPS Geofence transition
1872 * All geofence callbacks are called on the same thread
1873 */
1874 private void reportGeofenceTransition(int geofenceId, int flags, double latitude,
gomo4402af62017-01-11 13:20:13 -08001875 double longitude, double altitude, float speed, float bearing, float horizontalAccuracy,
1876 float verticalAccuracy, float speedAccuracy, float bearingAccuracy, long timestamp,
1877 int transition, long transitionTimestamp) {
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001878 if (mGeofenceHardwareImpl == null) {
1879 mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
1880 }
destradaa0682809a2013-08-12 18:50:30 -07001881 Location location = buildLocation(
1882 flags,
1883 latitude,
1884 longitude,
1885 altitude,
1886 speed,
1887 bearing,
gomo4402af62017-01-11 13:20:13 -08001888 horizontalAccuracy,
1889 verticalAccuracy,
1890 speedAccuracy,
1891 bearingAccuracy,
destradaa0682809a2013-08-12 18:50:30 -07001892 timestamp);
1893 mGeofenceHardwareImpl.reportGeofenceTransition(
1894 geofenceId,
1895 location,
1896 transition,
1897 transitionTimestamp,
1898 GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE,
1899 FusedBatchOptions.SourceTechnologies.GNSS);
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001900 }
1901
1902 /**
1903 * called from native code to report GPS status change.
1904 */
1905 private void reportGeofenceStatus(int status, int flags, double latitude,
gomo4402af62017-01-11 13:20:13 -08001906 double longitude, double altitude, float speed, float bearing, float horizontalAccuracy,
1907 float verticalAccuracy, float speedAccuracy, float bearingAccuracy, long timestamp) {
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001908 if (mGeofenceHardwareImpl == null) {
1909 mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
1910 }
destradaa0682809a2013-08-12 18:50:30 -07001911 Location location = buildLocation(
1912 flags,
1913 latitude,
1914 longitude,
1915 altitude,
1916 speed,
1917 bearing,
gomo4402af62017-01-11 13:20:13 -08001918 horizontalAccuracy,
1919 verticalAccuracy,
1920 speedAccuracy,
1921 bearingAccuracy,
destradaa0682809a2013-08-12 18:50:30 -07001922 timestamp);
1923 int monitorStatus = GeofenceHardware.MONITOR_CURRENTLY_UNAVAILABLE;
1924 if(status == GPS_GEOFENCE_AVAILABLE) {
1925 monitorStatus = GeofenceHardware.MONITOR_CURRENTLY_AVAILABLE;
1926 }
1927 mGeofenceHardwareImpl.reportGeofenceMonitorStatus(
1928 GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE,
1929 monitorStatus,
1930 location,
1931 FusedBatchOptions.SourceTechnologies.GNSS);
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001932 }
1933
1934 /**
1935 * called from native code - Geofence Add callback
1936 */
1937 private void reportGeofenceAddStatus(int geofenceId, int status) {
1938 if (mGeofenceHardwareImpl == null) {
1939 mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
1940 }
destradaa0682809a2013-08-12 18:50:30 -07001941 mGeofenceHardwareImpl.reportGeofenceAddStatus(geofenceId, getGeofenceStatus(status));
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001942 }
1943
1944 /**
1945 * called from native code - Geofence Remove callback
1946 */
1947 private void reportGeofenceRemoveStatus(int geofenceId, int status) {
1948 if (mGeofenceHardwareImpl == null) {
1949 mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
1950 }
destradaa0682809a2013-08-12 18:50:30 -07001951 mGeofenceHardwareImpl.reportGeofenceRemoveStatus(geofenceId, getGeofenceStatus(status));
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001952 }
1953
1954 /**
1955 * called from native code - Geofence Pause callback
1956 */
1957 private void reportGeofencePauseStatus(int geofenceId, int status) {
1958 if (mGeofenceHardwareImpl == null) {
1959 mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
1960 }
destradaa0682809a2013-08-12 18:50:30 -07001961 mGeofenceHardwareImpl.reportGeofencePauseStatus(geofenceId, getGeofenceStatus(status));
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001962 }
1963
1964 /**
1965 * called from native code - Geofence Resume callback
1966 */
1967 private void reportGeofenceResumeStatus(int geofenceId, int status) {
1968 if (mGeofenceHardwareImpl == null) {
1969 mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
1970 }
destradaa0682809a2013-08-12 18:50:30 -07001971 mGeofenceHardwareImpl.reportGeofenceResumeStatus(geofenceId, getGeofenceStatus(status));
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001972 }
1973
Danke Xie22d1f9f2009-08-18 18:28:45 -04001974 //=============================================================
1975 // NI Client support
Miguel Torroja1e84da82010-07-27 07:02:24 +02001976 //=============================================================
Danke Xie22d1f9f2009-08-18 18:28:45 -04001977 private final INetInitiatedListener mNetInitiatedListener = new INetInitiatedListener.Stub() {
destradaaef752b62015-04-17 13:10:47 -07001978 // Sends a response for an NI request to HAL.
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001979 @Override
Miguel Torroja1e84da82010-07-27 07:02:24 +02001980 public boolean sendNiResponse(int notificationId, int userResponse)
1981 {
1982 // TODO Add Permission check
Danke Xie22d1f9f2009-08-18 18:28:45 -04001983
Miguel Torroja1e84da82010-07-27 07:02:24 +02001984 if (DEBUG) Log.d(TAG, "sendNiResponse, notifId: " + notificationId +
1985 ", response: " + userResponse);
1986 native_send_ni_response(notificationId, userResponse);
1987 return true;
1988 }
Danke Xie22d1f9f2009-08-18 18:28:45 -04001989 };
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001990
Danke Xie22d1f9f2009-08-18 18:28:45 -04001991 public INetInitiatedListener getNetInitiatedListener() {
1992 return mNetInitiatedListener;
1993 }
1994
1995 // Called by JNI function to report an NI request.
Miguel Torroja1e84da82010-07-27 07:02:24 +02001996 public void reportNiNotification(
1997 int notificationId,
1998 int niType,
1999 int notifyFlags,
2000 int timeout,
2001 int defaultResponse,
2002 String requestorId,
2003 String text,
2004 int requestorIdEncoding,
Hridya Valsaraju2ea29602016-09-13 08:38:09 -07002005 int textEncoding
Danke Xie22d1f9f2009-08-18 18:28:45 -04002006 )
Miguel Torroja1e84da82010-07-27 07:02:24 +02002007 {
2008 Log.i(TAG, "reportNiNotification: entered");
2009 Log.i(TAG, "notificationId: " + notificationId +
2010 ", niType: " + niType +
2011 ", notifyFlags: " + notifyFlags +
2012 ", timeout: " + timeout +
2013 ", defaultResponse: " + defaultResponse);
2014
2015 Log.i(TAG, "requestorId: " + requestorId +
2016 ", text: " + text +
2017 ", requestorIdEncoding: " + requestorIdEncoding +
2018 ", textEncoding: " + textEncoding);
2019
2020 GpsNiNotification notification = new GpsNiNotification();
2021
2022 notification.notificationId = notificationId;
2023 notification.niType = niType;
2024 notification.needNotify = (notifyFlags & GpsNetInitiatedHandler.GPS_NI_NEED_NOTIFY) != 0;
2025 notification.needVerify = (notifyFlags & GpsNetInitiatedHandler.GPS_NI_NEED_VERIFY) != 0;
2026 notification.privacyOverride = (notifyFlags & GpsNetInitiatedHandler.GPS_NI_PRIVACY_OVERRIDE) != 0;
2027 notification.timeout = timeout;
2028 notification.defaultResponse = defaultResponse;
2029 notification.requestorId = requestorId;
2030 notification.text = text;
2031 notification.requestorIdEncoding = requestorIdEncoding;
2032 notification.textEncoding = textEncoding;
2033
Miguel Torroja1e84da82010-07-27 07:02:24 +02002034 mNIHandler.handleNiNotification(notification);
2035 }
2036
2037 /**
2038 * Called from native code to request set id info.
2039 * We should be careful about receiving null string from the TelephonyManager,
2040 * because sending null String to JNI function would cause a crash.
2041 */
2042
2043 private void requestSetID(int flags) {
2044 TelephonyManager phone = (TelephonyManager)
2045 mContext.getSystemService(Context.TELEPHONY_SERVICE);
destradaaef752b62015-04-17 13:10:47 -07002046 int type = AGPS_SETID_TYPE_NONE;
Miguel Torroja1e84da82010-07-27 07:02:24 +02002047 String data = "";
2048
2049 if ((flags & AGPS_RIL_REQUEST_SETID_IMSI) == AGPS_RIL_REQUEST_SETID_IMSI) {
2050 String data_temp = phone.getSubscriberId();
2051 if (data_temp == null) {
2052 // This means the framework does not have the SIM card ready.
2053 } else {
2054 // This means the framework has the SIM card.
2055 data = data_temp;
2056 type = AGPS_SETID_TYPE_IMSI;
2057 }
2058 }
2059 else if ((flags & AGPS_RIL_REQUEST_SETID_MSISDN) == AGPS_RIL_REQUEST_SETID_MSISDN) {
2060 String data_temp = phone.getLine1Number();
2061 if (data_temp == null) {
2062 // This means the framework does not have the SIM card ready.
2063 } else {
2064 // This means the framework has the SIM card.
2065 data = data_temp;
2066 type = AGPS_SETID_TYPE_MSISDN;
2067 }
2068 }
2069 native_agps_set_id(type, data);
2070 }
2071
2072 /**
Mike Lockwood9b9fb5c2011-06-29 15:09:40 -04002073 * Called from native code to request utc time info
2074 */
Mike Lockwood9b9fb5c2011-06-29 15:09:40 -04002075 private void requestUtcTime() {
destradaae21252a2015-09-08 12:32:59 -07002076 if (DEBUG) Log.d(TAG, "utcTimeRequest");
Mike Lockwood9b9fb5c2011-06-29 15:09:40 -04002077 sendMessage(INJECT_NTP_TIME, 0, null);
2078 }
2079
2080 /**
Miguel Torroja1e84da82010-07-27 07:02:24 +02002081 * Called from native code to request reference location info
2082 */
2083
Hridya Valsaraju2ea29602016-09-13 08:38:09 -07002084 private void requestRefLocation() {
Miguel Torroja1e84da82010-07-27 07:02:24 +02002085 TelephonyManager phone = (TelephonyManager)
2086 mContext.getSystemService(Context.TELEPHONY_SERVICE);
Victoria Leased50d0c32012-10-29 13:16:17 -07002087 final int phoneType = phone.getPhoneType();
2088 if (phoneType == TelephonyManager.PHONE_TYPE_GSM) {
Miguel Torroja1e84da82010-07-27 07:02:24 +02002089 GsmCellLocation gsm_cell = (GsmCellLocation) phone.getCellLocation();
Victoria Leased50d0c32012-10-29 13:16:17 -07002090 if ((gsm_cell != null) && (phone.getNetworkOperator() != null)
2091 && (phone.getNetworkOperator().length() > 3)) {
Miguel Torroja1e84da82010-07-27 07:02:24 +02002092 int type;
2093 int mcc = Integer.parseInt(phone.getNetworkOperator().substring(0,3));
2094 int mnc = Integer.parseInt(phone.getNetworkOperator().substring(3));
Mike Lockwoodedc0f3872010-10-22 09:16:17 -04002095 int networkType = phone.getNetworkType();
2096 if (networkType == TelephonyManager.NETWORK_TYPE_UMTS
2097 || networkType == TelephonyManager.NETWORK_TYPE_HSDPA
2098 || networkType == TelephonyManager.NETWORK_TYPE_HSUPA
Arun Ravindran58d46122012-07-30 17:50:21 +03002099 || networkType == TelephonyManager.NETWORK_TYPE_HSPA
2100 || networkType == TelephonyManager.NETWORK_TYPE_HSPAP) {
Miguel Torroja1e84da82010-07-27 07:02:24 +02002101 type = AGPS_REF_LOCATION_TYPE_UMTS_CELLID;
Mike Lockwoodedc0f3872010-10-22 09:16:17 -04002102 } else {
Miguel Torroja1e84da82010-07-27 07:02:24 +02002103 type = AGPS_REF_LOCATION_TYPE_GSM_CELLID;
Mike Lockwoodedc0f3872010-10-22 09:16:17 -04002104 }
Miguel Torroja1e84da82010-07-27 07:02:24 +02002105 native_agps_set_ref_location_cellid(type, mcc, mnc,
2106 gsm_cell.getLac(), gsm_cell.getCid());
Mike Lockwoodedc0f3872010-10-22 09:16:17 -04002107 } else {
Miguel Torroja1e84da82010-07-27 07:02:24 +02002108 Log.e(TAG,"Error getting cell location info.");
Mike Lockwoodedc0f3872010-10-22 09:16:17 -04002109 }
Victoria Leased50d0c32012-10-29 13:16:17 -07002110 } else if (phoneType == TelephonyManager.PHONE_TYPE_CDMA) {
2111 Log.e(TAG, "CDMA not supported.");
Mike Lockwoodedc0f3872010-10-22 09:16:17 -04002112 }
Miguel Torroja1e84da82010-07-27 07:02:24 +02002113 }
Danke Xie22d1f9f2009-08-18 18:28:45 -04002114
Mike Lockwood98e48692010-04-07 16:32:51 -04002115 private void sendMessage(int message, int arg, Object obj) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002116 // hold a wake lock until this message is delivered
Jeff Brown028872f2012-08-25 13:07:01 -07002117 // note that this assumes the message will not be removed from the queue before
2118 // it is handled (otherwise the wake lock would be leaked).
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002119 mWakeLock.acquire();
gomo4402af62017-01-11 13:20:13 -08002120 Log.i(TAG, "WakeLock acquired by sendMessage(" + message + ", " + arg + ", " + obj + ")");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002121 mHandler.obtainMessage(message, arg, 1, obj).sendToTarget();
Mike Lockwood98e48692010-04-07 16:32:51 -04002122 }
2123
Mike Lockwood62a8fc12010-03-22 14:23:26 -04002124 private final class ProviderHandler extends Handler {
Victoria Lease5cd731a2012-12-19 15:04:21 -08002125 public ProviderHandler(Looper looper) {
2126 super(looper, null, true /*async*/);
Jeff Brown028872f2012-08-25 13:07:01 -07002127 }
2128
Mike Lockwood62a8fc12010-03-22 14:23:26 -04002129 @Override
Mike Lockwood4a7b65e2010-10-25 16:35:55 -04002130 public void handleMessage(Message msg) {
Mike Lockwood98e48692010-04-07 16:32:51 -04002131 int message = msg.what;
2132 switch (message) {
Mike Lockwood62a8fc12010-03-22 14:23:26 -04002133 case ENABLE:
2134 if (msg.arg1 == 1) {
2135 handleEnable();
2136 } else {
2137 handleDisable();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002138 }
Mike Lockwood62a8fc12010-03-22 14:23:26 -04002139 break;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002140 case SET_REQUEST:
2141 GpsRequest gpsRequest = (GpsRequest) msg.obj;
2142 handleSetRequest(gpsRequest.request, gpsRequest.source);
Mike Lockwood03ca2162010-04-01 08:10:09 -07002143 break;
Mike Lockwood62a8fc12010-03-22 14:23:26 -04002144 case UPDATE_NETWORK_STATE:
destradaae21252a2015-09-08 12:32:59 -07002145 handleUpdateNetworkState((Network) msg.obj);
2146 break;
2147 case REQUEST_SUPL_CONNECTION:
2148 handleRequestSuplConnection((InetAddress) msg.obj);
2149 break;
2150 case RELEASE_SUPL_CONNECTION:
2151 handleReleaseSuplConnection(msg.arg1);
Mike Lockwood62a8fc12010-03-22 14:23:26 -04002152 break;
2153 case INJECT_NTP_TIME:
2154 handleInjectNtpTime();
2155 break;
2156 case DOWNLOAD_XTRA_DATA:
Wyatt Riley0d6e54e22016-10-05 12:03:03 -07002157 handleDownloadXtraData();
Mike Lockwood62a8fc12010-03-22 14:23:26 -04002158 break;
Kevin Tang40e1baf2012-01-10 14:32:44 -08002159 case INJECT_NTP_TIME_FINISHED:
2160 mInjectNtpTimePending = STATE_IDLE;
2161 break;
2162 case DOWNLOAD_XTRA_DATA_FINISHED:
2163 mDownloadXtraDataPending = STATE_IDLE;
2164 break;
Mike Lockwood62a8fc12010-03-22 14:23:26 -04002165 case UPDATE_LOCATION:
destradaae21252a2015-09-08 12:32:59 -07002166 handleUpdateLocation((Location) msg.obj);
Mike Lockwood62a8fc12010-03-22 14:23:26 -04002167 break;
destradaafb23c672015-04-16 14:01:27 -07002168 case SUBSCRIPTION_OR_SIM_CHANGED:
2169 subscriptionOrSimChanged(mContext);
2170 break;
2171 case INITIALIZE_HANDLER:
destradaae21252a2015-09-08 12:32:59 -07002172 handleInitialize();
destradaafb23c672015-04-16 14:01:27 -07002173 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002174 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002175 if (msg.arg2 == 1) {
2176 // wakelock was taken for this message, release it
2177 mWakeLock.release();
gomo4402af62017-01-11 13:20:13 -08002178 Log.i(TAG, "WakeLock released by handleMessage(" + message + ", " + msg.arg1 + ", "
2179 + msg.obj + ")");
Mike Lockwood98e48692010-04-07 16:32:51 -04002180 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002181 }
destradaafb23c672015-04-16 14:01:27 -07002182
2183 /**
Lifu Tang30f95a72016-01-07 23:20:38 -08002184 * This method is bound to {@link #GnssLocationProvider(Context, ILocationManager, Looper)}.
destradaafb23c672015-04-16 14:01:27 -07002185 * It is in charge of loading properties and registering for events that will be posted to
2186 * this handler.
2187 */
destradaae21252a2015-09-08 12:32:59 -07002188 private void handleInitialize() {
destradaafb23c672015-04-16 14:01:27 -07002189 // load default GPS configuration
2190 // (this configuration might change in the future based on SIM changes)
2191 reloadGpsProperties(mContext, mProperties);
2192
2193 // TODO: When this object "finishes" we should unregister by invoking
2194 // SubscriptionManager.getInstance(mContext).unregister(mOnSubscriptionsChangedListener);
2195 // This is not strictly necessary because it will be unregistered if the
2196 // notification fails but it is good form.
2197
2198 // Register for SubscriptionInfo list changes which is guaranteed
2199 // to invoke onSubscriptionsChanged the first time.
2200 SubscriptionManager.from(mContext)
2201 .addOnSubscriptionsChangedListener(mOnSubscriptionsChangedListener);
2202
2203 // listen for events
destradaaef752b62015-04-17 13:10:47 -07002204 IntentFilter intentFilter;
2205 if (native_is_agps_ril_supported()) {
2206 intentFilter = new IntentFilter();
2207 intentFilter.addAction(Intents.DATA_SMS_RECEIVED_ACTION);
2208 intentFilter.addDataScheme("sms");
2209 intentFilter.addDataAuthority("localhost", "7275");
2210 mContext.registerReceiver(mBroadcastReceiver, intentFilter, null, this);
destradaafb23c672015-04-16 14:01:27 -07002211
destradaaef752b62015-04-17 13:10:47 -07002212 intentFilter = new IntentFilter();
2213 intentFilter.addAction(Intents.WAP_PUSH_RECEIVED_ACTION);
2214 try {
2215 intentFilter.addDataType("application/vnd.omaloc-supl-init");
2216 } catch (IntentFilter.MalformedMimeTypeException e) {
2217 Log.w(TAG, "Malformed SUPL init mime type");
2218 }
2219 mContext.registerReceiver(mBroadcastReceiver, intentFilter, null, this);
2220 } else if (DEBUG) {
2221 Log.d(TAG, "Skipped registration for SMS/WAP-PUSH messages because AGPS Ril in GPS"
2222 + " HAL is not supported");
destradaafb23c672015-04-16 14:01:27 -07002223 }
destradaafb23c672015-04-16 14:01:27 -07002224
2225 intentFilter = new IntentFilter();
2226 intentFilter.addAction(ALARM_WAKEUP);
2227 intentFilter.addAction(ALARM_TIMEOUT);
destradaafb23c672015-04-16 14:01:27 -07002228 intentFilter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED);
Adam Lesinski87c17df2015-05-27 13:24:13 -07002229 intentFilter.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
destradaafb23c672015-04-16 14:01:27 -07002230 intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
2231 intentFilter.addAction(Intent.ACTION_SCREEN_ON);
2232 intentFilter.addAction(SIM_STATE_CHANGED);
2233 mContext.registerReceiver(mBroadcastReceiver, intentFilter, null, this);
2234
destradaae21252a2015-09-08 12:32:59 -07002235 // register for connectivity change events, this is equivalent to the deprecated way of
2236 // registering for CONNECTIVITY_ACTION broadcasts
2237 NetworkRequest.Builder networkRequestBuilder = new NetworkRequest.Builder();
2238 networkRequestBuilder.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
2239 networkRequestBuilder.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
2240 NetworkRequest networkRequest = networkRequestBuilder.build();
2241 mConnMgr.registerNetworkCallback(networkRequest, mNetworkConnectivityCallback);
2242
destradaafb23c672015-04-16 14:01:27 -07002243 // listen for PASSIVE_PROVIDER updates
2244 LocationManager locManager =
2245 (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
2246 long minTime = 0;
2247 float minDistance = 0;
2248 boolean oneShot = false;
2249 LocationRequest request = LocationRequest.createFromDeprecatedProvider(
2250 LocationManager.PASSIVE_PROVIDER,
2251 minTime,
2252 minDistance,
2253 oneShot);
2254 // Don't keep track of this request since it's done on behalf of other clients
2255 // (which are kept track of separately).
2256 request.setHideFromAppOps(true);
2257 locManager.requestLocationUpdates(
2258 request,
2259 new NetworkLocationListener(),
2260 getLooper());
2261 }
2262 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002263
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002264 private final class NetworkLocationListener implements LocationListener {
2265 @Override
2266 public void onLocationChanged(Location location) {
2267 // this callback happens on mHandler looper
2268 if (LocationManager.NETWORK_PROVIDER.equals(location.getProvider())) {
2269 handleUpdateLocation(location);
2270 }
2271 }
2272 @Override
2273 public void onStatusChanged(String provider, int status, Bundle extras) { }
2274 @Override
2275 public void onProviderEnabled(String provider) { }
2276 @Override
2277 public void onProviderDisabled(String provider) { }
2278 }
2279
Kevin Tanga5fe6b22011-06-05 14:25:16 -07002280 private String getSelectedApn() {
2281 Uri uri = Uri.parse("content://telephony/carriers/preferapn");
destradaa96a14702014-06-05 11:36:30 -07002282 Cursor cursor = null;
2283 try {
2284 cursor = mContext.getContentResolver().query(
2285 uri,
2286 new String[] { "apn" },
2287 null /* selection */,
2288 null /* selectionArgs */,
2289 Carriers.DEFAULT_SORT_ORDER);
2290 if (cursor != null && cursor.moveToFirst()) {
2291 return cursor.getString(0);
2292 } else {
2293 Log.e(TAG, "No APN found to select.");
2294 }
2295 } catch (Exception e) {
destradaaea8a8a62014-06-23 18:19:03 -07002296 Log.e(TAG, "Error encountered on selecting the APN.", e);
destradaa96a14702014-06-05 11:36:30 -07002297 } finally {
2298 if (cursor != null) {
Kevin Tanga5fe6b22011-06-05 14:25:16 -07002299 cursor.close();
2300 }
2301 }
destradaa96a14702014-06-05 11:36:30 -07002302
2303 return null;
2304 }
2305
2306 private int getApnIpType(String apn) {
destradaae21252a2015-09-08 12:32:59 -07002307 ensureInHandlerThread();
destradaa96a14702014-06-05 11:36:30 -07002308 if (apn == null) {
2309 return APN_INVALID;
2310 }
2311
destradaa96a14702014-06-05 11:36:30 -07002312 String selection = String.format("current = 1 and apn = '%s' and carrier_enabled = 1", apn);
2313 Cursor cursor = null;
2314 try {
2315 cursor = mContext.getContentResolver().query(
2316 Carriers.CONTENT_URI,
2317 new String[] { Carriers.PROTOCOL },
2318 selection,
2319 null,
2320 Carriers.DEFAULT_SORT_ORDER);
2321
2322 if (null != cursor && cursor.moveToFirst()) {
2323 return translateToApnIpType(cursor.getString(0), apn);
2324 } else {
2325 Log.e(TAG, "No entry found in query for APN: " + apn);
2326 }
2327 } catch (Exception e) {
2328 Log.e(TAG, "Error encountered on APN query for: " + apn, e);
2329 } finally {
2330 if (cursor != null) {
2331 cursor.close();
2332 }
2333 }
2334
2335 return APN_INVALID;
2336 }
2337
2338 private int translateToApnIpType(String ipProtocol, String apn) {
2339 if ("IP".equals(ipProtocol)) {
2340 return APN_IPV4;
2341 }
2342 if ("IPV6".equals(ipProtocol)) {
2343 return APN_IPV6;
2344 }
2345 if ("IPV4V6".equals(ipProtocol)) {
2346 return APN_IPV4V6;
2347 }
2348
2349 // we hit the default case so the ipProtocol is not recognized
2350 String message = String.format("Unknown IP Protocol: %s, for APN: %s", ipProtocol, apn);
2351 Log.e(TAG, message);
2352 return APN_INVALID;
2353 }
2354
2355 private void setRouting() {
2356 if (mAGpsDataConnectionIpAddr == null) {
2357 return;
2358 }
2359
destradaae21252a2015-09-08 12:32:59 -07002360 // TODO: replace the use of this deprecated API
destradaa96a14702014-06-05 11:36:30 -07002361 boolean result = mConnMgr.requestRouteToHostAddress(
2362 ConnectivityManager.TYPE_MOBILE_SUPL,
2363 mAGpsDataConnectionIpAddr);
2364
2365 if (!result) {
2366 Log.e(TAG, "Error requesting route to host: " + mAGpsDataConnectionIpAddr);
2367 } else if (DEBUG) {
2368 Log.d(TAG, "Successfully requested route to host: " + mAGpsDataConnectionIpAddr);
2369 }
Kevin Tanga5fe6b22011-06-05 14:25:16 -07002370 }
2371
destradaae21252a2015-09-08 12:32:59 -07002372 /**
2373 * @return {@code true} if there is a data network available for outgoing connections,
2374 * {@code false} otherwise.
2375 */
2376 private boolean isDataNetworkConnected() {
2377 NetworkInfo activeNetworkInfo = mConnMgr.getActiveNetworkInfo();
2378 return activeNetworkInfo != null && activeNetworkInfo.isConnected();
2379 }
2380
2381 /**
2382 * Ensures the calling function is running in the thread associated with {@link #mHandler}.
2383 */
2384 private void ensureInHandlerThread() {
2385 if (mHandler != null && Looper.myLooper() == mHandler.getLooper()) {
2386 return;
2387 }
2388 throw new RuntimeException("This method must run on the Handler thread.");
2389 }
2390
2391 /**
2392 * @return A string representing the current state stored in {@link #mAGpsDataConnectionState}.
2393 */
2394 private String agpsDataConnStateAsString() {
2395 switch(mAGpsDataConnectionState) {
2396 case AGPS_DATA_CONNECTION_CLOSED:
2397 return "CLOSED";
2398 case AGPS_DATA_CONNECTION_OPEN:
2399 return "OPEN";
2400 case AGPS_DATA_CONNECTION_OPENING:
2401 return "OPENING";
2402 default:
2403 return "<Unknown>";
2404 }
2405 }
2406
2407 /**
2408 * @return A string representing the given GPS_AGPS_DATA status.
2409 */
2410 private String agpsDataConnStatusAsString(int agpsDataConnStatus) {
2411 switch (agpsDataConnStatus) {
2412 case GPS_AGPS_DATA_CONNECTED:
2413 return "CONNECTED";
2414 case GPS_AGPS_DATA_CONN_DONE:
2415 return "DONE";
2416 case GPS_AGPS_DATA_CONN_FAILED:
2417 return "FAILED";
2418 case GPS_RELEASE_AGPS_DATA_CONN:
2419 return "RELEASE";
2420 case GPS_REQUEST_AGPS_DATA_CONN:
2421 return "REQUEST";
2422 default:
2423 return "<Unknown>";
2424 }
2425 }
2426
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002427 @Override
2428 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
2429 StringBuilder s = new StringBuilder();
destradaa25e8caf2015-08-24 14:14:44 -07002430 s.append(" mFixInterval=").append(mFixInterval).append('\n');
2431 s.append(" mDisableGps (battery saver mode)=").append(mDisableGps).append('\n');
2432 s.append(" mEngineCapabilities=0x").append(Integer.toHexString(mEngineCapabilities));
2433 s.append(" ( ");
2434 if (hasCapability(GPS_CAPABILITY_SCHEDULING)) s.append("SCHEDULING ");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002435 if (hasCapability(GPS_CAPABILITY_MSB)) s.append("MSB ");
2436 if (hasCapability(GPS_CAPABILITY_MSA)) s.append("MSA ");
2437 if (hasCapability(GPS_CAPABILITY_SINGLE_SHOT)) s.append("SINGLE_SHOT ");
2438 if (hasCapability(GPS_CAPABILITY_ON_DEMAND_TIME)) s.append("ON_DEMAND_TIME ");
destradaa25e8caf2015-08-24 14:14:44 -07002439 if (hasCapability(GPS_CAPABILITY_GEOFENCING)) s.append("GEOFENCING ");
2440 if (hasCapability(GPS_CAPABILITY_MEASUREMENTS)) s.append("MEASUREMENTS ");
2441 if (hasCapability(GPS_CAPABILITY_NAV_MESSAGES)) s.append("NAV_MESSAGES ");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002442 s.append(")\n");
2443
2444 s.append(native_get_internal_state());
2445 pw.append(s);
2446 }
2447
Wei Liu6f6326b2015-06-24 23:47:50 -07002448 /**
2449 * A simple implementation of exponential backoff.
2450 */
2451 private static final class BackOff {
2452 private static final int MULTIPLIER = 2;
2453 private final long mInitIntervalMillis;
2454 private final long mMaxIntervalMillis;
2455 private long mCurrentIntervalMillis;
2456
2457 public BackOff(long initIntervalMillis, long maxIntervalMillis) {
2458 mInitIntervalMillis = initIntervalMillis;
2459 mMaxIntervalMillis = maxIntervalMillis;
2460
2461 mCurrentIntervalMillis = mInitIntervalMillis / MULTIPLIER;
2462 }
2463
2464 public long nextBackoffMillis() {
2465 if (mCurrentIntervalMillis > mMaxIntervalMillis) {
2466 return mMaxIntervalMillis;
2467 }
2468
2469 mCurrentIntervalMillis *= MULTIPLIER;
2470 return mCurrentIntervalMillis;
2471 }
2472
2473 public void reset() {
2474 mCurrentIntervalMillis = mInitIntervalMillis / MULTIPLIER;
2475 }
2476 }
2477
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002478 // for GPS SV statistics
Lifu Tang120480f2016-02-07 18:08:19 -08002479 private static final int MAX_SVS = 64;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002480
2481 // preallocated arrays, to avoid memory allocation in reportStatus()
Lifu Tang120480f2016-02-07 18:08:19 -08002482 private int mSvidWithFlags[] = new int[MAX_SVS];
Lifu Tang76a620f2016-02-26 19:53:01 -08002483 private float mCn0s[] = new float[MAX_SVS];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002484 private float mSvElevations[] = new float[MAX_SVS];
2485 private float mSvAzimuths[] = new float[MAX_SVS];
gomo4402af62017-01-11 13:20:13 -08002486 private float mSvCarrierFreqs[] = new float[MAX_SVS];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002487 private int mSvCount;
Mike Lockwoodb16e7802009-08-06 09:26:02 -04002488 // preallocated to avoid memory allocation in reportNmea()
2489 private byte[] mNmeaBuffer = new byte[120];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002490
gomo4402af62017-01-11 13:20:13 -08002491 static { class_init_native(); }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002492 private static native void class_init_native();
2493 private static native boolean native_is_supported();
destradaaef752b62015-04-17 13:10:47 -07002494 private static native boolean native_is_agps_ril_supported();
2495 private static native boolean native_is_gnss_configuration_supported();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002496
2497 private native boolean native_init();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002498 private native void native_cleanup();
Mike Lockwood04598b62010-04-14 17:17:24 -04002499 private native boolean native_set_position_mode(int mode, int recurrence, int min_interval,
2500 int preferred_accuracy, int preferred_time);
2501 private native boolean native_start();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002502 private native boolean native_stop();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002503 private native void native_delete_aiding_data(int flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002504 // returns number of SVs
2505 // mask[0] is ephemeris mask and mask[1] is almanac mask
Lifu Tang76a620f2016-02-26 19:53:01 -08002506 private native int native_read_sv_status(int[] prnWithFlags, float[] cn0s, float[] elevations,
gomo4402af62017-01-11 13:20:13 -08002507 float[] azimuths, float[] carrierFrequencies);
Mike Lockwoodf602d362010-06-20 14:28:16 -07002508 private native int native_read_nmea(byte[] buffer, int bufferSize);
Mike Lockwoodd26ce0d2009-06-11 12:25:46 -04002509 private native void native_inject_location(double latitude, double longitude, float accuracy);
2510
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -06002511 // XTRA Support
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002512 private native void native_inject_time(long time, long timeReference, int uncertainty);
2513 private native boolean native_supports_xtra();
2514 private native void native_inject_xtra_data(byte[] data, int length);
The Android Open Source Project10592532009-03-18 17:39:46 -07002515
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -06002516 // DEBUG Support
2517 private native String native_get_internal_state();
2518
2519 // AGPS Support
destradaa96a14702014-06-05 11:36:30 -07002520 private native void native_agps_data_conn_open(String apn, int apnIpType);
Mike Lockwoode3635c92009-05-11 08:38:02 -04002521 private native void native_agps_data_conn_closed();
2522 private native void native_agps_data_conn_failed();
Miguel Torroja1e84da82010-07-27 07:02:24 +02002523 private native void native_agps_ni_message(byte [] msg, int length);
Mike Lockwooda9e54612009-06-19 14:54:42 -04002524 private native void native_set_agps_server(int type, String hostname, int port);
Danke Xie22d1f9f2009-08-18 18:28:45 -04002525
2526 // Network-initiated (NI) Support
2527 private native void native_send_ni_response(int notificationId, int userResponse);
Miguel Torroja1e84da82010-07-27 07:02:24 +02002528
2529 // AGPS ril suport
2530 private native void native_agps_set_ref_location_cellid(int type, int mcc, int mnc,
2531 int lac, int cid);
2532 private native void native_agps_set_id(int type, String setid);
Mike Lockwood50130bb2010-10-11 06:22:50 -04002533
2534 private native void native_update_network_state(boolean connected, int type,
Kevin Tanga5fe6b22011-06-05 14:25:16 -07002535 boolean roaming, boolean available, String extraInfo, String defaultAPN);
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07002536
2537 // Hardware Geofence support.
2538 private static native boolean native_is_geofence_supported();
2539 private static native boolean native_add_geofence(int geofenceId, double latitude,
2540 double longitude, double radius, int lastTransition,int monitorTransitions,
2541 int notificationResponsivenes, int unknownTimer);
2542 private static native boolean native_remove_geofence(int geofenceId);
2543 private static native boolean native_resume_geofence(int geofenceId, int transitions);
2544 private static native boolean native_pause_geofence(int geofenceId);
destradaaea8a8a62014-06-23 18:19:03 -07002545
2546 // Gps Hal measurements support.
2547 private static native boolean native_is_measurement_supported();
destradaa4b3e3932014-07-21 18:01:47 -07002548 private native boolean native_start_measurement_collection();
2549 private native boolean native_stop_measurement_collection();
2550
2551 // Gps Navigation message support.
2552 private static native boolean native_is_navigation_message_supported();
2553 private native boolean native_start_navigation_message_collection();
2554 private native boolean native_stop_navigation_message_collection();
Tsuwei Chen52617bb2014-08-25 11:49:11 -07002555
2556 // GNSS Configuration
Hridya Valsaraju2ea29602016-09-13 08:38:09 -07002557 private static native boolean native_set_supl_version(int version);
2558 private static native boolean native_set_supl_mode(int mode);
2559 private static native boolean native_set_supl_es(int es);
2560 private static native boolean native_set_lpp_profile(int lppProfile);
2561 private static native boolean native_set_gnss_pos_protocol_select(int gnssPosProtocolSelect);
2562 private static native boolean native_set_gps_lock(int gpsLock);
2563 private static native boolean native_set_emergency_supl_pdn(int emergencySuplPdn);
2564
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002565}