blob: 20711c05b67c9156582fa30df83b2739e391a771 [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
Mike Lockwood29c84342009-05-06 14:01:15 -040019import android.app.AlarmManager;
Dianne Hackborna06de0f2012-12-11 16:34:47 -080020import android.app.AppOpsManager;
Mike Lockwood29c84342009-05-06 14:01:15 -040021import android.app.PendingIntent;
The Android Open Source Project10592532009-03-18 17:39:46 -070022import android.content.BroadcastReceiver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080023import android.content.Context;
24import android.content.Intent;
The Android Open Source Project10592532009-03-18 17:39:46 -070025import android.content.IntentFilter;
Kevin Tanga5fe6b22011-06-05 14:25:16 -070026import android.database.Cursor;
destradaa0682809a2013-08-12 18:50:30 -070027import android.hardware.location.GeofenceHardware;
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -070028import android.hardware.location.GeofenceHardwareImpl;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080029import android.location.Criteria;
destradaa0682809a2013-08-12 18:50:30 -070030import android.location.FusedBatchOptions;
Lifu Tang30f95a72016-01-07 23:20:38 -080031import android.location.GnssStatus;
32import android.location.IGnssStatusListener;
33import android.location.IGnssStatusProvider;
Lifu Tang818aa2c2016-02-01 01:52:00 -080034import android.location.GnssMeasurementsEvent;
Lifu Tange8abe8e2016-04-01 10:32:05 -070035import android.location.GnssNavigationMessage;
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -070036import android.location.IGpsGeofenceHardware;
Mike Lockwood4e50b782009-04-03 08:24:43 -070037import android.location.ILocationManager;
Danke Xie22d1f9f2009-08-18 18:28:45 -040038import android.location.INetInitiatedListener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080039import android.location.Location;
Nick Pelly6fa9ad42012-07-16 12:18:23 -070040import android.location.LocationListener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080041import android.location.LocationManager;
42import android.location.LocationProvider;
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -070043import android.location.LocationRequest;
Mike Lockwood58bda982009-04-14 16:25:07 -040044import android.net.ConnectivityManager;
destradaae21252a2015-09-08 12:32:59 -070045import android.net.Network;
46import android.net.NetworkCapabilities;
Mike Lockwood03d24672009-10-08 15:45:03 -040047import android.net.NetworkInfo;
destradaae21252a2015-09-08 12:32:59 -070048import android.net.NetworkRequest;
Kevin Tanga5fe6b22011-06-05 14:25:16 -070049import android.net.Uri;
Kevin Tang40e1baf2012-01-10 14:32:44 -080050import android.os.AsyncTask;
jackqdyulei455e90a2017-02-09 15:29:16 -080051import android.os.PowerSaveState;
Dianne Hackborn91268cf2013-06-13 19:06:50 -070052import android.os.BatteryStats;
Mike Lockwood63aa5a62010-04-14 19:21:31 -040053import android.os.Binder;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080054import android.os.Bundle;
Ecco Park4fa1ab72016-10-24 13:04:52 -070055import android.os.PersistableBundle;
Mike Lockwood62a8fc12010-03-22 14:23:26 -040056import android.os.Handler;
Victoria Lease5cd731a2012-12-19 15:04:21 -080057import android.os.Looper;
Mike Lockwood62a8fc12010-03-22 14:23:26 -040058import android.os.Message;
Mike Lockwood0528b9b2009-05-07 10:12:54 -040059import android.os.PowerManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080060import android.os.RemoteException;
Mike Lockwood2f82c4e2009-04-17 08:24:10 -040061import android.os.ServiceManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080062import android.os.SystemClock;
Colin Cross7c030ed2014-01-28 09:33:53 -080063import android.os.SystemProperties;
Dianne Hackborn5ac72a22012-08-29 18:32:08 -070064import android.os.UserHandle;
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -070065import android.os.WorkSource;
Mike Lockwoodbcab8df2009-06-25 16:39:09 -040066import android.provider.Settings;
Kevin Tanga5fe6b22011-06-05 14:25:16 -070067import android.provider.Telephony.Carriers;
Miguel Torroja1e84da82010-07-27 07:02:24 +020068import android.provider.Telephony.Sms.Intents;
Wink Savillea374c3d2014-11-11 11:48:04 -080069import android.telephony.SubscriptionManager;
Wink Savilled09c4ca2014-11-22 10:08:16 -080070import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
Miguel Torroja1e84da82010-07-27 07:02:24 +020071import android.telephony.TelephonyManager;
Ecco Park4fa1ab72016-10-24 13:04:52 -070072import android.telephony.CarrierConfigManager;
Miguel Torroja1e84da82010-07-27 07:02:24 +020073import android.telephony.gsm.GsmCellLocation;
Colin Cross7c030ed2014-01-28 09:33:53 -080074import android.text.TextUtils;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080075import android.util.Log;
Jeff Sharkey104344e2011-07-10 14:20:41 -070076import android.util.NtpTrustedTime;
Dianne Hackborna06de0f2012-12-11 16:34:47 -080077
jackqdyulei455e90a2017-02-09 15:29:16 -080078import com.android.internal.app.IAppOpsService;
79import com.android.internal.app.IBatteryStats;
80import com.android.internal.location.GpsNetInitiatedHandler;
81import com.android.internal.location.GpsNetInitiatedHandler.GpsNiNotification;
82import com.android.internal.location.ProviderProperties;
83import com.android.internal.location.ProviderRequest;
84import com.android.server.power.BatterySaverPolicy;
85import com.android.server.power.BatterySaverPolicy.ServiceType;
86
87import libcore.io.IoUtils;
88
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080089import java.io.File;
Nick Pelly6fa9ad42012-07-16 12:18:23 -070090import java.io.FileDescriptor;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080091import java.io.FileInputStream;
92import java.io.IOException;
Nick Pelly6fa9ad42012-07-16 12:18:23 -070093import java.io.PrintWriter;
destradaaea8a8a62014-06-23 18:19:03 -070094import java.net.InetAddress;
95import java.net.UnknownHostException;
Wyatt Rileycf879db2017-01-12 13:57:38 -080096import java.util.ArrayList;
Andreas Gampee6748ce2015-12-11 18:00:38 -080097import java.util.Arrays;
Mike Lockwoodf1218be2010-01-29 09:20:06 -050098import java.util.Date;
Wyatt Rileycf879db2017-01-12 13:57:38 -080099import java.util.List;
Danke Xie22d1f9f2009-08-18 18:28:45 -0400100import java.util.Map.Entry;
Jake Hambyb49a73d2011-03-15 20:09:46 -0700101import java.util.Properties;
Hridya Valsaraju2ea29602016-09-13 08:38:09 -0700102import java.util.Map;
103import java.util.HashMap;
Colin Cross7c030ed2014-01-28 09:33:53 -0800104
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800105/**
gomo4402af62017-01-11 13:20:13 -0800106 * A GNSS implementation of LocationProvider used by LocationManager.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800107 *
108 * {@hide}
109 */
Lifu Tang30f95a72016-01-07 23:20:38 -0800110public class GnssLocationProvider implements LocationProviderInterface {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800111
Lifu Tang30f95a72016-01-07 23:20:38 -0800112 private static final String TAG = "GnssLocationProvider";
Mike Lockwood29c84342009-05-06 14:01:15 -0400113
Brian Muramatsu1715cb32012-08-08 17:32:21 -0700114 private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
115 private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400116
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700117 private static final ProviderProperties PROPERTIES = new ProviderProperties(
118 true, true, false, false, true, true, true,
119 Criteria.POWER_HIGH, Criteria.ACCURACY_FINE);
120
gomo4402af62017-01-11 13:20:13 -0800121 // these need to match GnssPositionMode enum in IGnss.hal
The Android Open Source Project10592532009-03-18 17:39:46 -0700122 private static final int GPS_POSITION_MODE_STANDALONE = 0;
123 private static final int GPS_POSITION_MODE_MS_BASED = 1;
124 private static final int GPS_POSITION_MODE_MS_ASSISTED = 2;
125
gomo4402af62017-01-11 13:20:13 -0800126 // these need to match GnssPositionRecurrence enum in IGnss.hal
Mike Lockwood04598b62010-04-14 17:17:24 -0400127 private static final int GPS_POSITION_RECURRENCE_PERIODIC = 0;
128 private static final int GPS_POSITION_RECURRENCE_SINGLE = 1;
129
gomo4402af62017-01-11 13:20:13 -0800130 // these need to match GnssStatusValue enum in IGnssCallback.hal
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800131 private static final int GPS_STATUS_NONE = 0;
132 private static final int GPS_STATUS_SESSION_BEGIN = 1;
133 private static final int GPS_STATUS_SESSION_END = 2;
134 private static final int GPS_STATUS_ENGINE_ON = 3;
135 private static final int GPS_STATUS_ENGINE_OFF = 4;
136
gomo4402af62017-01-11 13:20:13 -0800137 // these need to match AGnssStatusValue enum in IAGnssCallback.hal
Mike Lockwoode3635c92009-05-11 08:38:02 -0400138 /** AGPS status event values. */
139 private static final int GPS_REQUEST_AGPS_DATA_CONN = 1;
140 private static final int GPS_RELEASE_AGPS_DATA_CONN = 2;
141 private static final int GPS_AGPS_DATA_CONNECTED = 3;
142 private static final int GPS_AGPS_DATA_CONN_DONE = 4;
143 private static final int GPS_AGPS_DATA_CONN_FAILED = 5;
Mike Lockwood58bda982009-04-14 16:25:07 -0400144
gomo4402af62017-01-11 13:20:13 -0800145 // these need to match GnssLocationFlags enum in types.hal
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800146 private static final int LOCATION_INVALID = 0;
147 private static final int LOCATION_HAS_LAT_LONG = 1;
148 private static final int LOCATION_HAS_ALTITUDE = 2;
149 private static final int LOCATION_HAS_SPEED = 4;
150 private static final int LOCATION_HAS_BEARING = 8;
gomo4402af62017-01-11 13:20:13 -0800151 private static final int LOCATION_HAS_HORIZONTAL_ACCURACY = 16;
152 private static final int LOCATION_HAS_VERTICAL_ACCURACY = 32;
153 private static final int LOCATION_HAS_SPEED_ACCURACY = 64;
154 private static final int LOCATION_HAS_BEARING_ACCURACY = 128;
Mike Lockwoode3635c92009-05-11 08:38:02 -0400155
gomo4402af62017-01-11 13:20:13 -0800156
157 // IMPORTANT - the GPS_DELETE_* symbols here must match GnssAidingData enum in IGnss.hal
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800158 private static final int GPS_DELETE_EPHEMERIS = 0x0001;
159 private static final int GPS_DELETE_ALMANAC = 0x0002;
160 private static final int GPS_DELETE_POSITION = 0x0004;
161 private static final int GPS_DELETE_TIME = 0x0008;
162 private static final int GPS_DELETE_IONO = 0x0010;
163 private static final int GPS_DELETE_UTC = 0x0020;
164 private static final int GPS_DELETE_HEALTH = 0x0040;
165 private static final int GPS_DELETE_SVDIR = 0x0080;
166 private static final int GPS_DELETE_SVSTEER = 0x0100;
167 private static final int GPS_DELETE_SADATA = 0x0200;
168 private static final int GPS_DELETE_RTI = 0x0400;
169 private static final int GPS_DELETE_CELLDB_INFO = 0x8000;
170 private static final int GPS_DELETE_ALL = 0xFFFF;
171
gomo4402af62017-01-11 13:20:13 -0800172 // The GPS_CAPABILITY_* flags must match Capabilities enum in IGnssCallback.hal
Mike Lockwood04598b62010-04-14 17:17:24 -0400173 private static final int GPS_CAPABILITY_SCHEDULING = 0x0000001;
174 private static final int GPS_CAPABILITY_MSB = 0x0000002;
175 private static final int GPS_CAPABILITY_MSA = 0x0000004;
176 private static final int GPS_CAPABILITY_SINGLE_SHOT = 0x0000008;
Mike Lockwood9b9fb5c2011-06-29 15:09:40 -0400177 private static final int GPS_CAPABILITY_ON_DEMAND_TIME = 0x0000010;
destradaa6568d702014-10-27 12:47:41 -0700178 private static final int GPS_CAPABILITY_GEOFENCING = 0x0000020;
179 private static final int GPS_CAPABILITY_MEASUREMENTS = 0x0000040;
180 private static final int GPS_CAPABILITY_NAV_MESSAGES = 0x0000080;
Mike Lockwood04598b62010-04-14 17:17:24 -0400181
Tsuwei Chen462bcd82014-09-17 12:28:49 -0700182 // The AGPS SUPL mode
183 private static final int AGPS_SUPL_MODE_MSA = 0x02;
184 private static final int AGPS_SUPL_MODE_MSB = 0x01;
185
gomo4402af62017-01-11 13:20:13 -0800186 // these need to match AGnssType enum in IAGnssCallback.hal
Mike Lockwoode3635c92009-05-11 08:38:02 -0400187 private static final int AGPS_TYPE_SUPL = 1;
188 private static final int AGPS_TYPE_C2K = 2;
189
gomo4402af62017-01-11 13:20:13 -0800190 // these must match the ApnIpType enum in IAGnss.hal
destradaa96a14702014-06-05 11:36:30 -0700191 private static final int APN_INVALID = 0;
192 private static final int APN_IPV4 = 1;
193 private static final int APN_IPV6 = 2;
194 private static final int APN_IPV4V6 = 3;
195
Mike Lockwoode3635c92009-05-11 08:38:02 -0400196 // for mAGpsDataConnectionState
197 private static final int AGPS_DATA_CONNECTION_CLOSED = 0;
198 private static final int AGPS_DATA_CONNECTION_OPENING = 1;
199 private static final int AGPS_DATA_CONNECTION_OPEN = 2;
Mike Lockwood58bda982009-04-14 16:25:07 -0400200
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400201 // Handler messages
202 private static final int CHECK_LOCATION = 1;
203 private static final int ENABLE = 2;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700204 private static final int SET_REQUEST = 3;
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400205 private static final int UPDATE_NETWORK_STATE = 4;
206 private static final int INJECT_NTP_TIME = 5;
207 private static final int DOWNLOAD_XTRA_DATA = 6;
208 private static final int UPDATE_LOCATION = 7;
209 private static final int ADD_LISTENER = 8;
210 private static final int REMOVE_LISTENER = 9;
Kevin Tang40e1baf2012-01-10 14:32:44 -0800211 private static final int INJECT_NTP_TIME_FINISHED = 10;
212 private static final int DOWNLOAD_XTRA_DATA_FINISHED = 11;
destradaafb23c672015-04-16 14:01:27 -0700213 private static final int SUBSCRIPTION_OR_SIM_CHANGED = 12;
214 private static final int INITIALIZE_HANDLER = 13;
destradaae21252a2015-09-08 12:32:59 -0700215 private static final int REQUEST_SUPL_CONNECTION = 14;
216 private static final int RELEASE_SUPL_CONNECTION = 15;
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400217
Miguel Torroja1e84da82010-07-27 07:02:24 +0200218 // Request setid
219 private static final int AGPS_RIL_REQUEST_SETID_IMSI = 1;
220 private static final int AGPS_RIL_REQUEST_SETID_MSISDN = 2;
221
Hridya Valsaraju2ea29602016-09-13 08:38:09 -0700222 //TODO(b/33112647): Create gps_debug.conf with commented career parameters.
223 private static final String DEBUG_PROPERTIES_FILE = "/etc/gps_debug.conf";
Miguel Torroja1e84da82010-07-27 07:02:24 +0200224
225 // ref. location info
226 private static final int AGPS_REF_LOCATION_TYPE_GSM_CELLID = 1;
227 private static final int AGPS_REF_LOCATION_TYPE_UMTS_CELLID = 2;
Miguel Torroja1e84da82010-07-27 07:02:24 +0200228
229 // set id info
230 private static final int AGPS_SETID_TYPE_NONE = 0;
231 private static final int AGPS_SETID_TYPE_IMSI = 1;
232 private static final int AGPS_SETID_TYPE_MSISDN = 2;
233
destradaa0682809a2013-08-12 18:50:30 -0700234 private static final int GPS_GEOFENCE_UNAVAILABLE = 1<<0L;
235 private static final int GPS_GEOFENCE_AVAILABLE = 1<<1L;
236
gomo4402af62017-01-11 13:20:13 -0800237 // GPS Geofence errors. Should match GeofenceStatus enum in IGnssGeofenceCallback.hal.
destradaa0682809a2013-08-12 18:50:30 -0700238 private static final int GPS_GEOFENCE_OPERATION_SUCCESS = 0;
239 private static final int GPS_GEOFENCE_ERROR_TOO_MANY_GEOFENCES = 100;
240 private static final int GPS_GEOFENCE_ERROR_ID_EXISTS = -101;
241 private static final int GPS_GEOFENCE_ERROR_ID_UNKNOWN = -102;
242 private static final int GPS_GEOFENCE_ERROR_INVALID_TRANSITION = -103;
243 private static final int GPS_GEOFENCE_ERROR_GENERIC = -149;
244
Tsuwei Chen678c13c2014-09-22 17:48:41 -0700245 // TCP/IP constants.
246 // Valid TCP/UDP port range is (0, 65535].
247 private static final int TCP_MIN_PORT = 0;
248 private static final int TCP_MAX_PORT = 0xffff;
249
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700250 /** simpler wrapper for ProviderRequest + Worksource */
251 private static class GpsRequest {
252 public ProviderRequest request;
253 public WorkSource source;
254 public GpsRequest(ProviderRequest request, WorkSource source) {
255 this.request = request;
256 this.source = source;
257 }
258 }
259
260 private Object mLock = new Object();
261
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800262 // current status
Mike Lockwood15e3d0f2009-05-01 07:53:28 -0400263 private int mStatus = LocationProvider.TEMPORARILY_UNAVAILABLE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800264
265 // time for last status update
266 private long mStatusUpdateTime = SystemClock.elapsedRealtime();
Mike Lockwoodd53ba012010-04-15 20:41:26 -0400267
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800268 // turn off GPS fix icon if we haven't received a fix in 10 seconds
Mike Lockwood04598b62010-04-14 17:17:24 -0400269 private static final long RECENT_FIX_TIMEOUT = 10 * 1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800270
Mike Lockwood0632ca72009-05-14 15:51:03 -0400271 // stop trying if we do not receive a fix within 60 seconds
Mike Lockwood04598b62010-04-14 17:17:24 -0400272 private static final int NO_FIX_TIMEOUT = 60 * 1000;
Mike Lockwood0632ca72009-05-14 15:51:03 -0400273
Nick Pellyb041f232012-05-07 17:12:25 -0700274 // if the fix interval is below this we leave GPS on,
275 // if above then we cycle the GPS driver.
276 // Typical hot TTTF is ~5 seconds, so 10 seconds seems sane.
277 private static final int GPS_POLLING_THRESHOLD_INTERVAL = 10 * 1000;
278
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700279 // how often to request NTP time, in milliseconds
280 // current setting 24 hours
281 private static final long NTP_INTERVAL = 24*60*60*1000;
282 // how long to wait if we have a network error in NTP or XTRA downloading
Wei Liu6f6326b2015-06-24 23:47:50 -0700283 // the initial value of the exponential backoff
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700284 // current setting - 5 minutes
285 private static final long RETRY_INTERVAL = 5*60*1000;
Wei Liu6f6326b2015-06-24 23:47:50 -0700286 // how long to wait if we have a network error in NTP or XTRA downloading
287 // the max value of the exponential backoff
288 // current setting - 4 hours
289 private static final long MAX_RETRY_INTERVAL = 4*60*60*1000;
290
Wei Wangc5706f62017-04-18 11:26:26 -0700291 // Timeout when holding wakelocks for downloading XTRA data.
292 private static final long DOWNLOAD_XTRA_DATA_TIMEOUT_MS = 60 * 1000;
293
Wei Liu6f6326b2015-06-24 23:47:50 -0700294 private BackOff mNtpBackOff = new BackOff(RETRY_INTERVAL, MAX_RETRY_INTERVAL);
295 private BackOff mXtraBackOff = new BackOff(RETRY_INTERVAL, MAX_RETRY_INTERVAL);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700296
297 // true if we are enabled, protected by this
298 private boolean mEnabled;
299
Kevin Tang40e1baf2012-01-10 14:32:44 -0800300 // states for injecting ntp and downloading xtra data
301 private static final int STATE_PENDING_NETWORK = 0;
302 private static final int STATE_DOWNLOADING = 1;
303 private static final int STATE_IDLE = 2;
304
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400305 // flags to trigger NTP or XTRA data download when network becomes available
306 // initialized to true so we do NTP and XTRA when the network comes up after booting
Kevin Tang40e1baf2012-01-10 14:32:44 -0800307 private int mInjectNtpTimePending = STATE_PENDING_NETWORK;
308 private int mDownloadXtraDataPending = STATE_PENDING_NETWORK;
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400309
destradaa56b47f82015-07-24 10:56:18 -0700310 // set to true if the GPS engine requested on-demand NTP time requests
311 private boolean mOnDemandTimeInjection;
Mike Lockwood9b9fb5c2011-06-29 15:09:40 -0400312
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800313 // true if GPS is navigating
314 private boolean mNavigating;
Mike Lockwoodcf1d8cb2010-01-20 10:14:54 -0500315
316 // true if GPS engine is on
317 private boolean mEngineOn;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700318
Mike Lockwood04598b62010-04-14 17:17:24 -0400319 // requested frequency of fixes, in milliseconds
320 private int mFixInterval = 1000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800321
322 // true if we started navigation
323 private boolean mStarted;
324
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -0700325 // true if single shot request is in progress
326 private boolean mSingleShot;
327
Mike Lockwood04598b62010-04-14 17:17:24 -0400328 // capabilities of the GPS engine
329 private int mEngineCapabilities;
330
Mike Lockwood1a1cd3a2010-08-17 07:42:54 -0400331 // true if XTRA is supported
332 private boolean mSupportsXtra;
333
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800334 // for calculating time to first fix
335 private long mFixRequestTime = 0;
336 // time to first fix for most recent session
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700337 private int mTimeToFirstFix = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800338 // time we received our last fix
339 private long mLastFixTime;
340
Mike Lockwood04598b62010-04-14 17:17:24 -0400341 private int mPositionMode;
342
David Christied4edf4c2014-08-12 15:22:27 -0700343 // Current request from underlying location clients.
344 private ProviderRequest mProviderRequest = null;
345 // Current list of underlying location clients.
346 private WorkSource mWorkSource = null;
347 // True if gps should be disabled (used to support battery saver mode in settings).
348 private boolean mDisableGps = false;
349
destradaafb23c672015-04-16 14:01:27 -0700350 /**
351 * Properties loaded from PROPERTIES_FILE.
352 * It must be accessed only inside {@link #mHandler}.
353 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800354 private Properties mProperties;
destradaafb23c672015-04-16 14:01:27 -0700355
Mike Lockwood734d6032009-07-28 18:30:25 -0700356 private String mSuplServerHost;
Tsuwei Chen678c13c2014-09-22 17:48:41 -0700357 private int mSuplServerPort = TCP_MIN_PORT;
Mike Lockwood734d6032009-07-28 18:30:25 -0700358 private String mC2KServerHost;
359 private int mC2KServerPort;
Tsuwei Chen3324e952014-09-07 01:30:42 -0700360 private boolean mSuplEsEnabled = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800361
Mike Lockwood15e3d0f2009-05-01 07:53:28 -0400362 private final Context mContext;
Jeff Sharkey104344e2011-07-10 14:20:41 -0700363 private final NtpTrustedTime mNtpTime;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700364 private final ILocationManager mILocationManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800365 private Location mLocation = new Location(LocationManager.GPS_PROVIDER);
366 private Bundle mLocationExtras = new Bundle();
Lifu Tang30f95a72016-01-07 23:20:38 -0800367 private final GnssStatusListenerHelper mListenerHelper;
Lifu Tang818aa2c2016-02-01 01:52:00 -0800368 private final GnssMeasurementsProvider mGnssMeasurementsProvider;
369 private final GnssNavigationMessageProvider mGnssNavigationMessageProvider;
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400370
Victoria Lease5c24fd02012-10-01 11:00:50 -0700371 // Handler for processing events
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400372 private Handler mHandler;
The Android Open Source Project10592532009-03-18 17:39:46 -0700373
destradaae21252a2015-09-08 12:32:59 -0700374 /** It must be accessed only inside {@link #mHandler}. */
Mike Lockwoode3635c92009-05-11 08:38:02 -0400375 private int mAGpsDataConnectionState;
destradaae21252a2015-09-08 12:32:59 -0700376 /** It must be accessed only inside {@link #mHandler}. */
destradaa96a14702014-06-05 11:36:30 -0700377 private InetAddress mAGpsDataConnectionIpAddr;
destradaae21252a2015-09-08 12:32:59 -0700378
Mike Lockwood2f82c4e2009-04-17 08:24:10 -0400379 private final ConnectivityManager mConnMgr;
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700380 private final GpsNetInitiatedHandler mNIHandler;
Mike Lockwood2f82c4e2009-04-17 08:24:10 -0400381
Mike Lockwood0528b9b2009-05-07 10:12:54 -0400382 // Wakelocks
Lifu Tang30f95a72016-01-07 23:20:38 -0800383 private final static String WAKELOCK_KEY = "GnssLocationProvider";
Mike Lockwood0528b9b2009-05-07 10:12:54 -0400384 private final PowerManager.WakeLock mWakeLock;
Wei Wangb71c0492017-05-01 20:24:19 -0700385 private static final String DOWNLOAD_EXTRA_WAKELOCK_KEY = "GnssLocationProviderXtraDownload";
386 private final PowerManager.WakeLock mDownloadXtraWakeLock;
Mike Lockwood0528b9b2009-05-07 10:12:54 -0400387
Mike Lockwood29c84342009-05-06 14:01:15 -0400388 // Alarms
389 private final static String ALARM_WAKEUP = "com.android.internal.location.ALARM_WAKEUP";
Mike Lockwood0632ca72009-05-14 15:51:03 -0400390 private final static String ALARM_TIMEOUT = "com.android.internal.location.ALARM_TIMEOUT";
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700391
392 // SIM/Carrier info.
393 private final static String SIM_STATE_CHANGED = "android.intent.action.SIM_STATE_CHANGED";
394
Ecco Park624ac3c2016-07-18 14:08:05 -0700395 // Persist property for LPP_PROFILE
396 private final static String LPP_PROFILE = "persist.sys.gps.lpp";
397
Ecco Park624ac3c2016-07-18 14:08:05 -0700398
399
David Christied4edf4c2014-08-12 15:22:27 -0700400 private final PowerManager mPowerManager;
Mike Lockwood29c84342009-05-06 14:01:15 -0400401 private final AlarmManager mAlarmManager;
402 private final PendingIntent mWakeupIntent;
Mike Lockwood0632ca72009-05-14 15:51:03 -0400403 private final PendingIntent mTimeoutIntent;
Mike Lockwood29c84342009-05-06 14:01:15 -0400404
Dianne Hackborna06de0f2012-12-11 16:34:47 -0800405 private final IAppOpsService mAppOpsService;
Mike Lockwood2f82c4e2009-04-17 08:24:10 -0400406 private final IBatteryStats mBatteryStats;
The Android Open Source Project10592532009-03-18 17:39:46 -0700407
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700408 // only modified on handler thread
Dianne Hackborn002a54e2013-01-10 17:34:55 -0800409 private WorkSource mClientSource = new WorkSource();
Mike Lockwoodf1218be2010-01-29 09:20:06 -0500410
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -0700411 private GeofenceHardwareImpl mGeofenceHardwareImpl;
Lifu Tang82f893d2016-01-21 18:15:33 -0800412 private int mYearOfHardware = 0;
413
Wyatt Riley5d5bac82016-11-01 07:05:16 -0700414 // Set lower than the current ITAR limit of 600m/s to allow this to trigger even if GPS HAL
415 // stops output right at 600m/s, depriving this of the information of a device that reaches
416 // greater than 600m/s, and higher than the speed of sound to avoid impacting most use cases.
417 private static final float ITAR_SPEED_LIMIT_METERS_PER_SECOND = 400.0F;
418 private boolean mItarSpeedLimitExceeded = false;
419
Lifu Tang30f95a72016-01-07 23:20:38 -0800420 private final IGnssStatusProvider mGnssStatusProvider = new IGnssStatusProvider.Stub() {
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700421 @Override
Lifu Tang30f95a72016-01-07 23:20:38 -0800422 public void registerGnssStatusCallback(IGnssStatusListener callback) {
423 mListenerHelper.addListener(callback);
Mike Lockwood15e3d0f2009-05-01 07:53:28 -0400424 }
425
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700426 @Override
Lifu Tang30f95a72016-01-07 23:20:38 -0800427 public void unregisterGnssStatusCallback(IGnssStatusListener callback) {
428 mListenerHelper.removeListener(callback);
destradaaea8a8a62014-06-23 18:19:03 -0700429 }
430 };
Mike Lockwood15e3d0f2009-05-01 07:53:28 -0400431
Lifu Tang30f95a72016-01-07 23:20:38 -0800432 public IGnssStatusProvider getGnssStatusProvider() {
433 return mGnssStatusProvider;
Mike Lockwood15e3d0f2009-05-01 07:53:28 -0400434 }
435
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -0700436 public IGpsGeofenceHardware getGpsGeofenceProxy() {
437 return mGpsGeofenceBinder;
438 }
439
Lifu Tang818aa2c2016-02-01 01:52:00 -0800440 public GnssMeasurementsProvider getGnssMeasurementsProvider() {
441 return mGnssMeasurementsProvider;
destradaaea8a8a62014-06-23 18:19:03 -0700442 }
443
Lifu Tang818aa2c2016-02-01 01:52:00 -0800444 public GnssNavigationMessageProvider getGnssNavigationMessageProvider() {
445 return mGnssNavigationMessageProvider;
destradaa4b3e3932014-07-21 18:01:47 -0700446 }
447
destradaae21252a2015-09-08 12:32:59 -0700448 /**
449 * Callback used to listen for data connectivity changes.
450 */
451 private final ConnectivityManager.NetworkCallback mNetworkConnectivityCallback =
452 new ConnectivityManager.NetworkCallback() {
453 @Override
454 public void onAvailable(Network network) {
Wyatt Riley0d6e54e22016-10-05 12:03:03 -0700455 if (mInjectNtpTimePending == STATE_PENDING_NETWORK) {
456 requestUtcTime();
457 }
458 if (mDownloadXtraDataPending == STATE_PENDING_NETWORK) {
459 xtraDownloadRequest();
460 }
Wyatt Riley41f6bce2016-12-13 10:45:29 -0800461 // Always on, notify HAL so it can get data it needs
Wyatt Rileybb9c9902016-12-07 07:16:25 -0800462 sendMessage(UPDATE_NETWORK_STATE, 0 /*arg*/, network);
destradaae21252a2015-09-08 12:32:59 -0700463 }
464 };
465
466 /**
467 * Callback used to listen for availability of a requested SUPL connection.
468 * It is kept as a separate instance from {@link #mNetworkConnectivityCallback} to be able to
469 * manage the registration/un-registration lifetimes separate.
470 */
471 private final ConnectivityManager.NetworkCallback mSuplConnectivityCallback =
472 new ConnectivityManager.NetworkCallback() {
473 @Override
Wyatt Riley41f6bce2016-12-13 10:45:29 -0800474 public void onAvailable(Network network) {
475 // Specific to a change to a SUPL enabled network becoming ready
476 sendMessage(UPDATE_NETWORK_STATE, 0 /*arg*/, network);
477 }
478
479 @Override
destradaae21252a2015-09-08 12:32:59 -0700480 public void onLost(Network network) {
481 releaseSuplConnection(GPS_RELEASE_AGPS_DATA_CONN);
482 }
destradaae21252a2015-09-08 12:32:59 -0700483 };
484
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700485 private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
The Android Open Source Project10592532009-03-18 17:39:46 -0700486 @Override public void onReceive(Context context, Intent intent) {
487 String action = intent.getAction();
Tsuwei Chen48d37f92014-09-05 15:15:34 -0700488 if (DEBUG) Log.d(TAG, "receive broadcast intent, action: " + action);
destradaaee9fd342015-08-31 13:31:17 -0700489 if (action == null) {
490 return;
491 }
492
Mike Lockwood29c84342009-05-06 14:01:15 -0400493 if (action.equals(ALARM_WAKEUP)) {
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -0700494 startNavigating(false);
Mike Lockwood0632ca72009-05-14 15:51:03 -0400495 } else if (action.equals(ALARM_TIMEOUT)) {
Mike Lockwood0632ca72009-05-14 15:51:03 -0400496 hibernate();
David Christied4edf4c2014-08-12 15:22:27 -0700497 } else if (PowerManager.ACTION_POWER_SAVE_MODE_CHANGED.equals(action)
Adam Lesinski87c17df2015-05-27 13:24:13 -0700498 || PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED.equals(action)
David Christied4edf4c2014-08-12 15:22:27 -0700499 || Intent.ACTION_SCREEN_OFF.equals(action)
500 || Intent.ACTION_SCREEN_ON.equals(action)) {
501 updateLowPowerMode();
Wink Savillea374c3d2014-11-11 11:48:04 -0800502 } else if (action.equals(SIM_STATE_CHANGED)) {
503 subscriptionOrSimChanged(context);
David Christied4edf4c2014-08-12 15:22:27 -0700504 }
The Android Open Source Project10592532009-03-18 17:39:46 -0700505 }
Mike Lockwood29c84342009-05-06 14:01:15 -0400506 };
The Android Open Source Project10592532009-03-18 17:39:46 -0700507
Wink Savilled09c4ca2014-11-22 10:08:16 -0800508 private final OnSubscriptionsChangedListener mOnSubscriptionsChangedListener =
509 new OnSubscriptionsChangedListener() {
Wink Savillea374c3d2014-11-11 11:48:04 -0800510 @Override
Wink Savilled09c4ca2014-11-22 10:08:16 -0800511 public void onSubscriptionsChanged() {
destradaafb23c672015-04-16 14:01:27 -0700512 sendMessage(SUBSCRIPTION_OR_SIM_CHANGED, 0, null);
Wink Savillea374c3d2014-11-11 11:48:04 -0800513 }
514 };
515
516 private void subscriptionOrSimChanged(Context context) {
Joe Onorato0c484102016-02-01 18:04:24 -0800517 if (DEBUG) Log.d(TAG, "received SIM related action: ");
Wink Savillea374c3d2014-11-11 11:48:04 -0800518 TelephonyManager phone = (TelephonyManager)
519 mContext.getSystemService(Context.TELEPHONY_SERVICE);
Ecco Park4fa1ab72016-10-24 13:04:52 -0700520 CarrierConfigManager configManager = (CarrierConfigManager)
521 mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE);
Wink Savillea374c3d2014-11-11 11:48:04 -0800522 String mccMnc = phone.getSimOperator();
Ecco Park4fa1ab72016-10-24 13:04:52 -0700523 boolean isKeepLppProfile = false;
Wink Savillea374c3d2014-11-11 11:48:04 -0800524 if (!TextUtils.isEmpty(mccMnc)) {
Joe Onorato0c484102016-02-01 18:04:24 -0800525 if (DEBUG) Log.d(TAG, "SIM MCC/MNC is available: " + mccMnc);
Wink Savillea374c3d2014-11-11 11:48:04 -0800526 synchronized (mLock) {
Ecco Park4fa1ab72016-10-24 13:04:52 -0700527 if (configManager != null) {
528 PersistableBundle b = configManager.getConfig();
529 isKeepLppProfile = b.getBoolean(CarrierConfigManager.KEY_PERSIST_LPP_MODE_BOOL);
530 }
531 if (isKeepLppProfile) {
532 // load current properties for the carrier
533 loadPropertiesFromResource(context, mProperties);
534 String lpp_profile = mProperties.getProperty("LPP_PROFILE");
535 // set the persist property LPP_PROFILE for the value
536 SystemProperties.set(LPP_PROFILE, lpp_profile);
Ecco Park624ac3c2016-07-18 14:08:05 -0700537 } else {
Ecco Park4fa1ab72016-10-24 13:04:52 -0700538 // reset the persist property
539 SystemProperties.set(LPP_PROFILE, "");
Ecco Park624ac3c2016-07-18 14:08:05 -0700540 }
Wink Savillea374c3d2014-11-11 11:48:04 -0800541 reloadGpsProperties(context, mProperties);
542 mNIHandler.setSuplEsEnabled(mSuplEsEnabled);
543 }
544 } else {
Joe Onorato0c484102016-02-01 18:04:24 -0800545 if (DEBUG) Log.d(TAG, "SIM MCC/MNC is still not available");
Wink Savillea374c3d2014-11-11 11:48:04 -0800546 }
547 }
548
David Christied4edf4c2014-08-12 15:22:27 -0700549 private void updateLowPowerMode() {
Adam Lesinski87c17df2015-05-27 13:24:13 -0700550 // Disable GPS if we are in device idle mode.
551 boolean disableGps = mPowerManager.isDeviceIdleMode();
jackqdyulei455e90a2017-02-09 15:29:16 -0800552 final PowerSaveState result =
553 mPowerManager.getPowerSaveState(ServiceType.GPS);
554 switch (result.gpsMode) {
555 case BatterySaverPolicy.GPS_MODE_DISABLED_WHEN_SCREEN_OFF:
Adam Lesinski87c17df2015-05-27 13:24:13 -0700556 // If we are in battery saver mode and the screen is off, disable GPS.
jackqdyulei455e90a2017-02-09 15:29:16 -0800557 disableGps |= result.batterySaverEnabled && !mPowerManager.isInteractive();
David Christied4edf4c2014-08-12 15:22:27 -0700558 break;
David Christied4edf4c2014-08-12 15:22:27 -0700559 }
560 if (disableGps != mDisableGps) {
561 mDisableGps = disableGps;
562 updateRequirements();
563 }
564 }
565
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800566 public static boolean isSupported() {
567 return native_is_supported();
568 }
569
Hridya Valsaraju2ea29602016-09-13 08:38:09 -0700570 interface SetCarrierProperty {
571 public boolean set(int value);
572 }
573
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700574 private void reloadGpsProperties(Context context, Properties properties) {
Joe Onorato0c484102016-02-01 18:04:24 -0800575 if (DEBUG) Log.d(TAG, "Reset GPS properties, previous size = " + properties.size());
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700576 loadPropertiesFromResource(context, properties);
Ecco Park624ac3c2016-07-18 14:08:05 -0700577
Ecco Park624ac3c2016-07-18 14:08:05 -0700578 String lpp_prof = SystemProperties.get(LPP_PROFILE);
579 if (!TextUtils.isEmpty(lpp_prof)) {
580 // override default value of this if lpp_prof is not empty
581 properties.setProperty("LPP_PROFILE", lpp_prof);
582 }
Wyatt Riley3e1cd0b2017-04-19 17:57:14 -0700583 /*
584 * Overlay carrier properties from a debug configuration file.
585 */
586 loadPropertiesFromFile(DEBUG_PROPERTIES_FILE, properties);
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700587 // TODO: we should get rid of C2K specific setting.
588 setSuplHostPort(properties.getProperty("SUPL_HOST"),
589 properties.getProperty("SUPL_PORT"));
590 mC2KServerHost = properties.getProperty("C2K_HOST");
591 String portString = properties.getProperty("C2K_PORT");
592 if (mC2KServerHost != null && portString != null) {
593 try {
594 mC2KServerPort = Integer.parseInt(portString);
595 } catch (NumberFormatException e) {
596 Log.e(TAG, "unable to parse C2K_PORT: " + portString);
597 }
598 }
destradaaef752b62015-04-17 13:10:47 -0700599 if (native_is_gnss_configuration_supported()) {
Hridya Valsaraju2ea29602016-09-13 08:38:09 -0700600 Map<String, SetCarrierProperty> map = new HashMap<String, SetCarrierProperty>() {
601 {
602 put("SUPL_VER", (val) -> native_set_supl_version(val));
603 put("SUPL_MODE", (val) -> native_set_supl_mode(val));
604 put("SUPL_ES", (val) -> native_set_supl_es(val));
605 put("LPP_PROFILE", (val) -> native_set_lpp_profile(val));
606 put("A_GLONASS_POS_PROTOCOL_SELECT", (val) -> native_set_gnss_pos_protocol_select(val));
607 put("USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL", (val) -> native_set_emergency_supl_pdn(val));
608 put("GPS_LOCK", (val) -> native_set_gps_lock(val));
609 }
610 };
611
612 for(Entry<String, SetCarrierProperty> entry : map.entrySet()) {
613 String propertyName = entry.getKey();
614 String propertyValueString = properties.getProperty(propertyName);
615 if (propertyValueString != null) {
616 try {
617 int propertyValueInt = Integer.decode(propertyValueString);
618 boolean result = entry.getValue().set(propertyValueInt);
619 if (result == false) {
620 Log.e(TAG, "Unable to set " + propertyName);
621 }
622 } catch (NumberFormatException e) {
623 Log.e(TAG, "unable to parse propertyName: " + propertyValueString);
624 }
625 }
destradaaef752b62015-04-17 13:10:47 -0700626 }
627 } else if (DEBUG) {
628 Log.d(TAG, "Skipped configuration update because GNSS configuration in GPS HAL is not"
629 + " supported");
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700630 }
Tsuwei Chen3324e952014-09-07 01:30:42 -0700631
632 // SUPL_ES configuration.
633 String suplESProperty = mProperties.getProperty("SUPL_ES");
634 if (suplESProperty != null) {
635 try {
636 mSuplEsEnabled = (Integer.parseInt(suplESProperty) == 1);
637 } catch (NumberFormatException e) {
638 Log.e(TAG, "unable to parse SUPL_ES: " + suplESProperty);
639 }
640 }
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700641 }
642
643 private void loadPropertiesFromResource(Context context,
644 Properties properties) {
645 String[] configValues = context.getResources().getStringArray(
646 com.android.internal.R.array.config_gpsParameters);
647 for (String item : configValues) {
Joe Onorato0c484102016-02-01 18:04:24 -0800648 if (DEBUG) Log.d(TAG, "GpsParamsResource: " + item);
Tsuwei Chen7c485bf2014-09-10 15:33:34 -0700649 // We need to support "KEY =", but not "=VALUE".
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700650 String[] split = item.split("=");
651 if (split.length == 2) {
652 properties.setProperty(split[0].trim().toUpperCase(), split[1]);
653 } else {
654 Log.w(TAG, "malformed contents: " + item);
655 }
656 }
657 }
658
659 private boolean loadPropertiesFromFile(String filename,
660 Properties properties) {
Colin Cross7c030ed2014-01-28 09:33:53 -0800661 try {
662 File file = new File(filename);
663 FileInputStream stream = null;
664 try {
665 stream = new FileInputStream(file);
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700666 properties.load(stream);
Colin Cross7c030ed2014-01-28 09:33:53 -0800667 } finally {
668 IoUtils.closeQuietly(stream);
669 }
670
Colin Cross7c030ed2014-01-28 09:33:53 -0800671 } catch (IOException e) {
Wyatt Riley3e1cd0b2017-04-19 17:57:14 -0700672 if (DEBUG) Log.d(TAG, "Could not open GPS configuration file " + filename);
Colin Cross7c030ed2014-01-28 09:33:53 -0800673 return false;
674 }
675 return true;
676 }
677
Lifu Tang30f95a72016-01-07 23:20:38 -0800678 public GnssLocationProvider(Context context, ILocationManager ilocationManager,
Victoria Lease5cd731a2012-12-19 15:04:21 -0800679 Looper looper) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800680 mContext = context;
Jeff Sharkey104344e2011-07-10 14:20:41 -0700681 mNtpTime = NtpTrustedTime.getInstance(context);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700682 mILocationManager = ilocationManager;
Mike Lockwood63598a02010-02-24 11:52:59 -0500683
684 mLocation.setExtras(mLocationExtras);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800685
Mike Lockwood0528b9b2009-05-07 10:12:54 -0400686 // Create a wake lock
David Christied4edf4c2014-08-12 15:22:27 -0700687 mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
688 mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700689 mWakeLock.setReferenceCounted(true);
Mike Lockwood0528b9b2009-05-07 10:12:54 -0400690
Wei Wangb71c0492017-05-01 20:24:19 -0700691 // Create a separate wake lock for xtra downloader as it may be released due to timeout.
692 mDownloadXtraWakeLock = mPowerManager.newWakeLock(
693 PowerManager.PARTIAL_WAKE_LOCK, DOWNLOAD_EXTRA_WAKELOCK_KEY);
694 mDownloadXtraWakeLock.setReferenceCounted(true);
695
Mike Lockwood29c84342009-05-06 14:01:15 -0400696 mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
697 mWakeupIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_WAKEUP), 0);
Mike Lockwood0632ca72009-05-14 15:51:03 -0400698 mTimeoutIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_TIMEOUT), 0);
Mike Lockwood29c84342009-05-06 14:01:15 -0400699
Mike Lockwood58bda982009-04-14 16:25:07 -0400700 mConnMgr = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
701
Dianne Hackborna06de0f2012-12-11 16:34:47 -0800702 // App ops service to keep track of who is accessing the GPS
703 mAppOpsService = IAppOpsService.Stub.asInterface(ServiceManager.getService(
704 Context.APP_OPS_SERVICE));
705
Mike Lockwood2f82c4e2009-04-17 08:24:10 -0400706 // Battery statistics service to be notified when GPS turns on or off
Dianne Hackborn91268cf2013-06-13 19:06:50 -0700707 mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService(
708 BatteryStats.SERVICE_NAME));
Mike Lockwood2f82c4e2009-04-17 08:24:10 -0400709
destradaafb23c672015-04-16 14:01:27 -0700710 // Construct internal handler
711 mHandler = new ProviderHandler(looper);
712
713 // Load GPS configuration and register listeners in the background:
714 // some operations, such as opening files and registering broadcast receivers, can take a
715 // relative long time, so the ctor() is kept to create objects needed by this instance,
716 // while IO initialization and registration is delegated to our internal handler
717 // this approach is just fine because events are posted to our handler anyway
Tsuwei Chen52617bb2014-08-25 11:49:11 -0700718 mProperties = new Properties();
destradaafb23c672015-04-16 14:01:27 -0700719 sendMessage(INITIALIZE_HANDLER, 0, null);
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400720
Tsuwei Chen3324e952014-09-07 01:30:42 -0700721 // Create a GPS net-initiated handler.
722 mNIHandler = new GpsNetInitiatedHandler(context,
723 mNetInitiatedListener,
724 mSuplEsEnabled);
725
Lifu Tang30f95a72016-01-07 23:20:38 -0800726 mListenerHelper = new GnssStatusListenerHelper(mHandler) {
destradaa6568d702014-10-27 12:47:41 -0700727 @Override
728 protected boolean isAvailableInPlatform() {
destradaa13a60b02015-01-15 18:36:01 -0800729 return isSupported();
destradaa6568d702014-10-27 12:47:41 -0700730 }
731
732 @Override
733 protected boolean isGpsEnabled() {
734 return isEnabled();
735 }
736 };
737
Lifu Tang818aa2c2016-02-01 01:52:00 -0800738 mGnssMeasurementsProvider = new GnssMeasurementsProvider(mHandler) {
destradaa6568d702014-10-27 12:47:41 -0700739 @Override
740 public boolean isAvailableInPlatform() {
741 return native_is_measurement_supported();
742 }
743
744 @Override
745 protected boolean registerWithService() {
746 return native_start_measurement_collection();
747 }
748
749 @Override
750 protected void unregisterFromService() {
751 native_stop_measurement_collection();
752 }
753
754 @Override
755 protected boolean isGpsEnabled() {
756 return isEnabled();
757 }
758 };
759
Lifu Tang818aa2c2016-02-01 01:52:00 -0800760 mGnssNavigationMessageProvider = new GnssNavigationMessageProvider(mHandler) {
destradaa6568d702014-10-27 12:47:41 -0700761 @Override
762 protected boolean isAvailableInPlatform() {
763 return native_is_navigation_message_supported();
764 }
765
766 @Override
767 protected boolean registerWithService() {
768 return native_start_navigation_message_collection();
769 }
770
771 @Override
772 protected void unregisterFromService() {
773 native_stop_navigation_message_collection();
774 }
775
776 @Override
777 protected boolean isGpsEnabled() {
778 return isEnabled();
779 }
780 };
Siddharth Ray9be64f12017-06-21 15:14:44 -0700781
782 /*
783 * A cycle of native_init() and native_cleanup() is needed so that callbacks are registered
784 * after bootup even when location is disabled. This will allow Emergency SUPL to work even
785 * when location is disabled before device restart.
786 * */
787 boolean isInitialized = native_init();
788 if(!isInitialized) {
789 Log.d(TAG, "Failed to initialize at bootup");
790 } else {
791 native_cleanup();
792 }
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400793 }
794
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800795 /**
Mike Lockwoodd03ff942010-02-09 08:46:14 -0500796 * Returns the name of this provider.
797 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700798 @Override
Mike Lockwoodd03ff942010-02-09 08:46:14 -0500799 public String getName() {
800 return LocationManager.GPS_PROVIDER;
801 }
802
Nick Pelly6fa9ad42012-07-16 12:18:23 -0700803 @Override
804 public ProviderProperties getProperties() {
805 return PROPERTIES;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800806 }
807
destradaae21252a2015-09-08 12:32:59 -0700808 private void handleUpdateNetworkState(Network network) {
809 // retrieve NetworkInfo for this UID
810 NetworkInfo info = mConnMgr.getNetworkInfo(network);
811 if (info == null) {
812 return;
813 }
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400814
destradaae21252a2015-09-08 12:32:59 -0700815 boolean isConnected = info.isConnected();
Joe Onoratof5d95cb2010-01-07 21:48:32 -0500816 if (DEBUG) {
destradaae21252a2015-09-08 12:32:59 -0700817 String message = String.format(
818 "UpdateNetworkState, state=%s, connected=%s, info=%s, capabilities=%S",
819 agpsDataConnStateAsString(),
820 isConnected,
821 info,
822 mConnMgr.getNetworkCapabilities(network));
823 Log.d(TAG, message);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800824 }
Mike Lockwood03d24672009-10-08 15:45:03 -0400825
destradaae21252a2015-09-08 12:32:59 -0700826 if (native_is_agps_ril_supported()) {
827 boolean dataEnabled = TelephonyManager.getDefault().getDataEnabled();
828 boolean networkAvailable = info.isAvailable() && dataEnabled;
829 String defaultApn = getSelectedApn();
830 if (defaultApn == null) {
831 defaultApn = "dummy-apn";
destradaaef752b62015-04-17 13:10:47 -0700832 }
destradaae21252a2015-09-08 12:32:59 -0700833
834 native_update_network_state(
835 isConnected,
836 info.getType(),
837 info.isRoaming(),
838 networkAvailable,
839 info.getExtraInfo(),
840 defaultApn);
841 } else if (DEBUG) {
842 Log.d(TAG, "Skipped network state update because GPS HAL AGPS-RIL is not supported");
Mike Lockwood50130bb2010-10-11 06:22:50 -0400843 }
844
destradaae21252a2015-09-08 12:32:59 -0700845 if (mAGpsDataConnectionState == AGPS_DATA_CONNECTION_OPENING) {
846 if (isConnected) {
destradaa96a14702014-06-05 11:36:30 -0700847 String apnName = info.getExtraInfo();
Stephen Li83b69712011-01-25 18:47:28 -0800848 if (apnName == null) {
destradaae21252a2015-09-08 12:32:59 -0700849 // assign a dummy value in the case of C2K as otherwise we will have a runtime
850 // exception in the following call to native_agps_data_conn_open
Stephen Li83b69712011-01-25 18:47:28 -0800851 apnName = "dummy-apn";
852 }
destradaae21252a2015-09-08 12:32:59 -0700853 int apnIpType = getApnIpType(apnName);
destradaa96a14702014-06-05 11:36:30 -0700854 setRouting();
855 if (DEBUG) {
856 String message = String.format(
857 "native_agps_data_conn_open: mAgpsApn=%s, mApnIpType=%s",
destradaae21252a2015-09-08 12:32:59 -0700858 apnName,
859 apnIpType);
destradaa96a14702014-06-05 11:36:30 -0700860 Log.d(TAG, message);
Stephen Li8efd74d2011-03-01 20:56:00 -0800861 }
destradaae21252a2015-09-08 12:32:59 -0700862 native_agps_data_conn_open(apnName, apnIpType);
Mike Lockwood03d24672009-10-08 15:45:03 -0400863 mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPEN;
864 } else {
destradaae21252a2015-09-08 12:32:59 -0700865 handleReleaseSuplConnection(GPS_AGPS_DATA_CONN_FAILED);
Mike Lockwood03d24672009-10-08 15:45:03 -0400866 }
867 }
destradaae21252a2015-09-08 12:32:59 -0700868 }
Mike Lockwood03d24672009-10-08 15:45:03 -0400869
destradaae21252a2015-09-08 12:32:59 -0700870 private void handleRequestSuplConnection(InetAddress address) {
871 if (DEBUG) {
872 String message = String.format(
873 "requestSuplConnection, state=%s, address=%s",
874 agpsDataConnStateAsString(),
875 address);
876 Log.d(TAG, message);
877 }
878
879 if (mAGpsDataConnectionState != AGPS_DATA_CONNECTION_CLOSED) {
880 return;
881 }
882 mAGpsDataConnectionIpAddr = address;
883 mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPENING;
884
885 NetworkRequest.Builder requestBuilder = new NetworkRequest.Builder();
886 requestBuilder.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
887 requestBuilder.addCapability(NetworkCapabilities.NET_CAPABILITY_SUPL);
888 NetworkRequest request = requestBuilder.build();
889 mConnMgr.requestNetwork(
890 request,
Etan Cohene9aea9d2017-02-09 18:16:58 -0800891 mSuplConnectivityCallback);
destradaae21252a2015-09-08 12:32:59 -0700892 }
893
894 private void handleReleaseSuplConnection(int agpsDataConnStatus) {
895 if (DEBUG) {
896 String message = String.format(
897 "releaseSuplConnection, state=%s, status=%s",
898 agpsDataConnStateAsString(),
899 agpsDataConnStatusAsString(agpsDataConnStatus));
900 Log.d(TAG, message);
901 }
902
903 if (mAGpsDataConnectionState == AGPS_DATA_CONNECTION_CLOSED) {
904 return;
905 }
906 mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED;
907
908 mConnMgr.unregisterNetworkCallback(mSuplConnectivityCallback);
909 switch (agpsDataConnStatus) {
910 case GPS_AGPS_DATA_CONN_FAILED:
911 native_agps_data_conn_failed();
912 break;
913 case GPS_RELEASE_AGPS_DATA_CONN:
914 native_agps_data_conn_closed();
915 break;
916 default:
917 Log.e(TAG, "Invalid status to release SUPL connection: " + agpsDataConnStatus);
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400918 }
919 }
920
921 private void handleInjectNtpTime() {
Kevin Tang40e1baf2012-01-10 14:32:44 -0800922 if (mInjectNtpTimePending == STATE_DOWNLOADING) {
923 // already downloading data
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400924 return;
925 }
destradaae21252a2015-09-08 12:32:59 -0700926 if (!isDataNetworkConnected()) {
Kevin Tang40e1baf2012-01-10 14:32:44 -0800927 // try again when network is up
928 mInjectNtpTimePending = STATE_PENDING_NETWORK;
929 return;
Jeff Sharkey104344e2011-07-10 14:20:41 -0700930 }
Kevin Tang40e1baf2012-01-10 14:32:44 -0800931 mInjectNtpTimePending = STATE_DOWNLOADING;
Jeff Sharkey104344e2011-07-10 14:20:41 -0700932
Jeff Brown028872f2012-08-25 13:07:01 -0700933 // hold wake lock while task runs
934 mWakeLock.acquire();
Lifu Tangcbd2a142016-06-22 10:57:55 -0700935 Log.i(TAG, "WakeLock acquired by handleInjectNtpTime()");
Kevin Tang40e1baf2012-01-10 14:32:44 -0800936 AsyncTask.THREAD_POOL_EXECUTOR.execute(new Runnable() {
937 @Override
938 public void run() {
939 long delay;
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400940
Kevin Tang40e1baf2012-01-10 14:32:44 -0800941 // force refresh NTP cache when outdated
destradaa56b47f82015-07-24 10:56:18 -0700942 boolean refreshSuccess = true;
Kevin Tang40e1baf2012-01-10 14:32:44 -0800943 if (mNtpTime.getCacheAge() >= NTP_INTERVAL) {
destradaa56b47f82015-07-24 10:56:18 -0700944 refreshSuccess = mNtpTime.forceRefresh();
Kevin Tang40e1baf2012-01-10 14:32:44 -0800945 }
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400946
Kevin Tang40e1baf2012-01-10 14:32:44 -0800947 // only update when NTP time is fresh
948 if (mNtpTime.getCacheAge() < NTP_INTERVAL) {
949 long time = mNtpTime.getCachedNtpTime();
950 long timeReference = mNtpTime.getCachedNtpTimeReference();
951 long certainty = mNtpTime.getCacheCertainty();
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400952
Joe Onorato0c484102016-02-01 18:04:24 -0800953 if (DEBUG) {
Yipeng Cao276278d2017-05-18 13:27:30 -0700954 long now = System.currentTimeMillis();
Joe Onorato0c484102016-02-01 18:04:24 -0800955 Log.d(TAG, "NTP server returned: "
956 + time + " (" + new Date(time)
957 + ") reference: " + timeReference
958 + " certainty: " + certainty
959 + " system time offset: " + (time - now));
960 }
Kevin Tang40e1baf2012-01-10 14:32:44 -0800961
962 native_inject_time(time, timeReference, (int) certainty);
963 delay = NTP_INTERVAL;
Wei Liu6f6326b2015-06-24 23:47:50 -0700964 mNtpBackOff.reset();
Kevin Tang40e1baf2012-01-10 14:32:44 -0800965 } else {
destradaa56b47f82015-07-24 10:56:18 -0700966 Log.e(TAG, "requestTime failed");
Wei Liu6f6326b2015-06-24 23:47:50 -0700967 delay = mNtpBackOff.nextBackoffMillis();
Kevin Tang40e1baf2012-01-10 14:32:44 -0800968 }
969
Jeff Brown028872f2012-08-25 13:07:01 -0700970 sendMessage(INJECT_NTP_TIME_FINISHED, 0, null);
Kevin Tang40e1baf2012-01-10 14:32:44 -0800971
destradaa56b47f82015-07-24 10:56:18 -0700972 if (DEBUG) {
973 String message = String.format(
974 "onDemandTimeInjection=%s, refreshSuccess=%s, delay=%s",
975 mOnDemandTimeInjection,
976 refreshSuccess,
977 delay);
978 Log.d(TAG, message);
979 }
980 if (mOnDemandTimeInjection || !refreshSuccess) {
Kevin Tang40e1baf2012-01-10 14:32:44 -0800981 // send delayed message for next NTP injection
982 // since this is delayed and not urgent we do not hold a wake lock here
Jeff Brown028872f2012-08-25 13:07:01 -0700983 mHandler.sendEmptyMessageDelayed(INJECT_NTP_TIME, delay);
Kevin Tang40e1baf2012-01-10 14:32:44 -0800984 }
Jeff Brown028872f2012-08-25 13:07:01 -0700985
986 // release wake lock held by task
987 mWakeLock.release();
Lifu Tangcbd2a142016-06-22 10:57:55 -0700988 Log.i(TAG, "WakeLock released by handleInjectNtpTime()");
Kevin Tang40e1baf2012-01-10 14:32:44 -0800989 }
990 });
Mike Lockwood62a8fc12010-03-22 14:23:26 -0400991 }
992
993 private void handleDownloadXtraData() {
Wyatt Riley0d6e54e22016-10-05 12:03:03 -0700994 if (!mSupportsXtra) {
995 // native code reports xtra not supported, don't try
996 Log.d(TAG, "handleDownloadXtraData() called when Xtra not supported");
997 return;
998 }
Kevin Tang40e1baf2012-01-10 14:32:44 -0800999 if (mDownloadXtraDataPending == STATE_DOWNLOADING) {
1000 // already downloading data
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001001 return;
1002 }
destradaae21252a2015-09-08 12:32:59 -07001003 if (!isDataNetworkConnected()) {
Kevin Tang40e1baf2012-01-10 14:32:44 -08001004 // try again when network is up
1005 mDownloadXtraDataPending = STATE_PENDING_NETWORK;
1006 return;
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001007 }
Kevin Tang40e1baf2012-01-10 14:32:44 -08001008 mDownloadXtraDataPending = STATE_DOWNLOADING;
1009
Jeff Brown028872f2012-08-25 13:07:01 -07001010 // hold wake lock while task runs
Wei Wangb71c0492017-05-01 20:24:19 -07001011 mDownloadXtraWakeLock.acquire(DOWNLOAD_XTRA_DATA_TIMEOUT_MS);
Lifu Tangcbd2a142016-06-22 10:57:55 -07001012 Log.i(TAG, "WakeLock acquired by handleDownloadXtraData()");
Kevin Tang40e1baf2012-01-10 14:32:44 -08001013 AsyncTask.THREAD_POOL_EXECUTOR.execute(new Runnable() {
1014 @Override
1015 public void run() {
Andreas Gampedfdc6ac2014-10-28 20:42:53 -07001016 GpsXtraDownloader xtraDownloader = new GpsXtraDownloader(mProperties);
Kevin Tang40e1baf2012-01-10 14:32:44 -08001017 byte[] data = xtraDownloader.downloadXtraData();
1018 if (data != null) {
destradaae21252a2015-09-08 12:32:59 -07001019 if (DEBUG) Log.d(TAG, "calling native_inject_xtra_data");
Kevin Tang40e1baf2012-01-10 14:32:44 -08001020 native_inject_xtra_data(data, data.length);
Wei Liu6f6326b2015-06-24 23:47:50 -07001021 mXtraBackOff.reset();
Kevin Tang40e1baf2012-01-10 14:32:44 -08001022 }
1023
Jeff Brown028872f2012-08-25 13:07:01 -07001024 sendMessage(DOWNLOAD_XTRA_DATA_FINISHED, 0, null);
Kevin Tang40e1baf2012-01-10 14:32:44 -08001025
1026 if (data == null) {
1027 // try again later
1028 // since this is delayed and not urgent we do not hold a wake lock here
Wei Liu6f6326b2015-06-24 23:47:50 -07001029 mHandler.sendEmptyMessageDelayed(DOWNLOAD_XTRA_DATA,
1030 mXtraBackOff.nextBackoffMillis());
Kevin Tang40e1baf2012-01-10 14:32:44 -08001031 }
Kevin Tang40e1baf2012-01-10 14:32:44 -08001032
Wei Wangb71c0492017-05-01 20:24:19 -07001033 // Release wake lock held by task, synchronize on mLock in case multiple
1034 // download tasks overrun.
1035 synchronized (mLock) {
1036 if (mDownloadXtraWakeLock.isHeld()) {
1037 mDownloadXtraWakeLock.release();
1038 if (DEBUG) Log.d(TAG, "WakeLock released by handleDownloadXtraData()");
1039 } else {
1040 Log.e(TAG, "WakeLock expired before release in "
1041 + "handleDownloadXtraData()");
1042 }
Wei Wangc5706f62017-04-18 11:26:26 -07001043 }
Jeff Brown028872f2012-08-25 13:07:01 -07001044 }
Kevin Tang40e1baf2012-01-10 14:32:44 -08001045 });
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001046 }
1047
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001048 private void handleUpdateLocation(Location location) {
Mike Lockwoodd26ce0d2009-06-11 12:25:46 -04001049 if (location.hasAccuracy()) {
1050 native_inject_location(location.getLatitude(), location.getLongitude(),
1051 location.getAccuracy());
1052 }
Mike Lockwoodfd6e5f02009-05-21 11:28:20 -04001053 }
1054
1055 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001056 * Enables this provider. When enabled, calls to getStatus()
Mike Lockwood4e50b782009-04-03 08:24:43 -07001057 * must be handled. Hardware may be started up
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001058 * when the provider is enabled.
1059 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001060 @Override
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001061 public void enable() {
Laurent Tu7b5aeca2013-01-24 15:10:24 -08001062 synchronized (mLock) {
1063 if (mEnabled) return;
1064 mEnabled = true;
1065 }
1066
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001067 sendMessage(ENABLE, 1, null);
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001068 }
1069
Tsuwei Chen52617bb2014-08-25 11:49:11 -07001070 private void setSuplHostPort(String hostString, String portString) {
1071 if (hostString != null) {
1072 mSuplServerHost = hostString;
1073 }
1074 if (portString != null) {
1075 try {
1076 mSuplServerPort = Integer.parseInt(portString);
1077 } catch (NumberFormatException e) {
1078 Log.e(TAG, "unable to parse SUPL_PORT: " + portString);
1079 }
1080 }
Tsuwei Chen678c13c2014-09-22 17:48:41 -07001081 if (mSuplServerHost != null
1082 && mSuplServerPort > TCP_MIN_PORT
1083 && mSuplServerPort <= TCP_MAX_PORT) {
1084 native_set_agps_server(AGPS_TYPE_SUPL, mSuplServerHost, mSuplServerPort);
1085 }
Tsuwei Chen52617bb2014-08-25 11:49:11 -07001086 }
1087
Tsuwei Chen462bcd82014-09-17 12:28:49 -07001088 /**
1089 * Checks what SUPL mode to use, according to the AGPS mode as well as the
1090 * allowed mode from properties.
1091 *
1092 * @param properties GPS properties
1093 * @param agpsEnabled whether AGPS is enabled by settings value
1094 * @param singleShot whether "singleshot" is needed
1095 * @return SUPL mode (MSA vs MSB vs STANDALONE)
1096 */
1097 private int getSuplMode(Properties properties, boolean agpsEnabled, boolean singleShot) {
1098 if (agpsEnabled) {
1099 String modeString = properties.getProperty("SUPL_MODE");
1100 int suplMode = 0;
1101 if (!TextUtils.isEmpty(modeString)) {
1102 try {
1103 suplMode = Integer.parseInt(modeString);
1104 } catch (NumberFormatException e) {
1105 Log.e(TAG, "unable to parse SUPL_MODE: " + modeString);
1106 return GPS_POSITION_MODE_STANDALONE;
1107 }
1108 }
destradaabfb3bdb2015-04-29 14:42:35 -07001109 // MS-Based is the preferred mode for Assisted-GPS position computation, so we favor
1110 // such mode when it is available
1111 if (hasCapability(GPS_CAPABILITY_MSB) && (suplMode & AGPS_SUPL_MODE_MSB) != 0) {
1112 return GPS_POSITION_MODE_MS_BASED;
1113 }
1114 // for now, just as the legacy code did, we fallback to MS-Assisted if it is available,
1115 // do fallback only for single-shot requests, because it is too expensive to do for
1116 // periodic requests as well
Tsuwei Chen462bcd82014-09-17 12:28:49 -07001117 if (singleShot
1118 && hasCapability(GPS_CAPABILITY_MSA)
1119 && (suplMode & AGPS_SUPL_MODE_MSA) != 0) {
1120 return GPS_POSITION_MODE_MS_ASSISTED;
Tsuwei Chen462bcd82014-09-17 12:28:49 -07001121 }
1122 }
1123 return GPS_POSITION_MODE_STANDALONE;
1124 }
1125
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001126 private void handleEnable() {
1127 if (DEBUG) Log.d(TAG, "handleEnable");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001128
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001129 boolean enabled = native_init();
1130
1131 if (enabled) {
Mike Lockwood1a1cd3a2010-08-17 07:42:54 -04001132 mSupportsXtra = native_supports_xtra();
Tsuwei Chen678c13c2014-09-22 17:48:41 -07001133
1134 // TODO: remove the following native calls if we can make sure they are redundant.
Mike Lockwood734d6032009-07-28 18:30:25 -07001135 if (mSuplServerHost != null) {
1136 native_set_agps_server(AGPS_TYPE_SUPL, mSuplServerHost, mSuplServerPort);
1137 }
1138 if (mC2KServerHost != null) {
1139 native_set_agps_server(AGPS_TYPE_C2K, mC2KServerHost, mC2KServerPort);
1140 }
destradaa13a60b02015-01-15 18:36:01 -08001141
Lifu Tang818aa2c2016-02-01 01:52:00 -08001142 mGnssMeasurementsProvider.onGpsEnabledChanged();
1143 mGnssNavigationMessageProvider.onGpsEnabledChanged();
Wyatt Rileycf879db2017-01-12 13:57:38 -08001144 enableBatching();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001145 } else {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001146 synchronized (mLock) {
1147 mEnabled = false;
1148 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001149 Log.w(TAG, "Failed to enable location provider");
1150 }
1151 }
1152
1153 /**
1154 * Disables this provider. When disabled, calls to getStatus()
Mike Lockwood4e50b782009-04-03 08:24:43 -07001155 * need not be handled. Hardware may be shut
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001156 * down while the provider is disabled.
1157 */
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001158 @Override
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001159 public void disable() {
Laurent Tu7b5aeca2013-01-24 15:10:24 -08001160 synchronized (mLock) {
1161 if (!mEnabled) return;
1162 mEnabled = false;
1163 }
1164
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001165 sendMessage(ENABLE, 0, null);
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001166 }
1167
1168 private void handleDisable() {
Mike Lockwood89096312010-03-24 10:14:55 -04001169 if (DEBUG) Log.d(TAG, "handleDisable");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001170
David Christie3bc26142013-12-19 14:53:44 -08001171 updateClientUids(new WorkSource());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001172 stopNavigating();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001173 mAlarmManager.cancel(mWakeupIntent);
1174 mAlarmManager.cancel(mTimeoutIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001175
Wyatt Rileycf879db2017-01-12 13:57:38 -08001176 disableBatching();
Mike Lockwoodcf1d8cb2010-01-20 10:14:54 -05001177 // do this before releasing wakelock
1178 native_cleanup();
destradaa13a60b02015-01-15 18:36:01 -08001179
Lifu Tang818aa2c2016-02-01 01:52:00 -08001180 mGnssMeasurementsProvider.onGpsEnabledChanged();
1181 mGnssNavigationMessageProvider.onGpsEnabledChanged();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001182 }
1183
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001184 @Override
Mike Lockwoodd03ff942010-02-09 08:46:14 -05001185 public boolean isEnabled() {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001186 synchronized (mLock) {
1187 return mEnabled;
1188 }
Mike Lockwoodd03ff942010-02-09 08:46:14 -05001189 }
1190
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001191 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001192 public int getStatus(Bundle extras) {
1193 if (extras != null) {
1194 extras.putInt("satellites", mSvCount);
1195 }
1196 return mStatus;
1197 }
1198
1199 private void updateStatus(int status, int svCount) {
1200 if (status != mStatus || svCount != mSvCount) {
1201 mStatus = status;
1202 mSvCount = svCount;
1203 mLocationExtras.putInt("satellites", svCount);
1204 mStatusUpdateTime = SystemClock.elapsedRealtime();
1205 }
1206 }
1207
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001208 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001209 public long getStatusUpdateTime() {
1210 return mStatusUpdateTime;
1211 }
1212
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001213 @Override
1214 public void setRequest(ProviderRequest request, WorkSource source) {
1215 sendMessage(SET_REQUEST, 0, new GpsRequest(request, source));
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001216 }
1217
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001218 private void handleSetRequest(ProviderRequest request, WorkSource source) {
David Christied4edf4c2014-08-12 15:22:27 -07001219 mProviderRequest = request;
1220 mWorkSource = source;
1221 updateRequirements();
1222 }
1223
1224 // Called when the requirements for GPS may have changed
1225 private void updateRequirements() {
1226 if (mProviderRequest == null || mWorkSource == null) {
1227 return;
1228 }
1229
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001230 boolean singleShot = false;
1231
1232 // see if the request is for a single update
David Christied4edf4c2014-08-12 15:22:27 -07001233 if (mProviderRequest.locationRequests != null
1234 && mProviderRequest.locationRequests.size() > 0) {
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001235 // if any request has zero or more than one updates
1236 // requested, then this is not single-shot mode
1237 singleShot = true;
1238
David Christied4edf4c2014-08-12 15:22:27 -07001239 for (LocationRequest lr : mProviderRequest.locationRequests) {
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001240 if (lr.getNumUpdates() != 1) {
1241 singleShot = false;
1242 }
1243 }
1244 }
1245
David Christied4edf4c2014-08-12 15:22:27 -07001246 if (DEBUG) Log.d(TAG, "setRequest " + mProviderRequest);
Dante Russo260d6672016-06-20 11:11:59 -07001247 if (mProviderRequest.reportLocation && !mDisableGps && isEnabled()) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001248 // update client uids
David Christied4edf4c2014-08-12 15:22:27 -07001249 updateClientUids(mWorkSource);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001250
David Christied4edf4c2014-08-12 15:22:27 -07001251 mFixInterval = (int) mProviderRequest.interval;
Mike Lockwood03ca2162010-04-01 08:10:09 -07001252
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001253 // check for overflow
David Christied4edf4c2014-08-12 15:22:27 -07001254 if (mFixInterval != mProviderRequest.interval) {
1255 Log.w(TAG, "interval overflow: " + mProviderRequest.interval);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001256 mFixInterval = Integer.MAX_VALUE;
1257 }
Mike Lockwood03ca2162010-04-01 08:10:09 -07001258
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001259 // apply request to GPS engine
Mike Lockwood04598b62010-04-14 17:17:24 -04001260 if (mStarted && hasCapability(GPS_CAPABILITY_SCHEDULING)) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001261 // change period
Mike Lockwood04598b62010-04-14 17:17:24 -04001262 if (!native_set_position_mode(mPositionMode, GPS_POSITION_RECURRENCE_PERIODIC,
1263 mFixInterval, 0, 0)) {
1264 Log.e(TAG, "set_position_mode failed in setMinTime()");
1265 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001266 } else if (!mStarted) {
1267 // start GPS
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001268 startNavigating(singleShot);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001269 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001270 } else {
Dianne Hackborn002a54e2013-01-10 17:34:55 -08001271 updateClientUids(new WorkSource());
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001272
1273 stopNavigating();
1274 mAlarmManager.cancel(mWakeupIntent);
1275 mAlarmManager.cancel(mTimeoutIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001276 }
1277 }
1278
Dianne Hackborn002a54e2013-01-10 17:34:55 -08001279 private void updateClientUids(WorkSource source) {
1280 // Update work source.
1281 WorkSource[] changes = mClientSource.setReturningDiffs(source);
Victoria Leaseea78b852013-01-15 10:39:28 -08001282 if (changes == null) {
1283 return;
1284 }
Dianne Hackborn002a54e2013-01-10 17:34:55 -08001285 WorkSource newWork = changes[0];
1286 WorkSource goneWork = changes[1];
1287
1288 // Update sources that were not previously tracked.
1289 if (newWork != null) {
1290 int lastuid = -1;
1291 for (int i=0; i<newWork.size(); i++) {
Dianne Hackborn2e418422009-06-22 20:00:17 -07001292 try {
Dianne Hackborn002a54e2013-01-10 17:34:55 -08001293 int uid = newWork.get(i);
Dianne Hackborne98f5db2013-07-17 17:23:25 -07001294 mAppOpsService.startOperation(AppOpsManager.getToken(mAppOpsService),
1295 AppOpsManager.OP_GPS, uid, newWork.getName(i));
Dianne Hackborn002a54e2013-01-10 17:34:55 -08001296 if (uid != lastuid) {
1297 lastuid = uid;
1298 mBatteryStats.noteStartGps(uid);
1299 }
Dianne Hackborn2e418422009-06-22 20:00:17 -07001300 } catch (RemoteException e) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001301 Log.w(TAG, "RemoteException", e);
1302 }
1303 }
1304 }
1305
Dianne Hackborn002a54e2013-01-10 17:34:55 -08001306 // Update sources that are no longer tracked.
1307 if (goneWork != null) {
1308 int lastuid = -1;
1309 for (int i=0; i<goneWork.size(); i++) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001310 try {
Dianne Hackborn002a54e2013-01-10 17:34:55 -08001311 int uid = goneWork.get(i);
Dianne Hackborne98f5db2013-07-17 17:23:25 -07001312 mAppOpsService.finishOperation(AppOpsManager.getToken(mAppOpsService),
1313 AppOpsManager.OP_GPS, uid, goneWork.getName(i));
Dianne Hackborn002a54e2013-01-10 17:34:55 -08001314 if (uid != lastuid) {
1315 lastuid = uid;
1316 mBatteryStats.noteStopGps(uid);
1317 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001318 } catch (RemoteException e) {
1319 Log.w(TAG, "RemoteException", e);
Dianne Hackborn2e418422009-06-22 20:00:17 -07001320 }
Mike Lockwood2f82c4e2009-04-17 08:24:10 -04001321 }
1322 }
1323 }
1324
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001325 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001326 public boolean sendExtraCommand(String command, Bundle extras) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001327
Mike Lockwood63aa5a62010-04-14 19:21:31 -04001328 long identity = Binder.clearCallingIdentity();
1329 boolean result = false;
1330
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001331 if ("delete_aiding_data".equals(command)) {
Mike Lockwood63aa5a62010-04-14 19:21:31 -04001332 result = deleteAidingData(extras);
1333 } else if ("force_time_injection".equals(command)) {
destradaae21252a2015-09-08 12:32:59 -07001334 requestUtcTime();
Mike Lockwood63aa5a62010-04-14 19:21:31 -04001335 result = true;
1336 } else if ("force_xtra_injection".equals(command)) {
Mike Lockwood1a1cd3a2010-08-17 07:42:54 -04001337 if (mSupportsXtra) {
Mike Lockwood93bc44d2009-05-20 16:58:22 -04001338 xtraDownloadRequest();
Mike Lockwood63aa5a62010-04-14 19:21:31 -04001339 result = true;
Mike Lockwood93bc44d2009-05-20 16:58:22 -04001340 }
Mike Lockwood63aa5a62010-04-14 19:21:31 -04001341 } else {
1342 Log.w(TAG, "sendExtraCommand: unknown command " + command);
Mike Lockwood93bc44d2009-05-20 16:58:22 -04001343 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001344
Mike Lockwood63aa5a62010-04-14 19:21:31 -04001345 Binder.restoreCallingIdentity(identity);
1346 return result;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001347 }
1348
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001349 private IGpsGeofenceHardware mGpsGeofenceBinder = new IGpsGeofenceHardware.Stub() {
1350 public boolean isHardwareGeofenceSupported() {
1351 return native_is_geofence_supported();
1352 }
1353
1354 public boolean addCircularHardwareGeofence(int geofenceId, double latitude,
1355 double longitude, double radius, int lastTransition, int monitorTransitions,
1356 int notificationResponsiveness, int unknownTimer) {
1357 return native_add_geofence(geofenceId, latitude, longitude, radius,
1358 lastTransition, monitorTransitions, notificationResponsiveness, unknownTimer);
1359 }
1360
1361 public boolean removeHardwareGeofence(int geofenceId) {
1362 return native_remove_geofence(geofenceId);
1363 }
1364
1365 public boolean pauseHardwareGeofence(int geofenceId) {
1366 return native_pause_geofence(geofenceId);
1367 }
1368
1369 public boolean resumeHardwareGeofence(int geofenceId, int monitorTransition) {
1370 return native_resume_geofence(geofenceId, monitorTransition);
1371 }
1372 };
1373
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001374 private boolean deleteAidingData(Bundle extras) {
1375 int flags;
1376
1377 if (extras == null) {
1378 flags = GPS_DELETE_ALL;
1379 } else {
1380 flags = 0;
1381 if (extras.getBoolean("ephemeris")) flags |= GPS_DELETE_EPHEMERIS;
1382 if (extras.getBoolean("almanac")) flags |= GPS_DELETE_ALMANAC;
1383 if (extras.getBoolean("position")) flags |= GPS_DELETE_POSITION;
1384 if (extras.getBoolean("time")) flags |= GPS_DELETE_TIME;
1385 if (extras.getBoolean("iono")) flags |= GPS_DELETE_IONO;
1386 if (extras.getBoolean("utc")) flags |= GPS_DELETE_UTC;
1387 if (extras.getBoolean("health")) flags |= GPS_DELETE_HEALTH;
1388 if (extras.getBoolean("svdir")) flags |= GPS_DELETE_SVDIR;
1389 if (extras.getBoolean("svsteer")) flags |= GPS_DELETE_SVSTEER;
1390 if (extras.getBoolean("sadata")) flags |= GPS_DELETE_SADATA;
1391 if (extras.getBoolean("rti")) flags |= GPS_DELETE_RTI;
1392 if (extras.getBoolean("celldb-info")) flags |= GPS_DELETE_CELLDB_INFO;
1393 if (extras.getBoolean("all")) flags |= GPS_DELETE_ALL;
1394 }
1395
1396 if (flags != 0) {
1397 native_delete_aiding_data(flags);
1398 return true;
1399 }
1400
1401 return false;
1402 }
1403
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001404 private void startNavigating(boolean singleShot) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001405 if (!mStarted) {
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001406 if (DEBUG) Log.d(TAG, "startNavigating, singleShot is " + singleShot);
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001407 mTimeToFirstFix = 0;
1408 mLastFixTime = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001409 mStarted = true;
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001410 mSingleShot = singleShot;
Mike Lockwood03ca2162010-04-01 08:10:09 -07001411 mPositionMode = GPS_POSITION_MODE_STANDALONE;
Wyatt Riley5d5bac82016-11-01 07:05:16 -07001412 // Notify about suppressed output, if speed limit was previously exceeded.
1413 // Elsewhere, we check again with every speed output reported.
1414 if (mItarSpeedLimitExceeded) {
1415 Log.i(TAG, "startNavigating with ITAR limit in place. Output limited " +
1416 "until slow enough speed reported.");
1417 }
Mike Lockwood03ca2162010-04-01 08:10:09 -07001418
Tsuwei Chen462bcd82014-09-17 12:28:49 -07001419 boolean agpsEnabled =
1420 (Settings.Global.getInt(mContext.getContentResolver(),
1421 Settings.Global.ASSISTED_GPS_ENABLED, 1) != 0);
1422 mPositionMode = getSuplMode(mProperties, agpsEnabled, singleShot);
Mike Lockwoodbcab8df2009-06-25 16:39:09 -04001423
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001424 if (DEBUG) {
1425 String mode;
1426
1427 switch(mPositionMode) {
1428 case GPS_POSITION_MODE_STANDALONE:
1429 mode = "standalone";
1430 break;
1431 case GPS_POSITION_MODE_MS_ASSISTED:
1432 mode = "MS_ASSISTED";
1433 break;
1434 case GPS_POSITION_MODE_MS_BASED:
1435 mode = "MS_BASED";
1436 break;
1437 default:
1438 mode = "unknown";
1439 break;
1440 }
1441 Log.d(TAG, "setting position_mode to " + mode);
1442 }
1443
Mike Lockwood04598b62010-04-14 17:17:24 -04001444 int interval = (hasCapability(GPS_CAPABILITY_SCHEDULING) ? mFixInterval : 1000);
1445 if (!native_set_position_mode(mPositionMode, GPS_POSITION_RECURRENCE_PERIODIC,
1446 interval, 0, 0)) {
1447 mStarted = false;
1448 Log.e(TAG, "set_position_mode failed in startNavigating()");
1449 return;
1450 }
1451 if (!native_start()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001452 mStarted = false;
1453 Log.e(TAG, "native_start failed in startNavigating()");
Mike Lockwood0632ca72009-05-14 15:51:03 -04001454 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001455 }
1456
1457 // reset SV count to zero
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001458 updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, 0);
Yipeng Cao2a968ed2017-05-15 20:23:12 -07001459 mFixRequestTime = SystemClock.elapsedRealtime();
1460
Mike Lockwood04598b62010-04-14 17:17:24 -04001461 if (!hasCapability(GPS_CAPABILITY_SCHEDULING)) {
1462 // set timer to give up if we do not receive a fix within NO_FIX_TIMEOUT
1463 // and our fix interval is not short
1464 if (mFixInterval >= NO_FIX_TIMEOUT) {
1465 mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
1466 SystemClock.elapsedRealtime() + NO_FIX_TIMEOUT, mTimeoutIntent);
1467 }
Mike Lockwood0632ca72009-05-14 15:51:03 -04001468 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001469 }
1470 }
1471
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001472 private void stopNavigating() {
Mike Lockwood29c84342009-05-06 14:01:15 -04001473 if (DEBUG) Log.d(TAG, "stopNavigating");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001474 if (mStarted) {
1475 mStarted = false;
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001476 mSingleShot = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001477 native_stop();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001478 mTimeToFirstFix = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001479 mLastFixTime = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001480
1481 // reset SV count to zero
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001482 updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001483 }
1484 }
1485
Mike Lockwood0632ca72009-05-14 15:51:03 -04001486 private void hibernate() {
1487 // stop GPS until our next fix interval arrives
1488 stopNavigating();
Mike Lockwood0632ca72009-05-14 15:51:03 -04001489 mAlarmManager.cancel(mTimeoutIntent);
1490 mAlarmManager.cancel(mWakeupIntent);
1491 long now = SystemClock.elapsedRealtime();
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001492 mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, now + mFixInterval, mWakeupIntent);
Mike Lockwood04598b62010-04-14 17:17:24 -04001493 }
1494
1495 private boolean hasCapability(int capability) {
1496 return ((mEngineCapabilities & capability) != 0);
Mike Lockwood0632ca72009-05-14 15:51:03 -04001497 }
1498
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001499
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001500 /**
1501 * called from native code to update our position.
1502 */
Wyatt Riley5d229832017-02-10 17:06:00 -08001503 private void reportLocation(boolean hasLatLong, Location location) {
1504 if (location.hasSpeed()) {
1505 mItarSpeedLimitExceeded = location.getSpeed() > ITAR_SPEED_LIMIT_METERS_PER_SECOND;
Wyatt Riley5d5bac82016-11-01 07:05:16 -07001506 }
1507
1508 if (mItarSpeedLimitExceeded) {
1509 Log.i(TAG, "Hal reported a speed in excess of ITAR limit." +
1510 " GPS/GNSS Navigation output blocked.");
1511 return; // No output of location allowed
1512 }
1513
Wyatt Riley5d229832017-02-10 17:06:00 -08001514 if (VERBOSE) Log.v(TAG, "reportLocation " + location.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001515
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001516 synchronized (mLocation) {
Wyatt Riley5d229832017-02-10 17:06:00 -08001517 mLocation = location;
1518 // It would be nice to push the elapsed real-time timestamp
1519 // further down the stack, but this is still useful
1520 mLocation.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());
Sean Barbeauced2b2c2011-12-19 04:43:07 -05001521 mLocation.setExtras(mLocationExtras);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001522
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001523 try {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001524 mILocationManager.reportLocation(mLocation, false);
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001525 } catch (RemoteException e) {
1526 Log.e(TAG, "RemoteException calling reportLocation");
1527 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001528 }
1529
Yipeng Cao2a968ed2017-05-15 20:23:12 -07001530 mLastFixTime = SystemClock.elapsedRealtime();
Hakan Gustavssonfa94ff02010-02-23 09:12:38 +01001531 // report time to first fix
Wyatt Riley5d229832017-02-10 17:06:00 -08001532 if (mTimeToFirstFix == 0 && hasLatLong) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001533 mTimeToFirstFix = (int)(mLastFixTime - mFixRequestTime);
1534 if (DEBUG) Log.d(TAG, "TTFF: " + mTimeToFirstFix);
Hakan Gustavssonfa94ff02010-02-23 09:12:38 +01001535
1536 // notify status listeners
destradaaea8a8a62014-06-23 18:19:03 -07001537 mListenerHelper.onFirstFix(mTimeToFirstFix);
Hakan Gustavssonfa94ff02010-02-23 09:12:38 +01001538 }
1539
Stan Chesnutt1d72d8c2013-04-15 19:18:02 -07001540 if (mSingleShot) {
1541 stopNavigating();
1542 }
1543
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001544 if (mStarted && mStatus != LocationProvider.AVAILABLE) {
Mike Lockwoodd53ba012010-04-15 20:41:26 -04001545 // we want to time out if we do not receive a fix
Mike Lockwoodb7be5442010-02-24 14:34:50 -05001546 // within the time out and we are requesting infrequent fixes
Mike Lockwood04598b62010-04-14 17:17:24 -04001547 if (!hasCapability(GPS_CAPABILITY_SCHEDULING) && mFixInterval < NO_FIX_TIMEOUT) {
Mike Lockwoodb7be5442010-02-24 14:34:50 -05001548 mAlarmManager.cancel(mTimeoutIntent);
1549 }
1550
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001551 // send an intent to notify that the GPS is receiving fixes.
Mike Lockwood00b74272010-03-26 10:41:48 -04001552 Intent intent = new Intent(LocationManager.GPS_FIX_CHANGE_ACTION);
1553 intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, true);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07001554 mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001555 updateStatus(LocationProvider.AVAILABLE, mSvCount);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001556 }
Mike Lockwood29c84342009-05-06 14:01:15 -04001557
Nick Pellyb041f232012-05-07 17:12:25 -07001558 if (!hasCapability(GPS_CAPABILITY_SCHEDULING) && mStarted &&
1559 mFixInterval > GPS_POLLING_THRESHOLD_INTERVAL) {
Mike Lockwoodd53ba012010-04-15 20:41:26 -04001560 if (DEBUG) Log.d(TAG, "got fix, hibernating");
Mike Lockwood0632ca72009-05-14 15:51:03 -04001561 hibernate();
Mike Lockwood29c84342009-05-06 14:01:15 -04001562 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001563 }
1564
1565 /**
1566 * called from native code to update our status
1567 */
1568 private void reportStatus(int status) {
Mike Lockwoodb8d90332010-10-18 17:59:48 -04001569 if (DEBUG) Log.v(TAG, "reportStatus status: " + status);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001570
destradaaea8a8a62014-06-23 18:19:03 -07001571 boolean wasNavigating = mNavigating;
1572 switch (status) {
1573 case GPS_STATUS_SESSION_BEGIN:
1574 mNavigating = true;
1575 mEngineOn = true;
1576 break;
1577 case GPS_STATUS_SESSION_END:
1578 mNavigating = false;
1579 break;
1580 case GPS_STATUS_ENGINE_ON:
1581 mEngineOn = true;
1582 break;
1583 case GPS_STATUS_ENGINE_OFF:
1584 mEngineOn = false;
1585 mNavigating = false;
1586 break;
1587 }
Mike Lockwooddbd6fd82009-12-07 18:43:36 -05001588
destradaaea8a8a62014-06-23 18:19:03 -07001589 if (wasNavigating != mNavigating) {
destradaa13a60b02015-01-15 18:36:01 -08001590 mListenerHelper.onStatusChanged(mNavigating);
Mike Lockwoodcf1d8cb2010-01-20 10:14:54 -05001591
destradaaea8a8a62014-06-23 18:19:03 -07001592 // send an intent to notify that the GPS has been enabled or disabled
1593 Intent intent = new Intent(LocationManager.GPS_ENABLED_CHANGE_ACTION);
1594 intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, mNavigating);
1595 mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001596 }
1597 }
1598
1599 /**
1600 * called from native code to update SV info
1601 */
1602 private void reportSvStatus() {
gomo4402af62017-01-11 13:20:13 -08001603 int svCount = native_read_sv_status(mSvidWithFlags,
1604 mCn0s,
1605 mSvElevations,
1606 mSvAzimuths,
1607 mSvCarrierFreqs);
destradaaea8a8a62014-06-23 18:19:03 -07001608 mListenerHelper.onSvStatusChanged(
1609 svCount,
Lifu Tang120480f2016-02-07 18:08:19 -08001610 mSvidWithFlags,
Lifu Tang76a620f2016-02-26 19:53:01 -08001611 mCn0s,
destradaaea8a8a62014-06-23 18:19:03 -07001612 mSvElevations,
gomo4402af62017-01-11 13:20:13 -08001613 mSvAzimuths,
1614 mSvCarrierFreqs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001615
Mike Lockwood29c84342009-05-06 14:01:15 -04001616 if (VERBOSE) {
Lifu Tang30f95a72016-01-07 23:20:38 -08001617 Log.v(TAG, "SV count: " + svCount);
1618 }
1619 // Calculate number of sets used in fix.
1620 int usedInFixCount = 0;
1621 for (int i = 0; i < svCount; i++) {
Lifu Tang120480f2016-02-07 18:08:19 -08001622 if ((mSvidWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_USED_IN_FIX) != 0) {
Lifu Tang30f95a72016-01-07 23:20:38 -08001623 ++usedInFixCount;
1624 }
1625 if (VERBOSE) {
Lifu Tang120480f2016-02-07 18:08:19 -08001626 Log.v(TAG, "svid: " + (mSvidWithFlags[i] >> GnssStatus.SVID_SHIFT_WIDTH) +
Lifu Tang76a620f2016-02-26 19:53:01 -08001627 " cn0: " + mCn0s[i]/10 +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001628 " elev: " + mSvElevations[i] +
1629 " azimuth: " + mSvAzimuths[i] +
gomo4402af62017-01-11 13:20:13 -08001630 " carrier frequency: " + mSvCarrierFreqs[i] +
Lifu Tang120480f2016-02-07 18:08:19 -08001631 ((mSvidWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_HAS_EPHEMERIS_DATA) == 0
Lifu Tang30f95a72016-01-07 23:20:38 -08001632 ? " " : " E") +
Lifu Tang120480f2016-02-07 18:08:19 -08001633 ((mSvidWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_HAS_ALMANAC_DATA) == 0
Lifu Tang30f95a72016-01-07 23:20:38 -08001634 ? " " : " A") +
Lifu Tang120480f2016-02-07 18:08:19 -08001635 ((mSvidWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_USED_IN_FIX) == 0
gomo4402af62017-01-11 13:20:13 -08001636 ? "" : "U") +
1637 ((mSvidWithFlags[i] & GnssStatus.GNSS_SV_FLAGS_HAS_CARRIER_FREQUENCY) == 0
1638 ? "" : "F"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001639 }
1640 }
Kevin.KY Tsai0881f4f2010-05-21 15:10:39 -04001641 // return number of sets used in fix instead of total
Lifu Tang30f95a72016-01-07 23:20:38 -08001642 updateStatus(mStatus, usedInFixCount);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001643
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001644 if (mNavigating && mStatus == LocationProvider.AVAILABLE && mLastFixTime > 0 &&
Yipeng Cao2a968ed2017-05-15 20:23:12 -07001645 SystemClock.elapsedRealtime() - mLastFixTime > RECENT_FIX_TIMEOUT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001646 // send an intent to notify that the GPS is no longer receiving fixes.
Mike Lockwood00b74272010-03-26 10:41:48 -04001647 Intent intent = new Intent(LocationManager.GPS_FIX_CHANGE_ACTION);
1648 intent.putExtra(LocationManager.EXTRA_GPS_ENABLED, false);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07001649 mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
Mike Lockwood15e3d0f2009-05-01 07:53:28 -04001650 updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE, mSvCount);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001651 }
1652 }
Mike Lockwood58bda982009-04-14 16:25:07 -04001653
1654 /**
Mike Lockwoode3635c92009-05-11 08:38:02 -04001655 * called from native code to update AGPS status
Mike Lockwood58bda982009-04-14 16:25:07 -04001656 */
destradaa96a14702014-06-05 11:36:30 -07001657 private void reportAGpsStatus(int type, int status, byte[] ipaddr) {
Mike Lockwood58bda982009-04-14 16:25:07 -04001658 switch (status) {
Mike Lockwoode3635c92009-05-11 08:38:02 -04001659 case GPS_REQUEST_AGPS_DATA_CONN:
Mike Lockwoodb6e5fa82010-10-09 20:10:46 -04001660 if (DEBUG) Log.d(TAG, "GPS_REQUEST_AGPS_DATA_CONN");
Andreas Gampee6748ce2015-12-11 18:00:38 -08001661 Log.v(TAG, "Received SUPL IP addr[]: " + Arrays.toString(ipaddr));
destradaae21252a2015-09-08 12:32:59 -07001662 InetAddress connectionIpAddress = null;
destradaa96a14702014-06-05 11:36:30 -07001663 if (ipaddr != null) {
1664 try {
destradaae21252a2015-09-08 12:32:59 -07001665 connectionIpAddress = InetAddress.getByAddress(ipaddr);
1666 if (DEBUG) Log.d(TAG, "IP address converted to: " + connectionIpAddress);
destradaa96a14702014-06-05 11:36:30 -07001667 } catch (UnknownHostException e) {
1668 Log.e(TAG, "Bad IP Address: " + ipaddr, e);
destradaa96a14702014-06-05 11:36:30 -07001669 }
1670 }
destradaae21252a2015-09-08 12:32:59 -07001671 sendMessage(REQUEST_SUPL_CONNECTION, 0 /*arg*/, connectionIpAddress);
Mike Lockwood58bda982009-04-14 16:25:07 -04001672 break;
Mike Lockwoode3635c92009-05-11 08:38:02 -04001673 case GPS_RELEASE_AGPS_DATA_CONN:
Mike Lockwoodb6e5fa82010-10-09 20:10:46 -04001674 if (DEBUG) Log.d(TAG, "GPS_RELEASE_AGPS_DATA_CONN");
destradaae21252a2015-09-08 12:32:59 -07001675 releaseSuplConnection(GPS_RELEASE_AGPS_DATA_CONN);
Mike Lockwood58bda982009-04-14 16:25:07 -04001676 break;
Mike Lockwoode3635c92009-05-11 08:38:02 -04001677 case GPS_AGPS_DATA_CONNECTED:
Mike Lockwoodb6e5fa82010-10-09 20:10:46 -04001678 if (DEBUG) Log.d(TAG, "GPS_AGPS_DATA_CONNECTED");
Mike Lockwood58bda982009-04-14 16:25:07 -04001679 break;
Mike Lockwoode3635c92009-05-11 08:38:02 -04001680 case GPS_AGPS_DATA_CONN_DONE:
Mike Lockwoodb6e5fa82010-10-09 20:10:46 -04001681 if (DEBUG) Log.d(TAG, "GPS_AGPS_DATA_CONN_DONE");
Mike Lockwood58bda982009-04-14 16:25:07 -04001682 break;
Mike Lockwoode3635c92009-05-11 08:38:02 -04001683 case GPS_AGPS_DATA_CONN_FAILED:
Mike Lockwoodb6e5fa82010-10-09 20:10:46 -04001684 if (DEBUG) Log.d(TAG, "GPS_AGPS_DATA_CONN_FAILED");
Mike Lockwood58bda982009-04-14 16:25:07 -04001685 break;
destradaa931a37f2014-08-12 16:36:59 -07001686 default:
Joe Onorato0c484102016-02-01 18:04:24 -08001687 if (DEBUG) Log.d(TAG, "Received Unknown AGPS status: " + status);
Mike Lockwood58bda982009-04-14 16:25:07 -04001688 }
1689 }
1690
destradaae21252a2015-09-08 12:32:59 -07001691 private void releaseSuplConnection(int connStatus) {
1692 sendMessage(RELEASE_SUPL_CONNECTION, connStatus, null /*obj*/);
1693 }
1694
Mike Lockwoodb16e7802009-08-06 09:26:02 -04001695 /**
1696 * called from native code to report NMEA data received
1697 */
Mike Lockwoodf602d362010-06-20 14:28:16 -07001698 private void reportNmea(long timestamp) {
Wyatt Riley5d5bac82016-11-01 07:05:16 -07001699 if (!mItarSpeedLimitExceeded) {
1700 int length = native_read_nmea(mNmeaBuffer, mNmeaBuffer.length);
1701 String nmea = new String(mNmeaBuffer, 0 /* offset */, length);
1702 mListenerHelper.onNmeaReceived(timestamp, nmea);
1703 }
destradaaea8a8a62014-06-23 18:19:03 -07001704 }
Mike Lockwoodb16e7802009-08-06 09:26:02 -04001705
destradaaea8a8a62014-06-23 18:19:03 -07001706 /**
destradaa4b3e3932014-07-21 18:01:47 -07001707 * called from native code - Gps measurements callback
destradaaea8a8a62014-06-23 18:19:03 -07001708 */
Lifu Tang818aa2c2016-02-01 01:52:00 -08001709 private void reportMeasurementData(GnssMeasurementsEvent event) {
Wyatt Riley5d5bac82016-11-01 07:05:16 -07001710 if (!mItarSpeedLimitExceeded) {
1711 mGnssMeasurementsProvider.onMeasurementsAvailable(event);
1712 }
Mike Lockwoodb16e7802009-08-06 09:26:02 -04001713 }
1714
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001715 /**
destradaa4b3e3932014-07-21 18:01:47 -07001716 * called from native code - GPS navigation message callback
1717 */
Lifu Tange8abe8e2016-04-01 10:32:05 -07001718 private void reportNavigationMessage(GnssNavigationMessage event) {
Wyatt Riley5d5bac82016-11-01 07:05:16 -07001719 if (!mItarSpeedLimitExceeded) {
1720 mGnssNavigationMessageProvider.onNavigationMessageAvailable(event);
1721 }
destradaa4b3e3932014-07-21 18:01:47 -07001722 }
1723
1724 /**
Mike Lockwood04598b62010-04-14 17:17:24 -04001725 * called from native code to inform us what the GPS engine capabilities are
1726 */
1727 private void setEngineCapabilities(int capabilities) {
1728 mEngineCapabilities = capabilities;
Mike Lockwood9b9fb5c2011-06-29 15:09:40 -04001729
destradaa56b47f82015-07-24 10:56:18 -07001730 if (hasCapability(GPS_CAPABILITY_ON_DEMAND_TIME)) {
1731 mOnDemandTimeInjection = true;
Mike Lockwood9b9fb5c2011-06-29 15:09:40 -04001732 requestUtcTime();
1733 }
destradaa6568d702014-10-27 12:47:41 -07001734
Lifu Tang818aa2c2016-02-01 01:52:00 -08001735 mGnssMeasurementsProvider.onCapabilitiesUpdated(
destradaa6568d702014-10-27 12:47:41 -07001736 (capabilities & GPS_CAPABILITY_MEASUREMENTS) == GPS_CAPABILITY_MEASUREMENTS);
Lifu Tang818aa2c2016-02-01 01:52:00 -08001737 mGnssNavigationMessageProvider.onCapabilitiesUpdated(
destradaa6568d702014-10-27 12:47:41 -07001738 (capabilities & GPS_CAPABILITY_NAV_MESSAGES) == GPS_CAPABILITY_NAV_MESSAGES);
Mike Lockwood04598b62010-04-14 17:17:24 -04001739 }
1740
1741 /**
Lifu Tang82f893d2016-01-21 18:15:33 -08001742 * Called from native code to inform us the hardware information.
1743 */
Lifu Tang9363b942016-02-16 18:07:00 -08001744 private void setGnssYearOfHardware(int yearOfHardware) {
1745 if (DEBUG) Log.d(TAG, "setGnssYearOfHardware called with " + yearOfHardware);
Lifu Tang82f893d2016-01-21 18:15:33 -08001746 mYearOfHardware = yearOfHardware;
1747 }
1748
Lifu Tang9363b942016-02-16 18:07:00 -08001749 public interface GnssSystemInfoProvider {
Lifu Tang82f893d2016-01-21 18:15:33 -08001750 /**
1751 * Returns the year of GPS hardware.
1752 */
Lifu Tang9363b942016-02-16 18:07:00 -08001753 int getGnssYearOfHardware();
Lifu Tang82f893d2016-01-21 18:15:33 -08001754 }
1755
1756 /**
1757 * @hide
1758 */
Lifu Tang9363b942016-02-16 18:07:00 -08001759 public GnssSystemInfoProvider getGnssSystemInfoProvider() {
1760 return new GnssSystemInfoProvider() {
Lifu Tang82f893d2016-01-21 18:15:33 -08001761 @Override
Lifu Tang9363b942016-02-16 18:07:00 -08001762 public int getGnssYearOfHardware() {
Lifu Tang82f893d2016-01-21 18:15:33 -08001763 return mYearOfHardware;
1764 }
1765 };
1766 }
1767
Wyatt Rileycf879db2017-01-12 13:57:38 -08001768 public interface GnssBatchingProvider {
1769 /**
1770 * Returns the GNSS batching size
1771 */
1772 int getSize();
1773 /**
1774 * Starts the hardware batching operation
1775 */
1776 boolean start(long periodNanos, boolean wakeOnFifoFull);
1777 /**
1778 * Forces a flush of existing locations from the hardware batching
1779 */
1780 void flush();
1781 /**
1782 * Stops the batching operation
1783 */
1784 boolean stop();
1785 }
1786
1787 /**
1788 * @hide
1789 */
1790 public GnssBatchingProvider getGnssBatchingProvider() {
1791 return new GnssBatchingProvider() {
1792 @Override
1793 public int getSize() {
1794 return native_get_batch_size();
1795 }
1796 @Override
1797 public boolean start(long periodNanos, boolean wakeOnFifoFull) {
1798 if (periodNanos <= 0) {
1799 Log.e(TAG, "Invalid periodNanos " + periodNanos +
1800 "in batching request, not started");
1801 return false;
1802 }
1803 return native_start_batch(periodNanos, wakeOnFifoFull);
1804 }
1805 @Override
1806 public void flush() {
1807 native_flush_batch();
1808 }
1809 @Override
1810 public boolean stop() {
1811 return native_stop_batch();
1812 }
1813 };
1814 }
1815
1816 /**
1817 * Initialize Batching if enabled
1818 */
1819 private void enableBatching() {
1820 if (!native_init_batching()) {
1821 Log.e(TAG, "Failed to initialize GNSS batching");
1822 };
1823 }
1824
1825 /**
1826 * Disable batching
1827 */
1828 private void disableBatching() {
1829 native_stop_batch();
1830 native_cleanup_batching();
1831 }
1832
1833 /**
1834 * called from native code - GNSS location batch callback
1835 */
1836 private void reportLocationBatch(Location[] locationArray) {
1837 List<Location> locations = new ArrayList<>(Arrays.asList(locationArray));
1838 if(DEBUG) { Log.d(TAG, "Location batch of size " + locationArray.length + "reported"); }
1839 try {
1840 mILocationManager.reportLocationBatch(locations);
1841 } catch (RemoteException e) {
1842 Log.e(TAG, "RemoteException calling reportLocationBatch");
1843 }
1844 }
1845
Lifu Tang82f893d2016-01-21 18:15:33 -08001846 /**
Mike Lockwood62a8fc12010-03-22 14:23:26 -04001847 * called from native code to request XTRA data
1848 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001849 private void xtraDownloadRequest() {
Joe Onoratof5d95cb2010-01-07 21:48:32 -05001850 if (DEBUG) Log.d(TAG, "xtraDownloadRequest");
Mike Lockwood98e48692010-04-07 16:32:51 -04001851 sendMessage(DOWNLOAD_XTRA_DATA, 0, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001852 }
1853
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001854 /**
destradaa0682809a2013-08-12 18:50:30 -07001855 * Converts the GPS HAL status to the internal Geofence Hardware status.
1856 */
1857 private int getGeofenceStatus(int status) {
1858 switch(status) {
1859 case GPS_GEOFENCE_OPERATION_SUCCESS:
1860 return GeofenceHardware.GEOFENCE_SUCCESS;
1861 case GPS_GEOFENCE_ERROR_GENERIC:
1862 return GeofenceHardware.GEOFENCE_FAILURE;
1863 case GPS_GEOFENCE_ERROR_ID_EXISTS:
1864 return GeofenceHardware.GEOFENCE_ERROR_ID_EXISTS;
1865 case GPS_GEOFENCE_ERROR_INVALID_TRANSITION:
1866 return GeofenceHardware.GEOFENCE_ERROR_INVALID_TRANSITION;
1867 case GPS_GEOFENCE_ERROR_TOO_MANY_GEOFENCES:
1868 return GeofenceHardware.GEOFENCE_ERROR_TOO_MANY_GEOFENCES;
1869 case GPS_GEOFENCE_ERROR_ID_UNKNOWN:
1870 return GeofenceHardware.GEOFENCE_ERROR_ID_UNKNOWN;
1871 default:
1872 return -1;
1873 }
1874 }
1875
1876 /**
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001877 * Called from native to report GPS Geofence transition
1878 * All geofence callbacks are called on the same thread
1879 */
Wyatt Riley5d229832017-02-10 17:06:00 -08001880 private void reportGeofenceTransition(int geofenceId, Location location, int transition,
1881 long transitionTimestamp) {
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001882 if (mGeofenceHardwareImpl == null) {
1883 mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
1884 }
Wyatt Riley5d229832017-02-10 17:06:00 -08001885
destradaa0682809a2013-08-12 18:50:30 -07001886 mGeofenceHardwareImpl.reportGeofenceTransition(
1887 geofenceId,
1888 location,
1889 transition,
1890 transitionTimestamp,
1891 GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE,
1892 FusedBatchOptions.SourceTechnologies.GNSS);
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001893 }
1894
1895 /**
1896 * called from native code to report GPS status change.
1897 */
Wyatt Riley5d229832017-02-10 17:06:00 -08001898 private void reportGeofenceStatus(int status, Location location) {
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001899 if (mGeofenceHardwareImpl == null) {
1900 mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
1901 }
destradaa0682809a2013-08-12 18:50:30 -07001902 int monitorStatus = GeofenceHardware.MONITOR_CURRENTLY_UNAVAILABLE;
1903 if(status == GPS_GEOFENCE_AVAILABLE) {
1904 monitorStatus = GeofenceHardware.MONITOR_CURRENTLY_AVAILABLE;
1905 }
1906 mGeofenceHardwareImpl.reportGeofenceMonitorStatus(
1907 GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE,
1908 monitorStatus,
1909 location,
1910 FusedBatchOptions.SourceTechnologies.GNSS);
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001911 }
1912
1913 /**
1914 * called from native code - Geofence Add callback
1915 */
1916 private void reportGeofenceAddStatus(int geofenceId, int status) {
1917 if (mGeofenceHardwareImpl == null) {
1918 mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
1919 }
destradaa0682809a2013-08-12 18:50:30 -07001920 mGeofenceHardwareImpl.reportGeofenceAddStatus(geofenceId, getGeofenceStatus(status));
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001921 }
1922
1923 /**
1924 * called from native code - Geofence Remove callback
1925 */
1926 private void reportGeofenceRemoveStatus(int geofenceId, int status) {
1927 if (mGeofenceHardwareImpl == null) {
1928 mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
1929 }
destradaa0682809a2013-08-12 18:50:30 -07001930 mGeofenceHardwareImpl.reportGeofenceRemoveStatus(geofenceId, getGeofenceStatus(status));
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001931 }
1932
1933 /**
1934 * called from native code - Geofence Pause callback
1935 */
1936 private void reportGeofencePauseStatus(int geofenceId, int status) {
1937 if (mGeofenceHardwareImpl == null) {
1938 mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
1939 }
destradaa0682809a2013-08-12 18:50:30 -07001940 mGeofenceHardwareImpl.reportGeofencePauseStatus(geofenceId, getGeofenceStatus(status));
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001941 }
1942
1943 /**
1944 * called from native code - Geofence Resume callback
1945 */
1946 private void reportGeofenceResumeStatus(int geofenceId, int status) {
1947 if (mGeofenceHardwareImpl == null) {
1948 mGeofenceHardwareImpl = GeofenceHardwareImpl.getInstance(mContext);
1949 }
destradaa0682809a2013-08-12 18:50:30 -07001950 mGeofenceHardwareImpl.reportGeofenceResumeStatus(geofenceId, getGeofenceStatus(status));
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07001951 }
1952
Danke Xie22d1f9f2009-08-18 18:28:45 -04001953 //=============================================================
1954 // NI Client support
Miguel Torroja1e84da82010-07-27 07:02:24 +02001955 //=============================================================
Danke Xie22d1f9f2009-08-18 18:28:45 -04001956 private final INetInitiatedListener mNetInitiatedListener = new INetInitiatedListener.Stub() {
destradaaef752b62015-04-17 13:10:47 -07001957 // Sends a response for an NI request to HAL.
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001958 @Override
Miguel Torroja1e84da82010-07-27 07:02:24 +02001959 public boolean sendNiResponse(int notificationId, int userResponse)
1960 {
1961 // TODO Add Permission check
Danke Xie22d1f9f2009-08-18 18:28:45 -04001962
Miguel Torroja1e84da82010-07-27 07:02:24 +02001963 if (DEBUG) Log.d(TAG, "sendNiResponse, notifId: " + notificationId +
1964 ", response: " + userResponse);
1965 native_send_ni_response(notificationId, userResponse);
1966 return true;
1967 }
Danke Xie22d1f9f2009-08-18 18:28:45 -04001968 };
Nick Pelly6fa9ad42012-07-16 12:18:23 -07001969
Danke Xie22d1f9f2009-08-18 18:28:45 -04001970 public INetInitiatedListener getNetInitiatedListener() {
1971 return mNetInitiatedListener;
1972 }
1973
1974 // Called by JNI function to report an NI request.
Miguel Torroja1e84da82010-07-27 07:02:24 +02001975 public void reportNiNotification(
1976 int notificationId,
1977 int niType,
1978 int notifyFlags,
1979 int timeout,
1980 int defaultResponse,
1981 String requestorId,
1982 String text,
1983 int requestorIdEncoding,
Hridya Valsaraju2ea29602016-09-13 08:38:09 -07001984 int textEncoding
Danke Xie22d1f9f2009-08-18 18:28:45 -04001985 )
Miguel Torroja1e84da82010-07-27 07:02:24 +02001986 {
1987 Log.i(TAG, "reportNiNotification: entered");
1988 Log.i(TAG, "notificationId: " + notificationId +
1989 ", niType: " + niType +
1990 ", notifyFlags: " + notifyFlags +
1991 ", timeout: " + timeout +
1992 ", defaultResponse: " + defaultResponse);
1993
1994 Log.i(TAG, "requestorId: " + requestorId +
1995 ", text: " + text +
1996 ", requestorIdEncoding: " + requestorIdEncoding +
1997 ", textEncoding: " + textEncoding);
1998
1999 GpsNiNotification notification = new GpsNiNotification();
2000
2001 notification.notificationId = notificationId;
2002 notification.niType = niType;
2003 notification.needNotify = (notifyFlags & GpsNetInitiatedHandler.GPS_NI_NEED_NOTIFY) != 0;
2004 notification.needVerify = (notifyFlags & GpsNetInitiatedHandler.GPS_NI_NEED_VERIFY) != 0;
2005 notification.privacyOverride = (notifyFlags & GpsNetInitiatedHandler.GPS_NI_PRIVACY_OVERRIDE) != 0;
2006 notification.timeout = timeout;
2007 notification.defaultResponse = defaultResponse;
2008 notification.requestorId = requestorId;
2009 notification.text = text;
2010 notification.requestorIdEncoding = requestorIdEncoding;
2011 notification.textEncoding = textEncoding;
2012
Miguel Torroja1e84da82010-07-27 07:02:24 +02002013 mNIHandler.handleNiNotification(notification);
2014 }
2015
2016 /**
2017 * Called from native code to request set id info.
2018 * We should be careful about receiving null string from the TelephonyManager,
2019 * because sending null String to JNI function would cause a crash.
2020 */
2021
2022 private void requestSetID(int flags) {
2023 TelephonyManager phone = (TelephonyManager)
2024 mContext.getSystemService(Context.TELEPHONY_SERVICE);
destradaaef752b62015-04-17 13:10:47 -07002025 int type = AGPS_SETID_TYPE_NONE;
Miguel Torroja1e84da82010-07-27 07:02:24 +02002026 String data = "";
2027
2028 if ((flags & AGPS_RIL_REQUEST_SETID_IMSI) == AGPS_RIL_REQUEST_SETID_IMSI) {
2029 String data_temp = phone.getSubscriberId();
2030 if (data_temp == null) {
2031 // This means the framework does not have the SIM card ready.
2032 } else {
2033 // This means the framework has the SIM card.
2034 data = data_temp;
2035 type = AGPS_SETID_TYPE_IMSI;
2036 }
2037 }
2038 else if ((flags & AGPS_RIL_REQUEST_SETID_MSISDN) == AGPS_RIL_REQUEST_SETID_MSISDN) {
2039 String data_temp = phone.getLine1Number();
2040 if (data_temp == null) {
2041 // This means the framework does not have the SIM card ready.
2042 } else {
2043 // This means the framework has the SIM card.
2044 data = data_temp;
2045 type = AGPS_SETID_TYPE_MSISDN;
2046 }
2047 }
2048 native_agps_set_id(type, data);
2049 }
2050
2051 /**
Mike Lockwood9b9fb5c2011-06-29 15:09:40 -04002052 * Called from native code to request utc time info
2053 */
Mike Lockwood9b9fb5c2011-06-29 15:09:40 -04002054 private void requestUtcTime() {
destradaae21252a2015-09-08 12:32:59 -07002055 if (DEBUG) Log.d(TAG, "utcTimeRequest");
Mike Lockwood9b9fb5c2011-06-29 15:09:40 -04002056 sendMessage(INJECT_NTP_TIME, 0, null);
2057 }
2058
2059 /**
Miguel Torroja1e84da82010-07-27 07:02:24 +02002060 * Called from native code to request reference location info
2061 */
2062
Hridya Valsaraju2ea29602016-09-13 08:38:09 -07002063 private void requestRefLocation() {
Miguel Torroja1e84da82010-07-27 07:02:24 +02002064 TelephonyManager phone = (TelephonyManager)
2065 mContext.getSystemService(Context.TELEPHONY_SERVICE);
Victoria Leased50d0c32012-10-29 13:16:17 -07002066 final int phoneType = phone.getPhoneType();
2067 if (phoneType == TelephonyManager.PHONE_TYPE_GSM) {
Miguel Torroja1e84da82010-07-27 07:02:24 +02002068 GsmCellLocation gsm_cell = (GsmCellLocation) phone.getCellLocation();
Victoria Leased50d0c32012-10-29 13:16:17 -07002069 if ((gsm_cell != null) && (phone.getNetworkOperator() != null)
2070 && (phone.getNetworkOperator().length() > 3)) {
Miguel Torroja1e84da82010-07-27 07:02:24 +02002071 int type;
2072 int mcc = Integer.parseInt(phone.getNetworkOperator().substring(0,3));
2073 int mnc = Integer.parseInt(phone.getNetworkOperator().substring(3));
Mike Lockwoodedc0f3872010-10-22 09:16:17 -04002074 int networkType = phone.getNetworkType();
2075 if (networkType == TelephonyManager.NETWORK_TYPE_UMTS
2076 || networkType == TelephonyManager.NETWORK_TYPE_HSDPA
2077 || networkType == TelephonyManager.NETWORK_TYPE_HSUPA
Arun Ravindran58d46122012-07-30 17:50:21 +03002078 || networkType == TelephonyManager.NETWORK_TYPE_HSPA
2079 || networkType == TelephonyManager.NETWORK_TYPE_HSPAP) {
Miguel Torroja1e84da82010-07-27 07:02:24 +02002080 type = AGPS_REF_LOCATION_TYPE_UMTS_CELLID;
Mike Lockwoodedc0f3872010-10-22 09:16:17 -04002081 } else {
Miguel Torroja1e84da82010-07-27 07:02:24 +02002082 type = AGPS_REF_LOCATION_TYPE_GSM_CELLID;
Mike Lockwoodedc0f3872010-10-22 09:16:17 -04002083 }
Miguel Torroja1e84da82010-07-27 07:02:24 +02002084 native_agps_set_ref_location_cellid(type, mcc, mnc,
2085 gsm_cell.getLac(), gsm_cell.getCid());
Mike Lockwoodedc0f3872010-10-22 09:16:17 -04002086 } else {
Miguel Torroja1e84da82010-07-27 07:02:24 +02002087 Log.e(TAG,"Error getting cell location info.");
Mike Lockwoodedc0f3872010-10-22 09:16:17 -04002088 }
Victoria Leased50d0c32012-10-29 13:16:17 -07002089 } else if (phoneType == TelephonyManager.PHONE_TYPE_CDMA) {
2090 Log.e(TAG, "CDMA not supported.");
Mike Lockwoodedc0f3872010-10-22 09:16:17 -04002091 }
Miguel Torroja1e84da82010-07-27 07:02:24 +02002092 }
Danke Xie22d1f9f2009-08-18 18:28:45 -04002093
Mike Lockwood98e48692010-04-07 16:32:51 -04002094 private void sendMessage(int message, int arg, Object obj) {
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002095 // hold a wake lock until this message is delivered
Jeff Brown028872f2012-08-25 13:07:01 -07002096 // note that this assumes the message will not be removed from the queue before
2097 // it is handled (otherwise the wake lock would be leaked).
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002098 mWakeLock.acquire();
Wyatt Rileycf879db2017-01-12 13:57:38 -08002099 if (Log.isLoggable(TAG, Log.INFO)) {
2100 Log.i(TAG, "WakeLock acquired by sendMessage(" + messageIdAsString(message) + ", " + arg
2101 + ", " + obj + ")");
2102 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002103 mHandler.obtainMessage(message, arg, 1, obj).sendToTarget();
Mike Lockwood98e48692010-04-07 16:32:51 -04002104 }
2105
Mike Lockwood62a8fc12010-03-22 14:23:26 -04002106 private final class ProviderHandler extends Handler {
Victoria Lease5cd731a2012-12-19 15:04:21 -08002107 public ProviderHandler(Looper looper) {
2108 super(looper, null, true /*async*/);
Jeff Brown028872f2012-08-25 13:07:01 -07002109 }
2110
Mike Lockwood62a8fc12010-03-22 14:23:26 -04002111 @Override
Mike Lockwood4a7b65e2010-10-25 16:35:55 -04002112 public void handleMessage(Message msg) {
Mike Lockwood98e48692010-04-07 16:32:51 -04002113 int message = msg.what;
2114 switch (message) {
Mike Lockwood62a8fc12010-03-22 14:23:26 -04002115 case ENABLE:
2116 if (msg.arg1 == 1) {
2117 handleEnable();
2118 } else {
2119 handleDisable();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002120 }
Mike Lockwood62a8fc12010-03-22 14:23:26 -04002121 break;
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002122 case SET_REQUEST:
2123 GpsRequest gpsRequest = (GpsRequest) msg.obj;
2124 handleSetRequest(gpsRequest.request, gpsRequest.source);
Mike Lockwood03ca2162010-04-01 08:10:09 -07002125 break;
Mike Lockwood62a8fc12010-03-22 14:23:26 -04002126 case UPDATE_NETWORK_STATE:
destradaae21252a2015-09-08 12:32:59 -07002127 handleUpdateNetworkState((Network) msg.obj);
2128 break;
2129 case REQUEST_SUPL_CONNECTION:
2130 handleRequestSuplConnection((InetAddress) msg.obj);
2131 break;
2132 case RELEASE_SUPL_CONNECTION:
2133 handleReleaseSuplConnection(msg.arg1);
Mike Lockwood62a8fc12010-03-22 14:23:26 -04002134 break;
2135 case INJECT_NTP_TIME:
2136 handleInjectNtpTime();
2137 break;
2138 case DOWNLOAD_XTRA_DATA:
Wyatt Riley0d6e54e22016-10-05 12:03:03 -07002139 handleDownloadXtraData();
Mike Lockwood62a8fc12010-03-22 14:23:26 -04002140 break;
Kevin Tang40e1baf2012-01-10 14:32:44 -08002141 case INJECT_NTP_TIME_FINISHED:
2142 mInjectNtpTimePending = STATE_IDLE;
2143 break;
2144 case DOWNLOAD_XTRA_DATA_FINISHED:
2145 mDownloadXtraDataPending = STATE_IDLE;
2146 break;
Mike Lockwood62a8fc12010-03-22 14:23:26 -04002147 case UPDATE_LOCATION:
destradaae21252a2015-09-08 12:32:59 -07002148 handleUpdateLocation((Location) msg.obj);
Mike Lockwood62a8fc12010-03-22 14:23:26 -04002149 break;
destradaafb23c672015-04-16 14:01:27 -07002150 case SUBSCRIPTION_OR_SIM_CHANGED:
2151 subscriptionOrSimChanged(mContext);
2152 break;
2153 case INITIALIZE_HANDLER:
destradaae21252a2015-09-08 12:32:59 -07002154 handleInitialize();
destradaafb23c672015-04-16 14:01:27 -07002155 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002156 }
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002157 if (msg.arg2 == 1) {
2158 // wakelock was taken for this message, release it
2159 mWakeLock.release();
Wyatt Rileycf879db2017-01-12 13:57:38 -08002160 if (Log.isLoggable(TAG, Log.INFO)) {
2161 Log.i(TAG, "WakeLock released by handleMessage(" + messageIdAsString(message)
2162 + ", " + msg.arg1 + ", " + msg.obj + ")");
2163 }
Mike Lockwood98e48692010-04-07 16:32:51 -04002164 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002165 }
destradaafb23c672015-04-16 14:01:27 -07002166
2167 /**
Lifu Tang30f95a72016-01-07 23:20:38 -08002168 * This method is bound to {@link #GnssLocationProvider(Context, ILocationManager, Looper)}.
destradaafb23c672015-04-16 14:01:27 -07002169 * It is in charge of loading properties and registering for events that will be posted to
2170 * this handler.
2171 */
destradaae21252a2015-09-08 12:32:59 -07002172 private void handleInitialize() {
destradaafb23c672015-04-16 14:01:27 -07002173 // load default GPS configuration
2174 // (this configuration might change in the future based on SIM changes)
2175 reloadGpsProperties(mContext, mProperties);
2176
2177 // TODO: When this object "finishes" we should unregister by invoking
2178 // SubscriptionManager.getInstance(mContext).unregister(mOnSubscriptionsChangedListener);
2179 // This is not strictly necessary because it will be unregistered if the
2180 // notification fails but it is good form.
2181
2182 // Register for SubscriptionInfo list changes which is guaranteed
2183 // to invoke onSubscriptionsChanged the first time.
2184 SubscriptionManager.from(mContext)
2185 .addOnSubscriptionsChangedListener(mOnSubscriptionsChangedListener);
2186
2187 // listen for events
destradaaef752b62015-04-17 13:10:47 -07002188 IntentFilter intentFilter;
2189 if (native_is_agps_ril_supported()) {
2190 intentFilter = new IntentFilter();
2191 intentFilter.addAction(Intents.DATA_SMS_RECEIVED_ACTION);
2192 intentFilter.addDataScheme("sms");
2193 intentFilter.addDataAuthority("localhost", "7275");
2194 mContext.registerReceiver(mBroadcastReceiver, intentFilter, null, this);
destradaafb23c672015-04-16 14:01:27 -07002195
destradaaef752b62015-04-17 13:10:47 -07002196 intentFilter = new IntentFilter();
2197 intentFilter.addAction(Intents.WAP_PUSH_RECEIVED_ACTION);
2198 try {
2199 intentFilter.addDataType("application/vnd.omaloc-supl-init");
2200 } catch (IntentFilter.MalformedMimeTypeException e) {
2201 Log.w(TAG, "Malformed SUPL init mime type");
2202 }
2203 mContext.registerReceiver(mBroadcastReceiver, intentFilter, null, this);
2204 } else if (DEBUG) {
2205 Log.d(TAG, "Skipped registration for SMS/WAP-PUSH messages because AGPS Ril in GPS"
2206 + " HAL is not supported");
destradaafb23c672015-04-16 14:01:27 -07002207 }
destradaafb23c672015-04-16 14:01:27 -07002208
2209 intentFilter = new IntentFilter();
2210 intentFilter.addAction(ALARM_WAKEUP);
2211 intentFilter.addAction(ALARM_TIMEOUT);
destradaafb23c672015-04-16 14:01:27 -07002212 intentFilter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED);
Adam Lesinski87c17df2015-05-27 13:24:13 -07002213 intentFilter.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
destradaafb23c672015-04-16 14:01:27 -07002214 intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
2215 intentFilter.addAction(Intent.ACTION_SCREEN_ON);
2216 intentFilter.addAction(SIM_STATE_CHANGED);
2217 mContext.registerReceiver(mBroadcastReceiver, intentFilter, null, this);
2218
destradaae21252a2015-09-08 12:32:59 -07002219 // register for connectivity change events, this is equivalent to the deprecated way of
2220 // registering for CONNECTIVITY_ACTION broadcasts
2221 NetworkRequest.Builder networkRequestBuilder = new NetworkRequest.Builder();
2222 networkRequestBuilder.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
2223 networkRequestBuilder.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
2224 NetworkRequest networkRequest = networkRequestBuilder.build();
2225 mConnMgr.registerNetworkCallback(networkRequest, mNetworkConnectivityCallback);
2226
destradaafb23c672015-04-16 14:01:27 -07002227 // listen for PASSIVE_PROVIDER updates
2228 LocationManager locManager =
2229 (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
2230 long minTime = 0;
2231 float minDistance = 0;
2232 boolean oneShot = false;
2233 LocationRequest request = LocationRequest.createFromDeprecatedProvider(
2234 LocationManager.PASSIVE_PROVIDER,
2235 minTime,
2236 minDistance,
2237 oneShot);
2238 // Don't keep track of this request since it's done on behalf of other clients
2239 // (which are kept track of separately).
2240 request.setHideFromAppOps(true);
2241 locManager.requestLocationUpdates(
2242 request,
2243 new NetworkLocationListener(),
2244 getLooper());
2245 }
2246 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002247
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002248 private final class NetworkLocationListener implements LocationListener {
2249 @Override
2250 public void onLocationChanged(Location location) {
2251 // this callback happens on mHandler looper
2252 if (LocationManager.NETWORK_PROVIDER.equals(location.getProvider())) {
2253 handleUpdateLocation(location);
2254 }
2255 }
2256 @Override
2257 public void onStatusChanged(String provider, int status, Bundle extras) { }
2258 @Override
2259 public void onProviderEnabled(String provider) { }
2260 @Override
2261 public void onProviderDisabled(String provider) { }
2262 }
2263
Kevin Tanga5fe6b22011-06-05 14:25:16 -07002264 private String getSelectedApn() {
2265 Uri uri = Uri.parse("content://telephony/carriers/preferapn");
destradaa96a14702014-06-05 11:36:30 -07002266 Cursor cursor = null;
2267 try {
2268 cursor = mContext.getContentResolver().query(
2269 uri,
2270 new String[] { "apn" },
2271 null /* selection */,
2272 null /* selectionArgs */,
2273 Carriers.DEFAULT_SORT_ORDER);
2274 if (cursor != null && cursor.moveToFirst()) {
2275 return cursor.getString(0);
2276 } else {
2277 Log.e(TAG, "No APN found to select.");
2278 }
2279 } catch (Exception e) {
destradaaea8a8a62014-06-23 18:19:03 -07002280 Log.e(TAG, "Error encountered on selecting the APN.", e);
destradaa96a14702014-06-05 11:36:30 -07002281 } finally {
2282 if (cursor != null) {
Kevin Tanga5fe6b22011-06-05 14:25:16 -07002283 cursor.close();
2284 }
2285 }
destradaa96a14702014-06-05 11:36:30 -07002286
2287 return null;
2288 }
2289
2290 private int getApnIpType(String apn) {
destradaae21252a2015-09-08 12:32:59 -07002291 ensureInHandlerThread();
destradaa96a14702014-06-05 11:36:30 -07002292 if (apn == null) {
2293 return APN_INVALID;
2294 }
2295
destradaa96a14702014-06-05 11:36:30 -07002296 String selection = String.format("current = 1 and apn = '%s' and carrier_enabled = 1", apn);
2297 Cursor cursor = null;
2298 try {
2299 cursor = mContext.getContentResolver().query(
2300 Carriers.CONTENT_URI,
2301 new String[] { Carriers.PROTOCOL },
2302 selection,
2303 null,
2304 Carriers.DEFAULT_SORT_ORDER);
2305
2306 if (null != cursor && cursor.moveToFirst()) {
2307 return translateToApnIpType(cursor.getString(0), apn);
2308 } else {
2309 Log.e(TAG, "No entry found in query for APN: " + apn);
2310 }
2311 } catch (Exception e) {
2312 Log.e(TAG, "Error encountered on APN query for: " + apn, e);
2313 } finally {
2314 if (cursor != null) {
2315 cursor.close();
2316 }
2317 }
2318
2319 return APN_INVALID;
2320 }
2321
2322 private int translateToApnIpType(String ipProtocol, String apn) {
2323 if ("IP".equals(ipProtocol)) {
2324 return APN_IPV4;
2325 }
2326 if ("IPV6".equals(ipProtocol)) {
2327 return APN_IPV6;
2328 }
2329 if ("IPV4V6".equals(ipProtocol)) {
2330 return APN_IPV4V6;
2331 }
2332
2333 // we hit the default case so the ipProtocol is not recognized
2334 String message = String.format("Unknown IP Protocol: %s, for APN: %s", ipProtocol, apn);
2335 Log.e(TAG, message);
2336 return APN_INVALID;
2337 }
2338
2339 private void setRouting() {
2340 if (mAGpsDataConnectionIpAddr == null) {
2341 return;
2342 }
2343
destradaae21252a2015-09-08 12:32:59 -07002344 // TODO: replace the use of this deprecated API
destradaa96a14702014-06-05 11:36:30 -07002345 boolean result = mConnMgr.requestRouteToHostAddress(
2346 ConnectivityManager.TYPE_MOBILE_SUPL,
2347 mAGpsDataConnectionIpAddr);
2348
2349 if (!result) {
2350 Log.e(TAG, "Error requesting route to host: " + mAGpsDataConnectionIpAddr);
2351 } else if (DEBUG) {
2352 Log.d(TAG, "Successfully requested route to host: " + mAGpsDataConnectionIpAddr);
2353 }
Kevin Tanga5fe6b22011-06-05 14:25:16 -07002354 }
2355
destradaae21252a2015-09-08 12:32:59 -07002356 /**
2357 * @return {@code true} if there is a data network available for outgoing connections,
2358 * {@code false} otherwise.
2359 */
2360 private boolean isDataNetworkConnected() {
2361 NetworkInfo activeNetworkInfo = mConnMgr.getActiveNetworkInfo();
2362 return activeNetworkInfo != null && activeNetworkInfo.isConnected();
2363 }
2364
2365 /**
2366 * Ensures the calling function is running in the thread associated with {@link #mHandler}.
2367 */
2368 private void ensureInHandlerThread() {
2369 if (mHandler != null && Looper.myLooper() == mHandler.getLooper()) {
2370 return;
2371 }
2372 throw new RuntimeException("This method must run on the Handler thread.");
2373 }
2374
2375 /**
2376 * @return A string representing the current state stored in {@link #mAGpsDataConnectionState}.
2377 */
2378 private String agpsDataConnStateAsString() {
2379 switch(mAGpsDataConnectionState) {
2380 case AGPS_DATA_CONNECTION_CLOSED:
2381 return "CLOSED";
2382 case AGPS_DATA_CONNECTION_OPEN:
2383 return "OPEN";
2384 case AGPS_DATA_CONNECTION_OPENING:
2385 return "OPENING";
2386 default:
2387 return "<Unknown>";
2388 }
2389 }
2390
2391 /**
2392 * @return A string representing the given GPS_AGPS_DATA status.
2393 */
2394 private String agpsDataConnStatusAsString(int agpsDataConnStatus) {
2395 switch (agpsDataConnStatus) {
2396 case GPS_AGPS_DATA_CONNECTED:
2397 return "CONNECTED";
2398 case GPS_AGPS_DATA_CONN_DONE:
2399 return "DONE";
2400 case GPS_AGPS_DATA_CONN_FAILED:
2401 return "FAILED";
2402 case GPS_RELEASE_AGPS_DATA_CONN:
2403 return "RELEASE";
2404 case GPS_REQUEST_AGPS_DATA_CONN:
2405 return "REQUEST";
2406 default:
2407 return "<Unknown>";
2408 }
2409 }
2410
Wyatt Rileycf879db2017-01-12 13:57:38 -08002411 /**
2412 * @return A string representing the given message ID.
2413 */
2414 private String messageIdAsString(int message) {
2415 switch (message) {
2416 case ENABLE:
2417 return "ENABLE";
2418 case SET_REQUEST:
2419 return "SET_REQUEST";
2420 case UPDATE_NETWORK_STATE:
2421 return "UPDATE_NETWORK_STATE";
2422 case REQUEST_SUPL_CONNECTION:
2423 return "REQUEST_SUPL_CONNECTION";
2424 case RELEASE_SUPL_CONNECTION:
2425 return "RELEASE_SUPL_CONNECTION";
2426 case INJECT_NTP_TIME:
2427 return "INJECT_NTP_TIME";
2428 case DOWNLOAD_XTRA_DATA:
2429 return "DOWNLOAD_XTRA_DATA";
2430 case INJECT_NTP_TIME_FINISHED:
2431 return "INJECT_NTP_TIME_FINISHED";
2432 case DOWNLOAD_XTRA_DATA_FINISHED:
2433 return "DOWNLOAD_XTRA_DATA_FINISHED";
2434 case UPDATE_LOCATION:
2435 return "UPDATE_LOCATION";
2436 case SUBSCRIPTION_OR_SIM_CHANGED:
2437 return "SUBSCRIPTION_OR_SIM_CHANGED";
2438 case INITIALIZE_HANDLER:
2439 return "INITIALIZE_HANDLER";
2440 default:
2441 return "<Unknown>";
2442 }
2443 }
2444
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002445 @Override
2446 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
2447 StringBuilder s = new StringBuilder();
destradaa25e8caf2015-08-24 14:14:44 -07002448 s.append(" mFixInterval=").append(mFixInterval).append('\n');
2449 s.append(" mDisableGps (battery saver mode)=").append(mDisableGps).append('\n');
2450 s.append(" mEngineCapabilities=0x").append(Integer.toHexString(mEngineCapabilities));
2451 s.append(" ( ");
2452 if (hasCapability(GPS_CAPABILITY_SCHEDULING)) s.append("SCHEDULING ");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002453 if (hasCapability(GPS_CAPABILITY_MSB)) s.append("MSB ");
2454 if (hasCapability(GPS_CAPABILITY_MSA)) s.append("MSA ");
2455 if (hasCapability(GPS_CAPABILITY_SINGLE_SHOT)) s.append("SINGLE_SHOT ");
2456 if (hasCapability(GPS_CAPABILITY_ON_DEMAND_TIME)) s.append("ON_DEMAND_TIME ");
destradaa25e8caf2015-08-24 14:14:44 -07002457 if (hasCapability(GPS_CAPABILITY_GEOFENCING)) s.append("GEOFENCING ");
2458 if (hasCapability(GPS_CAPABILITY_MEASUREMENTS)) s.append("MEASUREMENTS ");
2459 if (hasCapability(GPS_CAPABILITY_NAV_MESSAGES)) s.append("NAV_MESSAGES ");
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002460 s.append(")\n");
2461
Wyatt Rileycf879db2017-01-12 13:57:38 -08002462 s.append(" internal state: ").append(native_get_internal_state());
2463 s.append("\n");
2464
Nick Pelly6fa9ad42012-07-16 12:18:23 -07002465 pw.append(s);
2466 }
2467
Wei Liu6f6326b2015-06-24 23:47:50 -07002468 /**
2469 * A simple implementation of exponential backoff.
2470 */
2471 private static final class BackOff {
2472 private static final int MULTIPLIER = 2;
2473 private final long mInitIntervalMillis;
2474 private final long mMaxIntervalMillis;
2475 private long mCurrentIntervalMillis;
2476
2477 public BackOff(long initIntervalMillis, long maxIntervalMillis) {
2478 mInitIntervalMillis = initIntervalMillis;
2479 mMaxIntervalMillis = maxIntervalMillis;
2480
2481 mCurrentIntervalMillis = mInitIntervalMillis / MULTIPLIER;
2482 }
2483
2484 public long nextBackoffMillis() {
2485 if (mCurrentIntervalMillis > mMaxIntervalMillis) {
2486 return mMaxIntervalMillis;
2487 }
2488
2489 mCurrentIntervalMillis *= MULTIPLIER;
2490 return mCurrentIntervalMillis;
2491 }
2492
2493 public void reset() {
2494 mCurrentIntervalMillis = mInitIntervalMillis / MULTIPLIER;
2495 }
2496 }
2497
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002498 // for GPS SV statistics
Lifu Tang120480f2016-02-07 18:08:19 -08002499 private static final int MAX_SVS = 64;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002500
2501 // preallocated arrays, to avoid memory allocation in reportStatus()
Lifu Tang120480f2016-02-07 18:08:19 -08002502 private int mSvidWithFlags[] = new int[MAX_SVS];
Lifu Tang76a620f2016-02-26 19:53:01 -08002503 private float mCn0s[] = new float[MAX_SVS];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002504 private float mSvElevations[] = new float[MAX_SVS];
2505 private float mSvAzimuths[] = new float[MAX_SVS];
gomo4402af62017-01-11 13:20:13 -08002506 private float mSvCarrierFreqs[] = new float[MAX_SVS];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002507 private int mSvCount;
Mike Lockwoodb16e7802009-08-06 09:26:02 -04002508 // preallocated to avoid memory allocation in reportNmea()
2509 private byte[] mNmeaBuffer = new byte[120];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002510
gomo4402af62017-01-11 13:20:13 -08002511 static { class_init_native(); }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002512 private static native void class_init_native();
2513 private static native boolean native_is_supported();
destradaaef752b62015-04-17 13:10:47 -07002514 private static native boolean native_is_agps_ril_supported();
2515 private static native boolean native_is_gnss_configuration_supported();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002516
2517 private native boolean native_init();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002518 private native void native_cleanup();
Mike Lockwood04598b62010-04-14 17:17:24 -04002519 private native boolean native_set_position_mode(int mode, int recurrence, int min_interval,
2520 int preferred_accuracy, int preferred_time);
2521 private native boolean native_start();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002522 private native boolean native_stop();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002523 private native void native_delete_aiding_data(int flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002524 // returns number of SVs
2525 // mask[0] is ephemeris mask and mask[1] is almanac mask
Lifu Tang76a620f2016-02-26 19:53:01 -08002526 private native int native_read_sv_status(int[] prnWithFlags, float[] cn0s, float[] elevations,
gomo4402af62017-01-11 13:20:13 -08002527 float[] azimuths, float[] carrierFrequencies);
Mike Lockwoodf602d362010-06-20 14:28:16 -07002528 private native int native_read_nmea(byte[] buffer, int bufferSize);
Mike Lockwoodd26ce0d2009-06-11 12:25:46 -04002529 private native void native_inject_location(double latitude, double longitude, float accuracy);
2530
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -06002531 // XTRA Support
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002532 private native void native_inject_time(long time, long timeReference, int uncertainty);
2533 private native boolean native_supports_xtra();
2534 private native void native_inject_xtra_data(byte[] data, int length);
The Android Open Source Project10592532009-03-18 17:39:46 -07002535
Fred Fettinger3c8fbdf2010-01-04 15:38:13 -06002536 // DEBUG Support
2537 private native String native_get_internal_state();
2538
2539 // AGPS Support
destradaa96a14702014-06-05 11:36:30 -07002540 private native void native_agps_data_conn_open(String apn, int apnIpType);
Mike Lockwoode3635c92009-05-11 08:38:02 -04002541 private native void native_agps_data_conn_closed();
2542 private native void native_agps_data_conn_failed();
Miguel Torroja1e84da82010-07-27 07:02:24 +02002543 private native void native_agps_ni_message(byte [] msg, int length);
Mike Lockwooda9e54612009-06-19 14:54:42 -04002544 private native void native_set_agps_server(int type, String hostname, int port);
Danke Xie22d1f9f2009-08-18 18:28:45 -04002545
2546 // Network-initiated (NI) Support
2547 private native void native_send_ni_response(int notificationId, int userResponse);
Miguel Torroja1e84da82010-07-27 07:02:24 +02002548
2549 // AGPS ril suport
2550 private native void native_agps_set_ref_location_cellid(int type, int mcc, int mnc,
2551 int lac, int cid);
2552 private native void native_agps_set_id(int type, String setid);
Mike Lockwood50130bb2010-10-11 06:22:50 -04002553
2554 private native void native_update_network_state(boolean connected, int type,
Kevin Tanga5fe6b22011-06-05 14:25:16 -07002555 boolean roaming, boolean available, String extraInfo, String defaultAPN);
Jaikumar Ganesh8ce470d2013-04-03 12:22:18 -07002556
2557 // Hardware Geofence support.
2558 private static native boolean native_is_geofence_supported();
2559 private static native boolean native_add_geofence(int geofenceId, double latitude,
2560 double longitude, double radius, int lastTransition,int monitorTransitions,
2561 int notificationResponsivenes, int unknownTimer);
2562 private static native boolean native_remove_geofence(int geofenceId);
2563 private static native boolean native_resume_geofence(int geofenceId, int transitions);
2564 private static native boolean native_pause_geofence(int geofenceId);
destradaaea8a8a62014-06-23 18:19:03 -07002565
2566 // Gps Hal measurements support.
2567 private static native boolean native_is_measurement_supported();
destradaa4b3e3932014-07-21 18:01:47 -07002568 private native boolean native_start_measurement_collection();
2569 private native boolean native_stop_measurement_collection();
2570
2571 // Gps Navigation message support.
2572 private static native boolean native_is_navigation_message_supported();
2573 private native boolean native_start_navigation_message_collection();
2574 private native boolean native_stop_navigation_message_collection();
Tsuwei Chen52617bb2014-08-25 11:49:11 -07002575
2576 // GNSS Configuration
Hridya Valsaraju2ea29602016-09-13 08:38:09 -07002577 private static native boolean native_set_supl_version(int version);
2578 private static native boolean native_set_supl_mode(int mode);
2579 private static native boolean native_set_supl_es(int es);
2580 private static native boolean native_set_lpp_profile(int lppProfile);
2581 private static native boolean native_set_gnss_pos_protocol_select(int gnssPosProtocolSelect);
2582 private static native boolean native_set_gps_lock(int gpsLock);
2583 private static native boolean native_set_emergency_supl_pdn(int emergencySuplPdn);
2584
Wyatt Rileycf879db2017-01-12 13:57:38 -08002585 // GNSS Batching
2586 private static native int native_get_batch_size();
2587 private static native boolean native_start_batch(long periodNanos, boolean wakeOnFifoFull);
2588 private static native void native_flush_batch();
2589 private static native boolean native_stop_batch();
2590 private static native boolean native_init_batching();
2591 private static native void native_cleanup_batching();
2592
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002593}